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 <iostream>
17 #include <unistd.h>
18 #include <chrono>
19 #include "securec.h"
20 #include "avcodec_common.h"
21 #include "avcodec_errors.h"
22 #include "media_description.h"
23 #include "native_avformat.h"
24 #include "demo_log.h"
25 #include "avcodec_codec_name.h"
26 #include "native_avmemory.h"
27 #include "native_avbuffer.h"
28 #include "ffmpeg_converter.h"
29 #include "avcodec_audio_avbuffer_encoder_demo.h"
30 
31 using namespace OHOS;
32 using namespace OHOS::MediaAVCodec;
33 using namespace OHOS::MediaAVCodec::AudioAacEncDemo;
34 using namespace std;
35 namespace {
36 constexpr uint32_t CHANNEL_COUNT_1 = 1;
37 constexpr uint32_t SAMPLE_RATE_8000 = 8000;
38 constexpr uint32_t BIT_RATE_64000 = 64000;
39 constexpr uint32_t CHANNEL_COUNT = 2;
40 constexpr uint32_t SAMPLE_RATE = 44100;
41 constexpr uint32_t FRAME_DURATION_US = 33000;
42 constexpr int32_t SAMPLE_FORMAT = AudioSampleFormat::SAMPLE_S32LE;
43 constexpr int32_t BIT_PER_CODE_COUNT = 16;
44 constexpr int32_t COMPLEXITY_COUNT = 10;
45 constexpr int32_t CHANNEL_1 = 1;
46 constexpr int32_t CHANNEL_2 = 2;
47 constexpr int32_t CHANNEL_3 = 3;
48 constexpr int32_t CHANNEL_4 = 4;
49 constexpr int32_t CHANNEL_5 = 5;
50 constexpr int32_t CHANNEL_6 = 6;
51 constexpr int32_t CHANNEL_7 = 7;
52 constexpr int32_t CHANNEL_8 = 8;
53 } // namespace
54 
55 
GetChannelLayout(int32_t channel)56 static uint64_t GetChannelLayout(int32_t channel)
57 {
58     switch (channel) {
59         case CHANNEL_1:
60             return MONO;
61         case CHANNEL_2:
62             return STEREO;
63         case CHANNEL_3:
64             return CH_2POINT1;
65         case CHANNEL_4:
66             return CH_3POINT1;
67         case CHANNEL_5:
68             return CH_4POINT1;
69         case CHANNEL_6:
70             return CH_5POINT1;
71         case CHANNEL_7:
72             return CH_6POINT1;
73         case CHANNEL_8:
74             return CH_7POINT1;
75         default:
76             return UNKNOWN_CHANNEL_LAYOUT;
77     }
78 }
79 
SplitStringFully(const string & str,const string & separator)80 static  vector<string> SplitStringFully(const string &str, const string &separator)
81 {
82     vector<string> dest;
83     string substring;
84     string::size_type start = 0;
85     string::size_type index = str.find_first_of(separator, start);
86 
87     while (index != string::npos) {
88         substring = str.substr(start, index - start);
89         dest.push_back(substring);
90         start = str.find_first_not_of(separator, index);
91         if (start == string::npos) {
92             return dest;
93         }
94         index = str.find_first_of(separator, start);
95     }
96     substring = str.substr(start);
97     dest.push_back(substring);
98 
99     return dest;
100 }
101 
StringReplace(std::string & strBig,const std::string & strsrc,const std::string & strdst)102 static void StringReplace(std::string &strBig, const std::string &strsrc, const std::string &strdst)
103 {
104     std::string::size_type pos = 0;
105     std::string::size_type srclen = strsrc.size();
106     std::string::size_type dstlen = strdst.size();
107 
108     while ((pos = strBig.find(strsrc, pos)) != std::string::npos) {
109         strBig.replace(pos, srclen, strdst);
110         pos += dstlen;
111     }
112 }
113 
GetParamsByName(string decoderName,string inputFile,int32_t & channelCount,int32_t & sampleRate,long & bitrate)114 static void GetParamsByName(string decoderName, string inputFile, int32_t &channelCount,
115     int32_t &sampleRate, long &bitrate)
116 {
117     int32_t opusNameSplitNum = 4;
118     int32_t splitNum1 = 1;
119     int32_t splitNum2 = 2;
120     int32_t splitNum3 = 3;
121 
122     vector<string> dest = SplitStringFully(inputFile, "_");
123     if (decoderName == "OH.Media.Codec.Encoder.Audio.Opus") {
124         if (dest.size() < opusNameSplitNum) {
125             cout << "split error !!!" << endl;
126             return;
127         }
128         channelCount = stoi(dest[splitNum3]);
129         sampleRate = stoi(dest[splitNum1]);
130 
131         string bitStr = dest[splitNum2];
132         StringReplace(bitStr, "k", "000");
133         bitrate = atol(bitStr.c_str());
134     } else {
135         if (dest.size() < opusNameSplitNum) {
136             cout << "split error !!!" << endl;
137             return;
138         }
139         channelCount = stoi(dest[splitNum3]);
140         sampleRate = stoi(dest[splitNum2]);
141 
142         string bitStr = dest[splitNum1];
143         StringReplace(bitStr, "k", "000");
144         bitrate = atol(bitStr.c_str());
145     }
146 }
147 
OnError(OH_AVCodec * codec,int32_t errorCode,void * userData)148 static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
149 {
150     (void)codec;
151     (void)errorCode;
152     (void)userData;
153     cout << "Error received, errorCode:" << errorCode << endl;
154 }
155 
OnOutputFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)156 static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
157 {
158     (void)codec;
159     (void)format;
160     (void)userData;
161     cout << "OnOutputFormatChanged received" << endl;
162 }
163 
OnInputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)164 static void OnInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
165 {
166     (void)codec;
167     AEncSignal *signal = static_cast<AEncSignal *>(userData);
168     unique_lock<mutex> lock(signal->inMutex_);
169     signal->inQueue_.push(index);
170     signal->inBufferQueue_.push(buffer);
171     signal->inCond_.notify_all();
172 }
173 
OnOutputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)174 static void OnOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
175 {
176     (void)codec;
177     AEncSignal *signal = static_cast<AEncSignal *>(userData);
178     unique_lock<mutex> lock(signal->outMutex_);
179     signal->outQueue_.push(index);
180     signal->outBufferQueue_.push(buffer);
181     if (buffer) {
182         cout << "OnOutputBufferAvailable received, index:" << index << ", size:" << buffer->buffer_->memory_->GetSize()
183              << ", flags:" << buffer->buffer_->flag_ << ", pts: " << buffer->buffer_->pts_ << endl;
184     } else {
185         cout << "OnOutputBufferAvailable error, attr is nullptr!" << endl;
186     }
187     signal->outCond_.notify_all();
188 }
189 
InitFile(std::string inputFile,std::string outputFile)190 bool AudioBufferAacEncDemo::InitFile(std::string inputFile, std::string outputFile)
191 {
192     std::cout << "InitFile enter" << std::endl;
193     if (inputFile_.is_open()) {
194         inputFile_.close();
195     }
196     if (inputFile.find("mp4") != std::string::npos || inputFile.find("m4a") != std::string::npos ||
197         inputFile.find("ts") != std::string::npos) {
198         audioType_ = AudioBufferFormatType::TYPE_vivid;
199     } else if (inputFile.find("opus") != std::string::npos) {
200         audioType_ = AudioBufferFormatType::TYPE_OPUS;
201         inputFile_.open(inputFile, std::ios::in | std::ios::binary);
202         DEMO_CHECK_AND_RETURN_RET_LOG(inputFile_.is_open(), false, "Fatal: open input file failed");
203         std::cout << "InitFile ok = " << std::endl;
204     } else if (inputFile.find("g711") != std::string::npos) {
205         std::cout << "g711 enter " << std::endl;
206         audioType_ = AudioBufferFormatType::TYPE_G711MU;
207         std::cout << "g711 inputFile: " << inputFile << std::endl;
208         inputFile_.open(inputFile, std::ios::in | std::ios::binary);
209         std::cout << "inputFile open: " << std::endl;
210         DEMO_CHECK_AND_RETURN_RET_LOG(inputFile_.is_open(), false, "Fatal: open input file failed");
211         std::cout << "g711 InitFile ok = " << std::endl;
212     } else {
213         audioType_ = AudioBufferFormatType::TYPE_AAC;
214         inputFile_.open(inputFile, std::ios::in | std::ios::binary);
215         DEMO_CHECK_AND_RETURN_RET_LOG(inputFile_.is_open(), false, "Fatal: open input file failed");
216     }
217     fileSize_ = GetFileSize(inputFile.data());
218     outputFile_.open(outputFile, std::ios::out | std::ios::binary);
219     DEMO_CHECK_AND_RETURN_RET_LOG(outputFile_.is_open(), false, "Fatal: open output file failed");
220     inputFile_str = inputFile;
221     outputFile_str = outputFile;
222     return true;
223 }
224 
RunCase(std::string inputFile,std::string outputFile)225 bool AudioBufferAacEncDemo::RunCase(std::string inputFile, std::string outputFile)
226 {
227     DEMO_CHECK_AND_RETURN_RET_LOG(InitFile(inputFile, outputFile), false, "Fatal: InitFile file failed");
228     DEMO_CHECK_AND_RETURN_RET_LOG(CreateEnc() == AVCS_ERR_OK, false, "Fatal: CreateEnc fail");
229     OH_AVFormat *format = OH_AVFormat_Create();
230     int32_t channelCount;
231     int32_t sampleRate;
232     long bitrate;
233     if (audioType_ == AudioBufferFormatType::TYPE_AAC) {
234         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(), CHANNEL_COUNT);
235         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), SAMPLE_RATE);
236         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(), SAMPLE_FORMAT);
237     }
238     if (audioType_ == AudioBufferFormatType::TYPE_OPUS) {
239         GetParamsByName("OH.Media.Codec.Encoder.Audio.Opus", inputFile, channelCount, sampleRate, bitrate);
240         channels_ = channelCount;
241         sampleRate_ = sampleRate;
242 
243         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(), channels_);
244         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), sampleRate_);
245         OH_AVFormat_SetLongValue(format, MediaDescriptionKey::MD_KEY_BITRATE.data(), bitrate);
246         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(),
247                                 AudioSampleFormat::SAMPLE_S16LE);
248         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_BITS_PER_CODED_SAMPLE.data(), BIT_PER_CODE_COUNT);
249         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_COMPLIANCE_LEVEL.data(), COMPLEXITY_COUNT);
250     } else if (audioType_ == AudioBufferFormatType::TYPE_G711MU) {
251         channelCount = CHANNEL_COUNT_1;
252         sampleRate = SAMPLE_RATE_8000;
253         bitrate = BIT_RATE_64000;
254         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(), channelCount);
255         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), sampleRate);
256         OH_AVFormat_SetLongValue(format, MediaDescriptionKey::MD_KEY_BITRATE.data(), bitrate);
257         OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(),
258                                 AudioSampleFormat::SAMPLE_S16LE);
259         std::cout << "RunCase OH_AVFormat_SetIntValue" << std::endl;
260     }
261     DEMO_CHECK_AND_RETURN_RET_LOG(Configure(format) == AVCS_ERR_OK, false, "Fatal: Configure fail");
262     DEMO_CHECK_AND_RETURN_RET_LOG(Start() == AVCS_ERR_OK, false, "Fatal: Start fail");
263     auto start = chrono::steady_clock::now();
264     {
265         unique_lock<mutex> lock(signal_->startMutex_);
266         signal_->startCond_.wait(lock, [this]() { return (!(isRunning_.load())); });
267     }
268     auto end = chrono::steady_clock::now();
269     std::cout << "Encode finished, time = " << std::chrono::duration_cast<chrono::milliseconds>(end - start).count()
270               << " ms" << std::endl;
271     DEMO_CHECK_AND_RETURN_RET_LOG(Stop() == AVCS_ERR_OK, false, "Fatal: Stop fail");
272     DEMO_CHECK_AND_RETURN_RET_LOG(Release() == AVCS_ERR_OK, false, "Fatal: Release fail");
273     OH_AVFormat_Destroy(format);
274     return true;
275 }
276 
GetFileSize(const std::string & filePath)277 int32_t AudioBufferAacEncDemo::GetFileSize(const std::string &filePath)
278 {
279     std::ifstream file(filePath, std::ios::binary | std::ios::ate);
280     if (!file) {
281         std::cerr << "Failed to open file: " << filePath << std::endl;
282         return -1;
283     }
284 
285     std::streampos fileSize = file.tellg(); // 获取文件大小
286     file.close();
287 
288     return (int32_t)fileSize;
289 }
290 
AudioBufferAacEncDemo()291 AudioBufferAacEncDemo::AudioBufferAacEncDemo() : isRunning_(false), audioEnc_(nullptr), signal_(nullptr), frameCount_(0)
292 {
293     signal_ = new AEncSignal();
294     DEMO_CHECK_AND_RETURN_LOG(signal_ != nullptr, "Fatal: No memory");
295 }
296 
~AudioBufferAacEncDemo()297 AudioBufferAacEncDemo::~AudioBufferAacEncDemo()
298 {
299     if (signal_) {
300         delete signal_;
301         signal_ = nullptr;
302     }
303 }
304 
CreateEnc()305 int32_t AudioBufferAacEncDemo::CreateEnc()
306 {
307     if (audioType_ == AudioBufferFormatType::TYPE_AAC) {
308         audioEnc_ = OH_AudioCodec_CreateByName((AVCodecCodecName::AUDIO_ENCODER_AAC_NAME).data());
309     } else if (audioType_ == AudioBufferFormatType::TYPE_FLAC) {
310         audioEnc_ = OH_AudioCodec_CreateByName((AVCodecCodecName::AUDIO_ENCODER_FLAC_NAME).data());
311     } else if (audioType_ == AudioBufferFormatType::TYPE_OPUS) {
312         audioEnc_ = OH_AudioCodec_CreateByName((AVCodecCodecName::AUDIO_ENCODER_OPUS_NAME).data());
313         std::cout << "CreateDec opus ok = " << std::endl;
314     } else if (audioType_ == AudioBufferFormatType::TYPE_G711MU) {
315         audioEnc_ = OH_AudioCodec_CreateByName((AVCodecCodecName::AUDIO_ENCODER_G711MU_NAME).data());
316     } else {
317         return AVCS_ERR_INVALID_VAL;
318     }
319     DEMO_CHECK_AND_RETURN_RET_LOG(audioEnc_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: CreateByName fail");
320     if (signal_ == nullptr) {
321         signal_ = new AEncSignal();
322         DEMO_CHECK_AND_RETURN_RET_LOG(signal_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
323     }
324     cb_ = {&OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable};
325     int32_t ret = OH_AudioCodec_RegisterCallback(audioEnc_, cb_, signal_);
326     DEMO_CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCS_ERR_UNKNOWN, "Fatal: SetCallback fail");
327 
328     return AVCS_ERR_OK;
329 }
330 
Configure(OH_AVFormat * format)331 int32_t AudioBufferAacEncDemo::Configure(OH_AVFormat *format)
332 {
333     int32_t ret = OH_AudioCodec_Configure(audioEnc_, format);
334     std::cout << "AudioBufferAacEncDemo::Configure :" << ret << std::endl;
335     return ret;
336 }
337 
Start()338 int32_t AudioBufferAacEncDemo::Start()
339 {
340     isRunning_.store(true);
341 
342     inputLoop_ = make_unique<thread>(&AudioBufferAacEncDemo::InputFunc, this);
343     DEMO_CHECK_AND_RETURN_RET_LOG(inputLoop_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
344 
345     outputLoop_ = make_unique<thread>(&AudioBufferAacEncDemo::OutputFunc, this);
346     DEMO_CHECK_AND_RETURN_RET_LOG(outputLoop_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
347 
348     return OH_AudioCodec_Start(audioEnc_);
349 }
350 
Stop()351 int32_t AudioBufferAacEncDemo::Stop()
352 {
353     isRunning_.store(false);
354 
355     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
356         {
357             unique_lock<mutex> lock(signal_->inMutex_);
358             signal_->inCond_.notify_all();
359         }
360         inputLoop_->join();
361         inputLoop_ = nullptr;
362         while (!signal_->inQueue_.empty()) {
363             signal_->inQueue_.pop();
364         }
365         while (!signal_->inBufferQueue_.empty()) {
366             signal_->inBufferQueue_.pop();
367         }
368     }
369 
370     if (outputLoop_ != nullptr && outputLoop_->joinable()) {
371         {
372             unique_lock<mutex> lock(signal_->outMutex_);
373             signal_->outCond_.notify_all();
374         }
375         outputLoop_->join();
376         outputLoop_ = nullptr;
377         while (!signal_->outQueue_.empty()) {
378             signal_->outQueue_.pop();
379         }
380         while (!signal_->outBufferQueue_.empty()) {
381             signal_->outBufferQueue_.pop();
382         }
383     }
384 
385     return OH_AudioCodec_Stop(audioEnc_);
386 }
387 
Flush()388 int32_t AudioBufferAacEncDemo::Flush()
389 {
390     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
391         {
392             unique_lock<mutex> lock(signal_->inMutex_);
393             signal_->inCond_.notify_all();
394         }
395         inputLoop_->join();
396         inputLoop_ = nullptr;
397         while (!signal_->inQueue_.empty()) {
398             signal_->inQueue_.pop();
399         }
400         while (!signal_->inBufferQueue_.empty()) {
401             signal_->inBufferQueue_.pop();
402         }
403         std::cout << "clear input buffer!\n";
404     }
405 
406     if (outputLoop_ != nullptr && outputLoop_->joinable()) {
407         {
408             unique_lock<mutex> lock(signal_->outMutex_);
409             signal_->outCond_.notify_all();
410         }
411         outputLoop_->join();
412         outputLoop_ = nullptr;
413         while (!signal_->outQueue_.empty()) {
414             signal_->outQueue_.pop();
415         }
416         while (!signal_->outBufferQueue_.empty()) {
417             signal_->outBufferQueue_.pop();
418         }
419         std::cout << "clear output buffer!\n";
420     }
421     return OH_AudioCodec_Flush(audioEnc_);
422 }
423 
Reset()424 int32_t AudioBufferAacEncDemo::Reset()
425 {
426     return OH_AudioCodec_Reset(audioEnc_);
427 }
428 
Release()429 int32_t AudioBufferAacEncDemo::Release()
430 {
431     return OH_AudioCodec_Destroy(audioEnc_);
432 }
433 
HandleEOS(const uint32_t & index)434 void AudioBufferAacEncDemo::HandleEOS(const uint32_t &index)
435 {
436     OH_AudioCodec_PushInputBuffer(audioEnc_, index);
437     std::cout << "end buffer\n";
438     signal_->inQueue_.pop();
439     signal_->inBufferQueue_.pop();
440 }
441 
InputFunc()442 void AudioBufferAacEncDemo::InputFunc()
443 {
444     int64_t g77mu_size = 320;
445     double time_20ms = 0.02;
446     int32_t frameBytes = channels_ * sizeof(short) * sampleRate_ * time_20ms;
447     if (audioType_ == AudioBufferFormatType::TYPE_OPUS) {
448         frameBytes = channels_ * sizeof(short) * sampleRate_ * time_20ms;
449     } else if (audioType_ == AudioBufferFormatType::TYPE_G711MU) {
450         frameBytes = g77mu_size;
451     }
452     DEMO_CHECK_AND_RETURN_LOG(inputFile_.is_open(), "Fatal: open file fail");
453     while (isRunning_.load()) {
454         unique_lock<mutex> lock(signal_->inMutex_);
455         signal_->inCond_.wait(lock, [this]() { return (signal_->inQueue_.size() > 0 || !isRunning_.load()); });
456         if (!isRunning_.load()) {
457             break;
458         }
459         uint32_t index = signal_->inQueue_.front();
460         auto buffer = signal_->inBufferQueue_.front();
461         DEMO_CHECK_AND_BREAK_LOG(buffer != nullptr, "Fatal: GetInputBuffer fail");
462         if (!inputFile_.eof()) {
463             inputFile_.read((char *)OH_AVBuffer_GetAddr(buffer), frameBytes);
464             buffer->buffer_->memory_->SetSize(frameBytes);
465         } else {
466             buffer->buffer_->memory_->SetSize(1);
467             buffer->buffer_->flag_ = AVCODEC_BUFFER_FLAGS_EOS;
468             HandleEOS(index);
469             break;
470         }
471         int32_t ret = AVCS_ERR_OK;
472         if (isFirstFrame_) {
473             buffer->buffer_->flag_ = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
474             ret = OH_AudioCodec_PushInputBuffer(audioEnc_, index);
475             isFirstFrame_ = false;
476         } else {
477             buffer->buffer_->flag_ = AVCODEC_BUFFER_FLAGS_NONE;
478             ret = OH_AudioCodec_PushInputBuffer(audioEnc_, index);
479         }
480         timeStamp_ += FRAME_DURATION_US;
481         signal_->inQueue_.pop();
482         signal_->inBufferQueue_.pop();
483         frameCount_++;
484         if (ret != AVCS_ERR_OK) {
485             break;
486         }
487     }
488     if (inputFile_.is_open()) {
489         inputFile_.close();
490     }
491 }
492 
OutputFunc()493 void AudioBufferAacEncDemo::OutputFunc()
494 {
495     DEMO_CHECK_AND_RETURN_LOG(outputFile_.is_open(), "Fatal: open output file fail");
496     while (isRunning_.load()) {
497         unique_lock<mutex> lock(signal_->outMutex_);
498         signal_->outCond_.wait(lock, [this]() { return (signal_->outQueue_.size() > 0 || !isRunning_.load()); });
499 
500         if (!isRunning_.load()) {
501             cout << "wait to stop, exit" << endl;
502             break;
503         }
504 
505         uint32_t index = signal_->outQueue_.front();
506         OH_AVBuffer *avBuffer = signal_->outBufferQueue_.front();
507         if (avBuffer == nullptr) {
508             cout << "OutputFunc OH_AVBuffer is nullptr" << endl;
509             continue;
510         }
511         std::cout << "OutputFunc index:" << index << endl;
512         if (avBuffer != nullptr) {
513             outputFile_.write(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(avBuffer)),
514                               avBuffer->buffer_->memory_->GetSize());
515         }
516         if (avBuffer != nullptr &&
517             (avBuffer->buffer_->flag_ == AVCODEC_BUFFER_FLAGS_EOS || avBuffer->buffer_->memory_->GetSize() == 0)) {
518             cout << "encode eos" << endl;
519             isRunning_.store(false);
520             signal_->startCond_.notify_all();
521         }
522 
523         signal_->outBufferQueue_.pop();
524         signal_->outQueue_.pop();
525         if (OH_AudioCodec_FreeOutputBuffer(audioEnc_, index) != AV_ERR_OK) {
526             cout << "Fatal: FreeOutputData fail" << endl;
527             break;
528         }
529         if (avBuffer->buffer_->flag_ == AVCODEC_BUFFER_FLAGS_EOS) {
530             cout << "decode eos" << endl;
531             isRunning_.store(false);
532             signal_->startCond_.notify_all();
533         }
534     }
535     cout << "stop, exit" << endl;
536     outputFile_.close();
537 }
538 
CreateByMime(const char * mime)539 OH_AVCodec *AudioBufferAacEncDemo::CreateByMime(const char *mime)
540 {
541     if (mime != nullptr) {
542         if (0 == strcmp(mime, "audio/mp4a-latm")) {
543             audioType_ = AudioBufferFormatType::TYPE_AAC;
544             cout << "creat, aac" << endl;
545         } else if (0 == strcmp(mime, "audio/flac")) {
546             audioType_ = AudioBufferFormatType::TYPE_FLAC;
547             cout << "creat, flac" << endl;
548         } else {
549             audioType_ = AudioBufferFormatType::TYPE_G711MU;
550         }
551     }
552 
553     return OH_AudioCodec_CreateByMime(mime, true);
554 }
555 
CreateByName(const char * name)556 OH_AVCodec *AudioBufferAacEncDemo::CreateByName(const char *name)
557 {
558     return OH_AudioCodec_CreateByName(name);
559 }
560 
Destroy(OH_AVCodec * codec)561 OH_AVErrCode AudioBufferAacEncDemo::Destroy(OH_AVCodec *codec)
562 {
563     OH_AVErrCode ret = OH_AudioCodec_Destroy(codec);
564     ClearQueue();
565     return ret;
566 }
567 
SetCallback(OH_AVCodec * codec)568 OH_AVErrCode AudioBufferAacEncDemo::SetCallback(OH_AVCodec *codec)
569 {
570     if (codec == nullptr) {
571         cout << "SetCallback, codec null" << endl;
572     }
573     if (signal_ == nullptr) {
574         cout << "SetCallback, signal_ null" << endl;
575     }
576     cb_ = {&OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable};
577     return OH_AudioCodec_RegisterCallback(codec, cb_, signal_);
578 }
579 
Configure(OH_AVCodec * codec,OH_AVFormat * format,int32_t channel,int32_t sampleRate,int64_t bitRate,int32_t sampleFormat,int32_t sampleBit,int32_t complexity)580 OH_AVErrCode AudioBufferAacEncDemo::Configure(OH_AVCodec *codec, OH_AVFormat *format, int32_t channel,
581                                               int32_t sampleRate, int64_t bitRate, int32_t sampleFormat,
582                                               int32_t sampleBit, int32_t complexity)
583 {
584     if (format == nullptr) {
585         return OH_AudioCodec_Configure(codec, format);
586     }
587     if (audioType_ == AudioBufferFormatType::TYPE_AAC) {
588         OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, channel);
589         OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, sampleRate);
590         OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, bitRate);
591         OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, sampleFormat);
592         OH_AVFormat_SetIntValue(format, OH_MD_KEY_BITS_PER_CODED_SAMPLE, sampleBit);
593         OH_AVFormat_SetIntValue(format, OH_MD_KEY_AAC_IS_ADTS, 1);
594         cout << "config, aac" << endl;
595     } else if (audioType_ == AudioBufferFormatType::TYPE_FLAC) {
596         uint64_t channelLayout = GetChannelLayout(channel);
597         OH_AVFormat_SetLongValue(format, OH_MD_KEY_CHANNEL_LAYOUT, channelLayout);
598         OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, channel);
599         OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, sampleRate);
600         OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, bitRate);
601         OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, sampleFormat);
602         OH_AVFormat_SetIntValue(format, OH_MD_KEY_BITS_PER_CODED_SAMPLE, sampleBit);
603         cout << "config, flac" << endl;
604     } else {
605         OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, channel);
606         OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, sampleRate);
607         OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, bitRate);
608         OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, sampleFormat);
609         OH_AVFormat_SetIntValue(format, OH_MD_KEY_BITS_PER_CODED_SAMPLE, sampleBit);
610         OH_AVFormat_SetIntValue(format, OH_MD_KEY_COMPLIANCE_LEVEL, complexity);
611     }
612     OH_AVErrCode ret = OH_AudioCodec_Configure(codec, format);
613     return ret;
614 }
615 
Prepare(OH_AVCodec * codec)616 OH_AVErrCode AudioBufferAacEncDemo::Prepare(OH_AVCodec *codec)
617 {
618     return OH_AudioCodec_Prepare(codec);
619 }
620 
Start(OH_AVCodec * codec)621 OH_AVErrCode AudioBufferAacEncDemo::Start(OH_AVCodec *codec)
622 {
623     return OH_AudioCodec_Start(codec);
624 }
625 
Stop(OH_AVCodec * codec)626 OH_AVErrCode AudioBufferAacEncDemo::Stop(OH_AVCodec *codec)
627 {
628     OH_AVErrCode ret = OH_AudioCodec_Stop(codec);
629     ClearQueue();
630     return ret;
631 }
632 
Flush(OH_AVCodec * codec)633 OH_AVErrCode AudioBufferAacEncDemo::Flush(OH_AVCodec *codec)
634 {
635     OH_AVErrCode ret = OH_AudioCodec_Flush(codec);
636     std::cout << "Flush ret:" << ret << endl;
637     ClearQueue();
638     return ret;
639 }
640 
Reset(OH_AVCodec * codec)641 OH_AVErrCode AudioBufferAacEncDemo::Reset(OH_AVCodec *codec)
642 {
643     return OH_AudioCodec_Reset(codec);
644 }
645 
GetOutputDescription(OH_AVCodec * codec)646 OH_AVFormat *AudioBufferAacEncDemo::GetOutputDescription(OH_AVCodec *codec)
647 {
648     return OH_AudioCodec_GetOutputDescription(codec);
649 }
650 
PushInputData(OH_AVCodec * codec,uint32_t index)651 OH_AVErrCode AudioBufferAacEncDemo::PushInputData(OH_AVCodec *codec, uint32_t index)
652 {
653     OH_AVCodecBufferAttr info;
654 
655     if (!signal_->inBufferQueue_.empty()) {
656         auto buffer = signal_->inBufferQueue_.front();
657         info.size = buffer->buffer_->memory_->GetSize();
658         info.pts = buffer->buffer_->pts_;
659         info.flags = buffer->buffer_->flag_;
660         OH_AVErrCode ret = OH_AVBuffer_SetBufferAttr(buffer, &info);
661         if (ret != AV_ERR_OK) {
662             return ret;
663         }
664     }
665     return OH_AudioCodec_PushInputBuffer(codec, index);
666 }
667 
PushInputDataEOS(OH_AVCodec * codec,uint32_t index)668 OH_AVErrCode AudioBufferAacEncDemo::PushInputDataEOS(OH_AVCodec *codec, uint32_t index)
669 {
670     OH_AVCodecBufferAttr info;
671     info.size = 0;
672     info.offset = 0;
673     info.pts = 0;
674     info.flags = AVCODEC_BUFFER_FLAGS_EOS;
675 
676     if (!signal_->inBufferQueue_.empty()) {
677         unique_lock<mutex> lock(signal_->inMutex_);
678         auto buffer = signal_->inBufferQueue_.front();
679         OH_AVBuffer_SetBufferAttr(buffer, &info);
680         signal_->inBufferQueue_.pop();
681     }
682     return OH_AudioCodec_PushInputBuffer(codec, index);
683 }
684 
FreeOutputData(OH_AVCodec * codec,uint32_t index)685 OH_AVErrCode AudioBufferAacEncDemo::FreeOutputData(OH_AVCodec *codec, uint32_t index)
686 {
687     return OH_AudioCodec_FreeOutputBuffer(codec, index);
688 }
689 
IsValid(OH_AVCodec * codec,bool * isValid)690 OH_AVErrCode AudioBufferAacEncDemo::IsValid(OH_AVCodec *codec, bool *isValid)
691 {
692     return OH_AudioCodec_IsValid(codec, isValid);
693 }
694 
GetInputIndex()695 uint32_t AudioBufferAacEncDemo::GetInputIndex()
696 {
697     int32_t sleep_time = 0;
698     uint32_t index;
699     uint32_t timeout = 5;
700     while (signal_->inQueue_.empty() && sleep_time < timeout) {
701         sleep(1);
702         sleep_time++;
703     }
704     lock_guard<mutex> lock(signal_->inMutex_);
705     if (sleep_time >= timeout) {
706         return 0;
707     } else {
708         index = signal_->inQueue_.front();
709         signal_->inQueue_.pop();
710     }
711     return index;
712 }
713 
GetOutputIndex()714 uint32_t AudioBufferAacEncDemo::GetOutputIndex()
715 {
716     int32_t sleep_time = 0;
717     uint32_t index;
718     uint32_t timeout = 5;
719     while (signal_->outQueue_.empty() && sleep_time < timeout) {
720         sleep(1);
721         sleep_time++;
722     }
723     if (sleep_time >= timeout) {
724         return 0;
725     } else {
726         index = signal_->outQueue_.front();
727         signal_->outQueue_.pop();
728     }
729     return index;
730 }
731 
ClearQueue()732 void AudioBufferAacEncDemo::ClearQueue()
733 {
734     while (!signal_->inQueue_.empty())
735         signal_->inQueue_.pop();
736     while (!signal_->outQueue_.empty())
737         signal_->outQueue_.pop();
738     while (!signal_->inBufferQueue_.empty())
739         signal_->inBufferQueue_.pop();
740     while (!signal_->outBufferQueue_.empty())
741         signal_->outBufferQueue_.pop();
742 }
743 
SetParameter(OH_AVCodec * codec,OH_AVFormat * format,int32_t channel,int32_t sampleRate,int64_t bitRate,int32_t sampleFormat,int32_t sampleBit,int32_t complexity)744 OH_AVErrCode AudioBufferAacEncDemo::SetParameter(OH_AVCodec *codec, OH_AVFormat *format, int32_t channel,
745                                                  int32_t sampleRate, int64_t bitRate, int32_t sampleFormat,
746                                                  int32_t sampleBit, int32_t complexity)
747 {
748     if (format == nullptr) {
749         return OH_AudioCodec_SetParameter(codec, format);
750     }
751     OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, channel);
752     OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, sampleRate);
753     OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, bitRate);
754     OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, sampleFormat);
755     OH_AVFormat_SetIntValue(format, OH_MD_KEY_BITS_PER_CODED_SAMPLE, sampleBit);
756     OH_AVFormat_SetIntValue(format, OH_MD_KEY_COMPLIANCE_LEVEL, complexity);
757     if (audioType_ == AudioBufferFormatType::TYPE_AAC) {
758         OH_AVFormat_SetIntValue(format, OH_MD_KEY_AAC_IS_ADTS, 1);
759     } else if (audioType_ == AudioBufferFormatType::TYPE_FLAC) {
760         uint64_t channelLayout = GetChannelLayout(channel);
761         OH_AVFormat_SetLongValue(format, OH_MD_KEY_CHANNEL_LAYOUT, channelLayout);
762     }
763     OH_AVErrCode ret = OH_AudioCodec_SetParameter(codec, format);
764     return ret;
765 }