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