• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 #include <arpa/inet.h>
16 #include <sys/time.h>
17 #include <utility>
18 #include "iconsumer_surface.h"
19 #include "openssl/crypto.h"
20 #include "openssl/sha.h"
21 #include "videodec_ndk_sample.h"
22 using namespace OHOS;
23 using namespace OHOS::Media;
24 using namespace std;
25 namespace {
26 const string MIME_TYPE = "video/avc";
27 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
28 constexpr int64_t NANOS_IN_MICRO = 1000L;
29 constexpr int32_t THREE = 3;
30 constexpr int32_t EIGHT = 8;
31 constexpr int32_t TEN = 10;
32 constexpr int32_t SIXTEEN = 16;
33 constexpr int32_t TWENTY_FOUR = 24;
34 constexpr uint32_t FRAME_INTERVAL = 1; // 16666
35 constexpr uint8_t H264_NALU_TYPE = 0x1f;
36 constexpr uint32_t START_CODE_SIZE = 4;
37 constexpr uint8_t START_CODE[START_CODE_SIZE] = {0, 0, 0, 1};
38 constexpr uint8_t SPS = 7;
39 constexpr uint8_t PPS = 8;
40 
41 SHA512_CTX c;
42 sptr<Surface> cs = nullptr;
43 sptr<Surface> ps = nullptr;
44 unsigned char md[SHA512_DIGEST_LENGTH];
45 VDecNdkSample *dec_sample = nullptr;
46 
clearIntqueue(std::queue<uint32_t> & q)47 void clearIntqueue(std::queue<uint32_t> &q)
48 {
49     std::queue<uint32_t> empty;
50     swap(empty, q);
51 }
52 
clearBufferqueue(std::queue<OH_AVCodecBufferAttr> & q)53 void clearBufferqueue(std::queue<OH_AVCodecBufferAttr> &q)
54 {
55     std::queue<OH_AVCodecBufferAttr> empty;
56     swap(empty, q);
57 }
58 } // namespace
59 
60 class TestConsumerListener : public IBufferConsumerListener {
61 public:
TestConsumerListener(sptr<Surface> cs,std::string_view name)62     TestConsumerListener(sptr<Surface> cs, std::string_view name) : cs(cs) {};
~TestConsumerListener()63     ~TestConsumerListener() {}
OnBufferAvailable()64     void OnBufferAvailable() override
65     {
66         sptr<SurfaceBuffer> buffer;
67         int32_t flushFence;
68         cs->AcquireBuffer(buffer, flushFence, timestamp, damage);
69 
70         cs->ReleaseBuffer(buffer, -1);
71     }
72 
73 private:
74     int64_t timestamp = 0;
75     Rect damage = {};
76     sptr<Surface> cs {nullptr};
77 };
~VDecNdkSample()78 VDecNdkSample::~VDecNdkSample()
79 {
80     Release();
81 }
82 
VdecError(OH_AVCodec * codec,int32_t errorCode,void * userData)83 void VdecError(OH_AVCodec *codec, int32_t errorCode, void *userData)
84 {
85     cout << "Error errorCode=" << errorCode << endl;
86     dec_sample->StopInloop();
87     dec_sample->StopOutloop();
88     dec_sample->ReleaseInFile();
89     dec_sample->Release();
90 }
91 
VdecFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)92 void VdecFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
93 {
94     cout << "Format Changed" << endl;
95     int32_t current_width = 0;
96     int32_t current_height = 0;
97     OH_AVFormat_GetIntValue(format, OH_MD_KEY_WIDTH, &current_width);
98     OH_AVFormat_GetIntValue(format, OH_MD_KEY_HEIGHT, &current_height);
99     dec_sample->DEFAULT_WIDTH = current_width;
100     dec_sample->DEFAULT_HEIGHT = current_height;
101 }
102 
VdecInputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,void * userData)103 void VdecInputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
104 {
105     VDecSignal *signal = static_cast<VDecSignal *>(userData);
106     unique_lock<mutex> lock(signal->inMutex_);
107     signal->inIdxQueue_.push(index);
108     signal->inBufferQueue_.push(data);
109     signal->inCond_.notify_all();
110 }
111 
VdecOutputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,OH_AVCodecBufferAttr * attr,void * userData)112 void VdecOutputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
113                          void *userData)
114 {
115     VDecSignal *signal = static_cast<VDecSignal *>(userData);
116     unique_lock<mutex> lock(signal->outMutex_);
117     signal->outIdxQueue_.push(index);
118     signal->attrQueue_.push(*attr);
119     signal->outBufferQueue_.push(data);
120     signal->outCond_.notify_all();
121 }
122 
Flush_buffer()123 void VDecNdkSample::Flush_buffer()
124 {
125     unique_lock<mutex> inLock(signal_->inMutex_);
126     clearIntqueue(signal_->inIdxQueue_);
127     std::queue<OH_AVMemory *> empty;
128     swap(empty, signal_->inBufferQueue_);
129     signal_->inCond_.notify_all();
130     inLock.unlock();
131     unique_lock<mutex> outLock(signal_->outMutex_);
132     clearIntqueue(signal_->outIdxQueue_);
133     clearBufferqueue(signal_->attrQueue_);
134     signal_->outCond_.notify_all();
135     outLock.unlock();
136 }
137 
MdCompare(unsigned char buffer[],int len,const char * source[])138 bool VDecNdkSample::MdCompare(unsigned char buffer[], int len, const char *source[])
139 {
140     bool result = true;
141     for (int i = 0; i < len; i++) {
142     }
143     return result;
144 }
145 
GetSystemTimeUs()146 int64_t VDecNdkSample::GetSystemTimeUs()
147 {
148     struct timespec now;
149     (void)clock_gettime(CLOCK_BOOTTIME, &now);
150     int64_t nanoTime = (int64_t)now.tv_sec * NANOS_IN_SECOND + now.tv_nsec;
151     return nanoTime / NANOS_IN_MICRO;
152 }
153 
ConfigureVideoDecoder()154 int32_t VDecNdkSample::ConfigureVideoDecoder()
155 {
156     OH_AVFormat *format = OH_AVFormat_Create();
157     if (format == nullptr) {
158         cout << "Fatal: Failed to create format" << endl;
159         return AV_ERR_UNKNOWN;
160     }
161     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
162     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
163     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_NV12);
164     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
165     int ret = OH_VideoDecoder_Configure(vdec_, format);
166     OH_AVFormat_Destroy(format);
167     return ret;
168 }
169 
RunVideoDec_Surface(string codeName)170 int32_t VDecNdkSample::RunVideoDec_Surface(string codeName)
171 {
172     SF_OUTPUT = true;
173     int err = AV_ERR_OK;
174     cs = Surface::CreateSurfaceAsConsumer();
175     sptr<IBufferConsumerListener> listener = new TestConsumerListener(cs, OUT_DIR);
176     cs->RegisterConsumerListener(listener);
177     auto p = cs->GetProducer();
178     ps = Surface::CreateSurfaceAsProducer(p);
179     OHNativeWindow *nativeWindow = CreateNativeWindowFromSurface(&ps);
180     if (!nativeWindow) {
181         cout << "Failed to create surface" << endl;
182         return AV_ERR_UNKNOWN;
183     }
184     err = CreateVideoDecoder(codeName);
185     if (err != AV_ERR_OK) {
186         cout << "Failed to create video decoder" << endl;
187         return err;
188     }
189     err = SetVideoDecoderCallback();
190     if (err != AV_ERR_OK) {
191         cout << "Failed to setCallback" << endl;
192         Release();
193         return err;
194     }
195     err = ConfigureVideoDecoder();
196     if (err != AV_ERR_OK) {
197         cout << "Failed to configure video decoder" << endl;
198         Release();
199         return err;
200     }
201     err = OH_VideoDecoder_SetSurface(vdec_, nativeWindow);
202     if (err != AV_ERR_OK) {
203         cout << "Failed to set surface" << endl;
204         return err;
205     }
206     err = StartVideoDecoder();
207     if (err != AV_ERR_OK) {
208         cout << "Failed to start video decoder" << endl;
209         Release();
210         return err;
211     }
212     return err;
213 }
214 
RunVideoDec(string codeName)215 int32_t VDecNdkSample::RunVideoDec(string codeName)
216 {
217     SF_OUTPUT = false;
218     int err = CreateVideoDecoder(codeName);
219     if (err != AV_ERR_OK) {
220         cout << "Failed to create video decoder" << endl;
221         return err;
222     }
223 
224     err = ConfigureVideoDecoder();
225     if (err != AV_ERR_OK) {
226         cout << "Failed to configure video decoder" << endl;
227         Release();
228         return err;
229     }
230 
231     err = SetVideoDecoderCallback();
232     if (err != AV_ERR_OK) {
233         cout << "Failed to setCallback" << endl;
234         Release();
235         return err;
236     }
237 
238     err = StartVideoDecoder();
239     if (err != AV_ERR_OK) {
240         cout << "Failed to start video decoder" << endl;
241         Release();
242         return err;
243     }
244     return err;
245 }
246 
SetVideoDecoderCallback()247 int32_t VDecNdkSample::SetVideoDecoderCallback()
248 {
249     signal_ = new VDecSignal();
250     if (signal_ == nullptr) {
251         cout << "Failed to new VDecSignal" << endl;
252         return AV_ERR_UNKNOWN;
253     }
254 
255     cb_.onError = VdecError;
256     cb_.onStreamChanged = VdecFormatChanged;
257     cb_.onNeedInputData = VdecInputDataReady;
258     cb_.onNeedOutputData = VdecOutputDataReady;
259     return OH_VideoDecoder_SetCallback(vdec_, cb_, static_cast<void *>(signal_));
260 }
261 
ReleaseInFile()262 void VDecNdkSample::ReleaseInFile()
263 {
264     if (inFile_ != nullptr) {
265         if (inFile_->is_open()) {
266             inFile_->close();
267         }
268         inFile_.reset();
269         inFile_ = nullptr;
270     }
271 }
272 
StopInloop()273 void VDecNdkSample::StopInloop()
274 {
275     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
276         unique_lock<mutex> lock(signal_->inMutex_);
277         clearIntqueue(signal_->inIdxQueue_);
278         signal_->inCond_.notify_all();
279         lock.unlock();
280 
281         inputLoop_->join();
282         inputLoop_.reset();
283     }
284 }
285 
CreateVideoDecoder(string codeName)286 int32_t VDecNdkSample::CreateVideoDecoder(string codeName)
287 {
288     vdec_ = OH_VideoDecoder_CreateByName(codeName.c_str());
289     dec_sample = this;
290     return vdec_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
291 }
292 
StartVideoDecoder()293 int32_t VDecNdkSample::StartVideoDecoder()
294 {
295     isRunning_.store(true);
296     int ret = OH_VideoDecoder_Start(vdec_);
297     if (ret != AV_ERR_OK) {
298         cout << "Failed to start codec" << endl;
299         isRunning_.store(false);
300         ReleaseInFile();
301         Release();
302         return ret;
303     }
304     inFile_ = make_unique<ifstream>();
305     if (inFile_ == nullptr) {
306         isRunning_.store(false);
307         (void)OH_VideoDecoder_Stop(vdec_);
308         return AV_ERR_UNKNOWN;
309     }
310     inFile_->open(INP_DIR, ios::in | ios::binary);
311     if (!inFile_->is_open()) {
312         cout << "failed open file " << INP_DIR << endl;
313         isRunning_.store(false);
314         (void)OH_VideoDecoder_Stop(vdec_);
315         inFile_->close();
316         inFile_.reset();
317         inFile_ = nullptr;
318         return AV_ERR_UNKNOWN;
319     }
320 
321     inputLoop_ = make_unique<thread>(&VDecNdkSample::InputFuncTest, this);
322     if (inputLoop_ == nullptr) {
323         cout << "Failed to create input loop" << endl;
324         isRunning_.store(false);
325         (void)OH_VideoDecoder_Stop(vdec_);
326         ReleaseInFile();
327         return AV_ERR_UNKNOWN;
328     }
329     outputLoop_ = make_unique<thread>(&VDecNdkSample::OutputFuncTest, this);
330     if (outputLoop_ == nullptr) {
331         cout << "Failed to create output loop" << endl;
332         isRunning_.store(false);
333         (void)OH_VideoDecoder_Stop(vdec_);
334         ReleaseInFile();
335         StopInloop();
336         Release();
337         return AV_ERR_UNKNOWN;
338     }
339 
340     return AV_ERR_OK;
341 }
342 
testAPI()343 void VDecNdkSample::testAPI()
344 {
345     cs = Surface::CreateSurfaceAsConsumer();
346     sptr<IBufferConsumerListener> listener = new TestConsumerListener(cs, OUT_DIR);
347     cs->RegisterConsumerListener(listener);
348     auto p = cs->GetProducer();
349     ps = Surface::CreateSurfaceAsProducer(p);
350     OHNativeWindow *nativeWindow = CreateNativeWindowFromSurface(&ps);
351     OH_VideoDecoder_SetSurface(vdec_, nativeWindow);
352 
353     OH_VideoDecoder_Prepare(vdec_);
354     OH_VideoDecoder_Start(vdec_);
355 
356     OH_AVFormat *format = OH_AVFormat_Create();
357     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
358     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
359     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_NV12);
360     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
361     OH_VideoDecoder_SetParameter(vdec_, format);
362     OH_AVFormat_Destroy(format);
363     OH_VideoDecoder_GetOutputDescription(vdec_);
364     OH_VideoDecoder_Flush(vdec_);
365     OH_VideoDecoder_Stop(vdec_);
366     OH_VideoDecoder_Reset(vdec_);
367     bool isvalid = false;
368     OH_VideoDecoder_IsValid(vdec_, &isvalid);
369 }
370 
WaitForEOS()371 void VDecNdkSample::WaitForEOS()
372 {
373     if (inputLoop_ && inputLoop_->joinable()) {
374         inputLoop_->join();
375     }
376     if (outputLoop_ && outputLoop_->joinable()) {
377         outputLoop_->join();
378     }
379 }
380 
InputFuncTest()381 void VDecNdkSample::InputFuncTest()
382 {
383     while (true) {
384         if (!isRunning_.load()) {
385             break;
386         }
387         if (REPEAT_START_FLUSH_BEFORE_EOS > 0) {
388             REPEAT_START_FLUSH_BEFORE_EOS--;
389             OH_VideoDecoder_Flush(vdec_);
390             Flush_buffer();
391             OH_VideoDecoder_Start(vdec_);
392         }
393         if (REPEAT_START_STOP_BEFORE_EOS > 0) {
394             REPEAT_START_STOP_BEFORE_EOS--;
395             OH_VideoDecoder_Stop(vdec_);
396             Flush_buffer();
397             OH_VideoDecoder_Start(vdec_);
398         }
399         uint32_t index;
400         unique_lock<mutex> lock(signal_->inMutex_);
401         signal_->inCond_.wait(lock, [this]() { return signal_->inIdxQueue_.size() > 0; });
402         if (!isRunning_.load()) {
403             break;
404         }
405         index = signal_->inIdxQueue_.front();
406         auto buffer = signal_->inBufferQueue_.front();
407 
408         signal_->inIdxQueue_.pop();
409         signal_->inBufferQueue_.pop();
410         lock.unlock();
411         if (!inFile_->eof()) {
412             int ret = PushData(index, buffer);
413             if (ret == 1) {
414                 break;
415             }
416         }
417         if (sleepOnFPS) {
418             usleep(FRAME_INTERVAL);
419         }
420     }
421 }
422 
PushData(uint32_t index,OH_AVMemory * buffer)423 int32_t VDecNdkSample::PushData(uint32_t index, OH_AVMemory *buffer)
424 {
425     static uint32_t repeat_count = 0;
426     OH_AVCodecBufferAttr attr;
427     if (BEFORE_EOS_INPUT && frameCount_ > TEN) {
428         SetEOS(index);
429         return 1;
430     }
431     if (BEFORE_EOS_INPUT_INPUT && frameCount_ > TEN) {
432         memset_s(&attr, sizeof(OH_AVCodecBufferAttr), 0, sizeof(OH_AVCodecBufferAttr));
433         attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
434         BEFORE_EOS_INPUT_INPUT = false;
435     }
436     char ch[4] = {};
437     (void)inFile_->read(ch, START_CODE_SIZE);
438     if (repeatRun && inFile_->eof()) {
439         inFile_->clear();
440         inFile_->seekg(0, ios::beg);
441         cout << "repeat run " << repeat_count << endl;
442         repeat_count++;
443         return 0;
444     }
445     if (inFile_->eof()) {
446         SetEOS(index);
447         return 1;
448     }
449     uint32_t bufferSize = (uint32_t)(((ch[3] & 0xFF)) | ((ch[2] & 0xFF) << EIGHT) | ((ch[1] & 0xFF) << SIXTEEN) |
450                                      ((ch[0] & 0xFF) << TWENTY_FOUR));
451     if (bufferSize >= DEFAULT_WIDTH * DEFAULT_HEIGHT * THREE >> 1) {
452         cout << "read bufferSize abnormal. buffersize = " << bufferSize << endl;
453         return 1;
454     }
455 
456     return SendData(bufferSize, index, buffer);
457 }
458 
SendData(uint32_t bufferSize,uint32_t index,OH_AVMemory * buffer)459 uint32_t VDecNdkSample::SendData(uint32_t bufferSize, uint32_t index, OH_AVMemory *buffer)
460 {
461     OH_AVCodecBufferAttr attr;
462     uint8_t *fileBuffer = new uint8_t[bufferSize + START_CODE_SIZE];
463     if (fileBuffer == nullptr) {
464         cout << "Fatal: no memory" << endl;
465         delete[] fileBuffer;
466         return 0;
467     }
468     if (memcpy_s(fileBuffer, bufferSize + START_CODE_SIZE, START_CODE, START_CODE_SIZE) != EOK) {
469         cout << "Fatal: memory copy failed" << endl;
470     }
471     (void)inFile_->read((char *)fileBuffer + START_CODE_SIZE, bufferSize);
472     if ((fileBuffer[START_CODE_SIZE] & H264_NALU_TYPE) == SPS ||
473         (fileBuffer[START_CODE_SIZE] & H264_NALU_TYPE) == PPS) {
474         attr.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
475     } else {
476         attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
477     }
478 
479     int32_t size = OH_AVMemory_GetSize(buffer);
480     if (size < bufferSize + START_CODE_SIZE) {
481         delete[] fileBuffer;
482         cout << "buffer size not enough." << endl;
483         return 0;
484     }
485     uint8_t *avBuffer = OH_AVMemory_GetAddr(buffer);
486     if (avBuffer == nullptr) {
487         cout << "avBuffer == nullptr" << endl;
488         inFile_->clear();
489         inFile_->seekg(0, ios::beg);
490         delete[] fileBuffer;
491         return 0;
492     }
493     if (memcpy_s(avBuffer, size, fileBuffer, bufferSize + START_CODE_SIZE) != EOK) {
494         delete[] fileBuffer;
495         cout << "Fatal: memcpy fail" << endl;
496         return 0;
497     }
498     int64_t startPts = GetSystemTimeUs();
499     attr.pts = startPts;
500     attr.size = bufferSize + START_CODE_SIZE;
501     attr.offset = 0;
502     int32_t result = OH_VideoDecoder_PushInputData(vdec_, index, attr);
503     if (result != AV_ERR_OK) {
504         errCount = errCount + 1;
505         cout << "push input data failed,error:" << result << endl;
506     }
507     delete[] fileBuffer;
508     frameCount_ = frameCount_ + 1;
509     return 0;
510 }
511 
OutputFuncTest()512 void VDecNdkSample::OutputFuncTest()
513 {
514     SHA512_Init(&c);
515     while (true) {
516         if (!isRunning_.load()) {
517             break;
518         }
519         OH_AVCodecBufferAttr attr;
520         uint32_t index;
521         unique_lock<mutex> lock(signal_->outMutex_);
522         signal_->outCond_.wait(lock, [this]() { return signal_->outIdxQueue_.size() > 0; });
523         if (!isRunning_.load()) {
524             break;
525         }
526         index = signal_->outIdxQueue_.front();
527         attr = signal_->attrQueue_.front();
528         OH_AVMemory *buffer = signal_->outBufferQueue_.front();
529         signal_->outBufferQueue_.pop();
530         signal_->outIdxQueue_.pop();
531         signal_->attrQueue_.pop();
532         lock.unlock();
533         if (attr.flags == AVCODEC_BUFFER_FLAGS_EOS) {
534             SHA512_Final(md, &c);
535             OPENSSL_cleanse(&c, sizeof(c));
536             MdCompare(md, SHA512_DIGEST_LENGTH, fileSourcesha256);
537             if (AFTER_EOS_DESTORY_CODEC) {
538                 (void)Stop();
539                 Release();
540             }
541             break;
542         }
543         ProcessOutputData(buffer, index);
544         if (errCount > 0) {
545             break;
546         }
547     }
548 }
549 
ProcessOutputData(OH_AVMemory * buffer,uint32_t index)550 void VDecNdkSample::ProcessOutputData(OH_AVMemory *buffer, uint32_t index)
551 {
552     if (!SF_OUTPUT) {
553         uint32_t size = OH_AVMemory_GetSize(buffer);
554         if (size >= DEFAULT_WIDTH * DEFAULT_HEIGHT * THREE >> 1) {
555             uint8_t *cropBuffer = new uint8_t[size];
556             if (memcpy_s(cropBuffer, DEFAULT_WIDTH * DEFAULT_HEIGHT, OH_AVMemory_GetAddr(buffer),
557                          DEFAULT_WIDTH * DEFAULT_HEIGHT) != EOK) {
558                 cout << "Fatal: memory copy failed Y" << endl;
559             }
560             // copy UV
561             uint32_t uvSize = size - DEFAULT_WIDTH * DEFAULT_HEIGHT;
562             if (memcpy_s(cropBuffer + DEFAULT_WIDTH * DEFAULT_HEIGHT, uvSize,
563                          OH_AVMemory_GetAddr(buffer) + DEFAULT_WIDTH * DEFAULT_HEIGHT, uvSize) != EOK) {
564                 cout << "Fatal: memory copy failed UV" << endl;
565             }
566             SHA512_Update(&c, cropBuffer, size);
567             delete[] cropBuffer;
568         }
569         if (OH_VideoDecoder_FreeOutputData(vdec_, index) != AV_ERR_OK) {
570             cout << "Fatal: ReleaseOutputBuffer fail" << endl;
571             errCount = errCount + 1;
572         }
573     } else {
574         if (OH_VideoDecoder_RenderOutputData(vdec_, index) != AV_ERR_OK) {
575             cout << "Fatal: RenderOutputBuffer fail" << endl;
576             errCount = errCount + 1;
577         }
578     }
579 }
580 
state_EOS()581 int32_t VDecNdkSample::state_EOS()
582 {
583     uint32_t index;
584     unique_lock<mutex> lock(signal_->inMutex_);
585     signal_->inCond_.wait(lock, [this]() { return signal_->inIdxQueue_.size() > 0; });
586     index = signal_->inIdxQueue_.front();
587     signal_->inIdxQueue_.pop();
588     signal_->inBufferQueue_.pop();
589     lock.unlock();
590     OH_AVCodecBufferAttr attr;
591     attr.pts = 0;
592     attr.size = 0;
593     attr.offset = 0;
594     attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
595     return OH_VideoDecoder_PushInputData(vdec_, index, attr);
596 }
597 
SetEOS(uint32_t index)598 void VDecNdkSample::SetEOS(uint32_t index)
599 {
600     OH_AVCodecBufferAttr attr;
601     attr.pts = 0;
602     attr.size = 0;
603     attr.offset = 0;
604     attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
605     int32_t res = OH_VideoDecoder_PushInputData(vdec_, index, attr);
606     cout << "OH_VideoDecoder_PushInputData    EOS   res: " << res << endl;
607 }
608 
Flush()609 int32_t VDecNdkSample::Flush()
610 {
611     unique_lock<mutex> inLock(signal_->inMutex_);
612     clearIntqueue(signal_->inIdxQueue_);
613     signal_->inCond_.notify_all();
614     inLock.unlock();
615     unique_lock<mutex> outLock(signal_->outMutex_);
616     clearIntqueue(signal_->outIdxQueue_);
617     clearBufferqueue(signal_->attrQueue_);
618     signal_->outCond_.notify_all();
619     outLock.unlock();
620 
621     return OH_VideoDecoder_Flush(vdec_);
622 }
623 
Reset()624 int32_t VDecNdkSample::Reset()
625 {
626     isRunning_.store(false);
627     StopInloop();
628     StopOutloop();
629     ReleaseInFile();
630     return OH_VideoDecoder_Reset(vdec_);
631 }
632 
Release()633 int32_t VDecNdkSample::Release()
634 {
635     int ret = 0;
636     if (vdec_ != nullptr) {
637         ret = OH_VideoDecoder_Destroy(vdec_);
638         vdec_ = nullptr;
639     }
640 
641     if (signal_ != nullptr) {
642         delete signal_;
643         signal_ = nullptr;
644     }
645     return ret;
646 }
647 
Stop()648 int32_t VDecNdkSample::Stop()
649 {
650     StopInloop();
651     clearIntqueue(signal_->outIdxQueue_);
652     clearBufferqueue(signal_->attrQueue_);
653     ReleaseInFile();
654     return OH_VideoDecoder_Stop(vdec_);
655 }
656 
Start()657 int32_t VDecNdkSample::Start()
658 {
659     return OH_VideoDecoder_Start(vdec_);
660 }
661 
StopOutloop()662 void VDecNdkSample::StopOutloop()
663 {
664     if (outputLoop_ != nullptr && outputLoop_->joinable()) {
665         unique_lock<mutex> lock(signal_->outMutex_);
666         clearIntqueue(signal_->outIdxQueue_);
667         clearBufferqueue(signal_->attrQueue_);
668         signal_->outCond_.notify_all();
669         lock.unlock();
670     }
671 }
672 
SetParameter(OH_AVFormat * format)673 int32_t VDecNdkSample::SetParameter(OH_AVFormat *format)
674 {
675     return OH_VideoDecoder_SetParameter(vdec_, format);
676 }