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