1da853ecaSopenharmony_ci/*
2da853ecaSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd.
3da853ecaSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4da853ecaSopenharmony_ci * you may not use this file except in compliance with the License.
5da853ecaSopenharmony_ci * You may obtain a copy of the License at
6da853ecaSopenharmony_ci *
7da853ecaSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8da853ecaSopenharmony_ci *
9da853ecaSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10da853ecaSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11da853ecaSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12da853ecaSopenharmony_ci * See the License for the specific language governing permissions and
13da853ecaSopenharmony_ci * limitations under the License.
14da853ecaSopenharmony_ci */
15da853ecaSopenharmony_ci#include <arpa/inet.h>
16da853ecaSopenharmony_ci#include <sys/time.h>
17da853ecaSopenharmony_ci#include <utility>
18da853ecaSopenharmony_ci#include "videodec_sample.h"
19da853ecaSopenharmony_ci#include "native_avcapability.h"
20da853ecaSopenharmony_ciusing namespace OHOS;
21da853ecaSopenharmony_ciusing namespace OHOS::Media;
22da853ecaSopenharmony_ciusing namespace std;
23da853ecaSopenharmony_cinamespace {
24da853ecaSopenharmony_ciconstexpr int64_t NANOS_IN_SECOND = 1000000000L;
25da853ecaSopenharmony_ciconstexpr int64_t NANOS_IN_MICRO = 1000L;
26da853ecaSopenharmony_ciconstexpr int32_t EIGHT = 8;
27da853ecaSopenharmony_ciconstexpr int32_t SIXTEEN = 16;
28da853ecaSopenharmony_ciconstexpr int32_t TWENTY_FOUR = 24;
29da853ecaSopenharmony_ciconstexpr uint8_t H264_NALU_TYPE = 0x1f;
30da853ecaSopenharmony_ciconstexpr uint32_t START_CODE_SIZE = 4;
31da853ecaSopenharmony_ciconstexpr uint8_t START_CODE[START_CODE_SIZE] = {0, 0, 0, 1};
32da853ecaSopenharmony_ciconstexpr uint8_t SEI = 6;
33da853ecaSopenharmony_ciconstexpr uint8_t SPS = 7;
34da853ecaSopenharmony_ciconstexpr uint8_t PPS = 8;
35da853ecaSopenharmony_ci
36da853ecaSopenharmony_ciVDecFuzzSample *g_decSample = nullptr;
37da853ecaSopenharmony_cibool g_fuzzError = false;
38da853ecaSopenharmony_civoid clearIntqueue(std::queue<uint32_t> &q)
39da853ecaSopenharmony_ci{
40da853ecaSopenharmony_ci    std::queue<uint32_t> empty;
41da853ecaSopenharmony_ci    swap(empty, q);
42da853ecaSopenharmony_ci}
43da853ecaSopenharmony_ci
44da853ecaSopenharmony_civoid clearBufferqueue(std::queue<OH_AVCodecBufferAttr> &q)
45da853ecaSopenharmony_ci{
46da853ecaSopenharmony_ci    std::queue<OH_AVCodecBufferAttr> empty;
47da853ecaSopenharmony_ci    swap(empty, q);
48da853ecaSopenharmony_ci}
49da853ecaSopenharmony_ci
50da853ecaSopenharmony_civoid clearAvBufferQueue(std::queue<OH_AVMemory *> &q)
51da853ecaSopenharmony_ci{
52da853ecaSopenharmony_ci    std::queue<OH_AVMemory *> empty;
53da853ecaSopenharmony_ci    swap(empty, q);
54da853ecaSopenharmony_ci}
55da853ecaSopenharmony_ci} // namespace
56da853ecaSopenharmony_ci
57da853ecaSopenharmony_ciclass TestConsumerListener : public IBufferConsumerListener {
58da853ecaSopenharmony_cipublic:
59da853ecaSopenharmony_ci    TestConsumerListener(sptr<Surface> cs) : cs(cs) {};
60da853ecaSopenharmony_ci    ~TestConsumerListener() {}
61da853ecaSopenharmony_ci    void OnBufferAvailable() override
62da853ecaSopenharmony_ci    {
63da853ecaSopenharmony_ci        sptr<SurfaceBuffer> buffer;
64da853ecaSopenharmony_ci        int32_t flushFence;
65da853ecaSopenharmony_ci        cs->AcquireBuffer(buffer, flushFence, timestamp, damage);
66da853ecaSopenharmony_ci
67da853ecaSopenharmony_ci        cs->ReleaseBuffer(buffer, -1);
68da853ecaSopenharmony_ci    }
69da853ecaSopenharmony_ci
70da853ecaSopenharmony_ciprivate:
71da853ecaSopenharmony_ci    int64_t timestamp = 0;
72da853ecaSopenharmony_ci    Rect damage = {};
73da853ecaSopenharmony_ci    sptr<Surface> cs {nullptr};
74da853ecaSopenharmony_ci};
75da853ecaSopenharmony_ci
76da853ecaSopenharmony_ciVDecFuzzSample::~VDecFuzzSample()
77da853ecaSopenharmony_ci{
78da853ecaSopenharmony_ci    if (nativeWindow) {
79da853ecaSopenharmony_ci        OH_NativeWindow_DestroyNativeWindow(nativeWindow);
80da853ecaSopenharmony_ci        nativeWindow = nullptr;
81da853ecaSopenharmony_ci    }
82da853ecaSopenharmony_ci    Stop();
83da853ecaSopenharmony_ci    Release();
84da853ecaSopenharmony_ci}
85da853ecaSopenharmony_ci
86da853ecaSopenharmony_civoid VdecError(OH_AVCodec *codec, int32_t errorCode, void *userData)
87da853ecaSopenharmony_ci{
88da853ecaSopenharmony_ci    cout << "Error errorCode=" << errorCode << endl;
89da853ecaSopenharmony_ci}
90da853ecaSopenharmony_ci
91da853ecaSopenharmony_civoid VdecFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
92da853ecaSopenharmony_ci{
93da853ecaSopenharmony_ci    int32_t currentWidth = 0;
94da853ecaSopenharmony_ci    int32_t currentHeight = 0;
95da853ecaSopenharmony_ci    OH_AVFormat_GetIntValue(format, OH_MD_KEY_WIDTH, &currentWidth);
96da853ecaSopenharmony_ci    OH_AVFormat_GetIntValue(format, OH_MD_KEY_HEIGHT, &currentHeight);
97da853ecaSopenharmony_ci    g_decSample->defaultWidth = currentWidth;
98da853ecaSopenharmony_ci    g_decSample->defaultHeight = currentHeight;
99da853ecaSopenharmony_ci}
100da853ecaSopenharmony_ci
101da853ecaSopenharmony_civoid VdecInputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
102da853ecaSopenharmony_ci{
103da853ecaSopenharmony_ci    VDecSignal *signal = static_cast<VDecSignal *>(userData);
104da853ecaSopenharmony_ci    unique_lock<mutex> lock(signal->inMutex_);
105da853ecaSopenharmony_ci    signal->inIdxQueue_.push(index);
106da853ecaSopenharmony_ci    signal->inBufferQueue_.push(data);
107da853ecaSopenharmony_ci    signal->inCond_.notify_all();
108da853ecaSopenharmony_ci}
109da853ecaSopenharmony_ci
110da853ecaSopenharmony_civoid VdecOutputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
111da853ecaSopenharmony_ci                         void *userData)
112da853ecaSopenharmony_ci{
113da853ecaSopenharmony_ci    if (g_decSample->isSurfMode) {
114da853ecaSopenharmony_ci        OH_VideoDecoder_RenderOutputData(codec, index);
115da853ecaSopenharmony_ci    } else {
116da853ecaSopenharmony_ci        OH_VideoDecoder_FreeOutputData(codec, index);
117da853ecaSopenharmony_ci    }
118da853ecaSopenharmony_ci}
119da853ecaSopenharmony_ci
120da853ecaSopenharmony_ciint64_t VDecFuzzSample::GetSystemTimeUs()
121da853ecaSopenharmony_ci{
122da853ecaSopenharmony_ci    struct timespec now;
123da853ecaSopenharmony_ci    (void)clock_gettime(CLOCK_BOOTTIME, &now);
124da853ecaSopenharmony_ci    int64_t nanoTime = static_cast<int64_t>(now.tv_sec) * NANOS_IN_SECOND + now.tv_nsec;
125da853ecaSopenharmony_ci    return nanoTime / NANOS_IN_MICRO;
126da853ecaSopenharmony_ci}
127da853ecaSopenharmony_ci
128da853ecaSopenharmony_ciint32_t VDecFuzzSample::ConfigureVideoDecoder()
129da853ecaSopenharmony_ci{
130da853ecaSopenharmony_ci    OH_AVFormat *format = OH_AVFormat_Create();
131da853ecaSopenharmony_ci    if (format == nullptr) {
132da853ecaSopenharmony_ci        cout << "Fatal: Failed to create format" << endl;
133da853ecaSopenharmony_ci        return AV_ERR_UNKNOWN;
134da853ecaSopenharmony_ci    }
135da853ecaSopenharmony_ci    (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, defaultWidth);
136da853ecaSopenharmony_ci    (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, defaultHeight);
137da853ecaSopenharmony_ci    (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_ROTATION, defaultRotation);
138da853ecaSopenharmony_ci    (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, defaultPixelFormat);
139da853ecaSopenharmony_ci    int ret = OH_VideoDecoder_Configure(vdec_, format);
140da853ecaSopenharmony_ci    OH_AVFormat_Destroy(format);
141da853ecaSopenharmony_ci    if (isSurfMode) {
142da853ecaSopenharmony_ci        cs = Surface::CreateSurfaceAsConsumer();
143da853ecaSopenharmony_ci        sptr<IBufferConsumerListener> listener = new TestConsumerListener(cs);
144da853ecaSopenharmony_ci        cs->RegisterConsumerListener(listener);
145da853ecaSopenharmony_ci        auto p = cs->GetProducer();
146da853ecaSopenharmony_ci        ps = Surface::CreateSurfaceAsProducer(p);
147da853ecaSopenharmony_ci        nativeWindow = CreateNativeWindowFromSurface(&ps);
148da853ecaSopenharmony_ci        OH_VideoDecoder_SetSurface(vdec_, nativeWindow);
149da853ecaSopenharmony_ci    }
150da853ecaSopenharmony_ci    return ret;
151da853ecaSopenharmony_ci}
152da853ecaSopenharmony_ci
153da853ecaSopenharmony_ciint32_t VDecFuzzSample::RunVideoDec()
154da853ecaSopenharmony_ci{
155da853ecaSopenharmony_ci    int err = CreateVideoDecoder();
156da853ecaSopenharmony_ci    if (err != AV_ERR_OK) {
157da853ecaSopenharmony_ci        cout << "Failed to create video decoder" << endl;
158da853ecaSopenharmony_ci        return err;
159da853ecaSopenharmony_ci    }
160da853ecaSopenharmony_ci
161da853ecaSopenharmony_ci    err = ConfigureVideoDecoder();
162da853ecaSopenharmony_ci    if (err != AV_ERR_OK) {
163da853ecaSopenharmony_ci        cout << "Failed to configure video decoder" << endl;
164da853ecaSopenharmony_ci        Release();
165da853ecaSopenharmony_ci        return err;
166da853ecaSopenharmony_ci    }
167da853ecaSopenharmony_ci
168da853ecaSopenharmony_ci    err = SetVideoDecoderCallback();
169da853ecaSopenharmony_ci    if (err != AV_ERR_OK) {
170da853ecaSopenharmony_ci        cout << "Failed to setCallback" << endl;
171da853ecaSopenharmony_ci        Release();
172da853ecaSopenharmony_ci        return err;
173da853ecaSopenharmony_ci    }
174da853ecaSopenharmony_ci
175da853ecaSopenharmony_ci    err = StartVideoDecoder();
176da853ecaSopenharmony_ci    if (err != AV_ERR_OK) {
177da853ecaSopenharmony_ci        cout << "Failed to start video decoder" << endl;
178da853ecaSopenharmony_ci        Release();
179da853ecaSopenharmony_ci        return err;
180da853ecaSopenharmony_ci    }
181da853ecaSopenharmony_ci    return err;
182da853ecaSopenharmony_ci}
183da853ecaSopenharmony_ci
184da853ecaSopenharmony_ciint32_t VDecFuzzSample::SetVideoDecoderCallback()
185da853ecaSopenharmony_ci{
186da853ecaSopenharmony_ci    signal_ = new VDecSignal();
187da853ecaSopenharmony_ci    if (signal_ == nullptr) {
188da853ecaSopenharmony_ci        cout << "Failed to new VDecSignal" << endl;
189da853ecaSopenharmony_ci        return AV_ERR_UNKNOWN;
190da853ecaSopenharmony_ci    }
191da853ecaSopenharmony_ci
192da853ecaSopenharmony_ci    cb_.onError = VdecError;
193da853ecaSopenharmony_ci    cb_.onStreamChanged = VdecFormatChanged;
194da853ecaSopenharmony_ci    cb_.onNeedInputData = VdecInputDataReady;
195da853ecaSopenharmony_ci    cb_.onNeedOutputData = VdecOutputDataReady;
196da853ecaSopenharmony_ci    return OH_VideoDecoder_SetCallback(vdec_, cb_, static_cast<void *>(signal_));
197da853ecaSopenharmony_ci}
198da853ecaSopenharmony_ci
199da853ecaSopenharmony_civoid VDecFuzzSample::ReleaseInFile()
200da853ecaSopenharmony_ci{
201da853ecaSopenharmony_ci    if (inFile_ != nullptr) {
202da853ecaSopenharmony_ci        if (inFile_->is_open()) {
203da853ecaSopenharmony_ci            inFile_->close();
204da853ecaSopenharmony_ci        }
205da853ecaSopenharmony_ci        inFile_.reset();
206da853ecaSopenharmony_ci        inFile_ = nullptr;
207da853ecaSopenharmony_ci    }
208da853ecaSopenharmony_ci}
209da853ecaSopenharmony_ci
210da853ecaSopenharmony_civoid VDecFuzzSample::StopInLoop()
211da853ecaSopenharmony_ci{
212da853ecaSopenharmony_ci    if (inputLoop_ != nullptr && inputLoop_->joinable()) {
213da853ecaSopenharmony_ci        unique_lock<mutex> lock(signal_->inMutex_);
214da853ecaSopenharmony_ci        clearIntqueue(signal_->inIdxQueue_);
215da853ecaSopenharmony_ci        signal_->inCond_.notify_all();
216da853ecaSopenharmony_ci        lock.unlock();
217da853ecaSopenharmony_ci
218da853ecaSopenharmony_ci        inputLoop_->join();
219da853ecaSopenharmony_ci        inputLoop_.reset();
220da853ecaSopenharmony_ci    }
221da853ecaSopenharmony_ci}
222da853ecaSopenharmony_ci
223da853ecaSopenharmony_ciint32_t VDecFuzzSample::StartVideoDecoder()
224da853ecaSopenharmony_ci{
225da853ecaSopenharmony_ci    int ret = OH_VideoDecoder_Start(vdec_);
226da853ecaSopenharmony_ci    if (ret != AV_ERR_OK) {
227da853ecaSopenharmony_ci        cout << "Failed to start codec" << endl;
228da853ecaSopenharmony_ci        return ret;
229da853ecaSopenharmony_ci    }
230da853ecaSopenharmony_ci    isRunning_.store(true);
231da853ecaSopenharmony_ci    inFile_ = make_unique<ifstream>();
232da853ecaSopenharmony_ci    if (inFile_ == nullptr) {
233da853ecaSopenharmony_ci        isRunning_.store(false);
234da853ecaSopenharmony_ci        (void)OH_VideoDecoder_Stop(vdec_);
235da853ecaSopenharmony_ci        return AV_ERR_UNKNOWN;
236da853ecaSopenharmony_ci    }
237da853ecaSopenharmony_ci    inFile_->open(inpDir, ios::in | ios::binary);
238da853ecaSopenharmony_ci    if (!inFile_->is_open()) {
239da853ecaSopenharmony_ci        cout << "failed open file " << endl;
240da853ecaSopenharmony_ci        isRunning_.store(false);
241da853ecaSopenharmony_ci        (void)OH_VideoDecoder_Stop(vdec_);
242da853ecaSopenharmony_ci        inFile_->close();
243da853ecaSopenharmony_ci        inFile_.reset();
244da853ecaSopenharmony_ci        inFile_ = nullptr;
245da853ecaSopenharmony_ci        return AV_ERR_UNKNOWN;
246da853ecaSopenharmony_ci    }
247da853ecaSopenharmony_ci
248da853ecaSopenharmony_ci    inputLoop_ = make_unique<thread>(&VDecFuzzSample::InputFuncAVCC, this);
249da853ecaSopenharmony_ci    if (inputLoop_ == nullptr) {
250da853ecaSopenharmony_ci        cout << "Failed to create input loop" << endl;
251da853ecaSopenharmony_ci        isRunning_.store(false);
252da853ecaSopenharmony_ci        (void)OH_VideoDecoder_Stop(vdec_);
253da853ecaSopenharmony_ci        ReleaseInFile();
254da853ecaSopenharmony_ci        return AV_ERR_UNKNOWN;
255da853ecaSopenharmony_ci    }
256da853ecaSopenharmony_ci    return AV_ERR_OK;
257da853ecaSopenharmony_ci}
258da853ecaSopenharmony_ci
259da853ecaSopenharmony_ciint32_t VDecFuzzSample::CreateVideoDecoder()
260da853ecaSopenharmony_ci{
261da853ecaSopenharmony_ci    OH_AVCapability *cap = OH_AVCodec_GetCapabilityByCategory(OH_AVCODEC_MIMETYPE_VIDEO_AVC, false, HARDWARE);
262da853ecaSopenharmony_ci    string codecName = OH_AVCapability_GetName(cap);
263da853ecaSopenharmony_ci    vdec_ = OH_VideoDecoder_CreateByName("aabbcc");
264da853ecaSopenharmony_ci    if (vdec_) {
265da853ecaSopenharmony_ci        OH_VideoDecoder_Destroy(vdec_);
266da853ecaSopenharmony_ci        vdec_ = nullptr;
267da853ecaSopenharmony_ci    }
268da853ecaSopenharmony_ci    OH_AVCodec *tmpDec = OH_VideoDecoder_CreateByMime("aabbcc");
269da853ecaSopenharmony_ci    if (tmpDec) {
270da853ecaSopenharmony_ci        OH_VideoDecoder_Destroy(tmpDec);
271da853ecaSopenharmony_ci        tmpDec = nullptr;
272da853ecaSopenharmony_ci    }
273da853ecaSopenharmony_ci    tmpDec = OH_VideoDecoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
274da853ecaSopenharmony_ci    if (tmpDec) {
275da853ecaSopenharmony_ci        OH_VideoDecoder_Destroy(tmpDec);
276da853ecaSopenharmony_ci        tmpDec = nullptr;
277da853ecaSopenharmony_ci    }
278da853ecaSopenharmony_ci    vdec_ = OH_VideoDecoder_CreateByName(codecName.c_str());
279da853ecaSopenharmony_ci    g_decSample = this;
280da853ecaSopenharmony_ci    return vdec_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
281da853ecaSopenharmony_ci}
282da853ecaSopenharmony_ci
283da853ecaSopenharmony_civoid VDecFuzzSample::WaitForEOS()
284da853ecaSopenharmony_ci{
285da853ecaSopenharmony_ci    if (inputLoop_ && inputLoop_->joinable()) {
286da853ecaSopenharmony_ci        inputLoop_->join();
287da853ecaSopenharmony_ci    }
288da853ecaSopenharmony_ci}
289da853ecaSopenharmony_ci
290da853ecaSopenharmony_civoid VDecFuzzSample::CopyStartCode(uint8_t *frameBuffer, uint32_t bufferSize, OH_AVCodecBufferAttr &attr)
291da853ecaSopenharmony_ci{
292da853ecaSopenharmony_ci    switch (frameBuffer[START_CODE_SIZE] & H264_NALU_TYPE) {
293da853ecaSopenharmony_ci        case SPS:
294da853ecaSopenharmony_ci        case PPS:
295da853ecaSopenharmony_ci        case SEI:
296da853ecaSopenharmony_ci            if (memcpy_s(frameBuffer, bufferSize + START_CODE_SIZE, START_CODE, START_CODE_SIZE) != EOK) {
297da853ecaSopenharmony_ci                cout << "Fatal: memory copy failed" << endl;
298da853ecaSopenharmony_ci            }
299da853ecaSopenharmony_ci            attr.pts = GetSystemTimeUs();
300da853ecaSopenharmony_ci            attr.size = bufferSize + START_CODE_SIZE;
301da853ecaSopenharmony_ci            attr.offset = 0;
302da853ecaSopenharmony_ci            attr.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
303da853ecaSopenharmony_ci            break;
304da853ecaSopenharmony_ci        default: {
305da853ecaSopenharmony_ci            if (memcpy_s(frameBuffer, bufferSize + START_CODE_SIZE, START_CODE, START_CODE_SIZE) != EOK) {
306da853ecaSopenharmony_ci                cout << "Fatal: memory copy failed" << endl;
307da853ecaSopenharmony_ci            }
308da853ecaSopenharmony_ci            attr.pts = GetSystemTimeUs();
309da853ecaSopenharmony_ci            attr.size = bufferSize + START_CODE_SIZE;
310da853ecaSopenharmony_ci            attr.offset = 0;
311da853ecaSopenharmony_ci            attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
312da853ecaSopenharmony_ci        }
313da853ecaSopenharmony_ci    }
314da853ecaSopenharmony_ci}
315da853ecaSopenharmony_ci
316da853ecaSopenharmony_ciint32_t VDecFuzzSample::ReadData(uint32_t index, OH_AVMemory *buffer)
317da853ecaSopenharmony_ci{
318da853ecaSopenharmony_ci    uint8_t ch[4] = {};
319da853ecaSopenharmony_ci    (void)inFile_->read(reinterpret_cast<char *>(ch), START_CODE_SIZE);
320da853ecaSopenharmony_ci    if (inFile_->eof()) {
321da853ecaSopenharmony_ci        SetEOS(index);
322da853ecaSopenharmony_ci        return 1;
323da853ecaSopenharmony_ci    }
324da853ecaSopenharmony_ci    uint32_t bufferSize = static_cast<uint32_t>(((ch[3] & 0xFF)) | ((ch[2] & 0xFF) << EIGHT) |
325da853ecaSopenharmony_ci    ((ch[1] & 0xFF) << SIXTEEN) | ((ch[0] & 0xFF) << TWENTY_FOUR));
326da853ecaSopenharmony_ci
327da853ecaSopenharmony_ci    return SendData(bufferSize, index, buffer);
328da853ecaSopenharmony_ci}
329da853ecaSopenharmony_ci
330da853ecaSopenharmony_ciuint32_t VDecFuzzSample::SendData(uint32_t bufferSize, uint32_t index, OH_AVMemory *buffer)
331da853ecaSopenharmony_ci{
332da853ecaSopenharmony_ci    OH_AVCodecBufferAttr attr;
333da853ecaSopenharmony_ci    uint8_t *frameBuffer = new uint8_t[bufferSize + START_CODE_SIZE];
334da853ecaSopenharmony_ci    (void)inFile_->read(reinterpret_cast<char *>(frameBuffer + START_CODE_SIZE), bufferSize);
335da853ecaSopenharmony_ci    CopyStartCode(frameBuffer, bufferSize, attr);
336da853ecaSopenharmony_ci    int32_t size = OH_AVMemory_GetSize(buffer);
337da853ecaSopenharmony_ci    if (size < attr.size) {
338da853ecaSopenharmony_ci        delete[] frameBuffer;
339da853ecaSopenharmony_ci        isRunning_.store(false);
340da853ecaSopenharmony_ci        return 1;
341da853ecaSopenharmony_ci    }
342da853ecaSopenharmony_ci    uint8_t *bufferAddr = OH_AVMemory_GetAddr(buffer);
343da853ecaSopenharmony_ci    if (memcpy_s(bufferAddr, size, frameBuffer, attr.size) != EOK) {
344da853ecaSopenharmony_ci        delete[] frameBuffer;
345da853ecaSopenharmony_ci        isRunning_.store(false);
346da853ecaSopenharmony_ci        return 1;
347da853ecaSopenharmony_ci    }
348da853ecaSopenharmony_ci    delete[] frameBuffer;
349da853ecaSopenharmony_ci    int32_t ret = OH_VideoDecoder_PushInputData(vdec_, index, attr);
350da853ecaSopenharmony_ci    if (ret != AV_ERR_OK) {
351da853ecaSopenharmony_ci        errCount++;
352da853ecaSopenharmony_ci    }
353da853ecaSopenharmony_ci    frameCount_++;
354da853ecaSopenharmony_ci    if (inFile_->eof()) {
355da853ecaSopenharmony_ci        isRunning_.store(false);
356da853ecaSopenharmony_ci    }
357da853ecaSopenharmony_ci    return 0;
358da853ecaSopenharmony_ci}
359da853ecaSopenharmony_ci
360da853ecaSopenharmony_civoid VDecFuzzSample::InputFuncAVCC()
361da853ecaSopenharmony_ci{
362da853ecaSopenharmony_ci    frameCount_ = 1;
363da853ecaSopenharmony_ci    errCount = 0;
364da853ecaSopenharmony_ci    while (true) {
365da853ecaSopenharmony_ci        if (!isRunning_.load()) {
366da853ecaSopenharmony_ci            break;
367da853ecaSopenharmony_ci        }
368da853ecaSopenharmony_ci        unique_lock<mutex> lock(signal_->inMutex_);
369da853ecaSopenharmony_ci        signal_->inCond_.wait(lock, [this]() {
370da853ecaSopenharmony_ci            if (!isRunning_.load()) {
371da853ecaSopenharmony_ci                cout << "quit signal" << endl;
372da853ecaSopenharmony_ci                return true;
373da853ecaSopenharmony_ci            }
374da853ecaSopenharmony_ci            return signal_->inIdxQueue_.size() > 0;
375da853ecaSopenharmony_ci        });
376da853ecaSopenharmony_ci        if (!isRunning_.load()) {
377da853ecaSopenharmony_ci            break;
378da853ecaSopenharmony_ci        }
379da853ecaSopenharmony_ci        uint32_t index = signal_->inIdxQueue_.front();
380da853ecaSopenharmony_ci        auto buffer = signal_->inBufferQueue_.front();
381da853ecaSopenharmony_ci        signal_->inIdxQueue_.pop();
382da853ecaSopenharmony_ci        signal_->inBufferQueue_.pop();
383da853ecaSopenharmony_ci        lock.unlock();
384da853ecaSopenharmony_ci        if (!inFile_->eof()) {
385da853ecaSopenharmony_ci            int ret = ReadData(index, buffer);
386da853ecaSopenharmony_ci            if (ret == 1) {
387da853ecaSopenharmony_ci                break;
388da853ecaSopenharmony_ci            }
389da853ecaSopenharmony_ci        }
390da853ecaSopenharmony_ci    }
391da853ecaSopenharmony_ci}
392da853ecaSopenharmony_ci
393da853ecaSopenharmony_ciOH_AVErrCode VDecFuzzSample::InputFuncFUZZ(const uint8_t *data, size_t size)
394da853ecaSopenharmony_ci{
395da853ecaSopenharmony_ci    uint32_t index;
396da853ecaSopenharmony_ci    unique_lock<mutex> lock(signal_->inMutex_);
397da853ecaSopenharmony_ci    signal_->inCond_.wait(lock, [this]() {
398da853ecaSopenharmony_ci        if (!isRunning_.load() && g_fuzzError) {
399da853ecaSopenharmony_ci            return true;
400da853ecaSopenharmony_ci        }
401da853ecaSopenharmony_ci        return signal_->inIdxQueue_.size() > 0;
402da853ecaSopenharmony_ci    });
403da853ecaSopenharmony_ci    if (g_fuzzError)
404da853ecaSopenharmony_ci        return AV_ERR_TIMEOUT;
405da853ecaSopenharmony_ci    index = signal_->inIdxQueue_.front();
406da853ecaSopenharmony_ci    auto buffer = signal_->inBufferQueue_.front();
407da853ecaSopenharmony_ci    lock.unlock();
408da853ecaSopenharmony_ci    int32_t bufferSize = OH_AVMemory_GetSize(buffer);
409da853ecaSopenharmony_ci    uint8_t *bufferAddr = OH_AVMemory_GetAddr(buffer);
410da853ecaSopenharmony_ci
411da853ecaSopenharmony_ci    if (memcpy_s(bufferAddr, bufferSize, data, size) != EOK) {
412da853ecaSopenharmony_ci        cout << "Fatal: memcpy fail" << endl;
413da853ecaSopenharmony_ci        return AV_ERR_NO_MEMORY;
414da853ecaSopenharmony_ci    }
415da853ecaSopenharmony_ci    OH_AVCodecBufferAttr attr;
416da853ecaSopenharmony_ci    attr.pts = GetSystemTimeUs();
417da853ecaSopenharmony_ci    attr.size = bufferSize;
418da853ecaSopenharmony_ci    attr.offset = 0;
419da853ecaSopenharmony_ci    attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
420da853ecaSopenharmony_ci    OH_AVErrCode ret = OH_VideoDecoder_PushInputData(vdec_, index, attr);
421da853ecaSopenharmony_ci    signal_->inIdxQueue_.pop();
422da853ecaSopenharmony_ci    signal_->inBufferQueue_.pop();
423da853ecaSopenharmony_ci    return ret;
424da853ecaSopenharmony_ci}
425da853ecaSopenharmony_ci
426da853ecaSopenharmony_civoid VDecFuzzSample::SetEOS(uint32_t index)
427da853ecaSopenharmony_ci{
428da853ecaSopenharmony_ci    OH_AVCodecBufferAttr attr;
429da853ecaSopenharmony_ci    attr.pts = 0;
430da853ecaSopenharmony_ci    attr.size = 0;
431da853ecaSopenharmony_ci    attr.offset = 0;
432da853ecaSopenharmony_ci    attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
433da853ecaSopenharmony_ci    int32_t res = OH_VideoDecoder_PushInputData(vdec_, index, attr);
434da853ecaSopenharmony_ci    cout << "OH_VideoDecoder_PushInputData    EOS   res: " << res << endl;
435da853ecaSopenharmony_ci}
436da853ecaSopenharmony_ci
437da853ecaSopenharmony_ciint32_t VDecFuzzSample::Flush()
438da853ecaSopenharmony_ci{
439da853ecaSopenharmony_ci    unique_lock<mutex> inLock(signal_->inMutex_);
440da853ecaSopenharmony_ci    clearIntqueue(signal_->inIdxQueue_);
441da853ecaSopenharmony_ci    signal_->inCond_.notify_all();
442da853ecaSopenharmony_ci    inLock.unlock();
443da853ecaSopenharmony_ci    unique_lock<mutex> outLock(signal_->outMutex_);
444da853ecaSopenharmony_ci    clearIntqueue(signal_->outIdxQueue_);
445da853ecaSopenharmony_ci    clearBufferqueue(signal_->attrQueue_);
446da853ecaSopenharmony_ci    signal_->outCond_.notify_all();
447da853ecaSopenharmony_ci    outLock.unlock();
448da853ecaSopenharmony_ci    isRunning_.store(false);
449da853ecaSopenharmony_ci    return OH_VideoDecoder_Flush(vdec_);
450da853ecaSopenharmony_ci}
451da853ecaSopenharmony_ci
452da853ecaSopenharmony_ciint32_t VDecFuzzSample::Reset()
453da853ecaSopenharmony_ci{
454da853ecaSopenharmony_ci    isRunning_.store(false);
455da853ecaSopenharmony_ci    StopInLoop();
456da853ecaSopenharmony_ci    ReleaseInFile();
457da853ecaSopenharmony_ci    return OH_VideoDecoder_Reset(vdec_);
458da853ecaSopenharmony_ci}
459da853ecaSopenharmony_ci
460da853ecaSopenharmony_ciint32_t VDecFuzzSample::Release()
461da853ecaSopenharmony_ci{
462da853ecaSopenharmony_ci    int ret = 0;
463da853ecaSopenharmony_ci    if (vdec_ != nullptr) {
464da853ecaSopenharmony_ci        ret = OH_VideoDecoder_Destroy(vdec_);
465da853ecaSopenharmony_ci        vdec_ = nullptr;
466da853ecaSopenharmony_ci    }
467da853ecaSopenharmony_ci
468da853ecaSopenharmony_ci    if (signal_ != nullptr) {
469da853ecaSopenharmony_ci        clearAvBufferQueue(signal_->inBufferQueue_);
470da853ecaSopenharmony_ci        delete signal_;
471da853ecaSopenharmony_ci        signal_ = nullptr;
472da853ecaSopenharmony_ci    }
473da853ecaSopenharmony_ci    return ret;
474da853ecaSopenharmony_ci}
475da853ecaSopenharmony_ci
476da853ecaSopenharmony_ciint32_t VDecFuzzSample::Stop()
477da853ecaSopenharmony_ci{
478da853ecaSopenharmony_ci    StopInLoop();
479da853ecaSopenharmony_ci    clearIntqueue(signal_->outIdxQueue_);
480da853ecaSopenharmony_ci    clearBufferqueue(signal_->attrQueue_);
481da853ecaSopenharmony_ci    ReleaseInFile();
482da853ecaSopenharmony_ci    return OH_VideoDecoder_Stop(vdec_);
483da853ecaSopenharmony_ci}
484da853ecaSopenharmony_ci
485da853ecaSopenharmony_ciint32_t VDecFuzzSample::Start()
486da853ecaSopenharmony_ci{
487da853ecaSopenharmony_ci    int32_t ret = OH_VideoDecoder_Start(vdec_);
488da853ecaSopenharmony_ci    if (ret == AV_ERR_OK) {
489da853ecaSopenharmony_ci        isRunning_.store(true);
490da853ecaSopenharmony_ci    }
491da853ecaSopenharmony_ci    return ret;
492da853ecaSopenharmony_ci}
493da853ecaSopenharmony_ci
494da853ecaSopenharmony_civoid VDecFuzzSample::SetParameter(int32_t data)
495da853ecaSopenharmony_ci{
496da853ecaSopenharmony_ci    OH_AVFormat *format = OH_AVFormat_Create();
497da853ecaSopenharmony_ci    (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, data);
498da853ecaSopenharmony_ci    (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, data);
499da853ecaSopenharmony_ci    OH_VideoDecoder_SetParameter(vdec_, format);
500da853ecaSopenharmony_ci    OH_AVFormat_Destroy(format);
501da853ecaSopenharmony_ci}