• 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 "gtest/gtest.h"
17 #include "audio_info.h"
18 #include "av_common.h"
19 #include "native_avcodec_base.h"
20 #include "avcodec_video_encoder.h"
21 #include "avcodec_video_decoder.h"
22 #include "native_avmemory.h"
23 #include "VDecEncNdkSample.h"
24 
25 using namespace OHOS;
26 using namespace OHOS::Media;
27 using namespace std;
28 
29 namespace {
30     constexpr uint32_t SAMPLE_DURATION_US = 23000;
31     constexpr uint32_t ES[] = {
32         2106, 11465, 321, 72, 472, 68, 76, 79, 509, 90, 677, 88, 956, 99, 347, 77, 452, 681, 81, 1263, 94, 106, 97,
33         998, 97, 797, 93, 1343, 150, 116, 117, 926, 1198, 128, 110, 78, 1582, 158, 135, 112, 1588, 165, 132,
34         128, 1697, 168, 149, 117, 1938, 170, 141, 142, 1830, 106, 161, 122, 1623, 160, 154, 156, 1998, 230,
35         177, 139, 1650, 186, 128, 134, 1214, 122, 1411, 120, 1184, 128, 1591, 195, 145, 105, 1587, 169, 140,
36         118, 1952, 177, 150, 161, 1437, 159, 123, 1758, 180, 165, 144, 1936, 214, 191, 175, 2122, 180, 179,
37         160, 1927, 161, 184, 119, 1973, 218, 210, 129, 1962, 196, 127, 154, 2308, 173, 127, 1572, 142, 122};
38     constexpr uint32_t ES_LENGTH = sizeof(ES) / sizeof(uint32_t);
39     constexpr int32_t STOPNUM = 10000;
40 
VdecAsyncError(OH_AVCodec * codec,int32_t errorCode,void * userData)41     void VdecAsyncError(OH_AVCodec *codec, int32_t errorCode, void *userData)
42     {
43         cout << "DEC Error errorCode=" << errorCode << endl;
44         VDecEncSignal* vcodecSignal_ = static_cast<VDecEncSignal *>(userData);
45         vcodecSignal_->errorNum_ += 1;
46     }
47 
VdecAsyncStreamChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)48     void VdecAsyncStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
49     {
50         cout << "DEC Format Changed" << endl;
51     }
VdecAsyncNeedInputData(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,void * userData)52     void VdecAsyncNeedInputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
53     {
54         VDecEncSignal* vcodecSignal_ = static_cast<VDecEncSignal *>(userData);
55         unique_lock<mutex> lock(vcodecSignal_->inMutexDec_);
56         if (vcodecSignal_->isVdecFlushing_.load()) {
57             cout << "VdecAsyncNeedInputData isVdecFlushing_ is true, return" << endl;
58             return;
59         }
60         vcodecSignal_->inQueueDec_.push(index);
61         vcodecSignal_->inBufferQueueDec_.push(data);
62         vcodecSignal_->inCondDec_.notify_all();
63     }
64 
VdecAsyncNewOutputData(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,OH_AVCodecBufferAttr * attr,void * userData)65     void VdecAsyncNewOutputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data,
66                                 OH_AVCodecBufferAttr *attr, void *userData)
67     {
68         VDecEncSignal* vcodecSignal_ = static_cast<VDecEncSignal *>(userData);
69         unique_lock<mutex> lock(vcodecSignal_->outMutexDec_);
70         if (vcodecSignal_->isVdecFlushing_.load()) {
71             cout << "VdecAsyncNeedInputData isVdecFlushing_ is true, return" << endl;
72             return;
73         }
74         vcodecSignal_->outQueueDec_.push(index);
75         vcodecSignal_->flagQueueDec_.push(attr->flags);
76         vcodecSignal_->outCondDec_.notify_all();
77     }
78 
79 
VencAsyncError(OH_AVCodec * codec,int32_t errorCode,void * userData)80     void VencAsyncError(OH_AVCodec *codec, int32_t errorCode, void *userData)
81     {
82         cout << "ENC Error errorCode=" << errorCode << endl;
83         VDecEncSignal* vcodecSignal_ = static_cast<VDecEncSignal *>(userData);
84         vcodecSignal_->errorNum_ += 1;
85     }
86 
VencAsyncStreamChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)87     void VencAsyncStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
88     {
89         cout << "ENC Format Changed" << endl;
90     }
91 
VencAsyncNewOutputData(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,OH_AVCodecBufferAttr * attr,void * userData)92     void VencAsyncNewOutputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data,
93                                 OH_AVCodecBufferAttr *attr, void *userData)
94     {
95         VDecEncSignal* vcodecSignal_ = static_cast<VDecEncSignal *>(userData);
96         unique_lock<mutex> lock(vcodecSignal_->outMutexEnc_);
97         if (vcodecSignal_->isVencFlushing_.load()) {
98             cout << "VdecAsyncNeedInputData isVencFlushing_ is true, return" << endl;
99             return;
100         }
101         vcodecSignal_->outQueueEnc_.push(index);
102         vcodecSignal_->sizeQueueEnc_.push(attr->size);
103         vcodecSignal_->flagQueueEnc_.push(attr->flags);
104         vcodecSignal_->outBufferQueueEnc_.push(data);
105         vcodecSignal_->outCondEnc_.notify_all();
106     }
107 
clearIntqueue(std::queue<uint32_t> & q)108     void clearIntqueue (std::queue<uint32_t>& q)
109     {
110         std::queue<uint32_t> empty;
111         swap(empty, q);
112     }
113 
clearBufferqueue(std::queue<OH_AVMemory * > & q)114     void clearBufferqueue (std::queue<OH_AVMemory *>& q)
115     {
116         std::queue<OH_AVMemory *> empty;
117         swap(empty, q);
118     }
119 }
120 
~VDecEncNdkSample()121 VDecEncNdkSample::~VDecEncNdkSample()
122 {
123     OH_VideoDecoder_Destroy(vdec_);
124     OH_VideoEncoder_Destroy(venc_);
125 
126     delete vcodecSignal_;
127     vcodecSignal_ = nullptr;
128 }
129 
SetReadPath(std::string filepath)130 void VDecEncNdkSample::SetReadPath(std::string filepath)
131 {
132     inFile_ = filepath;
133     if (testFile_ == nullptr) {
134         testFile_ = std::make_unique<std::ifstream>();
135     }
136     testFile_->open(inFile_, std::ios::in | std::ios::binary);
137 }
138 
SetSavePath(std::string filepath)139 void VDecEncNdkSample::SetSavePath(std::string filepath)
140 {
141     outFile_ = filepath;
142 }
143 
SetEosState(bool needSetEos)144 void VDecEncNdkSample::SetEosState(bool needSetEos)
145 {
146     setEos = needSetEos;
147 }
148 
ReRead()149 void VDecEncNdkSample::ReRead()
150 {
151     if (testFile_ != nullptr) {
152         testFile_->close();
153         cout << "ReRead close before file success " << endl;
154     }
155     cout << "ReRead inFile is " << inFile_ << endl;
156     testFile_->open(inFile_, std::ios::in | std::ios::binary);
157     if (testFile_ != nullptr) {
158         cout << "testFile open success" << endl;
159     }
160     decInCnt_ = 0;
161     isFirstDecFrame_ = true;
162     timeStampDec_ = 0;
163 }
164 
ResetDecParam()165 void VDecEncNdkSample::ResetDecParam()
166 {
167     decInCnt_ = 0;
168     decOutCnt_ = 0;
169     isDecInputEOS = false;
170     isDecOutputEOS = false;
171     unique_lock<mutex> lockIn(vcodecSignal_->inMutexDec_);
172     clearIntqueue(vcodecSignal_->inQueueDec_);
173     clearBufferqueue(vcodecSignal_->inBufferQueueDec_);
174     vcodecSignal_->inCondDec_.notify_all();
175     unique_lock<mutex> lockOut(vcodecSignal_->outMutexDec_);
176     clearIntqueue(vcodecSignal_->outQueueDec_);
177     clearIntqueue(vcodecSignal_->flagQueueDec_);
178     clearBufferqueue(vcodecSignal_->outBufferQueueDec_);
179     vcodecSignal_->outCondDec_.notify_all();
180     isDecRunning_.store(true);
181     cout << "isDecRunning_.load() is " << isDecRunning_.load() << endl;
182 }
ResetEncParam()183 void VDecEncNdkSample::ResetEncParam()
184 {
185     encOutCnt_ = 0;
186     isEncInputEOS = false;
187     isEncOutputEOS = false;
188     unique_lock<mutex> lockOut(vcodecSignal_->outMutexEnc_);
189     clearIntqueue(vcodecSignal_->outQueueEnc_);
190     clearIntqueue(vcodecSignal_->sizeQueueEnc_);
191     clearIntqueue(vcodecSignal_->flagQueueEnc_);
192     clearBufferqueue(vcodecSignal_->outBufferQueueEnc_);
193     vcodecSignal_->outCondEnc_.notify_all();
194     isEncRunning_.store(true);
195     cout << "isEncRunning_.load() is " << isEncRunning_.load() << endl;
196 }
197 
CreateVideoDecoderByMime(std::string mimetype)198 struct OH_AVCodec* VDecEncNdkSample::CreateVideoDecoderByMime(std::string mimetype)
199 {
200     if (mimetype == "video/avc") {
201         cout << "mimetype == 'video/avc'" << endl;
202         vdec_ = OH_VideoDecoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
203     } else {
204         vdec_ = OH_VideoDecoder_CreateByMime(mimetype.c_str());
205     }
206     NDK_CHECK_AND_RETURN_RET_LOG(vdec_ != nullptr, nullptr, "Fatal: OH_VideoDecoder_CreateByMime");
207     if (vcodecSignal_ == nullptr) {
208         vcodecSignal_ = new VDecEncSignal();
209         NDK_CHECK_AND_RETURN_RET_LOG(vcodecSignal_ != nullptr, nullptr, "Fatal: No Memory");
210     }
211     cbDec_.onError = VdecAsyncError;
212     cbDec_.onStreamChanged = VdecAsyncStreamChanged;
213     cbDec_.onNeedInputData = VdecAsyncNeedInputData;
214     cbDec_.onNeedOutputData = VdecAsyncNewOutputData;
215     int32_t ret = OH_VideoDecoder_SetCallback(vdec_, cbDec_, static_cast<void *>(vcodecSignal_));
216     NDK_CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, NULL, "Fatal: OH_VideoDecoder_SetCallback");
217     return vdec_;
218 }
219 
CreateVideoDecoderByName(std::string name)220 struct OH_AVCodec* VDecEncNdkSample::CreateVideoDecoderByName(std::string name)
221 {
222     vdec_ = OH_VideoDecoder_CreateByName(name.c_str());
223     NDK_CHECK_AND_RETURN_RET_LOG(vdec_ != nullptr, nullptr, "Fatal: OH_VideoDecoder_CreateByName");
224     if (vcodecSignal_ == nullptr) {
225         vcodecSignal_ = new VDecEncSignal();
226         NDK_CHECK_AND_RETURN_RET_LOG(vcodecSignal_ != nullptr, nullptr, "Fatal: No Memory");
227     }
228     cbDec_.onError = VdecAsyncError;
229     cbDec_.onStreamChanged = VdecAsyncStreamChanged;
230     cbDec_.onNeedInputData = VdecAsyncNeedInputData;
231     cbDec_.onNeedOutputData = VdecAsyncNewOutputData;
232     int32_t ret = OH_VideoDecoder_SetCallback(vdec_, cbDec_, static_cast<void *>(vcodecSignal_));
233     NDK_CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, NULL, "Fatal: OH_VideoDecoder_SetCallback");
234     return vdec_;
235 }
236 
ConfigureDec(struct OH_AVFormat * format)237 int32_t VDecEncNdkSample::ConfigureDec(struct OH_AVFormat *format)
238 {
239     return OH_VideoDecoder_Configure(vdec_, format);
240 }
241 
SetParameterDec(struct OH_AVFormat * format)242 int32_t VDecEncNdkSample::SetParameterDec(struct OH_AVFormat *format)
243 {
244     return OH_VideoDecoder_SetParameter(vdec_, format);
245 }
246 
PrepareDec()247 int32_t VDecEncNdkSample::PrepareDec()
248 {
249     return OH_VideoDecoder_Prepare(vdec_);
250 }
251 
StartDec()252 int32_t VDecEncNdkSample::StartDec()
253 {
254     cout << "Enter dec start" << endl;
255     isDecRunning_.store(true);
256 
257     if (inputLoopDec_ == nullptr) {
258         inputLoopDec_ = make_unique<thread>(&VDecEncNdkSample::InputFuncDec, this);
259         NDK_CHECK_AND_RETURN_RET_LOG(inputLoopDec_ != nullptr, AV_ERR_UNKNOWN, "Fatal: No memory");
260     }
261     if (outputLoopDec_ == nullptr) {
262         outputLoopDec_ = make_unique<thread>(&VDecEncNdkSample::OutputFuncDec, this);
263         NDK_CHECK_AND_RETURN_RET_LOG(outputLoopDec_ != nullptr, AV_ERR_UNKNOWN, "Fatal: No memory");
264     }
265     cout << "Exit dec start" << endl;
266     return OH_VideoDecoder_Start(vdec_);
267 }
268 
StopDec()269 int32_t VDecEncNdkSample::StopDec()
270 {
271     cout << "ENTER DEC stop" << endl;
272     unique_lock<mutex> lock(vcodecSignal_->inMutexDec_);
273     unique_lock<mutex> lock2(vcodecSignal_->outMutexDec_);
274     vcodecSignal_->isVdecFlushing_.store(true);
275     lock.unlock();
276     lock2.unlock();
277     int32_t ret =  OH_VideoDecoder_Stop(vdec_);
278     unique_lock<mutex> lockIn(vcodecSignal_->inMutexDec_);
279     clearIntqueue(vcodecSignal_->inQueueDec_);
280     clearBufferqueue(vcodecSignal_->inBufferQueueDec_);
281     vcodecSignal_->inCondDec_.notify_all();
282     lockIn.unlock();
283     unique_lock<mutex> lockOut(vcodecSignal_->outMutexDec_);
284     clearIntqueue(vcodecSignal_->outQueueDec_);
285     clearIntqueue(vcodecSignal_->flagQueueDec_);
286     clearBufferqueue(vcodecSignal_->outBufferQueueDec_);
287     vcodecSignal_->outCondDec_.notify_all();
288     lockOut.unlock();
289     vcodecSignal_->isVdecFlushing_.store(false);
290     cout << "EXIT DEC stop" << endl;
291     return ret;
292 }
293 
FlushDec()294 int32_t VDecEncNdkSample::FlushDec()
295 {
296     cout << "ENTER DEC FLUSH" << endl;
297     unique_lock<mutex> lock(vcodecSignal_->inMutexDec_);
298     unique_lock<mutex> lock2(vcodecSignal_->outMutexDec_);
299     vcodecSignal_->isVdecFlushing_.store(true);
300     lock.unlock();
301     lock2.unlock();
302     int32_t ret =  OH_VideoDecoder_Flush(vdec_);
303     unique_lock<mutex> lockIn(vcodecSignal_->inMutexDec_);
304     clearIntqueue(vcodecSignal_->inQueueDec_);
305     clearBufferqueue(vcodecSignal_->inBufferQueueDec_);
306     vcodecSignal_->inCondDec_.notify_all();
307     lockIn.unlock();
308     unique_lock<mutex> lockOut(vcodecSignal_->outMutexDec_);
309     clearIntqueue(vcodecSignal_->outQueueDec_);
310     clearIntqueue(vcodecSignal_->flagQueueDec_);
311     clearBufferqueue(vcodecSignal_->outBufferQueueDec_);
312     vcodecSignal_->outCondDec_.notify_all();
313     lockOut.unlock();
314     vcodecSignal_->isVdecFlushing_.store(false);
315     cout << "EXIT DEC FLUSH" << endl;
316     return ret;
317 }
318 
ResetDec()319 int32_t VDecEncNdkSample::ResetDec()
320 {
321     cout << "Enter DEC reset" << endl;
322     unique_lock<mutex> lock(vcodecSignal_->inMutexDec_);
323     unique_lock<mutex> lock2(vcodecSignal_->outMutexDec_);
324     vcodecSignal_->isVdecFlushing_.store(true);
325     lock.unlock();
326     lock2.unlock();
327     int32_t ret =  OH_VideoDecoder_Reset(vdec_);
328     unique_lock<mutex> lockIn(vcodecSignal_->inMutexDec_);
329     clearIntqueue(vcodecSignal_->inQueueDec_);
330     clearBufferqueue(vcodecSignal_->inBufferQueueDec_);
331     vcodecSignal_->inCondDec_.notify_all();
332     lockIn.unlock();
333     unique_lock<mutex> lockOut(vcodecSignal_->outMutexDec_);
334     clearIntqueue(vcodecSignal_->outQueueDec_);
335     clearIntqueue(vcodecSignal_->flagQueueDec_);
336     clearBufferqueue(vcodecSignal_->outBufferQueueDec_);
337     vcodecSignal_->outCondDec_.notify_all();
338     lockOut.unlock();
339     vcodecSignal_->isVdecFlushing_.store(false);
340     cout << "Exit DEC reset" << endl;
341     return ret;
342 }
343 
ReleaseDec()344 int32_t VDecEncNdkSample::ReleaseDec()
345 {
346     cout << "Enter DEC release" << endl;
347     isDecRunning_.store(false);
348     if (inputLoopDec_ != nullptr && inputLoopDec_->joinable()) {
349         unique_lock<mutex> lock(vcodecSignal_->inMutexDec_);
350         vcodecSignal_->inQueueDec_.push(STOPNUM);
351         vcodecSignal_->inCondDec_.notify_all();
352         lock.unlock();
353         inputLoopDec_->join();
354         inputLoopDec_.reset();
355     }
356     if (outputLoopDec_ != nullptr && outputLoopDec_->joinable()) {
357         unique_lock<mutex> lock(vcodecSignal_->outMutexDec_);
358         vcodecSignal_->outQueueDec_.push(STOPNUM);
359         vcodecSignal_->outCondDec_.notify_all();
360         lock.unlock();
361         outputLoopDec_->join();
362         outputLoopDec_.reset();
363     }
364     OH_VideoDecoder_Destroy(vdec_);
365     cout << "Exit DEC release" << endl;
366     return AV_ERR_OK;
367 }
368 
PopInqueueDec()369 void VDecEncNdkSample::PopInqueueDec()
370 {
371     if (vcodecSignal_ == nullptr) {
372         return;
373     }
374     vcodecSignal_->inQueueDec_.pop();
375     vcodecSignal_->inBufferQueueDec_.pop();
376 }
377 
PushInbufferDec(uint32_t index,uint32_t bufferSize)378 int32_t VDecEncNdkSample::PushInbufferDec(uint32_t index, uint32_t bufferSize)
379 {
380     if (vdec_ == nullptr) {
381         return AV_ERR_INVALID_VAL;
382     }
383     struct OH_AVCodecBufferAttr attr;
384     attr.offset = 0;
385     if (decInCnt_ == ES_LENGTH) {
386         attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
387         attr.pts = 0;
388         attr.size = 0;
389         cout << "EOS Frame, frameCount = " << decInCnt_ << endl;
390         isDecInputEOS = true;
391     } else {
392         attr.pts = timeStampDec_;
393         attr.size = bufferSize;
394         if (isFirstDecFrame_) {
395             attr.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
396             isFirstDecFrame_ = false;
397         } else {
398             attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
399         }
400     }
401     return OH_VideoDecoder_PushInputData(vdec_, index, attr);
402 }
403 
InputFuncDec()404 void VDecEncNdkSample::InputFuncDec()
405 {
406     while (true) {
407         cout << "ENTER DEC IN" << endl;
408         if (!isDecRunning_.load()) {
409             break;
410         }
411         unique_lock<mutex> lock(vcodecSignal_->inMutexDec_);
412         vcodecSignal_->inCondDec_.wait(lock, [this]() { return vcodecSignal_->inQueueDec_.size() > 0; });
413         if (!isDecRunning_.load()) {
414             break;
415         }
416 
417         uint32_t index = vcodecSignal_->inQueueDec_.front();
418         OH_AVMemory *buffer = reinterpret_cast<OH_AVMemory *>(vcodecSignal_->inBufferQueueDec_.front());
419         if (vcodecSignal_->isVdecFlushing_.load() || isDecInputEOS || buffer == nullptr) {
420             PopInqueueDec();
421             continue;
422         }
423         NDK_CHECK_AND_RETURN_LOG(testFile_ != nullptr && testFile_->is_open(), "Fatal: open file fail");
424         uint32_t bufferSize = 0;
425         if (decInCnt_ < ES_LENGTH) {
426             bufferSize = ES[decInCnt_];
427             char *fileBuffer = (char *)malloc(sizeof(char) * bufferSize + 1);
428             NDK_CHECK_AND_RETURN_LOG(fileBuffer != nullptr, "Fatal: malloc fail");
429             (void)testFile_->read(fileBuffer, bufferSize);
430             if (testFile_->eof()) {
431                 free(fileBuffer);
432                 cout << "Finish" << endl;
433                 break;
434             }
435             if (memcpy_s(OH_AVMemory_GetAddr(buffer), OH_AVMemory_GetSize(buffer), fileBuffer, bufferSize) != EOK
436                 || buffer == nullptr) {
437                 free(fileBuffer);
438                 PopInqueueDec();
439                 continue;
440             }
441             free(fileBuffer);
442         }
443         if (PushInbufferDec(index, bufferSize) != AV_ERR_OK) {
444             cout << "Fatal: OH_VideoDecoder_PushInputData fail, exit" << endl;
445             vcodecSignal_->errorNum_ += 1;
446         } else {
447             decInCnt_++;
448         }
449         timeStampDec_ += SAMPLE_DURATION_US;
450         PopInqueueDec();
451     }
452 }
453 
PopOutqueueDec()454 void VDecEncNdkSample::PopOutqueueDec()
455 {
456     if (vcodecSignal_ == nullptr) {
457         return;
458     }
459     vcodecSignal_->outQueueDec_.pop();
460     vcodecSignal_->flagQueueDec_.pop();
461 }
462 
SendEncEos()463 void VDecEncNdkSample::SendEncEos()
464 {
465     if (vcodecSignal_ == nullptr || venc_== nullptr) {
466         return;
467     }
468     if (setEos) {
469         int32_t ret = OH_VideoEncoder_NotifyEndOfStream(venc_);
470         if (ret == 0) {
471             cout << "ENC IN: input EOS " << endl;
472             isEncInputEOS = true;
473         } else {
474             cout << "ENC IN: input EOS fail" << endl;
475             vcodecSignal_->errorNum_ += 1;
476         }
477     }
478 }
479 
OutputFuncDec()480 void VDecEncNdkSample::OutputFuncDec()
481 {
482     while (true) {
483         if (!isDecRunning_.load()) {
484             break;
485         }
486         unique_lock<mutex> lock(vcodecSignal_->outMutexDec_);
487         vcodecSignal_->outCondDec_.wait(lock, [this]() { return vcodecSignal_->outQueueDec_.size() > 0; });
488         if (!isDecRunning_.load()) {
489             break;
490         }
491         if (vcodecSignal_->isVdecFlushing_.load() || vcodecSignal_->isVencFlushing_.load() || isEncInputEOS) {
492             PopOutqueueDec();
493             continue;
494         }
495 
496         uint32_t index = vcodecSignal_->outQueueDec_.front();
497         uint32_t outflag = vcodecSignal_->flagQueueDec_.front();
498         if (outflag == 0) {
499             uint32_t ret;
500             if (needRender) {
501                 ret = OH_VideoDecoder_RenderOutputData(vdec_, index);
502             } else {
503                 ret = OH_VideoDecoder_FreeOutputData(vdec_, index);
504             }
505             if (ret == 0) {
506                 decOutCnt_ += 1;
507                 cout << "DEC OUT.: render output success, decOutCnt_ is " << decOutCnt_ << endl;
508             } else {
509                 cout << "DEC OUT. Fatal: ReleaseOutputBuffer fail" << endl;
510                 vcodecSignal_->errorNum_ += 1;
511                 break;
512             }
513         } else {
514             cout << "DEC OUT.: output EOS" << endl;
515             isDecOutputEOS = true;
516             SendEncEos();
517         }
518         PopOutqueueDec();
519     }
520 }
521 
CreateVideoEncoderByMime(std::string mimetype)522 struct OH_AVCodec* VDecEncNdkSample::CreateVideoEncoderByMime(std::string mimetype)
523 {
524     if (mimetype == "video/avc") {
525         venc_ = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
526     } else {
527         venc_ = OH_VideoEncoder_CreateByMime(mimetype.c_str());
528     }
529     NDK_CHECK_AND_RETURN_RET_LOG(venc_ != nullptr, nullptr, "Fatal: OH_VideoEncoder_CreateByMime");
530 
531     if (vcodecSignal_ == nullptr) {
532         vcodecSignal_ = new VDecEncSignal();
533         NDK_CHECK_AND_RETURN_RET_LOG(vcodecSignal_ != nullptr, nullptr, "Fatal: No Memory");
534     }
535     cbEnc_.onError = VencAsyncError;
536     cbEnc_.onStreamChanged = VencAsyncStreamChanged;
537     cbEnc_.onNeedOutputData = VencAsyncNewOutputData;
538     int32_t ret = OH_VideoEncoder_SetCallback(venc_, cbEnc_, static_cast<void *>(vcodecSignal_));
539     NDK_CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, NULL, "Fatal: OH_VideoEncoder_SetCallback");
540     return venc_;
541 }
542 
CreateVideoEncoderByName(std::string name)543 struct OH_AVCodec* VDecEncNdkSample::CreateVideoEncoderByName(std::string name)
544 {
545     venc_ = OH_VideoEncoder_CreateByName(name.c_str());
546     NDK_CHECK_AND_RETURN_RET_LOG(venc_ != nullptr, nullptr, "Fatal: OH_VideoEncoder_CreateByName");
547 
548     if (vcodecSignal_ == nullptr) {
549         vcodecSignal_ = new VDecEncSignal();
550         NDK_CHECK_AND_RETURN_RET_LOG(vcodecSignal_ != nullptr, nullptr, "Fatal: No Memory");
551     }
552     cbEnc_.onError = VencAsyncError;
553     cbEnc_.onStreamChanged = VencAsyncStreamChanged;
554     cbEnc_.onNeedOutputData = VencAsyncNewOutputData;
555     int32_t ret = OH_VideoEncoder_SetCallback(venc_, cbEnc_, static_cast<void *>(vcodecSignal_));
556     NDK_CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, NULL, "Fatal: OH_VideoEncoder_SetCallback");
557     return venc_;
558 }
559 
ConfigureEnc(struct OH_AVFormat * format)560 int32_t VDecEncNdkSample::ConfigureEnc(struct OH_AVFormat *format)
561 {
562     return OH_VideoEncoder_Configure(venc_, format);
563 }
564 
SetParameterEnc(struct OH_AVFormat * format)565 int32_t VDecEncNdkSample::SetParameterEnc(struct OH_AVFormat *format)
566 {
567     return OH_VideoEncoder_SetParameter(venc_, format);
568 }
569 
570 
GetSurface()571 int32_t VDecEncNdkSample::GetSurface()
572 {
573     return OH_VideoEncoder_GetSurface(venc_, &nativeWindow_);
574 }
575 
SetOutputSurface()576 int32_t VDecEncNdkSample::SetOutputSurface()
577 {
578     return OH_VideoDecoder_SetSurface(vdec_, nativeWindow_);
579 }
580 
PrepareEnc()581 int32_t VDecEncNdkSample::PrepareEnc()
582 {
583     return OH_VideoEncoder_Prepare(venc_);
584 }
585 
StartEnc()586 int32_t VDecEncNdkSample::StartEnc()
587 {
588     cout << "Enter enc start" << endl;
589     isEncRunning_.store(true);
590     if (outputLoopEnc_ == nullptr) {
591         outputLoopEnc_ = make_unique<thread>(&VDecEncNdkSample::OutputFuncEnc, this);
592         NDK_CHECK_AND_RETURN_RET_LOG(outputLoopEnc_ != nullptr, AV_ERR_UNKNOWN, "Fatal: No memory");
593     }
594     cout << "Exit enc start" << endl;
595     return OH_VideoEncoder_Start(venc_);
596 }
597 
StopEnc()598 int32_t VDecEncNdkSample::StopEnc()
599 {
600     cout << "Enter enc stop" << endl;
601     unique_lock<mutex> lock(vcodecSignal_->outMutexEnc_);
602     vcodecSignal_->isVencFlushing_.store(true);
603     lock.unlock();
604     int32_t ret =  OH_VideoEncoder_Stop(venc_);
605     unique_lock<mutex> lockOut(vcodecSignal_->outMutexEnc_);
606     clearIntqueue(vcodecSignal_->outQueueEnc_);
607     clearIntqueue(vcodecSignal_->sizeQueueEnc_);
608     clearIntqueue(vcodecSignal_->flagQueueEnc_);
609     clearBufferqueue(vcodecSignal_->outBufferQueueEnc_);
610     vcodecSignal_->outCondEnc_.notify_all();
611     lockOut.unlock();
612     vcodecSignal_->isVencFlushing_.store(false);
613     cout << "Exit enc stop" << endl;
614     return ret;
615 }
616 
FlushEnc()617 int32_t VDecEncNdkSample::FlushEnc()
618 {
619     cout << "Enter enc flush" << endl;
620     unique_lock<mutex> lock(vcodecSignal_->outMutexEnc_);
621     vcodecSignal_->isVencFlushing_.store(true);
622     lock.unlock();
623     int32_t ret =  OH_VideoEncoder_Flush(venc_);
624     unique_lock<mutex> lockOut(vcodecSignal_->outMutexEnc_);
625     clearIntqueue(vcodecSignal_->outQueueEnc_);
626     clearIntqueue(vcodecSignal_->sizeQueueEnc_);
627     clearIntqueue(vcodecSignal_->flagQueueEnc_);
628     clearBufferqueue(vcodecSignal_->outBufferQueueEnc_);
629     vcodecSignal_->outCondEnc_.notify_all();
630     lockOut.unlock();
631     vcodecSignal_->isVencFlushing_.store(false);
632     cout << "Exit enc flush" << endl;
633     return ret;
634 }
635 
ResetEnc()636 int32_t VDecEncNdkSample::ResetEnc()
637 {
638     cout << "Enter enc reset" << endl;
639     unique_lock<mutex> lock(vcodecSignal_->outMutexEnc_);
640     vcodecSignal_->isVencFlushing_.store(true);
641     lock.unlock();
642     int32_t ret =  OH_VideoEncoder_Reset(venc_);
643     unique_lock<mutex> lockOut(vcodecSignal_->outMutexEnc_);
644     clearIntqueue(vcodecSignal_->outQueueEnc_);
645     clearIntqueue(vcodecSignal_->sizeQueueEnc_);
646     clearIntqueue(vcodecSignal_->flagQueueEnc_);
647     clearBufferqueue(vcodecSignal_->outBufferQueueEnc_);
648     vcodecSignal_->outCondEnc_.notify_all();
649     lockOut.unlock();
650     vcodecSignal_->isVencFlushing_.store(false);
651     cout << "exit enc reset" << endl;
652     return ret;
653 }
654 
ReleaseEnc()655 int32_t VDecEncNdkSample::ReleaseEnc()
656 {
657     cout << "Enter enc release" << endl;
658     isEncRunning_.store(false);
659     if (outputLoopEnc_ != nullptr && outputLoopEnc_->joinable()) {
660         unique_lock<mutex> lock(vcodecSignal_->outMutexEnc_);
661         vcodecSignal_->outQueueEnc_.push(STOPNUM);
662         vcodecSignal_->outCondEnc_.notify_all();
663         lock.unlock();
664         outputLoopEnc_->join();
665         outputLoopEnc_.reset();
666     }
667     cout << "exit enc release" << endl;
668     OH_VideoEncoder_Destroy(venc_);
669     cout << "exit enc destroy" << endl;
670     return AV_ERR_OK;
671 }
672 
PopOutqueueEnc()673 void VDecEncNdkSample::PopOutqueueEnc()
674 {
675     if (vcodecSignal_ == nullptr) {
676         return;
677     }
678     vcodecSignal_->outQueueEnc_.pop();
679     vcodecSignal_->sizeQueueEnc_.pop();
680     vcodecSignal_->flagQueueEnc_.pop();
681     vcodecSignal_->outBufferQueueEnc_.pop();
682 }
683 
WriteToFile()684 int32_t VDecEncNdkSample::WriteToFile()
685 {
686     auto buffer = vcodecSignal_->outBufferQueueEnc_.front();
687     uint32_t size = vcodecSignal_->sizeQueueEnc_.front();
688     if (buffer == nullptr) {
689         cout << "getOutPut Buffer fail" << endl;
690         return AV_ERR_INVALID_VAL;
691     }
692     FILE *outFile = fopen(outFile_.c_str(), "a");
693     if (outFile == nullptr) {
694         cout << "dump data fail" << endl;
695         return AV_ERR_INVALID_VAL;
696     } else {
697         fwrite(OH_AVMemory_GetAddr(buffer), 1, size, outFile);
698     }
699     return fclose(outFile);
700 }
701 
OutputFuncEnc()702 void VDecEncNdkSample::OutputFuncEnc()
703 {
704     while (true) {
705         if (!isEncRunning_.load()) {
706             break;
707         }
708         unique_lock<mutex> lock(vcodecSignal_->outMutexEnc_);
709         vcodecSignal_->outCondEnc_.wait(lock, [this]() { return vcodecSignal_->outQueueEnc_.size() > 0; });
710         if (!isEncRunning_.load()) {
711             break;
712         }
713         if (vcodecSignal_->isVencFlushing_.load() || isEncOutputEOS) {
714             PopOutqueueEnc();
715             continue;
716         }
717 
718         uint32_t index = vcodecSignal_->outQueueEnc_.front();
719         uint32_t encOutflag = vcodecSignal_->flagQueueEnc_.front();
720         if (encOutflag == 1) {
721             cout << "ENC get output EOS" << endl;
722             isEncOutputEOS = true;
723         } else {
724             if (WriteToFile() != 0) {
725                 PopOutqueueEnc();
726                 continue;
727             }
728             uint32_t ret = OH_VideoEncoder_FreeOutputData(venc_, index);
729             if (ret != 0) {
730                 cout << "Fatal: ReleaseOutputBuffer fail" << endl;
731                 vcodecSignal_->errorNum_ += 1;
732             } else {
733                 encOutCnt_ += 1;
734                 cout << "ENC OUT.: output success, encOutCnt_ is " << encOutCnt_ << endl;
735             }
736         }
737         PopOutqueueEnc();
738     }
739 }
740 
CalcuError()741 int32_t VDecEncNdkSample::CalcuError()
742 {
743     cout << "errorNum_ is :" << vcodecSignal_->errorNum_ << endl;
744     cout << "decInCnt_ is :" << decInCnt_ << endl;
745     cout << "decOutCnt_ is :" << decOutCnt_ << endl;
746     cout << "encOutCnt_ is :" << encOutCnt_ << endl;
747     cout << "DEC inQueueDec_.size() is " << vcodecSignal_->inQueueDec_.size() << endl;
748     cout << "DEC outQueueDec_.size() is " << vcodecSignal_->outQueueDec_.size() << endl;
749     cout << "DEC outBufferQueueDec_.size() is " << vcodecSignal_->outBufferQueueDec_.size() << endl;
750     cout << "DEC outQueueEnc_.size() is " << vcodecSignal_->outQueueEnc_.size() << endl;
751     return vcodecSignal_->errorNum_ ;
752 }
753 
GetFrameCount()754 int32_t VDecEncNdkSample::GetFrameCount()
755 {
756     return encOutCnt_;
757 }
GetEncEosState()758 bool VDecEncNdkSample::GetEncEosState()
759 {
760     return isEncOutputEOS;
761 }
GetDecEosState()762 bool VDecEncNdkSample::GetDecEosState()
763 {
764     return isDecOutputEOS;
765 }