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 }