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_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 "securec.h"
28 
29 using namespace OHOS;
30 using namespace OHOS::MediaAVCodec;
31 using namespace OHOS::MediaAVCodec::AudioDemo;
32 using namespace std;
33 namespace {
34 constexpr uint32_t CHANNEL_COUNT = 2;
35 constexpr uint32_t SAMPLE_RATE = 44100;
36 constexpr uint32_t DEFAULT_AAC_TYPE = 1;
37 constexpr int64_t BITS_RATE[TYPE_MAX] = {199000, 261000, 60000, 320000};
38 constexpr uint32_t AMRWB_SAMPLE_RATE = 16000;
39 constexpr uint32_t AMRNB_SAMPLE_RATE = 8000;
40 constexpr uint32_t OPUS_SAMPLE_RATE = 48000;
41 constexpr string_view INPUT_AAC_FILE_PATH = "/data/test/media/aac_2c_44100hz_199k.dat";
42 constexpr string_view OUTPUT_AAC_PCM_FILE_PATH = "/data/test/media/aac_2c_44100hz_199k.pcm";
43 constexpr string_view INPUT_FLAC_FILE_PATH = "/data/test/media/flac_2c_44100hz_261k.dat";
44 constexpr string_view OUTPUT_FLAC_PCM_FILE_PATH = "/data/test/media/flac_2c_44100hz_261k.pcm";
45 constexpr string_view INPUT_MP3_FILE_PATH = "/data/test/media/mp3_2c_44100hz_60k.dat";
46 constexpr string_view OUTPUT_MP3_PCM_FILE_PATH = "/data/test/media/mp3_2c_44100hz_60k.pcm";
47 constexpr string_view INPUT_VORBIS_FILE_PATH = "/data/test/media/vorbis_2c_44100hz_320k.dat";
48 constexpr string_view OUTPUT_VORBIS_PCM_FILE_PATH = "/data/test/media/vorbis_2c_44100hz_320k.pcm";
49 constexpr string_view INPUT_AMRNB_FILE_PATH = "/data/test/media/voice_amrnb_10200.dat";
50 constexpr string_view OUTPUT_AMRNB_PCM_FILE_PATH = "/data/test/media/voice_amrnb_10200.pcm";
51 constexpr string_view INPUT_AMRWB_FILE_PATH = "/data/test/media/voice_amrwb_23850.dat";
52 constexpr string_view OUTPUT_AMRWB_PCM_FILE_PATH = "/data/test/media/voice_amrwb_23850.pcm";
53 constexpr string_view INPUT_OPUS_FILE_PATH = "/data/test/media/opus_48000.dat";
54 constexpr string_view OUTPUT_OPUS_PCM_FILE_PATH = "/data/test/media/opus_48000.pcm";
55 constexpr string_view INPUT_G711MU_FILE_PATH = "/data/test/media/g711mu_8kHz.dat";
56 constexpr string_view OUTPUT_G711MU_PCM_FILE_PATH = "/data/test/media/g711mu_8kHz_decode.pcm";
57 } // namespace
58 
OnError(OH_AVCodec * codec,int32_t errorCode,void * userData)59 static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
60 {
61     (void)codec;
62     (void)errorCode;
63     (void)userData;
64     cout << "Error received, errorCode:" << errorCode << endl;
65 }
66 
OnOutputFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)67 static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
68 {
69     (void)codec;
70     (void)format;
71     (void)userData;
72     cout << "OnOutputFormatChanged received" << endl;
73 }
74 
OnInputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,void * userData)75 static void OnInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
76 {
77     (void)codec;
78     ADecSignal *signal = static_cast<ADecSignal *>(userData);
79     unique_lock<mutex> lock(signal->inMutex_);
80     signal->inQueue_.push(index);
81     signal->inBufferQueue_.push(data);
82     signal->inCond_.notify_all();
83 }
84 
OnOutputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,OH_AVCodecBufferAttr * attr,void * userData)85 static void OnOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
86                                     void *userData)
87 {
88     (void)codec;
89     ADecSignal *signal = static_cast<ADecSignal *>(userData);
90     unique_lock<mutex> lock(signal->outMutex_);
91     signal->outQueue_.push(index);
92     signal->outBufferQueue_.push(data);
93     if (attr) {
94         signal->attrQueue_.push(*attr);
95     } else {
96         cout << "OnOutputBufferAvailable error, attr is nullptr!" << endl;
97     }
98     signal->outCond_.notify_all();
99 }
100 
InitFile(AudioFormatType audioType)101 bool ADecDemo::InitFile(AudioFormatType audioType)
102 {
103     if (audioType == TYPE_AAC) {
104         inputFile_.open(INPUT_AAC_FILE_PATH, std::ios::binary);
105         pcmOutputFile_.open(OUTPUT_AAC_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
106     } else if (audioType == TYPE_FLAC) {
107         inputFile_.open(INPUT_FLAC_FILE_PATH, std::ios::binary);
108         pcmOutputFile_.open(OUTPUT_FLAC_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
109     } else if (audioType == TYPE_MP3) {
110         inputFile_.open(INPUT_MP3_FILE_PATH, std::ios::binary);
111         pcmOutputFile_.open(OUTPUT_MP3_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
112     } else if (audioType == TYPE_VORBIS) {
113         inputFile_.open(INPUT_VORBIS_FILE_PATH, std::ios::binary);
114         pcmOutputFile_.open(OUTPUT_VORBIS_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
115     } else if (audioType == TYPE_AMRNB) {
116         inputFile_.open(INPUT_AMRNB_FILE_PATH, std::ios::binary);
117         pcmOutputFile_.open(OUTPUT_AMRNB_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
118     } else if (audioType == TYPE_AMRWB) {
119         inputFile_.open(INPUT_AMRWB_FILE_PATH, std::ios::binary);
120         pcmOutputFile_.open(OUTPUT_AMRWB_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
121     } else if (audioType == TYPE_OPUS) {
122         inputFile_.open(INPUT_OPUS_FILE_PATH, std::ios::binary);
123         pcmOutputFile_.open(OUTPUT_OPUS_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
124     } else if (audioType == TYPE_G711MU) {
125         inputFile_.open(INPUT_G711MU_FILE_PATH, std::ios::binary);
126         pcmOutputFile_.open(OUTPUT_G711MU_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
127     } else {
128         std::cout << "audio format type not support\n";
129         return false;
130     }
131     DEMO_CHECK_AND_RETURN_RET_LOG(inputFile_.is_open(), false, "Fatal: open input file failed");
132     DEMO_CHECK_AND_RETURN_RET_LOG(pcmOutputFile_.is_open(), false, "Fatal: open output file failed");
133     return true;
134 }
135 
RunCase(AudioFormatType audioType)136 void ADecDemo::RunCase(AudioFormatType audioType)
137 {
138     DEMO_CHECK_AND_RETURN_LOG(InitFile(audioType), "Fatal: InitFile file failed");
139     audioType_ = audioType;
140     DEMO_CHECK_AND_RETURN_LOG(CreateDec() == AVCS_ERR_OK, "Fatal: CreateDec fail");
141     OH_AVFormat *format = OH_AVFormat_Create();
142     int32_t channelCount = 1;
143     int32_t sampleRate = SAMPLE_RATE;
144     if (audioType == TYPE_AAC) {
145         channelCount = CHANNEL_COUNT;
146         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_AAC_IS_ADTS.data(), DEFAULT_AAC_TYPE);
147         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(),
148                                 OH_BitsPerSample::SAMPLE_S16LE);
149     } else if (audioType == TYPE_AMRNB || audioType == TYPE_G711MU) {
150         sampleRate = AMRNB_SAMPLE_RATE;
151     } else if (audioType == TYPE_AMRWB) {
152         sampleRate = AMRWB_SAMPLE_RATE;
153         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(),
154                                 OH_BitsPerSample::SAMPLE_S16LE);
155     } else if (audioType == TYPE_OPUS) {
156         sampleRate = OPUS_SAMPLE_RATE;
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[audioType]);
161     if (audioType == 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(), (uint8_t *)buffer,
175                               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 
ADecDemo()187 ADecDemo::ADecDemo() : audioDec_(nullptr), signal_(nullptr), audioType_(TYPE_AAC) {}
188 
~ADecDemo()189 ADecDemo::~ADecDemo()
190 {
191     if (signal_) {
192         delete signal_;
193         signal_ = nullptr;
194     }
195     if (inputFile_.is_open()) {
196         inputFile_.close();
197     }
198     if (pcmOutputFile_.is_open()) {
199         pcmOutputFile_.close();
200     }
201 }
202 
CreateDec()203 int32_t ADecDemo::CreateDec()
204 {
205     if (audioType_ == TYPE_AAC) {
206         audioDec_ = OH_AudioDecoder_CreateByName((AVCodecCodecName::AUDIO_DECODER_AAC_NAME).data());
207     } else if (audioType_ == TYPE_FLAC) {
208         audioDec_ = OH_AudioDecoder_CreateByName((AVCodecCodecName::AUDIO_DECODER_FLAC_NAME).data());
209     } else if (audioType_ == TYPE_MP3) {
210         audioDec_ = OH_AudioDecoder_CreateByName((AVCodecCodecName::AUDIO_DECODER_MP3_NAME).data());
211     } else if (audioType_ == TYPE_VORBIS) {
212         audioDec_ = OH_AudioDecoder_CreateByName((AVCodecCodecName::AUDIO_DECODER_VORBIS_NAME).data());
213     } else if (audioType_ == TYPE_AMRNB) {
214         audioDec_ = OH_AudioDecoder_CreateByName((AVCodecCodecName::AUDIO_DECODER_AMRNB_NAME).data());
215     } else if (audioType_ == TYPE_AMRWB) {
216         audioDec_ = OH_AudioDecoder_CreateByName((AVCodecCodecName::AUDIO_DECODER_AMRWB_NAME).data());
217     } else if (audioType_ == TYPE_OPUS) {
218         audioDec_ = OH_AudioDecoder_CreateByName((AVCodecCodecName::AUDIO_DECODER_OPUS_NAME).data());
219     } else if (audioType_ == TYPE_G711MU) {
220         audioDec_ = OH_AudioDecoder_CreateByName((AVCodecCodecName::AUDIO_DECODER_G711MU_NAME).data());
221     } else {
222         return AVCS_ERR_INVALID_VAL;
223     }
224     DEMO_CHECK_AND_RETURN_RET_LOG(audioDec_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: CreateByName fail");
225 
226     signal_ = new ADecSignal();
227     DEMO_CHECK_AND_RETURN_RET_LOG(signal_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
228 
229     cb_ = {&OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable};
230     int32_t ret = OH_AudioDecoder_SetCallback(audioDec_, cb_, signal_);
231     DEMO_CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCS_ERR_UNKNOWN, "Fatal: SetCallback fail");
232 
233     return AVCS_ERR_OK;
234 }
235 
Configure(OH_AVFormat * format)236 int32_t ADecDemo::Configure(OH_AVFormat *format)
237 {
238     return OH_AudioDecoder_Configure(audioDec_, format);
239 }
240 
Start()241 int32_t ADecDemo::Start()
242 {
243     isRunning_.store(true);
244 
245     inputLoop_ = make_unique<thread>(&ADecDemo::InputFunc, this);
246     DEMO_CHECK_AND_RETURN_RET_LOG(inputLoop_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
247 
248     outputLoop_ = make_unique<thread>(&ADecDemo::OutputFunc, this);
249     DEMO_CHECK_AND_RETURN_RET_LOG(outputLoop_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
250 
251     return OH_AudioDecoder_Start(audioDec_);
252 }
253 
Stop()254 int32_t ADecDemo::Stop()
255 {
256     isRunning_.store(false);
257     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
258         {
259             unique_lock<mutex> lock(signal_->inMutex_);
260             signal_->inCond_.notify_all();
261         }
262         inputLoop_->join();
263         inputLoop_ = nullptr;
264         while (!signal_->inQueue_.empty()) {
265             signal_->inQueue_.pop();
266         }
267         while (!signal_->inBufferQueue_.empty()) {
268             signal_->inBufferQueue_.pop();
269         }
270     }
271 
272     if (outputLoop_ != nullptr && outputLoop_->joinable()) {
273         {
274             unique_lock<mutex> lock(signal_->outMutex_);
275             signal_->outCond_.notify_all();
276         }
277         outputLoop_->join();
278         outputLoop_ = nullptr;
279         while (!signal_->outQueue_.empty()) {
280             signal_->outQueue_.pop();
281         }
282         while (!signal_->attrQueue_.empty()) {
283             signal_->attrQueue_.pop();
284         }
285         while (!signal_->outBufferQueue_.empty()) {
286             signal_->outBufferQueue_.pop();
287         }
288     }
289     std::cout << "start stop!\n";
290     return OH_AudioDecoder_Stop(audioDec_);
291 }
292 
Flush()293 int32_t ADecDemo::Flush()
294 {
295     isRunning_.store(false);
296     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
297         {
298             unique_lock<mutex> lock(signal_->inMutex_);
299             signal_->inCond_.notify_all();
300         }
301         inputLoop_->join();
302         inputLoop_ = nullptr;
303         while (!signal_->inQueue_.empty()) {
304             signal_->inQueue_.pop();
305         }
306         while (!signal_->inBufferQueue_.empty()) {
307             signal_->inBufferQueue_.pop();
308         }
309         std::cout << "clear input buffer!\n";
310     }
311 
312     if (outputLoop_ != nullptr && outputLoop_->joinable()) {
313         {
314             unique_lock<mutex> lock(signal_->outMutex_);
315             signal_->outCond_.notify_all();
316         }
317         outputLoop_->join();
318         outputLoop_ = nullptr;
319         while (!signal_->outQueue_.empty()) {
320             signal_->outQueue_.pop();
321         }
322         while (!signal_->attrQueue_.empty()) {
323             signal_->attrQueue_.pop();
324         }
325         while (!signal_->outBufferQueue_.empty()) {
326             signal_->outBufferQueue_.pop();
327         }
328         std::cout << "clear output buffer!\n";
329     }
330     return OH_AudioDecoder_Flush(audioDec_);
331 }
332 
Reset()333 int32_t ADecDemo::Reset()
334 {
335     return OH_AudioDecoder_Reset(audioDec_);
336 }
337 
Release()338 int32_t ADecDemo::Release()
339 {
340     return OH_AudioDecoder_Destroy(audioDec_);
341 }
342 
HandleInputEOS(const uint32_t index)343 void ADecDemo::HandleInputEOS(const uint32_t index)
344 {
345     OH_AVCodecBufferAttr info;
346     info.size = 0;
347     info.offset = 0;
348     info.pts = 0;
349     info.flags = AVCODEC_BUFFER_FLAGS_EOS;
350     OH_AudioDecoder_PushInputData(audioDec_, index, info);
351     signal_->inBufferQueue_.pop();
352     signal_->inQueue_.pop();
353 }
354 
HandleNormalInput(const uint32_t & index,const int64_t pts,const size_t size)355 int32_t ADecDemo::HandleNormalInput(const uint32_t &index, const int64_t pts, const size_t size)
356 {
357     OH_AVCodecBufferAttr info;
358     info.size = size;
359     info.offset = 0;
360     info.pts = pts;
361 
362     int32_t ret = AVCS_ERR_OK;
363     if (isFirstFrame_) {
364         info.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
365         ret = OH_AudioDecoder_PushInputData(audioDec_, index, info);
366         isFirstFrame_ = false;
367     } else {
368         info.flags = AVCODEC_BUFFER_FLAGS_NONE;
369         ret = OH_AudioDecoder_PushInputData(audioDec_, index, info);
370     }
371     signal_->inQueue_.pop();
372     signal_->inBufferQueue_.pop();
373     frameCount_++;
374     return ret;
375 }
376 
InputFunc()377 void ADecDemo::InputFunc()
378 {
379     int64_t size;
380     int64_t pts;
381 
382     while (isRunning_.load()) {
383         unique_lock<mutex> lock(signal_->inMutex_);
384         signal_->inCond_.wait(lock, [this]() { return (signal_->inQueue_.size() > 0 || !isRunning_.load()); });
385 
386         if (!isRunning_.load()) {
387             break;
388         }
389 
390         uint32_t index = signal_->inQueue_.front();
391         auto buffer = signal_->inBufferQueue_.front();
392         DEMO_CHECK_AND_BREAK_LOG(buffer != nullptr, "Fatal: GetInputBuffer fail");
393         inputFile_.read(reinterpret_cast<char *>(&size), sizeof(size));
394         if (inputFile_.eof() || inputFile_.gcount() == 0 || size == 0) {
395             HandleInputEOS(index);
396             std::cout << "end buffer\n";
397             break;
398         }
399         DEMO_CHECK_AND_BREAK_LOG(inputFile_.gcount() == sizeof(size), "Fatal: read size fail");
400         inputFile_.read(reinterpret_cast<char *>(&pts), sizeof(pts));
401         DEMO_CHECK_AND_BREAK_LOG(inputFile_.gcount() == sizeof(pts), "Fatal: read pts fail");
402         inputFile_.read((char *)OH_AVMemory_GetAddr(buffer), size);
403         DEMO_CHECK_AND_BREAK_LOG(inputFile_.gcount() == size, "Fatal: read buffer fail");
404 
405         int32_t ret = HandleNormalInput(index, pts, size);
406         if (ret != AVCS_ERR_OK) {
407             cout << "Fatal error, exit" << endl;
408             break;
409         }
410     }
411     inputFile_.close();
412 }
413 
OutputFunc()414 void ADecDemo::OutputFunc()
415 {
416     DEMO_CHECK_AND_RETURN_LOG(pcmOutputFile_.is_open(), "Fatal: output file failedis not open");
417     while (isRunning_.load()) {
418         unique_lock<mutex> lock(signal_->outMutex_);
419         signal_->outCond_.wait(lock, [this]() { return (signal_->outQueue_.size() > 0 || !isRunning_.load()); });
420 
421         if (!isRunning_.load()) {
422             cout << "wait to stop, exit" << endl;
423             break;
424         }
425 
426         uint32_t index = signal_->outQueue_.front();
427         OH_AVCodecBufferAttr attr = signal_->attrQueue_.front();
428         OH_AVMemory *data = signal_->outBufferQueue_.front();
429         if (attr.flags != AVCODEC_BUFFER_FLAGS_EOS && data != nullptr) {
430             pcmOutputFile_.write(reinterpret_cast<char *>(OH_AVMemory_GetAddr(data)), attr.size);
431         }
432 
433         if (attr.flags == AVCODEC_BUFFER_FLAGS_EOS) {
434             cout << "decode eos" << endl;
435             isRunning_.store(false);
436             signal_->startCond_.notify_all();
437         }
438         signal_->outBufferQueue_.pop();
439         signal_->attrQueue_.pop();
440         signal_->outQueue_.pop();
441         if (OH_AudioDecoder_FreeOutputData(audioDec_, index) != AV_ERR_OK) {
442             cout << "Fatal: FreeOutputData fail" << endl;
443             break;
444         }
445     }
446     pcmOutputFile_.close();
447 }
448