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