1 /*
2 * Copyright (C) 2022 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 "AudioEncoderDemoCommon.h"
17 #include <iostream>
18 #include <fstream>
19 #include <cstdio>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <dlfcn.h>
23 #include "avcodec_errors.h"
24 #include "media_description.h"
25
26 using namespace OHOS;
27 using namespace OHOS::MediaAVCodec;
28 using namespace std;
29
30 namespace OHOS {
31 namespace MediaAVCodec {
OnError(OH_AVCodec * codec,int32_t errorCode,void * userData)32 void OnError(OH_AVCodec* codec, int32_t errorCode, void* userData)
33 {
34 (void)codec;
35 (void)errorCode;
36 (void)userData;
37 cout << "Error received, errorCode:" << errorCode << endl;
38 }
39
OnOutputFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)40 void OnOutputFormatChanged(OH_AVCodec* codec, OH_AVFormat* format, void* userData)
41 {
42 (void)codec;
43 (void)format;
44 (void)userData;
45 cout << "OnOutputFormatChanged received" << endl;
46 }
47
OnInputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,void * userData)48 void OnInputBufferAvailable(OH_AVCodec* codec, uint32_t index, OH_AVMemory* data, void* userData)
49 {
50 (void)codec;
51 AEncSignal* signal_ = static_cast<AEncSignal*>(userData);
52 cout << "OnInputBufferAvailable received, index:" << index << endl;
53 unique_lock<mutex> lock(signal_->inMutex_);
54 signal_->inQueue_.push(index);
55 signal_->inBufferQueue_.push(data);
56 signal_->inCond_.notify_all();
57 }
58
OnOutputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,OH_AVCodecBufferAttr * attr,void * userData)59 void OnOutputBufferAvailable(OH_AVCodec* codec, uint32_t index,
60 OH_AVMemory* data, OH_AVCodecBufferAttr* attr, void* userData)
61 {
62 (void)codec;
63 AEncSignal* signal_ = static_cast<AEncSignal*>(userData);
64 cout << "OnOutputBufferAvailable received, index:" << index << endl;
65 unique_lock<mutex> lock(signal_->outMutex_);
66 signal_->outQueue_.push(index);
67 signal_->outBufferQueue_.push(data);
68 if (attr) {
69 cout << "OnOutputBufferAvailable received, index:" << index <<
70 ", attr->size:" << attr->size << endl;
71 signal_->attrQueue_.push(*attr);
72 } else {
73 cout << "OnOutputBufferAvailable error, attr is nullptr!" << endl;
74 }
75 signal_->outCond_.notify_all();
76 }
77 }
78 }
79
AudioEncoderDemo()80 AudioEncoderDemo::AudioEncoderDemo()
81 {
82 signal_ = new AEncSignal();
83 innersignal_ = make_shared<AEncSignal>();
84 }
85
~AudioEncoderDemo()86 AudioEncoderDemo::~AudioEncoderDemo()
87 {
88 if (signal_) {
89 delete signal_;
90 signal_ = nullptr;
91 }
92 }
93
NativeCreateByMime(const char * mime)94 OH_AVCodec* AudioEncoderDemo::NativeCreateByMime(const char* mime)
95 {
96 return OH_AudioEncoder_CreateByMime(mime);
97 }
98
NativeCreateByName(const char * name)99 OH_AVCodec* AudioEncoderDemo::NativeCreateByName(const char* name)
100 {
101 return OH_AudioEncoder_CreateByName(name);
102 }
103
NativeDestroy(OH_AVCodec * codec)104 OH_AVErrCode AudioEncoderDemo::NativeDestroy(OH_AVCodec *codec)
105 {
106 stopThread();
107 return OH_AudioEncoder_Destroy(codec);
108 }
109
NativeSetCallback(OH_AVCodec * codec,OH_AVCodecAsyncCallback callback)110 OH_AVErrCode AudioEncoderDemo::NativeSetCallback(OH_AVCodec* codec, OH_AVCodecAsyncCallback callback)
111 {
112 return OH_AudioEncoder_SetCallback(codec, callback, signal_);
113 }
114
NativeConfigure(OH_AVCodec * codec,OH_AVFormat * format)115 OH_AVErrCode AudioEncoderDemo::NativeConfigure(OH_AVCodec* codec, OH_AVFormat* format)
116 {
117 return OH_AudioEncoder_Configure(codec, format);
118 }
119
NativePrepare(OH_AVCodec * codec)120 OH_AVErrCode AudioEncoderDemo::NativePrepare(OH_AVCodec* codec)
121 {
122 return OH_AudioEncoder_Prepare(codec);
123 }
124
NativeStart(OH_AVCodec * codec)125 OH_AVErrCode AudioEncoderDemo::NativeStart(OH_AVCodec* codec)
126 {
127 if (!isRunning_.load()) {
128 cout << "Native Start!!!" << endl;
129 isRunning_.store(true);
130 inputLoop_ = make_unique<thread>(&AudioEncoderDemo::updateInputData, this);
131 outputLoop_ = make_unique<thread>(&AudioEncoderDemo::updateOutputData, this);
132 }
133 OH_AVErrCode ret = OH_AudioEncoder_Start(codec);
134 sleep(1);
135 return ret;
136 }
137
NativeStop(OH_AVCodec * codec)138 OH_AVErrCode AudioEncoderDemo::NativeStop(OH_AVCodec* codec)
139 {
140 stopThread();
141 return OH_AudioEncoder_Stop(codec);
142 }
143
NativeFlush(OH_AVCodec * codec)144 OH_AVErrCode AudioEncoderDemo::NativeFlush(OH_AVCodec* codec)
145 {
146 stopThread();
147 return OH_AudioEncoder_Flush(codec);
148 }
149
NativeReset(OH_AVCodec * codec)150 OH_AVErrCode AudioEncoderDemo::NativeReset(OH_AVCodec* codec)
151 {
152 stopThread();
153 return OH_AudioEncoder_Reset(codec);
154 }
155
NativeGetOutputDescription(OH_AVCodec * codec)156 OH_AVFormat* AudioEncoderDemo::NativeGetOutputDescription(OH_AVCodec* codec)
157 {
158 return OH_AudioEncoder_GetOutputDescription(codec);
159 }
160
NativeSetParameter(OH_AVCodec * codec,OH_AVFormat * format)161 OH_AVErrCode AudioEncoderDemo::NativeSetParameter(OH_AVCodec* codec, OH_AVFormat* format)
162 {
163 return OH_AudioEncoder_SetParameter(codec, format);
164 }
165
NativePushInputData(OH_AVCodec * codec,uint32_t index,OH_AVCodecBufferAttr attr)166 OH_AVErrCode AudioEncoderDemo::NativePushInputData(OH_AVCodec* codec, uint32_t index,
167 OH_AVCodecBufferAttr attr)
168 {
169 return OH_AudioEncoder_PushInputData(codec, index, attr);
170 }
171
NativeFreeOutputData(OH_AVCodec * codec,uint32_t index)172 OH_AVErrCode AudioEncoderDemo::NativeFreeOutputData(OH_AVCodec* codec, uint32_t index)
173 {
174 return OH_AudioEncoder_FreeOutputData(codec, index);
175 }
176
NativeIsValid(OH_AVCodec * codec,bool * isVaild)177 OH_AVErrCode AudioEncoderDemo::NativeIsValid(OH_AVCodec* codec, bool* isVaild)
178 {
179 return OH_AudioEncoder_IsValid(codec, isVaild);
180 }
181
stopThread()182 void AudioEncoderDemo::stopThread()
183 {
184 isRunning_.store(false);
185 if (inputLoop_ != nullptr && inputLoop_->joinable()) {
186 unique_lock<mutex> lock(signal_->inMutex_);
187 signal_->inCond_.notify_all();
188 lock.unlock();
189 inputLoop_->join();
190 inputLoop_ = nullptr;
191 }
192
193 if (outputLoop_ != nullptr && outputLoop_->joinable()) {
194 unique_lock<mutex> lock(signal_->outMutex_);
195 signal_->outCond_.notify_all();
196 lock.unlock();
197 outputLoop_->join();
198 outputLoop_ = nullptr;
199 }
200
201 while (!signal_->inQueue_.empty()) signal_->inQueue_.pop();
202 while (!signal_->outQueue_.empty()) signal_->outQueue_.pop();
203 while (!signal_->inBufferQueue_.empty()) signal_->inBufferQueue_.pop();
204 while (!signal_->outBufferQueue_.empty()) signal_->outBufferQueue_.pop();
205 while (!signal_->attrQueue_.empty()) signal_->attrQueue_.pop();
206
207 while (!inIndexQueue_.empty()) inIndexQueue_.pop();
208 while (!inBufQueue_.empty()) inBufQueue_.pop();
209 while (!outIndexQueue_.empty()) outIndexQueue_.pop();
210 }
211
212
updateInputData()213 void AudioEncoderDemo::updateInputData()
214 {
215 while (isRunning_.load()) {
216 unique_lock<mutex> lock(signal_->inMutex_);
217 signal_->inCond_.wait(lock, [this]() {
218 return (signal_->inQueue_.size() > 0 || !isRunning_.load());
219 });
220
221 if (!isRunning_.load()) {
222 cout << "input wait to stop, exit" << endl;
223 break;
224 }
225
226 cout << "inQueue_ size is " << signal_->inQueue_.size() <<
227 ", inputBuf size is " << signal_->inBufferQueue_.size() << endl;
228 uint32_t inputIndex = signal_->inQueue_.front();
229 inIndexQueue_.push(inputIndex);
230 signal_->inQueue_.pop();
231
232 uint8_t* inputBuf = OH_AVMemory_GetAddr(signal_->inBufferQueue_.front());
233 inBufQueue_.push(inputBuf);
234 signal_->inBufferQueue_.pop();
235 cout << "input index is " << inputIndex << endl;
236 }
237 }
238
updateOutputData()239 void AudioEncoderDemo::updateOutputData()
240 {
241 while (isRunning_.load()) {
242 unique_lock<mutex> lock(signal_->outMutex_);
243 signal_->outCond_.wait(lock, [this]() {
244 return (signal_->outQueue_.size() > 0 || !isRunning_.load());
245 });
246
247 if (!isRunning_.load()) {
248 cout << "output wait to stop, exit" << endl;
249 break;
250 }
251 cout << "outQueue_ size is " << signal_->outQueue_.size() << ", outBufferQueue_ size is " <<
252 signal_->outBufferQueue_.size() << ", attrQueue_ size is " << signal_->attrQueue_.size() << endl;
253 uint32_t outputIndex = signal_->outQueue_.front();
254 outIndexQueue_.push(outputIndex);
255 signal_->outBufferQueue_.pop();
256 signal_->attrQueue_.pop();
257 signal_->outQueue_.pop();
258 cout << "output index is " << outputIndex << endl;
259 }
260 }
261
NativeGetInputIndex()262 uint32_t AudioEncoderDemo::NativeGetInputIndex()
263 {
264 while (inIndexQueue_.empty()) sleep(1);
265 uint32_t inputIndex = inIndexQueue_.front();
266 inIndexQueue_.pop();
267 return inputIndex;
268 }
269
NativeGetInputBuf()270 uint8_t* AudioEncoderDemo::NativeGetInputBuf()
271 {
272 while (inBufQueue_.empty()) sleep(1);
273 uint8_t* inputBuf = inBufQueue_.front();
274 inBufQueue_.pop();
275 return inputBuf;
276 }
277
NativeGetOutputIndex()278 uint32_t AudioEncoderDemo::NativeGetOutputIndex()
279 {
280 if (outIndexQueue_.empty()) {
281 return ERROR_INDEX;
282 }
283 uint32_t outputIndex = outIndexQueue_.front();
284 outIndexQueue_.pop();
285 return outputIndex;
286 }
287
HandleEOS(const uint32_t & index)288 void AudioEncoderDemo::HandleEOS(const uint32_t& index)
289 {
290 OH_AVCodecBufferAttr info;
291 info.size = 0;
292 info.offset = 0;
293 info.pts = 0;
294 info.flags = AVCODEC_BUFFER_FLAGS_EOS;
295 OH_AudioEncoder_PushInputData(audioEnc_, index, info);
296 std::cout << "end buffer\n";
297 signal_->inQueue_.pop();
298 signal_->inBufferQueue_.pop();
299 }
300
NativePushInput(uint32_t index)301 void AudioEncoderDemo::NativePushInput(uint32_t index)
302 {
303 OH_AVCodecBufferAttr info;
304 info.size = inputBufSize;
305 info.offset = 0;
306
307 if (isFirstFrame_) {
308 info.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
309 if (timerFlag == TIMER_INPUT) {
310 gettimeofday(&start, NULL);
311 }
312 OH_AudioEncoder_PushInputData(audioEnc_, index, info);
313 if (timerFlag == TIMER_INPUT) {
314 gettimeofday(&end, NULL);
315 totalTime += (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) / DEFAULT_TIME_NUM;
316 runTimes++;
317 }
318 isFirstFrame_ = false;
319 } else {
320 info.flags = AVCODEC_BUFFER_FLAGS_NONE;
321 if (timerFlag == TIMER_INPUT) {
322 gettimeofday(&start, NULL);
323 }
324 OH_AudioEncoder_PushInputData(audioEnc_, index, info);
325 if (timerFlag == TIMER_INPUT) {
326 gettimeofday(&end, NULL);
327 totalTime += (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) / DEFAULT_TIME_NUM;
328 runTimes++;
329 }
330 }
331 }
332
NativeInputFunc()333 void AudioEncoderDemo::NativeInputFunc()
334 {
335 inputFile_.open(inputFilePath, std::ios::binary);
336 while (isRunning_.load()) {
337 int32_t ret = AVCS_ERR_OK;
338 unique_lock<mutex> lock(signal_->inMutex_);
339 cout << "input wait !!!" << endl;
340 signal_->inCond_.wait(lock, [this]() {
341 return (signal_->inQueue_.size() > 0 || !isRunning_.load());
342 });
343
344 if (!isRunning_.load()) {
345 break;
346 }
347
348 uint32_t index = signal_->inQueue_.front();
349 auto buffer = signal_->inBufferQueue_.front();
350
351 gettimeofday(&inputStart, NULL);
352 if (!inputFile_.eof()) {
353 if (OH_AVMemory_GetAddr(buffer) == nullptr) {
354 cout << "buffer is nullptr" << endl;
355 }
356 inputFile_.read((char*)OH_AVMemory_GetAddr(buffer), inputBufSize);
357 } else {
358 HandleEOS(index);
359 break;
360 }
361 gettimeofday(&inputEnd, NULL);
362 otherTime += (inputEnd.tv_sec - inputStart.tv_sec) +
363 (inputEnd.tv_usec - inputStart.tv_usec) / DEFAULT_TIME_NUM;
364
365 NativePushInput(index);
366
367 timeStamp_ += FRAME_DURATION_US;
368 signal_->inQueue_.pop();
369 signal_->inBufferQueue_.pop();
370 frameCount_++;
371 if (ret != AVCS_ERR_OK) {
372 cout << "Fatal error, exit" << endl;
373 break;
374 }
375 }
376 inputFile_.close();
377 }
378
NativeGetDescription()379 void AudioEncoderDemo::NativeGetDescription()
380 {
381 if (isGetOutputDescription && curFormat == nullptr) {
382 cout << "before GetOutputDescription" << endl;
383 curFormat = OH_AudioEncoder_GetOutputDescription(audioEnc_);
384 if (curFormat == nullptr) {
385 cout << "GetOutputDescription error !!!" << endl;
386 }
387 }
388 if (timerFlag == TIMER_GETOUTPUTDESCRIPTION) {
389 gettimeofday(&start, NULL);
390 curFormat = OH_AudioEncoder_GetOutputDescription(audioEnc_);
391 gettimeofday(&end, NULL);
392 totalTime += (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) / DEFAULT_TIME_NUM;
393 runTimes++;
394 }
395 }
396
NativeWriteOutput(std::ofstream & outputFile,uint32_t index,OH_AVCodecBufferAttr attr,OH_AVMemory * data)397 void AudioEncoderDemo::NativeWriteOutput(std::ofstream &outputFile, uint32_t index,
398 OH_AVCodecBufferAttr attr, OH_AVMemory* data)
399 {
400 gettimeofday(&outputStart, NULL);
401 if (data != nullptr) {
402 cout << "OutputFunc write file,buffer index" << index << ", data size = " << attr.size << endl;
403 outputFile.write(reinterpret_cast<char*>(OH_AVMemory_GetAddr(data)), attr.size);
404 }
405 gettimeofday(&outputEnd, NULL);
406 otherTime += (outputEnd.tv_sec - outputStart.tv_sec) +
407 (outputEnd.tv_usec - outputStart.tv_usec) / DEFAULT_TIME_NUM;
408
409 cout << "attr.flags: " << attr.flags << endl;
410 if (attr.flags == AVCODEC_BUFFER_FLAGS_EOS || attr.size == 0) {
411 cout << "encode eos" << endl;
412 isRunning_.store(false);
413 }
414 }
415
416
NativeOutputFunc()417 void AudioEncoderDemo::NativeOutputFunc()
418 {
419 std::ofstream outputFile;
420 outputFile.open(outputFilePath, std::ios::out | std::ios::binary);
421 if (!outputFile.is_open()) {
422 std::cout << "open " << outputFilePath << " failed!" << std::endl;
423 }
424 while (isRunning_.load()) {
425 unique_lock<mutex> lock(signal_->outMutex_);
426 cout << "output wait !!!" << endl;
427 signal_->outCond_.wait(lock, [this]() {
428 return (signal_->outQueue_.size() > 0 || !isRunning_.load());
429 });
430
431 if (!isRunning_.load()) {
432 cout << "wait to stop, exit" << endl;
433 break;
434 }
435
436 uint32_t index = signal_->outQueue_.front();
437 OH_AVCodecBufferAttr attr = signal_->attrQueue_.front();
438 OH_AVMemory* data = signal_->outBufferQueue_.front();
439
440 NativeWriteOutput(outputFile, index, attr, data);
441
442 signal_->outBufferQueue_.pop();
443 signal_->attrQueue_.pop();
444 signal_->outQueue_.pop();
445
446 if (timerFlag == TIMER_FREEOUTPUT) {
447 gettimeofday(&start, NULL);
448 }
449 OH_AVErrCode ret = OH_AudioEncoder_FreeOutputData(audioEnc_, index);
450 if (timerFlag == TIMER_FREEOUTPUT) {
451 gettimeofday(&end, NULL);
452 totalTime += (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) / DEFAULT_TIME_NUM;
453 runTimes++;
454 }
455
456 if (ret != AV_ERR_OK) {
457 cout << "Fatal: FreeOutputData fail" << endl;
458 break;
459 }
460 NativeGetDescription();
461 }
462 outputFile.close();
463 }
464
setTimerFlag(int32_t flag)465 void AudioEncoderDemo::setTimerFlag(int32_t flag)
466 {
467 timerFlag = flag;
468 }
469
NativeCreateToStart(const char * name,OH_AVFormat * format)470 void AudioEncoderDemo::NativeCreateToStart(const char* name, OH_AVFormat* format)
471 {
472 cout << "create name is " << name << endl;
473 audioEnc_ = OH_AudioEncoder_CreateByName(name);
474 if (audioEnc_ == nullptr) {
475 cout << "create fail!!" << endl;
476 return;
477 }
478
479 if (strcmp(name, "OH.Media.Codec.Encoder.Audio.Flac") == 0) {
480 OH_AVFormat_GetIntValue(format, OH_MD_KEY_MAX_INPUT_SIZE, &inputBufSize);
481 } else if (strcmp(name, "OH.Media.Codec.Encoder.Audio.AAC") == 0) {
482 int channels;
483 OH_AVFormat_GetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, &channels);
484 inputBufSize = channels * AAC_FRAME_SIZE * AAC_DEFAULT_BYTES_PER_SAMPLE;
485 }
486
487 OH_AVErrCode result;
488
489 cb_ = { &OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable };
490 result = OH_AudioEncoder_SetCallback(audioEnc_, cb_, signal_);
491 cout << "SetCallback ret is: " << result << endl;
492
493 result = OH_AudioEncoder_Configure(audioEnc_, format);
494 cout << "Configure ret is: " << result << endl;
495 if (result < 0) {
496 cout << "Configure fail! ret is " << result << endl;
497 return;
498 }
499
500 result = OH_AudioEncoder_Prepare(audioEnc_);
501 cout << "Prepare ret is: " << result << endl;
502
503 // Start
504 isRunning_.store(true);
505 inputLoop_ = make_unique<thread>(&AudioEncoderDemo::NativeInputFunc, this);
506 outputLoop_ = make_unique<thread>(&AudioEncoderDemo::NativeOutputFunc, this);
507 result = OH_AudioEncoder_Start(audioEnc_);
508 cout << "Start ret is: " << result << endl;
509 }
510
NativeStopAndClear()511 void AudioEncoderDemo::NativeStopAndClear()
512 {
513 OH_AVErrCode result;
514 // Stop
515 isRunning_.store(false);
516 if (inputLoop_ != nullptr && inputLoop_->joinable()) {
517 unique_lock<mutex> lock(signal_->inMutex_);
518 signal_->inCond_.notify_all();
519 lock.unlock();
520 inputLoop_->join();
521 }
522
523 if (outputLoop_ != nullptr && outputLoop_->joinable()) {
524 unique_lock<mutex> lock(signal_->outMutex_);
525 signal_->outCond_.notify_all();
526 lock.unlock();
527 outputLoop_->join();
528 }
529 result = OH_AudioEncoder_Stop(audioEnc_);
530 cout << "Stop ret is: " << result << endl;
531
532 while (!signal_->inQueue_.empty()) signal_->inQueue_.pop();
533 while (!signal_->outQueue_.empty()) signal_->outQueue_.pop();
534 while (!signal_->inBufferQueue_.empty()) signal_->inBufferQueue_.pop();
535 while (!signal_->outBufferQueue_.empty()) signal_->outBufferQueue_.pop();
536 while (!signal_->attrQueue_.empty()) signal_->attrQueue_.pop();
537 }
538
NativeRunCase(std::string inputFile,std::string outputFile,const char * name,OH_AVFormat * format)539 void AudioEncoderDemo::NativeRunCase(std::string inputFile, std::string outputFile,
540 const char* name, OH_AVFormat* format)
541 {
542 inputFilePath = inputFile;
543 outputFilePath = outputFile;
544
545 NativeCreateToStart(name, format);
546
547 while (isRunning_.load()) {
548 sleep(1);
549 }
550
551 NativeStopAndClear();
552 OH_AVErrCode result = OH_AudioEncoder_Destroy(audioEnc_);
553 cout << "Destroy ret is: " << result << endl;
554
555 if (timerFlag != 0) {
556 cout << "total time is " << totalTime << ", run times is " << runTimes << endl;
557 }
558 }
559
560
NativeRunCaseWithoutCreate(OH_AVCodec * handle,std::string inputFile,std::string outputFile,OH_AVFormat * format,const char * name,bool needConfig)561 void AudioEncoderDemo::NativeRunCaseWithoutCreate(OH_AVCodec* handle, std::string inputFile,
562 std::string outputFile, OH_AVFormat* format, const char* name, bool needConfig)
563 {
564 inputFilePath = inputFile;
565 outputFilePath = outputFile;
566
567 audioEnc_ = handle;
568
569 if (strcmp(name, "OH.Media.Codec.Encoder.Audio.Flac") == 0) {
570 OH_AVFormat_GetIntValue(format, OH_MD_KEY_MAX_INPUT_SIZE, &inputBufSize);
571 } else if (strcmp(name, "OH.Media.Codec.Encoder.Audio.AAC") == 0) {
572 int channels;
573 OH_AVFormat_GetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, &channels);
574 inputBufSize = channels * AAC_FRAME_SIZE * AAC_DEFAULT_BYTES_PER_SAMPLE;
575 }
576
577 OH_AVErrCode result;
578 if (needConfig) {
579 result = OH_AudioEncoder_Configure(audioEnc_, format);
580 cout << "Configure ret is: " << result << endl;
581 if (result < 0) {
582 cout << "Configure fail! ret is " << result << endl;
583 return;
584 }
585
586 result = OH_AudioEncoder_Prepare(audioEnc_);
587 cout << "Prepare ret is: " << result << endl;
588 }
589
590 // Start
591 isRunning_.store(true);
592 inputLoop_ = make_unique<thread>(&AudioEncoderDemo::NativeInputFunc, this);
593 outputLoop_ = make_unique<thread>(&AudioEncoderDemo::NativeOutputFunc, this);
594 result = OH_AudioEncoder_Start(audioEnc_);
595 cout << "Start ret is: " << result << endl;
596
597 while (isRunning_.load()) {
598 sleep(1);
599 }
600
601 // Stop
602 isRunning_.store(false);
603 if (inputLoop_ != nullptr && inputLoop_->joinable()) {
604 unique_lock<mutex> lock(signal_->inMutex_);
605 signal_->inCond_.notify_all();
606 lock.unlock();
607 inputLoop_->join();
608 }
609
610 if (outputLoop_ != nullptr && outputLoop_->joinable()) {
611 unique_lock<mutex> lock(signal_->outMutex_);
612 signal_->outCond_.notify_all();
613 lock.unlock();
614 outputLoop_->join();
615 }
616 }
617
618
NativeRunCasePerformance(std::string inputFile,std::string outputFile,const char * name,OH_AVFormat * format)619 void AudioEncoderDemo::NativeRunCasePerformance(std::string inputFile, std::string outputFile,
620 const char* name, OH_AVFormat* format)
621 {
622 inputFilePath = inputFile;
623 outputFilePath = outputFile;
624
625 OH_AVErrCode result;
626 gettimeofday(&startTime, NULL);
627 NativeCreateToStart(name, format);
628
629 while (isRunning_.load()) {
630 sleep(1);
631 }
632
633 NativeStopAndClear();
634
635 result = OH_AudioEncoder_Destroy(audioEnc_);
636 cout << "Destroy ret is: " << result << endl;
637
638 gettimeofday(&endTime, NULL);
639 totalTime = (endTime.tv_sec - startTime.tv_sec) +
640 (endTime.tv_usec - startTime.tv_usec) / DEFAULT_TIME_NUM - otherTime;
641
642 cout << "cur decoder is " << name << ", total time is " << totalTime << endl;
643 }
644
645
NativeRunCaseFlush(std::string inputFile,std::string outputFileFirst,std::string outputFileSecond,const char * name,OH_AVFormat * format)646 void AudioEncoderDemo::NativeRunCaseFlush(std::string inputFile, std::string outputFileFirst,
647 std::string outputFileSecond, const char* name, OH_AVFormat* format)
648 {
649 inputFilePath = inputFile;
650 outputFilePath = outputFileFirst;
651
652 NativeCreateToStart(name, format);
653
654 while (isRunning_.load()) {
655 sleep(1);
656 }
657
658 OH_AVErrCode result;
659 NativeStopAndClear();
660
661 // Flush
662 result = OH_AudioEncoder_Flush(audioEnc_);
663 inputFilePath = inputFile;
664 outputFilePath = outputFileSecond;
665
666 isRunning_.store(true);
667 inputLoop_ = make_unique<thread>(&AudioEncoderDemo::NativeInputFunc, this);
668 outputLoop_ = make_unique<thread>(&AudioEncoderDemo::NativeOutputFunc, this);
669 result = OH_AudioEncoder_Start(audioEnc_);
670 cout << "Start ret is: " << result << endl;
671
672 while (isRunning_.load()) {
673 sleep(1);
674 }
675
676 NativeStopAndClear();
677
678 result = OH_AudioEncoder_Destroy(audioEnc_);
679 cout << "Destroy ret is: " << result << endl;
680 }
681
NativeRunCaseReset(std::string inputFile,std::string outputFileFirst,std::string outputFileSecond,const char * name,OH_AVFormat * format)682 void AudioEncoderDemo::NativeRunCaseReset(std::string inputFile, std::string outputFileFirst,
683 std::string outputFileSecond, const char* name, OH_AVFormat* format)
684 {
685 inputFilePath = inputFile;
686 outputFilePath = outputFileFirst;
687
688 OH_AVErrCode result;
689 NativeCreateToStart(name, format);
690
691 while (isRunning_.load()) {
692 sleep(1);
693 }
694
695 NativeStopAndClear();
696
697 // Reset
698 result = OH_AudioEncoder_Reset(audioEnc_);
699
700 inputFilePath = inputFile;
701 outputFilePath = outputFileSecond;
702
703 result = OH_AudioEncoder_Configure(audioEnc_, format);
704 if (result < 0) {
705 cout << "Configure fail! ret is " << result << endl;
706 return;
707 }
708
709 result = OH_AudioEncoder_Prepare(audioEnc_);
710 cout << "Prepare ret is: " << result << endl;
711
712 isRunning_.store(true);
713 inputLoop_ = make_unique<thread>(&AudioEncoderDemo::NativeInputFunc, this);
714 outputLoop_ = make_unique<thread>(&AudioEncoderDemo::NativeOutputFunc, this);
715 result = OH_AudioEncoder_Start(audioEnc_);
716 cout << "Start ret is: " << result << endl;
717
718 while (isRunning_.load()) {
719 sleep(1);
720 }
721
722 NativeStopAndClear();
723
724 result = OH_AudioEncoder_Destroy(audioEnc_);
725 cout << "Destroy ret is: " << result << endl;
726 }
727
728
NativeRunCaseGetOutputDescription(std::string inputFile,std::string outputFile,const char * name,OH_AVFormat * format)729 OH_AVFormat* AudioEncoderDemo::NativeRunCaseGetOutputDescription(std::string inputFile,
730 std::string outputFile, const char* name, OH_AVFormat* format)
731 {
732 inputFilePath = inputFile;
733 outputFilePath = outputFile;
734 isGetOutputDescription = true;
735
736 OH_AVErrCode result;
737 NativeCreateToStart(name, format);
738
739 while (isRunning_.load()) {
740 sleep(1);
741 }
742
743 NativeStopAndClear();
744
745 result = OH_AudioEncoder_Destroy(audioEnc_);
746 cout << "Destroy ret is: " << result << endl;
747
748 return curFormat;
749 }
750
751 // for test
TestOutputFunc()752 void AudioEncoderDemo::TestOutputFunc()
753 {
754 std::ofstream outputFile;
755 outputFile.open(outputFilePath, std::ios::out | std::ios::binary);
756 if (!outputFile.is_open()) {
757 std::cout << "open " << outputFilePath << " failed!" << std::endl;
758 }
759
760 while (isRunning_.load()) {
761 unique_lock<mutex> lock(signal_->outMutex_);
762 cout << "output wait !!!" << endl;
763 signal_->outCond_.wait(lock, [this]() {
764 return (signal_->outQueue_.size() > 0 || !isRunning_.load());
765 });
766
767 if (!isRunning_.load()) {
768 cout << "wait to stop, exit" << endl;
769 break;
770 }
771
772 uint32_t index = signal_->outQueue_.front();
773 OH_AVCodecBufferAttr attr = signal_->attrQueue_.front();
774 OH_AVMemory* data = signal_->outBufferQueue_.front();
775
776 if (data != nullptr) {
777 cout << "OutputFunc write file,buffer index" << index << ", data size = " << attr.size << endl;
778 int64_t size = attr.size;
779 outputFile.write((char*)(&size), sizeof(size));
780 int64_t pts = attr.pts;
781 outputFile.write((char*)(&pts), sizeof(pts));
782 outputFile.write(reinterpret_cast<char*>(OH_AVMemory_GetAddr(data)), attr.size);
783 }
784
785 cout << "attr.flags: " << attr.flags << endl;
786 if (attr.flags == AVCODEC_BUFFER_FLAGS_EOS || attr.size == 0) {
787 cout << "encode eos" << endl;
788 isRunning_.store(false);
789 }
790
791 signal_->outBufferQueue_.pop();
792 signal_->attrQueue_.pop();
793 signal_->outQueue_.pop();
794
795 OH_AVErrCode ret = OH_AudioEncoder_FreeOutputData(audioEnc_, index);
796 if (ret != AV_ERR_OK) {
797 cout << "Fatal: FreeOutputData fail" << endl;
798 break;
799 }
800 }
801 outputFile.close();
802 }
803
TestRunCase(std::string inputFile,std::string outputFile,const char * name,OH_AVFormat * format)804 void AudioEncoderDemo::TestRunCase(std::string inputFile, std::string outputFile,
805 const char* name, OH_AVFormat* format)
806 {
807 inputFilePath = inputFile;
808 outputFilePath = outputFile;
809
810 cout << "create name is " << name << endl;
811 audioEnc_ = OH_AudioEncoder_CreateByName(name);
812 if (audioEnc_ == nullptr) {
813 cout << "create fail!!" << endl;
814 return;
815 }
816
817 if (strcmp(name, "OH.Media.Codec.Encoder.Audio.Flac") == 0) {
818 OH_AVFormat_GetIntValue(format, OH_MD_KEY_MAX_INPUT_SIZE, &inputBufSize);
819 } else if (strcmp(name, "OH.Media.Codec.Encoder.Audio.AAC") == 0) {
820 int channels;
821 OH_AVFormat_GetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, &channels);
822 inputBufSize = channels * AAC_FRAME_SIZE * AAC_DEFAULT_BYTES_PER_SAMPLE;
823 }
824
825 OH_AVErrCode result;
826
827 cb_ = { &OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable };
828 result = OH_AudioEncoder_SetCallback(audioEnc_, cb_, signal_);
829 cout << "SetCallback ret is: " << result << endl;
830
831 result = OH_AudioEncoder_Configure(audioEnc_, format);
832 cout << "Configure ret is: " << result << endl;
833 if (result < 0) {
834 cout << "Configure fail! ret is " << result << endl;
835 return;
836 }
837
838 result = OH_AudioEncoder_Prepare(audioEnc_);
839 cout << "Prepare ret is: " << result << endl;
840
841 // Start
842 isRunning_.store(true);
843 inputLoop_ = make_unique<thread>(&AudioEncoderDemo::NativeInputFunc, this);
844 outputLoop_ = make_unique<thread>(&AudioEncoderDemo::TestOutputFunc, this);
845 result = OH_AudioEncoder_Start(audioEnc_);
846 cout << "Start ret is: " << result << endl;
847
848 while (isRunning_.load()) {
849 sleep(1);
850 }
851
852 NativeStopAndClear();
853
854 result = OH_AudioEncoder_Destroy(audioEnc_);
855 cout << "Destroy ret is: " << result << endl;
856 }
857
858
859 // inner
InnerCreateByMime(const std::string & mime)860 int32_t AudioEncoderDemo::InnerCreateByMime(const std::string& mime)
861 {
862 inneraudioEnc_ = AudioEncoderFactory::CreateByMime(mime);
863 std::cout << "InnerCreateByMime" << endl;
864 if (inneraudioEnc_ == nullptr) {
865 std::cout << "InnerEncoder create failed!" << std::endl;
866 return AVCS_ERR_INVALID_OPERATION;
867 }
868 return AVCS_ERR_OK;
869 }
870
InnerCreateByName(const std::string & name)871 int32_t AudioEncoderDemo::InnerCreateByName(const std::string& name)
872 {
873 inneraudioEnc_ = AudioEncoderFactory::CreateByName(name);
874 std::cout << "InnerCreateByName" << endl;
875 if (inneraudioEnc_ == nullptr) {
876 std::cout << "InnerEncoder create failed!" << std::endl;
877 return AVCS_ERR_INVALID_OPERATION;
878 }
879 return AVCS_ERR_OK;
880 }
881
InnerSetCallback(const std::shared_ptr<AVCodecCallback> & callback)882 int32_t AudioEncoderDemo::InnerSetCallback(const std::shared_ptr<AVCodecCallback>& callback)
883 {
884 return inneraudioEnc_->SetCallback(callback);
885 }
886
InnerConfigure(const Format & format)887 int32_t AudioEncoderDemo::InnerConfigure(const Format& format)
888 {
889 cout << "InnerConfigure" << endl;
890 if (inneraudioEnc_ == nullptr) {
891 std::cout << "InnerEncoder create failed!" << std::endl;
892 return AVCS_ERR_INVALID_OPERATION;
893 }
894 return inneraudioEnc_->Configure(format);
895 }
896
InnerStart()897 int32_t AudioEncoderDemo::InnerStart()
898 {
899 cout << "InnerStart" << endl;
900 if (inneraudioEnc_ == nullptr) {
901 std::cout << "InnerEncoder create failed!" << std::endl;
902 return AVCS_ERR_INVALID_OPERATION;
903 }
904 return inneraudioEnc_->Start();
905 }
906
InnerStartWithThread()907 int32_t AudioEncoderDemo::InnerStartWithThread()
908 {
909 if (!isRunning_.load()) {
910 cout << "InnerStartWithThread" << endl;
911 isRunning_.store(true);
912 inputLoop_ = make_unique<thread>(&AudioEncoderDemo::InnerUpdateInputData, this);
913 outputLoop_ = make_unique<thread>(&AudioEncoderDemo::InnerUpdateOutputData, this);
914 }
915 int32_t ret = inneraudioEnc_->Start();
916 sleep(1);
917 return ret;
918 }
919
InnerPrepare()920 int32_t AudioEncoderDemo::InnerPrepare()
921 {
922 cout << "InnerPrepare" << endl;
923 if (inneraudioEnc_ == nullptr) {
924 std::cout << "InnerEncoder create failed!" << std::endl;
925 return AVCS_ERR_INVALID_OPERATION;
926 }
927 return inneraudioEnc_->Prepare();
928 }
929
InnerStop()930 int32_t AudioEncoderDemo::InnerStop()
931 {
932 InnerStopThread();
933 cout << "InnerStop" << endl;
934 if (inneraudioEnc_ == nullptr) {
935 std::cout << "InnerEncoder create failed!" << std::endl;
936 return AVCS_ERR_INVALID_OPERATION;
937 }
938
939 return inneraudioEnc_->Stop();
940 }
941
InnerFlush()942 int32_t AudioEncoderDemo::InnerFlush()
943 {
944 cout << "InnerFlush" << endl;
945 if (inneraudioEnc_ == nullptr) {
946 std::cout << "InnerEncoder create failed!" << std::endl;
947 return AVCS_ERR_INVALID_OPERATION;
948 }
949 int32_t ret = inneraudioEnc_->Flush();
950
951 while (!innersignal_->inQueue_.empty())
952 innersignal_->inQueue_.pop();
953 while (!innersignal_->inInnerBufQueue_.empty())
954 innersignal_->inInnerBufQueue_.pop();
955 while (!innersignal_->outInnerBufQueue_.empty())
956 innersignal_->outInnerBufQueue_.pop();
957 while (!innersignal_->outQueue_.empty())
958 innersignal_->outQueue_.pop();
959 while (!innersignal_->infoQueue_.empty())
960 innersignal_->infoQueue_.pop();
961 while (!innersignal_->flagQueue_.empty())
962 innersignal_->flagQueue_.pop();
963
964 while (!inIndexQueue_.empty())
965 inIndexQueue_.pop();
966 while (!inBufQueue_.empty())
967 inBufQueue_.pop();
968 while (!outIndexQueue_.empty())
969 outIndexQueue_.pop();
970
971 return ret;
972 }
973
InnerReset()974 int32_t AudioEncoderDemo::InnerReset()
975 {
976 InnerStopThread();
977 cout << "InnerReset" << endl;
978 if (inneraudioEnc_ == nullptr) {
979 std::cout << "InnerEncoder create failed!" << std::endl;
980 return AVCS_ERR_INVALID_OPERATION;
981 }
982 return inneraudioEnc_->Reset();
983 }
984
InnerRelease()985 int32_t AudioEncoderDemo::InnerRelease()
986 {
987 cout << "InnerRelease" << endl;
988 if (inneraudioEnc_ == nullptr) {
989 std::cout << "InnerEncoder create failed!" << std::endl;
990 return AVCS_ERR_INVALID_OPERATION;
991 }
992 return inneraudioEnc_->Release();
993 }
994
InnerSetParameter(const Format & format)995 int32_t AudioEncoderDemo::InnerSetParameter(const Format& format)
996 {
997 cout << "InnerSetParameter" << endl;
998 if (inneraudioEnc_ == nullptr) {
999 std::cout << "InnerEncoder create failed!" << std::endl;
1000 return AVCS_ERR_INVALID_OPERATION;
1001 }
1002 return inneraudioEnc_->SetParameter(format);
1003 }
1004
InnerDestroy()1005 int32_t AudioEncoderDemo::InnerDestroy()
1006 {
1007 InnerStopThread();
1008 int ret = InnerRelease();
1009 inneraudioEnc_ = nullptr;
1010 return ret;
1011 }
1012
InnerQueueInputBuffer(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)1013 int32_t AudioEncoderDemo::InnerQueueInputBuffer(uint32_t index, AVCodecBufferInfo info,
1014 AVCodecBufferFlag flag)
1015 {
1016 cout << "InnerQueueInputBuffer" << endl;
1017 return inneraudioEnc_->QueueInputBuffer(index, info, flag);
1018 }
1019
InnerGetOutputFormat(Format & format)1020 int32_t AudioEncoderDemo::InnerGetOutputFormat(Format& format)
1021 {
1022 cout << "InnerGetOutputFormat" << endl;
1023 return inneraudioEnc_->GetOutputFormat(format);
1024 }
1025
InnerReleaseOutputBuffer(uint32_t index)1026 int32_t AudioEncoderDemo::InnerReleaseOutputBuffer(uint32_t index)
1027 {
1028 cout << "InnerReleaseOutputBuffer" << endl;
1029 return inneraudioEnc_->ReleaseOutputBuffer(index);
1030 }
1031
InnerStopThread()1032 void AudioEncoderDemo::InnerStopThread()
1033 {
1034 isRunning_.store(false);
1035 if (inputLoop_ != nullptr && inputLoop_->joinable()) {
1036 unique_lock<mutex> lock(innersignal_->inMutex_);
1037 innersignal_->inCond_.notify_all();
1038 lock.unlock();
1039 inputLoop_->join();
1040 inputLoop_ = nullptr;
1041 }
1042
1043 if (outputLoop_ != nullptr && outputLoop_->joinable()) {
1044 unique_lock<mutex> lock(innersignal_->outMutex_);
1045 innersignal_->outCond_.notify_all();
1046 lock.unlock();
1047 outputLoop_->join();
1048 outputLoop_ = nullptr;
1049 }
1050
1051 while (!innersignal_->inQueue_.empty()) innersignal_->inQueue_.pop();
1052 while (!innersignal_->outQueue_.empty()) innersignal_->outQueue_.pop();
1053 while (!innersignal_->infoQueue_.empty()) innersignal_->infoQueue_.pop();
1054 while (!innersignal_->flagQueue_.empty()) innersignal_->flagQueue_.pop();
1055 while (!innersignal_->inInnerBufQueue_.empty()) innersignal_->inInnerBufQueue_.pop();
1056 while (!innersignal_->outInnerBufQueue_.empty()) innersignal_->outInnerBufQueue_.pop();
1057 }
1058
InnerHandleEOS(const uint32_t & index)1059 void AudioEncoderDemo::InnerHandleEOS(const uint32_t& index)
1060 {
1061 AVCodecBufferInfo info;
1062 AVCodecBufferFlag flag;
1063 info.size = 0;
1064 info.offset = 0;
1065 info.presentationTimeUs = 0;
1066 flag = AVCODEC_BUFFER_FLAG_EOS;
1067 inneraudioEnc_->QueueInputBuffer(index, info, flag);
1068 std::cout << "end buffer\n";
1069 innersignal_->inQueue_.pop();
1070 }
1071
InnerInputFunc()1072 void AudioEncoderDemo::InnerInputFunc()
1073 {
1074 inputFile_.open(inputFilePath, std::ios::binary);
1075 if (!inputFile_.is_open()) {
1076 std::cout << "open file " << inputFilePath << " failed" << std::endl;
1077 isRunning_.store(false);
1078 return;
1079 }
1080 while (isRunning_.load()) {
1081 std::unique_lock<std::mutex> lock(innersignal_->inMutex_);
1082 innersignal_->inCond_.wait(lock, [this]() {
1083 return (innersignal_->inQueue_.size() > 0 || !isRunning_.load());
1084 });
1085 if (!isRunning_.load()) {
1086 break;
1087 }
1088
1089 uint32_t index = innersignal_->inQueue_.front();
1090 auto buffer = innersignal_->inInnerBufQueue_.front();
1091 if (buffer == nullptr) {
1092 isRunning_.store(false);
1093 std::cout << "buffer is null:" << index << "\n";
1094 break;
1095 }
1096
1097 if (!inputFile_.eof()) {
1098 inputFile_.read((char*)buffer->GetBase(), inputBufSize);
1099 } else {
1100 InnerHandleEOS(index);
1101 break;
1102 }
1103
1104 AVCodecBufferInfo info;
1105 AVCodecBufferFlag flag;
1106 info.size = inputBufSize;
1107 info.offset = 0;
1108
1109 int32_t ret = AVCS_ERR_OK;
1110
1111 flag = AVCODEC_BUFFER_FLAG_NONE;
1112 ret = inneraudioEnc_->QueueInputBuffer(index, info, flag);
1113 timeStamp_ += FRAME_DURATION_US;
1114 innersignal_->inQueue_.pop();
1115 innersignal_->inInnerBufQueue_.pop();
1116
1117 if (ret != AVCS_ERR_OK) {
1118 cout << "Fatal error, exit" << endl;
1119 isRunning_ = false;
1120 break;
1121 }
1122 }
1123 inputFile_.close();
1124 }
1125
InnerOutputFunc()1126 void AudioEncoderDemo::InnerOutputFunc()
1127 {
1128 std::ofstream outputFile;
1129 outputFile.open(outputFilePath, std::ios::out | std::ios::binary);
1130 if (!outputFile.is_open()) {
1131 std::cout << "open " << outputFilePath << " failed!" << std::endl;
1132 return;
1133 }
1134 while (isRunning_.load()) {
1135 unique_lock<mutex> lock(innersignal_->outMutex_);
1136 innersignal_->outCond_.wait(lock, [this]() {
1137 return (innersignal_->outQueue_.size() > 0 || !isRunning_.load());
1138 });
1139
1140 if (!isRunning_.load()) {
1141 cout << "wait to stop, exit" << endl;
1142 break;
1143 }
1144
1145 uint32_t index = innersignal_->outQueue_.front();
1146 auto flag = innersignal_->flagQueue_.front();
1147 auto buffer = innersignal_->outInnerBufQueue_.front();
1148 if (buffer == nullptr) {
1149 cout << "get output buffer is nullptr" << ", index:" << index << endl;
1150 }
1151 if (buffer != nullptr) {
1152 auto info = innersignal_->infoQueue_.front();
1153
1154 cout << "OutputFunc write file,buffer index" << index << ", data size = :" << info.size << endl;
1155 outputFile.write((char*)buffer->GetBase(), info.size);
1156 }
1157
1158 if (flag == AVCODEC_BUFFER_FLAG_EOS) {
1159 cout << "encode eos" << endl;
1160 isRunning_.store(false);
1161 break;
1162 }
1163 if (inneraudioEnc_->ReleaseOutputBuffer(index) != AVCS_ERR_OK) {
1164 cout << "Fatal: ReleaseOutputBuffer fail" << endl;
1165 break;
1166 }
1167 innersignal_->outQueue_.pop();
1168 innersignal_->infoQueue_.pop();
1169 innersignal_->flagQueue_.pop();
1170 innersignal_->outInnerBufQueue_.pop();
1171 }
1172 outputFile.close();
1173 }
1174
InnerCreateToStart(const std::string & name,Format & format)1175 void AudioEncoderDemo::InnerCreateToStart(const std::string& name, Format& format)
1176 {
1177 int32_t result;
1178
1179 cout << "create name is " << name << endl;
1180 InnerCreateByName(name);
1181 if (inneraudioEnc_ == nullptr) {
1182 cout << "create fail!!" << endl;
1183 return;
1184 }
1185
1186 if (name == "OH.Media.Codec.Encoder.Audio.Flac") {
1187 inputBufSize = INPUT_FRAME_BYTES;
1188 } else if (name == "OH.Media.Codec.Encoder.Audio.AAC") {
1189 int32_t channels;
1190 format.GetIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, channels);
1191 inputBufSize = channels * AAC_FRAME_SIZE * AAC_DEFAULT_BYTES_PER_SAMPLE;
1192 }
1193
1194 cout << "create done" << endl;
1195 innersignal_ = getSignal();
1196 cout << "innersignal_: " << innersignal_ << endl;
1197 innercb_ = make_unique<InnerAEnDemoCallback>(innersignal_);
1198 result = InnerSetCallback(innercb_);
1199 cout << "SetCallback ret is: " << result << endl;
1200
1201 result = InnerConfigure(format);
1202 cout << "Configure ret is: " << result << endl;
1203 if (result != 0) {
1204 cout << "Configure fail!! ret is " << result << endl;
1205 return;
1206 }
1207 result = InnerPrepare();
1208 cout << "InnerPrepare ret is: " << result << endl;
1209
1210 isRunning_.store(true);
1211 inputLoop_ = make_unique<thread>(&AudioEncoderDemo::InnerInputFunc, this);
1212 outputLoop_ = make_unique<thread>(&AudioEncoderDemo::InnerOutputFunc, this);
1213 result = InnerStart();
1214 cout << "Start ret is: " << result << endl;
1215 }
1216
InnerStopAndClear()1217 void AudioEncoderDemo::InnerStopAndClear()
1218 {
1219 int32_t result;
1220 isRunning_.store(false);
1221 if (inputLoop_ != nullptr && inputLoop_->joinable()) {
1222 unique_lock<mutex> lock(innersignal_->inMutex_);
1223 innersignal_->inCond_.notify_all();
1224 lock.unlock();
1225 inputLoop_->join();
1226 }
1227
1228 if (outputLoop_ != nullptr && outputLoop_->joinable()) {
1229 unique_lock<mutex> lock(innersignal_->outMutex_);
1230 innersignal_->outCond_.notify_all();
1231 lock.unlock();
1232 outputLoop_->join();
1233 }
1234 InnerStopThread();
1235 result = InnerStop();
1236 cout << "Stop ret is: " << result << endl;
1237 }
1238
InnerRunCase(std::string inputFile,std::string outputFile,const std::string & name,Format & format)1239 void AudioEncoderDemo::InnerRunCase(std::string inputFile, std::string outputFile,
1240 const std::string& name, Format& format)
1241 {
1242 inputFilePath = inputFile;
1243 outputFilePath = outputFile;
1244
1245 int32_t result;
1246
1247 InnerCreateToStart(name, format);
1248 while (isRunning_.load()) {
1249 sleep(1);
1250 }
1251
1252 // Stop
1253 InnerStopAndClear();
1254
1255 result = InnerDestroy();
1256 cout << "Destroy ret is: " << result << endl;
1257 }
1258
1259
InnerRunCaseFlush(std::string inputFile,std::string outputFileFirst,std::string outputFileSecond,const std::string & name,Format & format)1260 void AudioEncoderDemo::InnerRunCaseFlush(std::string inputFile, std::string outputFileFirst,
1261 std::string outputFileSecond, const std::string& name, Format& format)
1262 {
1263 inputFilePath = inputFile;
1264 outputFilePath = outputFileFirst;
1265
1266 int32_t result;
1267 InnerCreateToStart(name, format);
1268
1269 while (isRunning_.load()) {
1270 sleep(1);
1271 }
1272 InnerStopAndClear();
1273
1274 // flush
1275 result = InnerFlush();
1276 cout << "InnerFlush ret is: " << result << endl;
1277 inputFilePath = inputFile;
1278 outputFilePath = outputFileSecond;
1279
1280 // Start
1281 isRunning_.store(true);
1282 inputLoop_ = make_unique<thread>(&AudioEncoderDemo::InnerInputFunc, this);
1283 outputLoop_ = make_unique<thread>(&AudioEncoderDemo::InnerOutputFunc, this);
1284 result = InnerStart();
1285 cout << "Start ret is: " << result << endl;
1286
1287 while (isRunning_.load()) {
1288 sleep(1);
1289 }
1290 // Stop
1291 InnerStopAndClear();
1292
1293 result = InnerDestroy();
1294 cout << "Destroy ret is: " << result << endl;
1295 }
1296
InnerRunCaseReset(std::string inputFile,std::string outputFileFirst,std::string outputFileSecond,const std::string & name,Format & format)1297 void AudioEncoderDemo::InnerRunCaseReset(std::string inputFile, std::string outputFileFirst,
1298 std::string outputFileSecond, const std::string& name, Format& format)
1299 {
1300 inputFilePath = inputFile;
1301 outputFilePath = outputFileFirst;
1302
1303 int32_t result;
1304 InnerCreateToStart(name, format);
1305
1306 while (isRunning_.load()) {
1307 sleep(1);
1308 }
1309 // Stop
1310 InnerStopAndClear();
1311
1312 // reset
1313 result = InnerReset();
1314 cout << "InnerReset ret is: " << result << endl;
1315
1316 inputFilePath = inputFile;
1317 outputFilePath = outputFileSecond;
1318
1319 result = InnerConfigure(format);
1320 cout << "Configure ret is: " << result << endl;
1321 if (result != 0) {
1322 cout << "Configure fail!!" << endl;
1323 return;
1324 }
1325 result = InnerPrepare();
1326 cout << "Configure ret is: " << result << endl;
1327
1328 // Start
1329 isRunning_.store(true);
1330 inputLoop_ = make_unique<thread>(&AudioEncoderDemo::InnerInputFunc, this);
1331 outputLoop_ = make_unique<thread>(&AudioEncoderDemo::InnerOutputFunc, this);
1332 result = InnerStart();
1333 cout << "Start ret is: " << result << endl;
1334 while (isRunning_.load()) {
1335 sleep(1);
1336 }
1337
1338 InnerStopAndClear();
1339
1340 result = InnerDestroy();
1341 cout << "Destroy ret is: " << result << endl;
1342 }
1343
getSignal()1344 std::shared_ptr<AEncSignal> AudioEncoderDemo::getSignal()
1345 {
1346 return innersignal_;
1347 }
1348
1349
InnerAEnDemoCallback(shared_ptr<AEncSignal> signal)1350 InnerAEnDemoCallback::InnerAEnDemoCallback(shared_ptr<AEncSignal> signal) : innersignal_(signal) {}
1351
OnError(AVCodecErrorType errorType,int32_t errorCode)1352 void InnerAEnDemoCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
1353 {
1354 cout << "Error received, errorType:" << errorType << " errorCode:" << errorCode << endl;
1355 }
1356
OnOutputFormatChanged(const Format & format)1357 void InnerAEnDemoCallback::OnOutputFormatChanged(const Format& format)
1358 {
1359 (void)format;
1360 cout << "OnOutputFormatChanged received" << endl;
1361 }
1362
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVSharedMemory> buffer)1363 void InnerAEnDemoCallback::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVSharedMemory> buffer)
1364 {
1365 cout << "OnInputBufferAvailable received, index:" << index << endl;
1366 if (innersignal_ == nullptr) {
1367 std::cout << "buffer is null 1" << endl;
1368 }
1369 unique_lock<mutex> lock(innersignal_->inMutex_);
1370 innersignal_->inQueue_.push(index);
1371 innersignal_->inInnerBufQueue_.push(buffer);
1372 innersignal_->inCond_.notify_all();
1373 }
1374
OnOutputBufferAvailable(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag,std::shared_ptr<AVSharedMemory> buffer)1375 void InnerAEnDemoCallback::OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info,
1376 AVCodecBufferFlag flag, std::shared_ptr<AVSharedMemory> buffer)
1377 {
1378 (void)info;
1379 (void)flag;
1380 cout << "OnOutputBufferAvailable received, index:" << index << endl;
1381 unique_lock<mutex> lock(innersignal_->outMutex_);
1382 innersignal_->outQueue_.push(index);
1383 innersignal_->infoQueue_.push(info);
1384 innersignal_->flagQueue_.push(flag);
1385 innersignal_->outInnerBufQueue_.push(buffer);
1386 cout << "**********out info size = " << info.size << endl;
1387 innersignal_->outCond_.notify_all();
1388 }
1389
InnerGetInputIndex()1390 uint32_t AudioEncoderDemo::InnerGetInputIndex()
1391 {
1392 while (inIndexQueue_.empty()) sleep(1);
1393 uint32_t inputIndex = inIndexQueue_.front();
1394 inIndexQueue_.pop();
1395 return inputIndex;
1396 }
1397
InnerGetOutputIndex()1398 uint32_t AudioEncoderDemo::InnerGetOutputIndex()
1399 {
1400 if (outIndexQueue_.empty()) {
1401 return ERROR_INDEX;
1402 }
1403 uint32_t outputIndex = outIndexQueue_.front();
1404 outIndexQueue_.pop();
1405 return outputIndex;
1406 }
1407
InnerUpdateInputData()1408 void AudioEncoderDemo::InnerUpdateInputData()
1409 {
1410 while (isRunning_.load()) {
1411 unique_lock<mutex> lock(innersignal_->inMutex_);
1412 innersignal_->inCond_.wait(lock,
1413 [this]() { return (innersignal_->inQueue_.size() > 0 || !isRunning_.load()); });
1414
1415 if (!isRunning_.load()) {
1416 cout << "input wait to stop, exit" << endl;
1417 break;
1418 }
1419
1420 uint32_t inputIndex = innersignal_->inQueue_.front();
1421 inIndexQueue_.push(inputIndex);
1422 innersignal_->inQueue_.pop();
1423 cout << "input index is " << inputIndex << endl;
1424 }
1425 }
1426
InnerUpdateOutputData()1427 void AudioEncoderDemo::InnerUpdateOutputData()
1428 {
1429 while (isRunning_.load()) {
1430 unique_lock<mutex> lock(innersignal_->outMutex_);
1431 innersignal_->outCond_.wait(lock,
1432 [this]() { return (innersignal_->outQueue_.size() > 0 || !isRunning_.load()); });
1433
1434 if (!isRunning_.load()) {
1435 cout << "output wait to stop, exit" << endl;
1436 break;
1437 }
1438
1439 uint32_t outputIndex = innersignal_->outQueue_.front();
1440 outIndexQueue_.push(outputIndex);
1441 innersignal_->outQueue_.pop();
1442 innersignal_->infoQueue_.pop();
1443 innersignal_->flagQueue_.pop();
1444 cout << "output index is " << outputIndex << endl;
1445 }
1446 }
1447