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