• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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