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