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 #include "avcodec_audio_avbuffer_decoder_demo.h"
17 #include <iostream>
18 #include <unistd.h>
19 #include <chrono>
20 #include "avcodec_codec_name.h"
21 #include "avcodec_common.h"
22 #include "avcodec_errors.h"
23 #include "demo_log.h"
24 #include "media_description.h"
25 #include "native_avcodec_base.h"
26 #include "native_avformat.h"
27 #include "native_avbuffer.h"
28 #include "native_avmemory.h"
29 #include "securec.h"
30 #ifdef SUPPORT_DRM
31 #include "native_mediakeysession.h"
32 #include "native_mediakeysystem.h"
33 #endif
34 
35 using namespace OHOS;
36 using namespace OHOS::MediaAVCodec;
37 using namespace OHOS::MediaAVCodec::AudioBufferDemo;
38 using namespace std;
39 namespace {
40 constexpr uint32_t CHANNEL_COUNT = 2;
41 constexpr uint32_t SAMPLE_RATE = 44100;
42 constexpr uint32_t DEFAULT_AAC_TYPE = 1;
43 constexpr int64_t BITS_RATE[static_cast<uint32_t>(AudioBufferFormatType::TYPE_MAX)] = {199000, 261000, 60000, 320000};
44 constexpr uint32_t AMRWB_SAMPLE_RATE = 16000;
45 constexpr uint32_t AMRNB_SAMPLE_RATE = 8000;
46 constexpr string_view INPUT_AAC_FILE_PATH = "/data/test/media/aac_2c_44100hz_199k.dat";
47 constexpr string_view OUTPUT_AAC_PCM_FILE_PATH = "/data/test/media/aac_2c_44100hz_199k_dec.pcm";
48 constexpr string_view INPUT_FLAC_FILE_PATH = "/data/test/media/flac_2c_44100hz_261k.dat";
49 constexpr string_view OUTPUT_FLAC_PCM_FILE_PATH = "/data/test/media/flac_2c_44100hz_261k.pcm";
50 constexpr string_view INPUT_MP3_FILE_PATH = "/data/test/media/mp3_2c_44100hz_60k.dat";
51 constexpr string_view OUTPUT_MP3_PCM_FILE_PATH = "/data/test/media/mp3_2c_44100hz_60k.pcm";
52 constexpr string_view INPUT_VORBIS_FILE_PATH = "/data/test/media/vorbis_2c_44100hz_320k.dat";
53 constexpr string_view OUTPUT_VORBIS_PCM_FILE_PATH = "/data/test/media/vorbis_2c_44100hz_320k.pcm";
54 constexpr string_view INPUT_AMRNB_FILE_PATH = "/data/test/media/voice_amrnb_10200.dat";
55 constexpr string_view OUTPUT_AMRNB_PCM_FILE_PATH = "/data/test/media/voice_amrnb_10200.pcm";
56 constexpr string_view INPUT_AMRWB_FILE_PATH = "/data/test/media/voice_amrwb_23850.dat";
57 constexpr string_view OUTPUT_AMRWB_PCM_FILE_PATH = "/data/test/media/voice_amrwb_23850.pcm";
58 constexpr string_view INPUT_G711MU_FILE_PATH = "/data/test/media/g711mu_8kHz.dat";
59 constexpr string_view OUTPUT_G711MU_PCM_FILE_PATH = "/data/test/media/g711mu_8kHz_decode.pcm";
60 constexpr string_view INPUT_APE_FILE_PATH = "/data/test/media/ape.dat";
61 constexpr string_view OUTPUT_APE_PCM_FILE_PATH = "/data/test/media/ape_decode.pcm";
62 } // namespace
63 
OnError(OH_AVCodec * codec,int32_t errorCode,void * userData)64 static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
65 {
66     (void)codec;
67     (void)errorCode;
68     (void)userData;
69     cout << "Error received, errorCode:" << errorCode << endl;
70 }
71 
OnOutputFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)72 static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
73 {
74     (void)codec;
75     (void)format;
76     (void)userData;
77     cout << "OnOutputFormatChanged received" << endl;
78 }
79 
OnInputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * data,void * userData)80 static void OnInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *data, void *userData)
81 {
82     (void)codec;
83     ADecBufferSignal *signal = static_cast<ADecBufferSignal *>(userData);
84     unique_lock<mutex> lock(signal->inMutex_);
85     signal->inQueue_.push(index);
86     signal->inBufferQueue_.push(data);
87     signal->inCond_.notify_all();
88 }
89 
OnOutputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * data,void * userData)90 static void OnOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *data, void *userData)
91 {
92     (void)codec;
93     ADecBufferSignal *signal = static_cast<ADecBufferSignal *>(userData);
94     unique_lock<mutex> lock(signal->outMutex_);
95     signal->outQueue_.push(index);
96     signal->outBufferQueue_.push(data);
97     signal->outCond_.notify_all();
98 }
99 
InitFile(AudioBufferFormatType audioType)100 bool ADecBufferDemo::InitFile(AudioBufferFormatType audioType)
101 {
102     if (audioType == AudioBufferFormatType::TYPE_AAC) {
103         inputFile_.open(INPUT_AAC_FILE_PATH, std::ios::binary);
104         pcmOutputFile_.open(OUTPUT_AAC_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
105     } else if (audioType == AudioBufferFormatType::TYPE_FLAC) {
106         inputFile_.open(INPUT_FLAC_FILE_PATH, std::ios::binary);
107         pcmOutputFile_.open(OUTPUT_FLAC_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
108     } else if (audioType == AudioBufferFormatType::TYPE_MP3) {
109         inputFile_.open(INPUT_MP3_FILE_PATH, std::ios::binary);
110         pcmOutputFile_.open(OUTPUT_MP3_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
111     } else if (audioType == AudioBufferFormatType::TYPE_VORBIS) {
112         inputFile_.open(INPUT_VORBIS_FILE_PATH, std::ios::binary);
113         pcmOutputFile_.open(OUTPUT_VORBIS_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
114     } else if (audioType == AudioBufferFormatType::TYPE_AMRNB) {
115         inputFile_.open(INPUT_AMRNB_FILE_PATH, std::ios::binary);
116         pcmOutputFile_.open(OUTPUT_AMRNB_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
117     } else if (audioType == AudioBufferFormatType::TYPE_AMRWB) {
118         inputFile_.open(INPUT_AMRWB_FILE_PATH, std::ios::binary);
119         pcmOutputFile_.open(OUTPUT_AMRWB_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
120     } else if (audioType == AudioBufferFormatType::TYPE_G711MU) {
121         inputFile_.open(INPUT_G711MU_FILE_PATH, std::ios::binary);
122         pcmOutputFile_.open(OUTPUT_G711MU_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
123     } else if (audioType == AudioBufferFormatType::TYPE_APE) {
124         inputFile_.open(INPUT_APE_FILE_PATH, std::ios::binary);
125         pcmOutputFile_.open(OUTPUT_APE_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
126     } else {
127         std::cout << "audio format type not support\n";
128         return false;
129     }
130     DEMO_CHECK_AND_RETURN_RET_LOG(inputFile_.is_open(), false, "Fatal: open input file failed");
131     DEMO_CHECK_AND_RETURN_RET_LOG(pcmOutputFile_.is_open(), false, "Fatal: open output file failed");
132     return true;
133 }
134 
RunCase(AudioBufferFormatType audioType)135 void ADecBufferDemo::RunCase(AudioBufferFormatType audioType)
136 {
137     DEMO_CHECK_AND_RETURN_LOG(InitFile(audioType), "Fatal: InitFile file failed");
138     audioType_ = audioType;
139     DEMO_CHECK_AND_RETURN_LOG(CreateDec() == AVCS_ERR_OK, "Fatal: CreateDec fail");
140     OH_AVFormat *format = OH_AVFormat_Create();
141     int32_t channelCount = CHANNEL_COUNT;
142     int32_t sampleRate = SAMPLE_RATE;
143     if (audioType == AudioBufferFormatType::TYPE_AAC) {
144         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_AAC_IS_ADTS.data(), DEFAULT_AAC_TYPE);
145         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(),
146                                 OH_BitsPerSample::SAMPLE_S16LE);
147     } else if (audioType == AudioBufferFormatType::TYPE_AMRNB || audioType == AudioBufferFormatType::TYPE_G711MU) {
148         channelCount = 1;
149         sampleRate = AMRNB_SAMPLE_RATE;
150     } else if (audioType == AudioBufferFormatType::TYPE_AMRWB || audioType == AudioBufferFormatType::TYPE_APE) {
151         channelCount = 1;
152         sampleRate = AMRWB_SAMPLE_RATE;
153         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(),
154                                 OH_BitsPerSample::SAMPLE_S16LE);
155         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_BITS_PER_CODED_SAMPLE.data(),
156                                 16); // 16 bit pre code
157     }
158     OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(), channelCount);
159     OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), sampleRate);
160     OH_AVFormat_SetLongValue(format, MediaDescriptionKey::MD_KEY_BITRATE.data(), BITS_RATE[(uint32_t)audioType]);
161     if (audioType == AudioBufferFormatType::TYPE_VORBIS) {
162         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(),
163                                 OH_BitsPerSample::SAMPLE_S16LE);
164         int64_t extradataSize;
165         DEMO_CHECK_AND_RETURN_LOG(inputFile_.is_open(), "Fatal: file is not open");
166         inputFile_.read(reinterpret_cast<char *>(&extradataSize), sizeof(int64_t));
167         DEMO_CHECK_AND_RETURN_LOG(inputFile_.gcount() == sizeof(int64_t), "Fatal: read extradataSize bytes error");
168         if (extradataSize < 0) {
169             return;
170         }
171         char buffer[extradataSize];
172         inputFile_.read(buffer, extradataSize);
173         DEMO_CHECK_AND_RETURN_LOG(inputFile_.gcount() == extradataSize, "Fatal: read extradata bytes error");
174         OH_AVFormat_SetBuffer(format, MediaDescriptionKey::MD_KEY_CODEC_CONFIG.data(),
175                               reinterpret_cast<uint8_t *>(buffer), extradataSize);
176     }
177     DEMO_CHECK_AND_RETURN_LOG(Configure(format) == AVCS_ERR_OK, "Fatal: Configure fail");
178     DEMO_CHECK_AND_RETURN_LOG(Start() == AVCS_ERR_OK, "Fatal: Start fail");
179 
180     unique_lock<mutex> lock(signal_->startMutex_);
181     signal_->startCond_.wait(lock, [this]() { return (!(isRunning_.load())); });
182 
183     DEMO_CHECK_AND_RETURN_LOG(Stop() == AVCS_ERR_OK, "Fatal: Stop fail");
184     DEMO_CHECK_AND_RETURN_LOG(Release() == AVCS_ERR_OK, "Fatal: Release fail");
185 }
186 
RunDrmCase(AudioBufferFormatType audioType)187 void ADecBufferDemo::RunDrmCase(AudioBufferFormatType audioType)
188 {
189     std::cout << "ADecBufferDemo::RunDrmCase" <<std::endl;
190 #ifdef SUPPORT_DRM
191     audioType_ = audioType;
192     DEMO_CHECK_AND_RETURN_LOG(CreateDec() == AVCS_ERR_OK, "Fatal: CreateDec fail");
193 
194     // test 1:create mediakeysystem
195     std::cout << "Test OH_MediaKeySystem_Create" << std::endl;
196     MediaKeySystem *system = NULL;
197     uint32_t errNo = OH_MediaKeySystem_Create("com.clearplay.drm", &system);
198     std::cout << "Test OH_MediaKeySystem_Create result" << system <<"and ret" << errNo << std::endl;
199 
200     // test 2:create mediakeysystem
201     std::cout << "Test OH_MediaKeySystem_CreateMediaKeySession" <<std::endl;
202     DRM_ContentProtectionLevel contentProtectionLevel = CONTENT_PROTECTION_LEVEL_SW_CRYPTO;
203     MediaKeySession *session = NULL;
204     errNo = OH_MediaKeySystem_CreateMediaKeySession(system, &contentProtectionLevel, &session);
205     std::cout <<"Test OH_MediaKeySystem_CreateMediaKeySession result" << session << "and ret" << errNo << std::endl;
206 
207     // test 3:SetDecryptConfigTest
208     std::cout <<"Test OH_AudioCodec_SetDecryptionConfig"<<std::endl;
209     errNo = OH_AudioCodec_SetDecryptionConfig(audioDec_, session, false);
210     std::cout <<"Test OH_AudioCodec_SetDecryptionConfig result"<<session<<"and ret"<<errNo<<std::endl;
211 #endif
212 }
213 
ADecBufferDemo()214 ADecBufferDemo::ADecBufferDemo() : audioDec_(nullptr), signal_(nullptr), audioType_(AudioBufferFormatType::TYPE_AAC) {}
215 
~ADecBufferDemo()216 ADecBufferDemo::~ADecBufferDemo()
217 {
218     if (signal_) {
219         delete signal_;
220         signal_ = nullptr;
221     }
222     if (inputFile_.is_open()) {
223         inputFile_.close();
224     }
225     if (pcmOutputFile_.is_open()) {
226         pcmOutputFile_.close();
227     }
228 }
229 
CreateDec()230 int32_t ADecBufferDemo::CreateDec()
231 {
232     if (audioType_ == AudioBufferFormatType::TYPE_AAC) {
233         audioDec_ = OH_AudioCodec_CreateByName((AVCodecCodecName::AUDIO_DECODER_AAC_NAME).data());
234     } else if (audioType_ == AudioBufferFormatType::TYPE_FLAC) {
235         audioDec_ = OH_AudioCodec_CreateByName((AVCodecCodecName::AUDIO_DECODER_FLAC_NAME).data());
236     } else if (audioType_ == AudioBufferFormatType::TYPE_MP3) {
237         audioDec_ = OH_AudioCodec_CreateByName((AVCodecCodecName::AUDIO_DECODER_MP3_NAME).data());
238     } else if (audioType_ == AudioBufferFormatType::TYPE_VORBIS) {
239         audioDec_ = OH_AudioCodec_CreateByName((AVCodecCodecName::AUDIO_DECODER_VORBIS_NAME).data());
240     } else if (audioType_ == AudioBufferFormatType::TYPE_AMRNB) {
241         audioDec_ = OH_AudioCodec_CreateByName((AVCodecCodecName::AUDIO_DECODER_AMRNB_NAME).data());
242     } else if (audioType_ == AudioBufferFormatType::TYPE_AMRWB) {
243         audioDec_ = OH_AudioCodec_CreateByName((AVCodecCodecName::AUDIO_DECODER_AMRWB_NAME).data());
244     } else if (audioType_ == AudioBufferFormatType::TYPE_G711MU) {
245         audioDec_ = OH_AudioCodec_CreateByName((AVCodecCodecName::AUDIO_DECODER_G711MU_NAME).data());
246     } else if (audioType_ == AudioBufferFormatType::TYPE_APE) {
247         audioDec_ = OH_AudioCodec_CreateByName((AVCodecCodecName::AUDIO_DECODER_APE_NAME).data());
248     } else {
249         return AVCS_ERR_INVALID_VAL;
250     }
251     DEMO_CHECK_AND_RETURN_RET_LOG(audioDec_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: CreateByName fail");
252 
253     signal_ = new ADecBufferSignal();
254     DEMO_CHECK_AND_RETURN_RET_LOG(signal_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
255 
256     cb_ = {&OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable};
257     int32_t ret = OH_AudioCodec_RegisterCallback(audioDec_, cb_, signal_);
258     DEMO_CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCS_ERR_UNKNOWN, "Fatal: SetCallback fail");
259 
260     return AVCS_ERR_OK;
261 }
262 
Configure(OH_AVFormat * format)263 int32_t ADecBufferDemo::Configure(OH_AVFormat *format)
264 {
265     return OH_AudioCodec_Configure(audioDec_, format);
266 }
267 
Start()268 int32_t ADecBufferDemo::Start()
269 {
270     isRunning_.store(true);
271 
272     inputLoop_ = make_unique<thread>(&ADecBufferDemo::InputFunc, this);
273     DEMO_CHECK_AND_RETURN_RET_LOG(inputLoop_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
274 
275     outputLoop_ = make_unique<thread>(&ADecBufferDemo::OutputFunc, this);
276     DEMO_CHECK_AND_RETURN_RET_LOG(outputLoop_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
277 
278     return OH_AudioCodec_Start(audioDec_);
279 }
280 
Stop()281 int32_t ADecBufferDemo::Stop()
282 {
283     isRunning_.store(false);
284     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
285         {
286             unique_lock<mutex> lock(signal_->inMutex_);
287             signal_->inCond_.notify_all();
288         }
289         inputLoop_->join();
290         inputLoop_ = nullptr;
291         while (!signal_->inQueue_.empty()) {
292             signal_->inQueue_.pop();
293         }
294         while (!signal_->inBufferQueue_.empty()) {
295             signal_->inBufferQueue_.pop();
296         }
297     }
298 
299     if (outputLoop_ != nullptr && outputLoop_->joinable()) {
300         {
301             unique_lock<mutex> lock(signal_->outMutex_);
302             signal_->outCond_.notify_all();
303         }
304         outputLoop_->join();
305         outputLoop_ = nullptr;
306         while (!signal_->outQueue_.empty()) {
307             signal_->outQueue_.pop();
308         }
309         while (!signal_->outBufferQueue_.empty()) {
310             signal_->outBufferQueue_.pop();
311         }
312     }
313     std::cout << "start stop!\n";
314     return OH_AudioCodec_Stop(audioDec_);
315 }
316 
Flush()317 int32_t ADecBufferDemo::Flush()
318 {
319     isRunning_.store(false);
320     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
321         {
322             unique_lock<mutex> lock(signal_->inMutex_);
323             signal_->inCond_.notify_all();
324         }
325         inputLoop_->join();
326         inputLoop_ = nullptr;
327         while (!signal_->inQueue_.empty()) {
328             signal_->inQueue_.pop();
329         }
330         while (!signal_->inBufferQueue_.empty()) {
331             signal_->inBufferQueue_.pop();
332         }
333         std::cout << "clear input buffer!\n";
334     }
335 
336     if (outputLoop_ != nullptr && outputLoop_->joinable()) {
337         {
338             unique_lock<mutex> lock(signal_->outMutex_);
339             signal_->outCond_.notify_all();
340         }
341         outputLoop_->join();
342         outputLoop_ = nullptr;
343         while (!signal_->outQueue_.empty()) {
344             signal_->outQueue_.pop();
345         }
346         while (!signal_->outBufferQueue_.empty()) {
347             signal_->outBufferQueue_.pop();
348         }
349         std::cout << "clear output buffer!\n";
350     }
351     return OH_AudioCodec_Flush(audioDec_);
352 }
353 
Reset()354 int32_t ADecBufferDemo::Reset()
355 {
356     return OH_AudioCodec_Reset(audioDec_);
357 }
358 
Release()359 int32_t ADecBufferDemo::Release()
360 {
361     return OH_AudioCodec_Destroy(audioDec_);
362 }
363 
HandleInputEOS(const uint32_t index)364 void ADecBufferDemo::HandleInputEOS(const uint32_t index)
365 {
366     std::cout << "end buffer\n";
367     OH_AudioCodec_PushInputBuffer(audioDec_, index);
368     signal_->inBufferQueue_.pop();
369     signal_->inQueue_.pop();
370 }
371 
InputFunc()372 void ADecBufferDemo::InputFunc()
373 {
374     int64_t size;
375     int64_t pts;
376 
377     while (isRunning_.load()) {
378         unique_lock<mutex> lock(signal_->inMutex_);
379         signal_->inCond_.wait(lock, [this]() { return (signal_->inQueue_.size() > 0 || !isRunning_.load()); });
380 
381         if (!isRunning_.load()) {
382             break;
383         }
384 
385         uint32_t index = signal_->inQueue_.front();
386         auto buffer = signal_->inBufferQueue_.front();
387         DEMO_CHECK_AND_BREAK_LOG(buffer != nullptr, "Fatal: GetInputBuffer fail");
388         inputFile_.read(reinterpret_cast<char *>(&size), sizeof(size));
389         if (inputFile_.eof() || inputFile_.gcount() == 0 || size == 0) {
390             buffer->buffer_->memory_->SetSize(1);
391             buffer->buffer_->flag_ = AVCODEC_BUFFER_FLAGS_EOS;
392             HandleInputEOS(index);
393             cout << "Set EOS" << endl;
394             break;
395         }
396         DEMO_CHECK_AND_BREAK_LOG(inputFile_.gcount() == sizeof(size), "Fatal: read size fail");
397         inputFile_.read(reinterpret_cast<char *>(&buffer->buffer_->pts_), sizeof(buffer->buffer_->pts_));
398         DEMO_CHECK_AND_BREAK_LOG(inputFile_.gcount() == sizeof(pts), "Fatal: read pts fail");
399         inputFile_.read(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(buffer)), size);
400         buffer->buffer_->memory_->SetSize(size);
401         DEMO_CHECK_AND_BREAK_LOG(inputFile_.gcount() == size, "Fatal: read buffer fail");
402 
403         cout << "SetSize" << size << endl;
404         int32_t ret;
405         if (isFirstFrame_) {
406             buffer->buffer_->flag_ = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
407             ret = OH_AudioCodec_PushInputBuffer(audioDec_, index);
408             isFirstFrame_ = false;
409         } else {
410             buffer->buffer_->flag_ = AVCODEC_BUFFER_FLAGS_NONE;
411             ret = OH_AudioCodec_PushInputBuffer(audioDec_, index);
412         }
413         signal_->inQueue_.pop();
414         signal_->inBufferQueue_.pop();
415         frameCount_++;
416         if (ret != AVCS_ERR_OK) {
417             cout << "Fatal error, exit " << ret <<endl;
418             break;
419         }
420     }
421     cout << "stop, exit" << endl;
422     inputFile_.close();
423 }
424 
OutputFunc()425 void ADecBufferDemo::OutputFunc()
426 {
427     DEMO_CHECK_AND_RETURN_LOG(pcmOutputFile_.is_open(), "Fatal: output file failedis not open");
428     while (isRunning_.load()) {
429         unique_lock<mutex> lock(signal_->outMutex_);
430         signal_->outCond_.wait(lock, [this]() { return (signal_->outQueue_.size() > 0 || !isRunning_.load()); });
431 
432         if (!isRunning_.load()) {
433             cout << "wait to stop, exit" << endl;
434             break;
435         }
436 
437         uint32_t index = signal_->outQueue_.front();
438         OH_AVBuffer *data = signal_->outBufferQueue_.front();
439         if (data == nullptr) {
440             cout << "OutputFunc OH_AVBuffer is nullptr" << endl;
441             continue;
442         }
443         pcmOutputFile_.write(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(data)), data->buffer_->memory_->GetSize());
444 
445         if (data->buffer_->flag_ == AVCODEC_BUFFER_FLAGS_EOS || data->buffer_->memory_->GetSize() == 0) {
446             cout << "decode eos 1" << endl;
447             isRunning_.store(false);
448             signal_->startCond_.notify_all();
449         }
450         signal_->outBufferQueue_.pop();
451         signal_->outQueue_.pop();
452         if (OH_AudioCodec_FreeOutputBuffer(audioDec_, index) != AV_ERR_OK) {
453             cout << "Fatal: FreeOutputData fail" << endl;
454             break;
455         }
456         if (data->buffer_->flag_ == AVCODEC_BUFFER_FLAGS_EOS) {
457             cout << "decode eos 2" << endl;
458             isRunning_.store(false);
459             signal_->startCond_.notify_all();
460         }
461     }
462     cout << "stop, exit" << endl;
463     pcmOutputFile_.close();
464 }
465