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 ~AudioEndpoint() = default;
96 private:
97     virtual bool Config(const DeviceInfo &deviceInfo) = 0;
98 };
99 
100 class AudioEndpointSeparate : public AudioEndpoint {
101 public:
102     explicit AudioEndpointSeparate(EndpointType type, uint64_t id, AudioStreamType streamType);
103     ~AudioEndpointSeparate();
104 
105     bool Config(const DeviceInfo &deviceInfo) override;
106     bool StartDevice();
107     bool StopDevice();
108 
109     // when audio process start.
110     int32_t OnStart(IAudioProcessStream *processStream) override;
111     // when audio process pause.
112     int32_t OnPause(IAudioProcessStream *processStream) override;
113     // when audio process request update handle info.
114     int32_t OnUpdateHandleInfo(IAudioProcessStream *processStream) override;
115     int32_t LinkProcessStream(IAudioProcessStream *processStream) override;
116     int32_t UnlinkProcessStream(IAudioProcessStream *processStream) override;
117     int32_t GetPreferBufferInfo(uint32_t &totalSizeInframe, uint32_t &spanSizeInframe) override;
118 
119     void Dump(std::string &dumpString) override;
120 
121     std::string GetEndpointName() override;
122 
GetEndpointType()123     inline EndpointType GetEndpointType() override
124     {
125         return endpointType_;
126     }
127 
128     // for inner-cap
129     bool ShouldInnerCap() override;
130     int32_t EnableFastInnerCap() override;
131     int32_t DisableFastInnerCap() override;
132 
133     int32_t SetVolume(AudioStreamType streamType, float volume) override;
134 
135     int32_t ResolveBuffer(std::shared_ptr<OHAudioBuffer> &buffer) override;
136 
137     std::shared_ptr<OHAudioBuffer> GetBuffer() override;
138 
139     EndpointStatus GetStatus() override;
140 
141     void Release() override;
142 
GetDeviceInfo()143     DeviceInfo &GetDeviceInfo() override
144     {
145         return deviceInfo_;
146     }
147 
GetDeviceRole()148     DeviceRole GetDeviceRole() override
149     {
150         return deviceInfo_.deviceRole;
151     }
152 
153     float GetMaxAmplitude() override;
154     uint32_t GetLinkedProcessCount() override;
155 private:
156     int32_t PrepareDeviceBuffer(const DeviceInfo &deviceInfo);
157     int32_t GetAdapterBufferInfo(const DeviceInfo &deviceInfo);
158     void ResyncPosition();
159     void InitAudiobuffer(bool resetReadWritePos);
160     void ProcessData(const std::vector<AudioStreamData> &srcDataList, const AudioStreamData &dstData);
161 
162     bool GetDeviceHandleInfo(uint64_t &frames, int64_t &nanoTime);
163     int32_t GetProcLastWriteDoneInfo(const std::shared_ptr<OHAudioBuffer> processBuffer, uint64_t curWriteFrame,
164         uint64_t &proHandleFrame, int64_t &proHandleTime);
165 
166     bool IsAnyProcessRunning();
167 
168     std::string GetStatusStr(EndpointStatus status);
169 
170     int32_t WriteToSpecialProcBuf(const std::shared_ptr<OHAudioBuffer> &procBuf, const BufferDesc &readBuf);
171     void WriteToProcessBuffers(const BufferDesc &readBuf);
172 
173 private:
174     static constexpr int64_t ONE_MILLISECOND_DURATION = 1000000; // 1ms
175     // SamplingRate EncodingType SampleFormat Channel
176     DeviceInfo deviceInfo_;
177     AudioStreamInfo dstStreamInfo_;
178     EndpointType endpointType_;
179     uint64_t id_ = 0;
180     AudioStreamType streamType_ = STREAM_DEFAULT;
181     std::mutex listLock_;
182     std::vector<IAudioProcessStream *> processList_;
183     std::vector<std::shared_ptr<OHAudioBuffer>> processBufferList_;
184 
185     std::atomic<bool> isInited_ = false;
186     std::shared_ptr<IMmapAudioRendererSink> fastSink_ = nullptr;
187     int64_t spanDuration_ = 0; // nano second
188     int64_t serverAheadReadTime_ = 0;
189     int dstBufferFd_ = -1; // -1: invalid fd.
190     uint32_t dstTotalSizeInframe_ = 0;
191     uint32_t dstSpanSizeInframe_ = 0;
192     uint32_t dstByteSizePerFrame_ = 0;
193     std::shared_ptr<OHAudioBuffer> dstAudioBuffer_ = nullptr;
194     std::atomic<EndpointStatus> endpointStatus_ = INVALID;
195 
196     std::mutex loopThreadLock_;
197     std::condition_variable workThreadCV_;
198 
199     bool isDeviceRunningInIdel_ = true; // will call start sink when linked.
200     bool needResyncPosition_ = true;
201 };
202 
203 } // namespace AudioStandard
204 } // namespace OHOS
205 #endif // AUDIO_ENDPOINT_H
206