1 /*
2  * Copyright (c) 2020-2021 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 #include "player_audio_sink.h"
17 #include "player_sync.h"
18 #include "media_log.h"
19 #include <unistd.h>
20 #include <cmath>
21 #include <sys/time.h>
22 
23 namespace OHOS {
24 namespace Media {
25 #define CHECK_FAILED_RETURN(value, target, ret, printfString) \
26 do { \
27     if ((value) != (target)) { \
28         MEDIA_ERR_LOG(" %s ", (printfString != nullptr) ? (printfString) : " "); \
29         return (ret); \
30     } \
31 } while (0)
32 
33 #define CHECK_NULL_RETURN(value, ret, printfString) \
34 do { \
35     if ((value) == nullptr) { \
36         MEDIA_ERR_LOG(" %s ", (printfString != nullptr) ? (printfString) : " "); \
37         return (ret); \
38     } \
39 } while (0)
40 
41 const int32_t HALF_FACTOR = 2;
42 const int32_t MAX_QUEUE_BUF_NUM = 32;
43 const int32_t MAX_AUDIO_ADAPTER_NUM = 2;
44 const int32_t AUDIO_SAMPLE_WIDTH_BYTE = 2;
45 
AudioSink()46 AudioSink::AudioSink()
47     : started_(false), paused_(false), eosSended_(false), rendFrameCnt_(0), lastRendFrameCnt_(0),
48       pauseAfterPlay_(false), syncHdl_(nullptr), renderMode_(RENDER_MODE_NORMAL),
49       rendStartTime_(-1), lastRendPts_(AV_INVALID_PTS), lastRendSysTimeMs_(-1), renderDelay_(0),
50       leftVolume_(0.0f), rightVolume_(0.0f), eosPts_(AV_INVALID_PTS), receivedEos_(false), audioManager_(nullptr),
51       audioAdapter_(nullptr), audioRender_(nullptr), reportedFirstFrame(false), audioStreamType_(0)
52 {
53     ResetRendStartTime();
54     frameCacheQue_.clear();
55     frameReleaseQue_.clear();
56     callBack_.onEventCallback = nullptr;
57     callBack_.priv= nullptr;
58     attr_.sinkType = SINK_TYPE_BUT;
59     attr_.trackId = 0;
60     attr_.audAttr.format = 0;
61     attr_.audAttr.sampleFmt = 0;
62     attr_.audAttr.sampleRate = 0;
63     attr_.audAttr.channel = 0;
64     attr_.audAttr.volume = 0.0;
65     renderPort_.dir = PORT_OUT;
66     renderPort_.portId = 0;
67     renderPort_.portName = nullptr;
68 }
69 
~AudioSink()70 AudioSink::~AudioSink()
71 {
72     DeInit();
73 }
74 
DeInit()75 void AudioSink::DeInit()
76 {
77     started_ = false;
78     if (frameCacheQue_.size() != 0 || frameReleaseQue_.size()) {
79         MEDIA_ERR_LOG("frames should be released before DeInit!!!");
80     }
81     if (audioAdapter_ != nullptr && audioRender_ != nullptr) {
82         audioAdapter_->DestroyRender(audioAdapter_, audioRender_);
83     }
84     if (audioManager_ != nullptr) {
85         audioManager_->UnloadAdapter(audioManager_, audioAdapter_);
86     }
87     frameCacheQue_.clear();
88     frameReleaseQue_.clear();
89 }
90 
Init(SinkAttr & atrr)91 int32_t AudioSink::Init(SinkAttr &atrr)
92 {
93     attr_ = atrr;
94     audioManager_ = GetAudioManagerFuncs();
95     if (audioManager_ == nullptr) {
96         return SINK_GET_DEVICE_FAILED;
97     }
98     int32_t ret = 0;
99     int32_t size = -1;
100     struct AudioAdapterDescriptor *descs = nullptr;
101     audioManager_->GetAllAdapters(audioManager_, &descs, &size);
102     if (size > MAX_AUDIO_ADAPTER_NUM) {
103         return SINK_GET_DEVICE_FAILED;
104     }
105     for (int index = 0; index < size; index++) {
106         struct AudioAdapterDescriptor *desc = &descs[index];
107         for (int port = 0; (desc != nullptr && port < static_cast<int>(desc->portNum)); port++) {
108             if (desc->ports[port].dir == PORT_OUT &&
109                 (audioManager_->LoadAdapter(audioManager_, desc, &audioAdapter_)) == 0 && audioAdapter_ != nullptr) {
110                 (void)audioAdapter_->InitAllPorts(audioAdapter_);
111                 if (memcpy_s(&renderPort_, sizeof(struct AudioPort),
112                     &desc->ports[port], sizeof(struct AudioPort)) != 0) {
113                     MEDIA_ERR_LOG("memcpy_s failed");
114                 }
115                 break;
116             }
117         }
118     }
119     if (ret != 0 || audioAdapter_ == nullptr) {
120         MEDIA_ERR_LOG("load audiodevice failed");
121         return SINK_LAOD_DEVICE_FAILED;
122     }
123 
124     struct AudioSampleAttributes param;
125     param.sampleRate = attr_.audAttr.sampleRate;
126     param.format = AUDIO_FORMAT_TYPE_PCM_16_BIT;
127     param.channelCount = attr_.audAttr.channel;
128     param.interleaved = false;
129     param.type = (audioStreamType_ == 1) ? AUDIO_IN_COMMUNICATION : AUDIO_IN_MEDIA;
130     MEDIA_INFO_LOG("sampleRate:%u, channelCount:%u", param.sampleRate, param.channelCount);
131 
132     struct AudioDeviceDescriptor deviceDesc;
133     deviceDesc.portId = 0;
134     deviceDesc.pins = PIN_OUT_SPEAKER;
135     deviceDesc.desc = nullptr;
136     ret = audioAdapter_->CreateRender(audioAdapter_, &deviceDesc, &param, &audioRender_);
137     if (ret != 0 || audioRender_ == nullptr) {
138         MEDIA_ERR_LOG("AudioDeviceCreateRender failed");
139         return SINK_OPEN_STREAM_FAILED;
140     }
141     MEDIA_DEBUG_LOG("init success");
142     return SINK_SUCCESS;
143 }
144 
ResetRendStartTime()145 void AudioSink::ResetRendStartTime()
146 {
147     lastRendFrameCnt_ = 0;
148     lastRendPts_ = AV_INVALID_PTS;
149     rendStartTime_ = AV_INVALID_PTS;
150 }
151 
GetStatus(AudioSinkStatus & status)152 void AudioSink::GetStatus(AudioSinkStatus &status)
153 {
154     status.audFrameCount = rendFrameCnt_;
155 }
156 
UpdateAudioPts(int64_t lastPts,int64_t & timestamp,CodecBuffer & renderFrame)157 void AudioSink::UpdateAudioPts(int64_t lastPts, int64_t &timestamp, CodecBuffer &renderFrame)
158 {
159     if (renderFrame.timeStamp == -1) {
160         float sampleCnt = (renderFrame.buffer[0].length / attr_.audAttr.channel) / AUDIO_SAMPLE_WIDTH_BYTE;
161         float duration = (static_cast<int64_t>(sampleCnt) * MS_SCALE) / attr_.audAttr.sampleRate;
162         renderFrame.timeStamp = lastPts + duration;
163     }
164     timestamp = renderFrame.timeStamp;
165     renderDelay_ = 0;
166     if (audioRender_->GetLatency(audioRender_, &renderDelay_) == HI_SUCCESS) {
167         timestamp -= renderDelay_;
168     }
169 }
170 
QueueRenderFrame(const PlayerBufferInfo & frame,const bool cacheQueue)171 void AudioSink::QueueRenderFrame(const PlayerBufferInfo &frame, const bool cacheQueue)
172 {
173     std::lock_guard<std::mutex> lock(mutex_);
174     if (frame.info.bufferCnt == 0) {
175         return;
176     }
177     if (cacheQueue) {
178         frameCacheQue_.push_back(frame);
179     } else {
180         frameReleaseQue_.push_back(frame);
181     }
182 }
183 
GetRenderFrame(PlayerBufferInfo & renderFrame,const PlayerBufferInfo & frame)184 int32_t AudioSink::GetRenderFrame(PlayerBufferInfo &renderFrame, const PlayerBufferInfo &frame)
185 {
186     std::lock_guard<std::mutex> lock(mutex_);
187     int32_t ret = SINK_QUE_EMPTY;
188     if (frame.info.bufferCnt != 0) {
189         frameCacheQue_.push_back(frame);
190     }
191     if (frameCacheQue_.size() != 0) {
192         renderFrame = frameCacheQue_[0];
193         ret = SINK_SUCCESS;
194     }
195     return ret;
196 }
197 
ReleaseQueHeadFrame(void)198 void AudioSink::ReleaseQueHeadFrame(void)
199 {
200     std::lock_guard<std::mutex> lock(mutex_);
201     if (frameCacheQue_.size() != 0) {
202         PlayerBufferInfo frame = frameCacheQue_[0];
203         frameCacheQue_.erase(frameCacheQue_.begin());
204         frameReleaseQue_.push_back(frame);
205     }
206 }
207 
ReleaseQueAllFrame(void)208 void AudioSink::ReleaseQueAllFrame(void)
209 {
210     size_t i;
211     size_t queSize;
212     std::lock_guard<std::mutex> lock(mutex_);
213     queSize = frameCacheQue_.size();
214     if (queSize > MAX_QUEUE_BUF_NUM) {
215         return;
216     }
217     for (i = 0; i < queSize; i++) {
218         frameReleaseQue_.push_back(frameCacheQue_[i]);
219     }
220     frameCacheQue_.clear();
221 }
222 
DequeReleaseFrame(PlayerBufferInfo & frame)223 int32_t AudioSink::DequeReleaseFrame(PlayerBufferInfo &frame)
224 {
225     std::lock_guard<std::mutex> lock(mutex_);
226     if (frameReleaseQue_.size() == 0) {
227         return SINK_QUE_EMPTY;
228     }
229     frame = frameReleaseQue_[0];
230     frameReleaseQue_.erase(frameReleaseQue_.begin());
231     return SINK_SUCCESS;
232 }
233 
RenderRptEvent(EventCbType event)234 void AudioSink::RenderRptEvent(EventCbType event)
235 {
236     if (callBack_.onEventCallback != nullptr) {
237         if (event == EVNET_AUDIO_PLAY_EOS && eosSended_) {
238             return;
239         }
240         callBack_.onEventCallback(callBack_.priv, event, 0, 0);
241         if (event == EVNET_AUDIO_PLAY_EOS) {
242             eosSended_ = true;
243         }
244     }
245 }
246 
WriteToAudioDevice(CodecBuffer & renderFrame)247 int32_t AudioSink::WriteToAudioDevice(CodecBuffer &renderFrame)
248 {
249     int32_t ret;
250     uint64_t writeLen = 0;
251     if ((audioRender_ == nullptr) || (&renderFrame.buffer[0] == nullptr)) {
252         ReleaseQueHeadFrame();
253         return SINK_RENDER_ERROR;
254     }
255 
256     ret = audioRender_->RenderFrame(audioRender_, (void*)(renderFrame.buffer[0].buf + renderFrame.buffer[0].offset),
257         static_cast<uint64_t>(renderFrame.buffer[0].length), &writeLen);
258     if ((unsigned long)renderFrame.buffer[0].length != writeLen) {
259         return SINK_RENDER_FULL;
260     } else if (ret != HI_SUCCESS) {
261         ReleaseQueHeadFrame();
262         MEDIA_ERR_LOG("RenderFrame failed ret: %x", ret);
263         return SINK_RENDER_ERROR;
264     }
265     ReleaseQueHeadFrame();
266     return HI_SUCCESS;
267 }
268 
RenderFrame(PlayerBufferInfo & frame)269 int32_t AudioSink::RenderFrame(PlayerBufferInfo &frame)
270 {
271     SyncRet syncRet = SYNC_RET_PLAY;
272     int64_t crtPlayPts = 0;
273     uint64_t frameCnt;
274     PlayerBufferInfo renderFrame;
275     struct AudioTimeStamp timestamp;
276 
277     if (!reportedFirstFrame && renderMode_ == RENDER_MODE_PAUSE_AFTER_PLAY) {
278         callBack_.onEventCallback(callBack_.priv, EVNET_FIRST_AUDIO_REND, 0, 0);
279         reportedFirstFrame = true;
280         MEDIA_INFO_LOG("report first audio frame");
281     }
282 
283     if (paused_ || renderMode_ == RENDER_MODE_PAUSE_AFTER_PLAY) {
284         QueueRenderFrame(frame, true);
285         return SINK_SUCCESS;
286     }
287     if (!started_ || audioRender_ == nullptr) {
288         QueueRenderFrame(frame, false);
289         MEDIA_ERR_LOG("paused or audio dev not inited");
290         return SINK_RENDER_ERROR;
291     }
292 
293     if (GetRenderFrame(renderFrame, frame) != SINK_SUCCESS) {
294         if (receivedEos_) {
295             RenderRptEvent(EVNET_AUDIO_PLAY_EOS);
296             return SINK_RENDER_EOS;
297         }
298         return SINK_QUE_EMPTY;
299     }
300     if (pauseAfterPlay_) {
301         return SINK_SUCCESS;
302     }
303 
304     int32_t ret = audioRender_->GetRenderPosition(audioRender_, &frameCnt, &timestamp);
305     if (ret != HI_SUCCESS) {
306         MEDIA_ERR_LOG("GetRenderPosition failed,ret=0x%x", ret);
307         return SINK_RENDER_ERROR;
308     }
309 
310     UpdateAudioPts(lastRendPts_, crtPlayPts, renderFrame.info);
311     ret = (syncHdl_ != nullptr) ? syncHdl_->ProcAudFrame(crtPlayPts, syncRet) : HI_SUCCESS;
312     if (ret != HI_SUCCESS) {
313         MEDIA_ERR_LOG("ProcAudFrame pts: %lld failed", renderFrame.info.timeStamp);
314         ReleaseQueHeadFrame();
315         return SINK_RENDER_ERROR;
316     }
317     if (syncRet == SYNC_RET_PLAY) {
318         ret = WriteToAudioDevice(renderFrame.info);
319     } else if (syncRet == SYNC_RET_DROP) {
320         ReleaseQueHeadFrame();
321         ret = SINK_SUCCESS;
322     } else if (syncRet == SYNC_RET_REPEAT) {
323         ret = SINK_RENDER_DELAY;
324     } else {
325         MEDIA_ERR_LOG("aud invalid sync ret: %d", syncRet);
326         ReleaseQueHeadFrame();
327         ret =  SINK_RENDER_ERROR;
328     }
329 
330     if (ret == SINK_SUCCESS || ret == SINK_RENDER_ERROR) {
331         lastRendPts_ = renderFrame.info.timeStamp;
332         rendFrameCnt_++;
333     }
334     return ret;
335 }
336 
RenderEos(void)337 void AudioSink::RenderEos(void)
338 {
339     receivedEos_ = true;
340     eosPts_ = lastRendPts_;
341 }
342 
Start(void)343 int32_t AudioSink::Start(void)
344 {
345     CHECK_FAILED_RETURN(started_, false, SINK_SUCCESS, "have started");
346     CHECK_NULL_RETURN(audioRender_, SINK_INVALID_OP, "audio dev not inited");
347     int32_t ret = audioRender_->control.Start((AudioHandle)audioRender_);
348     if (ret == 0) {
349         started_ = true;
350     }
351     return ret;
352 }
353 
SetVolume(float left,float right)354 int32_t AudioSink::SetVolume(float left, float right)
355 {
356     float volume;
357     CHECK_FAILED_RETURN(started_, true, -1, "not started");
358     if (audioRender_ == nullptr) {
359         MEDIA_ERR_LOG("AudioSink::SetVolume failed audioRender_ null");
360         return -1;
361     }
362 
363     leftVolume_ = left;
364     rightVolume_ = right;
365     if ((leftVolume_ == 0) && (rightVolume_ != 0)) {
366         volume = rightVolume_;
367     } else if ((leftVolume_ != 0) && (rightVolume_ == 0)) {
368         volume = leftVolume_;
369     } else {
370         volume = (leftVolume_ + rightVolume_) / HALF_FACTOR;
371     }
372     audioRender_->volume.SetVolume(reinterpret_cast<AudioHandle>(audioRender_), volume);
373     return SINK_SUCCESS;
374 }
375 
GetVolume(float & left,float & right)376 int32_t AudioSink::GetVolume(float &left, float &right)
377 {
378     left = leftVolume_;
379     right = rightVolume_;
380     return SINK_SUCCESS;
381 }
382 
Stop(void)383 int32_t AudioSink::Stop(void)
384 {
385     if (started_ && audioRender_ != nullptr) {
386         (void)audioRender_->control.Stop(reinterpret_cast<AudioHandle>(audioRender_));
387     }
388     ReleaseQueAllFrame();
389     rendFrameCnt_ = 0;
390     started_ = false;
391     paused_ = false;
392     eosSended_ = false;
393     return SINK_SUCCESS;
394 }
395 
Pause(void)396 int32_t AudioSink::Pause(void)
397 {
398     if (started_ && audioRender_ != nullptr) {
399         (void)audioRender_->control.Pause(reinterpret_cast<AudioHandle>(audioRender_));
400     }
401     paused_ = true;
402     return SINK_SUCCESS;
403 }
404 
Resume(void)405 int32_t AudioSink::Resume(void)
406 {
407     CHECK_FAILED_RETURN(paused_, true, -1, "not paused");
408     CHECK_NULL_RETURN(audioRender_, -1, "audioRender_ is null");
409     (void)audioRender_->control.Resume(reinterpret_cast<AudioHandle>(audioRender_));
410     paused_ = false;
411     renderMode_ = RENDER_MODE_NORMAL;
412     return SINK_SUCCESS;
413 }
414 
Reset(void)415 int32_t AudioSink::Reset(void)
416 {
417     ReleaseQueAllFrame();
418     if (started_ && audioRender_ != nullptr) {
419         (void)audioRender_->control.Flush(reinterpret_cast<AudioHandle>(audioRender_));
420     }
421 
422     ResetRendStartTime();
423     receivedEos_ = false;
424     renderDelay_ = 0;
425     return SINK_SUCCESS;
426 }
427 
RegisterCallBack(PlayEventCallback & callback)428 int32_t AudioSink::RegisterCallBack(PlayEventCallback &callback)
429 {
430     callBack_ = callback;
431     return SINK_SUCCESS;
432 }
433 
SetSync(PlayerSync * sync)434 void AudioSink::SetSync(PlayerSync *sync)
435 {
436     syncHdl_ = sync;
437 }
438 
Flush(void)439 int32_t AudioSink::Flush(void)
440 {
441     if (started_ && audioRender_ != nullptr) {
442         (void)audioRender_->control.Flush(reinterpret_cast<AudioHandle>(audioRender_));
443     }
444     renderDelay_ = 0;
445     return 0;
446 }
447 
GetRenderPosition(int64_t & position)448 void AudioSink::GetRenderPosition(int64_t &position)
449 {
450     position = lastRendPts_;
451 }
452 
SetRenderMode(RenderMode mode)453 void AudioSink::SetRenderMode(RenderMode mode)
454 {
455     renderMode_ = mode;
456 }
457 
SetAudioStreamType(int32_t & type)458 void AudioSink::SetAudioStreamType(int32_t &type)
459 {
460     audioStreamType_ = type;
461 }
462 }
463 }