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