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 "videodec_sample.h"
19 using namespace OHOS;
20 using namespace OHOS::Media;
21 using namespace std;
22 namespace {
23 const string MIME_TYPE = "video/mp4v-es";
24 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
25 constexpr int64_t NANOS_IN_MICRO = 1000L;
26 constexpr uint32_t PREREAD_BUFFER_SIZE = 0.1 * 1024 * 1024;
27 constexpr uint8_t MPEG4_FRAME_HEAD[] = {0x00, 0x00, 0x01, 0xb6};
28 constexpr uint8_t MPEG4_SEQUENCE_HEAD[] = {0x00, 0x00, 0x01, 0xb0};
29 constexpr uint32_t START_CODE_SIZE = 4;
30 constexpr uint32_t MAX_WIDTH = 4000;
31 constexpr uint32_t MAX_HEIGHT = 3000;
32 constexpr uint32_t MAX_NALU_SIZE = MAX_WIDTH * MAX_HEIGHT << 1;
33 VDecFuzzSample *g_decSample = nullptr;
34
35 bool g_fuzzError = false;
36
clearIntqueue(std::queue<uint32_t> & q)37 void clearIntqueue(std::queue<uint32_t> &q)
38 {
39 std::queue<uint32_t> empty;
40 swap(empty, q);
41 }
42
clearBufferqueue(std::queue<OH_AVCodecBufferAttr> & q)43 void clearBufferqueue(std::queue<OH_AVCodecBufferAttr> &q)
44 {
45 std::queue<OH_AVCodecBufferAttr> empty;
46 swap(empty, q);
47 }
48
clearAvBufferQueue(std::queue<OH_AVMemory * > & q)49 void clearAvBufferQueue(std::queue<OH_AVMemory *> &q)
50 {
51 std::queue<OH_AVMemory *> empty;
52 swap(empty, q);
53 }
54 } // namespace
55
56 class TestConsumerListener : public IBufferConsumerListener {
57 public:
TestConsumerListener(sptr<Surface> cs)58 TestConsumerListener(sptr<Surface> cs) : cs(cs) {};
~TestConsumerListener()59 ~TestConsumerListener() {}
OnBufferAvailable()60 void OnBufferAvailable() override
61 {
62 sptr<SurfaceBuffer> buffer;
63 int32_t flushFence;
64 cs->AcquireBuffer(buffer, flushFence, timestamp, damage);
65
66 cs->ReleaseBuffer(buffer, -1);
67 }
68
69 private:
70 int64_t timestamp = 0;
71 Rect damage = {};
72 sptr<Surface> cs {nullptr};
73 };
74
~VDecFuzzSample()75 VDecFuzzSample::~VDecFuzzSample()
76 {
77 Release();
78 }
79
VdecError(OH_AVCodec * codec,int32_t errorCode,void * userData)80 void VdecError(OH_AVCodec *codec, int32_t errorCode, void *userData)
81 {
82 VDecSignal *signal = static_cast<VDecSignal *>(userData);
83 if (signal == nullptr) {
84 return;
85 }
86 cout << "Error errorCode=" << errorCode << endl;
87 g_fuzzError = true;
88 g_decSample->isRunning_.store(false);
89 signal->inCond_.notify_all();
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 currentWidth = 0;
96 int32_t currentHeight = 0;
97 OH_AVFormat_GetIntValue(format, OH_MD_KEY_WIDTH, ¤tWidth);
98 OH_AVFormat_GetIntValue(format, OH_MD_KEY_HEIGHT, ¤tHeight);
99 g_decSample->defaultWidth = currentWidth;
100 g_decSample->defaultHeight = currentHeight;
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 if (signal == nullptr) {
107 return;
108 }
109 unique_lock<mutex> lock(signal->inMutex_);
110 signal->inIdxQueue_.push(index);
111 signal->inBufferQueue_.push(data);
112 signal->inCond_.notify_all();
113 }
114
VdecOutputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,OH_AVCodecBufferAttr * attr,void * userData)115 void VdecOutputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
116 void *userData)
117 {
118 VDecSignal *signal = static_cast<VDecSignal *>(userData);
119 if (signal == nullptr) {
120 return;
121 }
122 unique_lock<mutex> lock(signal->outMutex_);
123 signal->outIdxQueue_.push(index);
124 signal->attrQueue_.push(*attr);
125 signal->outBufferQueue_.push(data);
126 signal->outCond_.notify_all();
127 if (g_decSample->isSurfMode) {
128 OH_VideoDecoder_RenderOutputData(codec, index);
129 } else {
130 OH_VideoDecoder_FreeOutputData(codec, index);
131 }
132 }
133
GetSystemTimeUs()134 int64_t VDecFuzzSample::GetSystemTimeUs()
135 {
136 struct timespec now;
137 (void)clock_gettime(CLOCK_BOOTTIME, &now);
138 int64_t nanoTime = static_cast<int64_t>(now.tv_sec) * NANOS_IN_SECOND + now.tv_nsec;
139 return nanoTime / NANOS_IN_MICRO;
140 }
141
ConfigureVideoDecoder()142 int32_t VDecFuzzSample::ConfigureVideoDecoder()
143 {
144 if (isSurfMode) {
145 cs = Surface::CreateSurfaceAsConsumer();
146 sptr<IBufferConsumerListener> listener = new TestConsumerListener(cs);
147 cs->RegisterConsumerListener(listener);
148 auto p = cs->GetProducer();
149 ps = Surface::CreateSurfaceAsProducer(p);
150 nativeWindow = CreateNativeWindowFromSurface(&ps);
151 OH_VideoDecoder_SetSurface(vdec_, nativeWindow);
152 }
153 OH_AVFormat *format = OH_AVFormat_Create();
154 if (format == nullptr) {
155 cout << "Fatal: Failed to create format" << endl;
156 return AV_ERR_UNKNOWN;
157 }
158 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, defaultWidth);
159 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, defaultHeight);
160 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, defaultFrameRate);
161 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_ROTATION, defaultRotation);
162 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, defaultPixelFormat);
163 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_DECODER_BLANK_FRAME_ON_SHUTDOWN, enbleBlankFrame);
164 int ret = OH_VideoDecoder_Configure(vdec_, format);
165 OH_AVFormat_Destroy(format);
166 return ret;
167 }
168
RunVideoDec(string codeName)169 int32_t VDecFuzzSample::RunVideoDec(string codeName)
170 {
171 int err = CreateVideoDecoder(codeName);
172 if (err != AV_ERR_OK) {
173 cout << "Failed to create video decoder" << endl;
174 return err;
175 }
176 err = ConfigureVideoDecoder();
177 if (err != AV_ERR_OK) {
178 cout << "Failed to configure video decoder" << endl;
179 Release();
180 return err;
181 }
182 err = SetVideoDecoderCallback();
183 if (err != AV_ERR_OK) {
184 cout << "Failed to setCallback" << endl;
185 Release();
186 return err;
187 }
188 err = StartVideoDecoder();
189 if (err != AV_ERR_OK) {
190 cout << "Failed to start video decoder" << endl;
191 Release();
192 return err;
193 }
194 return err;
195 }
196
SetVideoDecoderCallback()197 int32_t VDecFuzzSample::SetVideoDecoderCallback()
198 {
199 signal_ = new VDecSignal();
200 if (signal_ == nullptr) {
201 cout << "Failed to new VDecSignal" << endl;
202 return AV_ERR_UNKNOWN;
203 }
204
205 cb_.onError = VdecError;
206 cb_.onStreamChanged = VdecFormatChanged;
207 cb_.onNeedInputData = VdecInputDataReady;
208 cb_.onNeedOutputData = VdecOutputDataReady;
209 return OH_VideoDecoder_SetCallback(vdec_, cb_, static_cast<void *>(signal_));
210 }
211
ReleaseInFile()212 void VDecFuzzSample::ReleaseInFile()
213 {
214 if (inFile_ != nullptr) {
215 if (inFile_->is_open()) {
216 inFile_->close();
217 }
218 inFile_.reset();
219 inFile_ = nullptr;
220 }
221 }
222
StopInloop()223 void VDecFuzzSample::StopInloop()
224 {
225 if (inputLoop_ != nullptr && inputLoop_->joinable()) {
226 unique_lock<mutex> lock(signal_->inMutex_);
227 clearIntqueue(signal_->inIdxQueue_);
228 signal_->inCond_.notify_all();
229 lock.unlock();
230
231 inputLoop_->join();
232 inputLoop_.reset();
233 }
234 }
235
StartVideoDecoder()236 int32_t VDecFuzzSample::StartVideoDecoder()
237 {
238 int ret = OH_VideoDecoder_Start(vdec_);
239 if (ret != AV_ERR_OK) {
240 cout << "Failed to start codec" << endl;
241 return ret;
242 }
243
244 isRunning_.store(true);
245
246 inFile_ = make_unique<ifstream>();
247 if (inFile_ == nullptr) {
248 isRunning_.store(false);
249 (void)OH_VideoDecoder_Stop(vdec_);
250 return AV_ERR_UNKNOWN;
251 }
252 inFile_->open(inpDir, ios::in | ios::binary);
253 if (!inFile_->is_open()) {
254 cout << "open input file failed" << endl;
255 isRunning_.store(false);
256 (void)OH_VideoDecoder_Stop(vdec_);
257 inFile_->close();
258 inFile_.reset();
259 inFile_ = nullptr;
260 return AV_ERR_UNKNOWN;
261 }
262
263 inputLoop_ = make_unique<thread>(&VDecFuzzSample::InputFuncAVCC, this);
264 if (inputLoop_ == nullptr) {
265 cout << "Failed to create input loop" << endl;
266 isRunning_.store(false);
267 (void)OH_VideoDecoder_Stop(vdec_);
268 ReleaseInFile();
269 return AV_ERR_UNKNOWN;
270 }
271 return AV_ERR_OK;
272 }
273
CreateVideoDecoder(string codeName)274 int32_t VDecFuzzSample::CreateVideoDecoder(string codeName)
275 {
276 vdec_ = OH_VideoDecoder_CreateByName("aabbcc");
277 if (vdec_) {
278 OH_VideoDecoder_Destroy(vdec_);
279 vdec_ = nullptr;
280 }
281 OH_AVCodec *tmpDec = OH_VideoDecoder_CreateByMime("aabbcc");
282 if (tmpDec) {
283 OH_VideoDecoder_Destroy(tmpDec);
284 tmpDec = nullptr;
285 }
286 tmpDec = OH_VideoDecoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
287 if (tmpDec) {
288 OH_VideoDecoder_Destroy(tmpDec);
289 tmpDec = nullptr;
290 }
291 vdec_ = OH_VideoDecoder_CreateByName(codeName.c_str());
292 g_decSample = this;
293 return vdec_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
294 }
295
WaitForEOS()296 void VDecFuzzSample::WaitForEOS()
297 {
298 if (inputLoop_ && inputLoop_->joinable()) {
299 inputLoop_->join();
300 }
301 }
302
PtrStep(uint32_t & bufferSize,unsigned char ** pBuffer,uint32_t size)303 void VDecFuzzSample::PtrStep(uint32_t &bufferSize, unsigned char **pBuffer, uint32_t size)
304 {
305 pPrereadBuffer_ += size;
306 bufferSize += size;
307 *pBuffer += size;
308 }
309
PtrStepExtraRead(uint32_t & bufferSize,unsigned char ** pBuffer)310 void VDecFuzzSample::PtrStepExtraRead(uint32_t &bufferSize, unsigned char **pBuffer)
311 {
312 bufferSize -= START_CODE_SIZE;
313 *pBuffer -= START_CODE_SIZE;
314 pPrereadBuffer_ = 0;
315 }
316
GetBufferSize()317 void VDecFuzzSample::GetBufferSize()
318 {
319 auto pBuffer = mpegUnit_->data();
320 uint32_t bufferSize = 0;
321 mpegUnit_->resize(MAX_NALU_SIZE);
322 do {
323 auto pos1 = std::search(prereadBuffer_.get() + pPrereadBuffer_ + START_CODE_SIZE,
324 prereadBuffer_.get() + prereadBufferSize_, std::begin(MPEG4_FRAME_HEAD), std::end(MPEG4_FRAME_HEAD));
325 uint32_t size1 = std::distance(prereadBuffer_.get() + pPrereadBuffer_, pos1);
326 auto pos2 = std::search(prereadBuffer_.get() + pPrereadBuffer_, prereadBuffer_.get() +
327 pPrereadBuffer_ + size1, std::begin(MPEG4_SEQUENCE_HEAD), std::end(MPEG4_SEQUENCE_HEAD));
328 uint32_t size = std::distance(prereadBuffer_.get() + pPrereadBuffer_, pos2);
329 if (size == 0) {
330 auto pos3 = std::search(prereadBuffer_.get() + pPrereadBuffer_ + size1 + START_CODE_SIZE,
331 prereadBuffer_.get() + prereadBufferSize_, std::begin(MPEG4_FRAME_HEAD), std::end(MPEG4_FRAME_HEAD));
332 uint32_t size2 = std::distance(prereadBuffer_.get() + pPrereadBuffer_, pos3);
333 if (memcpy_s(pBuffer, size2, prereadBuffer_.get() + pPrereadBuffer_, size2) != EOK) {
334 return;
335 }
336 PtrStep(bufferSize, &pBuffer, size2);
337 if (!((pPrereadBuffer_ == prereadBufferSize_) && !inFile_->eof())) {
338 break;
339 }
340 } else if (size1 > size) {
341 if (memcpy_s(pBuffer, size, prereadBuffer_.get() + pPrereadBuffer_, size) != EOK) {
342 return;
343 }
344 PtrStep(bufferSize, &pBuffer, size);
345 if (!((pPrereadBuffer_ == prereadBufferSize_) && !inFile_->eof())) {
346 break;
347 }
348 } else {
349 if (memcpy_s(pBuffer, size1, prereadBuffer_.get() + pPrereadBuffer_, size1) != EOK) {
350 return;
351 }
352 PtrStep(bufferSize, &pBuffer, size1);
353 if (!((pPrereadBuffer_ == prereadBufferSize_) && !inFile_->eof())) {
354 break;
355 }
356 }
357 inFile_->read(reinterpret_cast<char *>(prereadBuffer_.get() + START_CODE_SIZE), PREREAD_BUFFER_SIZE);
358 prereadBufferSize_ = inFile_->gcount() + START_CODE_SIZE;
359 pPrereadBuffer_ = START_CODE_SIZE;
360 if (memcpy_s(prereadBuffer_.get(), START_CODE_SIZE, pBuffer - START_CODE_SIZE, START_CODE_SIZE) != EOK) {
361 return;
362 }
363 PtrStepExtraRead(bufferSize, &pBuffer);
364 } while (pPrereadBuffer_ != prereadBufferSize_);
365 mpegUnit_->resize(bufferSize);
366 }
367
ReadData(uint32_t index,OH_AVMemory * buffer)368 int32_t VDecFuzzSample::ReadData(uint32_t index, OH_AVMemory *buffer)
369 {
370 uint32_t bufferSize = 0;
371 if (inFile_->tellg() == 0) {
372 inFile_->read(reinterpret_cast<char *>(prereadBuffer_.get() + START_CODE_SIZE), PREREAD_BUFFER_SIZE);
373 prereadBufferSize_ = inFile_->gcount() + START_CODE_SIZE;
374 pPrereadBuffer_ = START_CODE_SIZE;
375 }
376
377 if (inFile_->eof() && finishLastPush) {
378 SetEOS(index);
379 mpegUnit_->resize(0);
380 return 1;
381 }
382
383 GetBufferSize();
384 bufferSize = mpegUnit_->size();
385 return SendData(bufferSize, index, buffer);
386 }
387
SendData(uint32_t bufferSize,uint32_t index,OH_AVMemory * buffer)388 uint32_t VDecFuzzSample::SendData(uint32_t bufferSize, uint32_t index, OH_AVMemory *buffer)
389 {
390 OH_AVCodecBufferAttr attr;
391 uint8_t *frameBuffer = nullptr;
392 if (bufferSize > 0) {
393 frameBuffer = new uint8_t[bufferSize];
394 } else {
395 delete[] frameBuffer;
396 return 0;
397 }
398 memcpy_s(frameBuffer, bufferSize, mpegUnit_->data(), bufferSize);
399 attr.pts = GetSystemTimeUs();
400 attr.size = bufferSize;
401 attr.offset = 0;
402 attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
403
404 if (pPrereadBuffer_ == prereadBufferSize_ && inFile_->eof()) {
405 finishLastPush = true;
406 }
407 int32_t size = OH_AVMemory_GetSize(buffer);
408 if (size < attr.size) {
409 delete[] frameBuffer;
410 cout << "ERROR:AVMemory not enough, buffer size" << attr.size << " AVMemory Size " << size << endl;
411 isRunning_.store(false);
412 return 1;
413 }
414 uint8_t *bufferAddr = OH_AVMemory_GetAddr(buffer);
415 if (memcpy_s(bufferAddr, size, frameBuffer, attr.size) != EOK) {
416 delete[] frameBuffer;
417 cout << "Fatal: memcpy fail" << endl;
418 isRunning_.store(false);
419 return 1;
420 }
421 delete[] frameBuffer;
422
423 int ret = OH_VideoDecoder_PushInputData(vdec_, index, attr);
424 if (ret != AV_ERR_OK) {
425 errCount++;
426 cout << "push input data failed, error:" << ret << endl;
427 }
428
429 if (inFile_->eof() && finishLastPush && repeatRun) {
430 inFile_->clear();
431 inFile_->seekg(0, ios::beg);
432 finishLastPush = false;
433 cout << "repeat" << endl;
434 return 0;
435 }
436
437 frameCount_ = frameCount_ + 1;
438 return 0;
439 }
440
InputFuncAVCC()441 void VDecFuzzSample::InputFuncAVCC()
442 {
443 frameCount_ = 1;
444 errCount = 0;
445 while (true) {
446 if (!isRunning_.load()) {
447 break;
448 }
449 unique_lock<mutex> lock(signal_->inMutex_);
450 signal_->inCond_.wait(lock, [this]() {
451 if (!isRunning_.load()) {
452 cout << "quit signal" << endl;
453 return true;
454 }
455 return signal_->inIdxQueue_.size() > 0;
456 });
457 if (!isRunning_.load()) {
458 break;
459 }
460 uint32_t index = signal_->inIdxQueue_.front();
461 auto buffer = signal_->inBufferQueue_.front();
462 signal_->inIdxQueue_.pop();
463 signal_->inBufferQueue_.pop();
464 lock.unlock();
465 int ret = ReadData(index, buffer);
466 if (ret == 1) {
467 break;
468 }
469 }
470 }
471
InputFuncFUZZ(const uint8_t * data,size_t size)472 OH_AVErrCode VDecFuzzSample::InputFuncFUZZ(const uint8_t *data, size_t size)
473 {
474 if (!isRunning_.load())
475 return AV_ERR_TIMEOUT;
476 uint32_t index;
477 unique_lock<mutex> lock(signal_->inMutex_);
478 signal_->inCond_.wait(lock, [this]() {
479 if (!isRunning_.load()) {
480 return true;
481 }
482 return signal_->inIdxQueue_.size() > 0;
483 });
484 if (!isRunning_.load())
485 return AV_ERR_TIMEOUT;
486 index = signal_->inIdxQueue_.front();
487 auto buffer = signal_->inBufferQueue_.front();
488 signal_->inIdxQueue_.pop();
489 signal_->inBufferQueue_.pop();
490 lock.unlock();
491 int32_t bufferSize = OH_AVMemory_GetSize(buffer);
492 uint8_t *bufferAddr = OH_AVMemory_GetAddr(buffer);
493
494 if (memcpy_s(bufferAddr, bufferSize, data, size) != EOK) {
495 cout << "Fatal: memcpy fail" << endl;
496 return AV_ERR_NO_MEMORY;
497 }
498 OH_AVCodecBufferAttr attr;
499 attr.pts = GetSystemTimeUs();
500 attr.size = bufferSize;
501 attr.offset = 0;
502 attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
503 OH_AVErrCode ret = OH_VideoDecoder_PushInputData(vdec_, index, attr);
504 return ret;
505 }
506
SetEOS(uint32_t index)507 void VDecFuzzSample::SetEOS(uint32_t index)
508 {
509 OH_AVCodecBufferAttr attr;
510 attr.pts = 0;
511 attr.size = 0;
512 attr.offset = 0;
513 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
514 int32_t res = OH_VideoDecoder_PushInputData(vdec_, index, attr);
515 cout << "OH_VideoDecoder_PushInputData EOS res: " << res << endl;
516 }
517
Flush()518 int32_t VDecFuzzSample::Flush()
519 {
520 unique_lock<mutex> inLock(signal_->inMutex_);
521 clearIntqueue(signal_->inIdxQueue_);
522 signal_->inCond_.notify_all();
523 inLock.unlock();
524 unique_lock<mutex> outLock(signal_->outMutex_);
525 clearIntqueue(signal_->outIdxQueue_);
526 clearBufferqueue(signal_->attrQueue_);
527 signal_->outCond_.notify_all();
528 isRunning_.store(false);
529 outLock.unlock();
530
531 return OH_VideoDecoder_Flush(vdec_);
532 }
533
Reset()534 int32_t VDecFuzzSample::Reset()
535 {
536 isRunning_.store(false);
537 StopInloop();
538 ReleaseInFile();
539 return OH_VideoDecoder_Reset(vdec_);
540 }
541
Release()542 int32_t VDecFuzzSample::Release()
543 {
544 int ret = 0;
545 if (vdec_ != nullptr) {
546 ret = OH_VideoDecoder_Destroy(vdec_);
547 vdec_ = nullptr;
548 }
549 if (signal_ != nullptr) {
550 clearAvBufferQueue(signal_->inBufferQueue_);
551 clearAvBufferQueue(signal_->outBufferQueue_);
552 delete signal_;
553 signal_ = nullptr;
554 }
555 return ret;
556 }
557
Stop()558 int32_t VDecFuzzSample::Stop()
559 {
560 StopInloop();
561 clearIntqueue(signal_->outIdxQueue_);
562 clearBufferqueue(signal_->attrQueue_);
563 ReleaseInFile();
564 return OH_VideoDecoder_Stop(vdec_);
565 }
566
Start()567 int32_t VDecFuzzSample::Start()
568 {
569 int32_t ret = 0;
570 ret = OH_VideoDecoder_Start(vdec_);
571 if (ret == AV_ERR_OK) {
572 isRunning_.store(true);
573 }
574 return ret;
575 }
576
SetParameter(OH_AVFormat * format)577 int32_t VDecFuzzSample::SetParameter(OH_AVFormat *format)
578 {
579 return OH_VideoDecoder_SetParameter(vdec_, format);
580 }