1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef AUDIO_ENDPOINT_H
17 #define AUDIO_ENDPOINT_H
18 
19 #include <sstream>
20 #include <memory>
21 #include <thread>
22 
23 #include "i_audio_renderer_sink.h"
24 #include "i_process_status_listener.h"
25 #include "linear_pos_time_model.h"
26 
27 namespace OHOS {
28 namespace AudioStandard {
29 // When AudioEndpoint is offline, notify the owner.
30 class IAudioEndpointStatusListener {
31 public:
32     enum HdiDeviceStatus : uint32_t {
33         STATUS_ONLINE = 0,
34         STATUS_OFFLINE,
35         STATUS_INVALID,
36     };
37 
38     /**
39      * When AudioEndpoint changed status, we need to notify AudioProcessStream.
40     */
41     virtual int32_t OnEndpointStatusChange(HdiDeviceStatus status) = 0;
42 };
43 
44 class AudioEndpoint : public IProcessStatusListener {
45 public:
46     static constexpr int32_t MAX_LINKED_PROCESS = 6; // 6
47     enum EndpointType : uint32_t {
48         TYPE_MMAP = 0,
49         TYPE_INVALID,
50         TYPE_INDEPENDENT,
51         TYPE_VOIP_MMAP
52     };
53 
54     enum EndpointStatus : uint32_t {
55         INVALID = 0,
56         UNLINKED, // no process linked
57         IDEL,     // no running process
58         STARTING, // calling start sink
59         RUNNING,  // at least one process is running
60         STOPPING, // calling stop sink
61         STOPPED   // sink stoped
62     };
63 
64     static std::shared_ptr<AudioEndpoint> CreateEndpoint(EndpointType type, uint64_t id,
65         const AudioProcessConfig &clientConfig, const DeviceInfo &deviceInfo);
66     static std::string GenerateEndpointKey(DeviceInfo &deviceInfo, int32_t endpointFlag);
67 
68     virtual std::string GetEndpointName() = 0;
69 
70     virtual EndpointType GetEndpointType() = 0;
71     virtual int32_t SetVolume(AudioStreamType streamType, float volume) = 0;
72     virtual int32_t ResolveBuffer(std::shared_ptr<OHAudioBuffer> &buffer) = 0;
73     virtual std::shared_ptr<OHAudioBuffer> GetBuffer() = 0;
74 
75     virtual EndpointStatus GetStatus() = 0;
76 
77     virtual void Release() = 0;
78 
79     virtual bool ShouldInnerCap() = 0;
80     virtual int32_t EnableFastInnerCap() = 0;
81     virtual int32_t DisableFastInnerCap() = 0;
82 
83     virtual int32_t LinkProcessStream(IAudioProcessStream *processStream) = 0;
84     virtual int32_t UnlinkProcessStream(IAudioProcessStream *processStream) = 0;
85 
86     virtual int32_t GetPreferBufferInfo(uint32_t &totalSizeInframe, uint32_t &spanSizeInframe) = 0;
87 
88     virtual void Dump(std::string &dumpString) = 0;
89 
90     virtual DeviceRole GetDeviceRole() = 0;
91     virtual DeviceInfo &GetDeviceInfo() = 0;
92     virtual float GetMaxAmplitude() = 0;
93     virtual uint32_t GetLinkedProcessCount() = 0;
94 
95     virtual AudioMode GetAudioMode() const = 0;
96 
97     virtual void SetHibernateEndpointRelease(const bool &isHibernate) = 0;
98 
99     virtual ~AudioEndpoint() = default;
100 private:
101     virtual bool Config(const DeviceInfo &deviceInfo) = 0;
102 };
103 
104 class AudioEndpointSeparate : public AudioEndpoint {
105 public:
106     explicit AudioEndpointSeparate(EndpointType type, uint64_t id, AudioStreamType streamType);
107     ~AudioEndpointSeparate();
108 
109     bool Config(const DeviceInfo &deviceInfo) override;
110     bool StartDevice();
111     bool StopDevice();
112 
113     // when audio process start.
114     int32_t OnStart(IAudioProcessStream *processStream) override;
115     // when audio process pause.
116     int32_t OnPause(IAudioProcessStream *processStream) override;
117     // when audio process request update handle info.
118     int32_t OnUpdateHandleInfo(IAudioProcessStream *processStream) override;
119     int32_t LinkProcessStream(IAudioProcessStream *processStream) override;
120     int32_t UnlinkProcessStream(IAudioProcessStream *processStream) override;
121     int32_t GetPreferBufferInfo(uint32_t &totalSizeInframe, uint32_t &spanSizeInframe) override;
122 
123     void Dump(std::string &dumpString) override;
124 
125     std::string GetEndpointName() override;
126 
127     inline EndpointType GetEndpointType() override
128     {
129         return endpointType_;
130     }
131 
132     // for inner-cap
133     bool ShouldInnerCap() override;
134     int32_t EnableFastInnerCap() override;
135     int32_t DisableFastInnerCap() override;
136 
137     int32_t SetVolume(AudioStreamType streamType, float volume) override;
138 
139     int32_t ResolveBuffer(std::shared_ptr<OHAudioBuffer> &buffer) override;
140 
141     std::shared_ptr<OHAudioBuffer> GetBuffer() override;
142 
143     EndpointStatus GetStatus() override;
144 
145     void Release() override;
146 
147     DeviceInfo &GetDeviceInfo() override
148     {
149         return deviceInfo_;
150     }
151 
152     DeviceRole GetDeviceRole() override
153     {
154         return deviceInfo_.deviceRole;
155     }
156 
157     float GetMaxAmplitude() override;
158 
159     uint32_t GetLinkedProcessCount() override;
160 
161     AudioMode GetAudioMode() const final;
162 
163     void SetHibernateEndpointRelease(const bool &isHibernate) override;
164 private:
165     int32_t PrepareDeviceBuffer(const DeviceInfo &deviceInfo);
166     int32_t GetAdapterBufferInfo(const DeviceInfo &deviceInfo);
167     void ResyncPosition();
168     void InitAudiobuffer(bool resetReadWritePos);
169     void ProcessData(const std::vector<AudioStreamData> &srcDataList, const AudioStreamData &dstData);
170 
171     bool GetDeviceHandleInfo(uint64_t &frames, int64_t &nanoTime);
172     int32_t GetProcLastWriteDoneInfo(const std::shared_ptr<OHAudioBuffer> processBuffer, uint64_t curWriteFrame,
173         uint64_t &proHandleFrame, int64_t &proHandleTime);
174 
175     bool IsAnyProcessRunning();
176 
177     std::string GetStatusStr(EndpointStatus status);
178 
179     int32_t WriteToSpecialProcBuf(const std::shared_ptr<OHAudioBuffer> &procBuf, const BufferDesc &readBuf);
180     void WriteToProcessBuffers(const BufferDesc &readBuf);
181 
182 private:
183     static constexpr int64_t ONE_MILLISECOND_DURATION = 1000000; // 1ms
184     // SamplingRate EncodingType SampleFormat Channel
185     DeviceInfo deviceInfo_;
186     AudioStreamInfo dstStreamInfo_;
187     EndpointType endpointType_;
188     uint64_t id_ = 0;
189     AudioStreamType streamType_ = STREAM_DEFAULT;
190     std::mutex listLock_;
191     std::vector<IAudioProcessStream *> processList_;
192     std::vector<std::shared_ptr<OHAudioBuffer>> processBufferList_;
193 
194     std::atomic<bool> isInited_ = false;
195     std::shared_ptr<IMmapAudioRendererSink> fastSink_ = nullptr;
196     int64_t spanDuration_ = 0; // nano second
197     int64_t serverAheadReadTime_ = 0;
198     int dstBufferFd_ = -1; // -1: invalid fd.
199     uint32_t dstTotalSizeInframe_ = 0;
200     uint32_t dstSpanSizeInframe_ = 0;
201     uint32_t dstByteSizePerFrame_ = 0;
202     std::shared_ptr<OHAudioBuffer> dstAudioBuffer_ = nullptr;
203     std::atomic<EndpointStatus> endpointStatus_ = INVALID;
204 
205     std::mutex loopThreadLock_;
206     std::condition_variable workThreadCV_;
207 
208     bool isDeviceRunningInIdel_ = true; // will call start sink when linked.
209     bool needResyncPosition_ = true;
210 };
211 
212 } // namespace AudioStandard
213 } // namespace OHOS
214 #endif // AUDIO_ENDPOINT_H
215