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