xref: /aosp_15_r20/external/libhevc/fuzzer/hevc_dec_fuzzer.cpp (revision c83a76b084498d55f252f48b2e3786804cdf24b7)
1*c83a76b0SSuyog Pawar /******************************************************************************
2*c83a76b0SSuyog Pawar  *
3*c83a76b0SSuyog Pawar  * Copyright (C) 2019 The Android Open Source Project
4*c83a76b0SSuyog Pawar  *
5*c83a76b0SSuyog Pawar  * Licensed under the Apache License, Version 2.0 (the "License");
6*c83a76b0SSuyog Pawar  * you may not use this file except in compliance with the License.
7*c83a76b0SSuyog Pawar  * You may obtain a copy of the License at:
8*c83a76b0SSuyog Pawar  *
9*c83a76b0SSuyog Pawar  * http://www.apache.org/licenses/LICENSE-2.0
10*c83a76b0SSuyog Pawar  *
11*c83a76b0SSuyog Pawar  * Unless required by applicable law or agreed to in writing, software
12*c83a76b0SSuyog Pawar  * distributed under the License is distributed on an "AS IS" BASIS,
13*c83a76b0SSuyog Pawar  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*c83a76b0SSuyog Pawar  * See the License for the specific language governing permissions and
15*c83a76b0SSuyog Pawar  * limitations under the License.
16*c83a76b0SSuyog Pawar  *
17*c83a76b0SSuyog Pawar  *****************************************************************************
18*c83a76b0SSuyog Pawar  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19*c83a76b0SSuyog Pawar  */
20*c83a76b0SSuyog Pawar 
21*c83a76b0SSuyog Pawar #include <stddef.h>
22*c83a76b0SSuyog Pawar #include <stdint.h>
23*c83a76b0SSuyog Pawar #include <stdio.h>
24*c83a76b0SSuyog Pawar #include <stdlib.h>
25*c83a76b0SSuyog Pawar #include <string.h>
26*c83a76b0SSuyog Pawar 
27*c83a76b0SSuyog Pawar #include <algorithm>
28*c83a76b0SSuyog Pawar #include <memory>
29*c83a76b0SSuyog Pawar 
30*c83a76b0SSuyog Pawar #include "ihevc_typedefs.h"
31*c83a76b0SSuyog Pawar #include "ihevcd_cxa.h"
32*c83a76b0SSuyog Pawar #include "iv.h"
33*c83a76b0SSuyog Pawar #include "ivd.h"
34*c83a76b0SSuyog Pawar 
35*c83a76b0SSuyog Pawar #define NELEMENTS(x) (sizeof(x) / sizeof(x[0]))
36*c83a76b0SSuyog Pawar #define ivd_api_function ihevcd_cxa_api_function
37*c83a76b0SSuyog Pawar const IV_COLOR_FORMAT_T supportedColorFormats[] = {
38*c83a76b0SSuyog Pawar     IV_YUV_420P,   IV_YUV_420SP_UV, IV_YUV_420SP_VU,
39*c83a76b0SSuyog Pawar     IV_YUV_422ILE, IV_RGB_565,      IV_RGBA_8888};
40*c83a76b0SSuyog Pawar 
41*c83a76b0SSuyog Pawar /* Decoder ignores invalid arch, i.e. for arm build, if SSSE3 is requested,
42*c83a76b0SSuyog Pawar  * decoder defaults to a supported configuration. So same set of supported
43*c83a76b0SSuyog Pawar  * architectures can be used in arm/arm64/x86 builds */
44*c83a76b0SSuyog Pawar const IVD_ARCH_T supportedArchitectures[] = {
45*c83a76b0SSuyog Pawar     ARCH_ARM_NONEON,  ARCH_ARM_A9Q,   ARCH_ARM_NEONINTR, ARCH_ARMV8_GENERIC,
46*c83a76b0SSuyog Pawar     ARCH_X86_GENERIC, ARCH_X86_SSSE3, ARCH_X86_SSE42};
47*c83a76b0SSuyog Pawar 
48*c83a76b0SSuyog Pawar enum {
49*c83a76b0SSuyog Pawar   OFFSET_COLOR_FORMAT = 6,
50*c83a76b0SSuyog Pawar   OFFSET_NUM_CORES,
51*c83a76b0SSuyog Pawar   OFFSET_ARCH,
52*c83a76b0SSuyog Pawar   /* Should be the last entry */
53*c83a76b0SSuyog Pawar   OFFSET_MAX,
54*c83a76b0SSuyog Pawar };
55*c83a76b0SSuyog Pawar 
56*c83a76b0SSuyog Pawar const static int kMaxNumDecodeCalls = 100;
57*c83a76b0SSuyog Pawar const static int kSupportedColorFormats = NELEMENTS(supportedColorFormats);
58*c83a76b0SSuyog Pawar const static int kSupportedArchitectures = NELEMENTS(supportedArchitectures);
59*c83a76b0SSuyog Pawar const static int kMaxCores = 4;
iv_aligned_malloc(void * ctxt,WORD32 alignment,WORD32 size)60*c83a76b0SSuyog Pawar void *iv_aligned_malloc(void *ctxt, WORD32 alignment, WORD32 size) {
61*c83a76b0SSuyog Pawar   void *buf = NULL;
62*c83a76b0SSuyog Pawar   (void)ctxt;
63*c83a76b0SSuyog Pawar   if (0 != posix_memalign(&buf, alignment, size)) {
64*c83a76b0SSuyog Pawar       return NULL;
65*c83a76b0SSuyog Pawar   }
66*c83a76b0SSuyog Pawar   return buf;
67*c83a76b0SSuyog Pawar }
68*c83a76b0SSuyog Pawar 
iv_aligned_free(void * ctxt,void * buf)69*c83a76b0SSuyog Pawar void iv_aligned_free(void *ctxt, void *buf) {
70*c83a76b0SSuyog Pawar   (void)ctxt;
71*c83a76b0SSuyog Pawar   free(buf);
72*c83a76b0SSuyog Pawar }
73*c83a76b0SSuyog Pawar 
74*c83a76b0SSuyog Pawar class Codec {
75*c83a76b0SSuyog Pawar  public:
76*c83a76b0SSuyog Pawar   Codec(IV_COLOR_FORMAT_T colorFormat, size_t numCores);
77*c83a76b0SSuyog Pawar   ~Codec();
78*c83a76b0SSuyog Pawar 
79*c83a76b0SSuyog Pawar   void createCodec();
80*c83a76b0SSuyog Pawar   void deleteCodec();
81*c83a76b0SSuyog Pawar   void resetCodec();
82*c83a76b0SSuyog Pawar   void setCores();
83*c83a76b0SSuyog Pawar   void allocFrame();
84*c83a76b0SSuyog Pawar   void freeFrame();
85*c83a76b0SSuyog Pawar   void decodeHeader(const uint8_t *data, size_t size);
86*c83a76b0SSuyog Pawar   IV_API_CALL_STATUS_T decodeFrame(const uint8_t *data, size_t size,
87*c83a76b0SSuyog Pawar                                    size_t *bytesConsumed);
88*c83a76b0SSuyog Pawar   void setParams(IVD_VIDEO_DECODE_MODE_T mode);
89*c83a76b0SSuyog Pawar   void setArchitecture(IVD_ARCH_T arch);
90*c83a76b0SSuyog Pawar 
91*c83a76b0SSuyog Pawar  private:
92*c83a76b0SSuyog Pawar   IV_COLOR_FORMAT_T mColorFormat;
93*c83a76b0SSuyog Pawar   size_t mNumCores;
94*c83a76b0SSuyog Pawar   iv_obj_t *mCodec;
95*c83a76b0SSuyog Pawar   ivd_out_bufdesc_t mOutBufHandle;
96*c83a76b0SSuyog Pawar   uint32_t mWidth;
97*c83a76b0SSuyog Pawar   uint32_t mHeight;
98*c83a76b0SSuyog Pawar };
99*c83a76b0SSuyog Pawar 
Codec(IV_COLOR_FORMAT_T colorFormat,size_t numCores)100*c83a76b0SSuyog Pawar Codec::Codec(IV_COLOR_FORMAT_T colorFormat, size_t numCores) {
101*c83a76b0SSuyog Pawar   mColorFormat = colorFormat;
102*c83a76b0SSuyog Pawar   mNumCores = numCores;
103*c83a76b0SSuyog Pawar   mCodec = nullptr;
104*c83a76b0SSuyog Pawar   mWidth = 0;
105*c83a76b0SSuyog Pawar   mHeight = 0;
106*c83a76b0SSuyog Pawar 
107*c83a76b0SSuyog Pawar   memset(&mOutBufHandle, 0, sizeof(mOutBufHandle));
108*c83a76b0SSuyog Pawar }
109*c83a76b0SSuyog Pawar 
~Codec()110*c83a76b0SSuyog Pawar Codec::~Codec() {}
111*c83a76b0SSuyog Pawar 
createCodec()112*c83a76b0SSuyog Pawar void Codec::createCodec() {
113*c83a76b0SSuyog Pawar   IV_API_CALL_STATUS_T ret;
114*c83a76b0SSuyog Pawar   ihevcd_cxa_create_ip_t create_ip{};
115*c83a76b0SSuyog Pawar   ihevcd_cxa_create_op_t create_op{};
116*c83a76b0SSuyog Pawar   void *fxns = (void *)&ivd_api_function;
117*c83a76b0SSuyog Pawar 
118*c83a76b0SSuyog Pawar   create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
119*c83a76b0SSuyog Pawar   create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 0;
120*c83a76b0SSuyog Pawar   create_ip.s_ivd_create_ip_t.e_output_format = mColorFormat;
121*c83a76b0SSuyog Pawar   create_ip.u4_keep_threads_active = 1;
122*c83a76b0SSuyog Pawar   create_ip.s_ivd_create_ip_t.pf_aligned_alloc = iv_aligned_malloc;
123*c83a76b0SSuyog Pawar   create_ip.s_ivd_create_ip_t.pf_aligned_free = iv_aligned_free;
124*c83a76b0SSuyog Pawar   create_ip.s_ivd_create_ip_t.pv_mem_ctxt = NULL;
125*c83a76b0SSuyog Pawar   create_ip.s_ivd_create_ip_t.u4_size = sizeof(ihevcd_cxa_create_ip_t);
126*c83a76b0SSuyog Pawar   create_op.s_ivd_create_op_t.u4_size = sizeof(ihevcd_cxa_create_op_t);
127*c83a76b0SSuyog Pawar 
128*c83a76b0SSuyog Pawar   ret = ivd_api_function(NULL, (void *)&create_ip, (void *)&create_op);
129*c83a76b0SSuyog Pawar   if (ret != IV_SUCCESS) {
130*c83a76b0SSuyog Pawar     return;
131*c83a76b0SSuyog Pawar   }
132*c83a76b0SSuyog Pawar   mCodec = (iv_obj_t *)create_op.s_ivd_create_op_t.pv_handle;
133*c83a76b0SSuyog Pawar   mCodec->pv_fxns = fxns;
134*c83a76b0SSuyog Pawar   mCodec->u4_size = sizeof(iv_obj_t);
135*c83a76b0SSuyog Pawar }
136*c83a76b0SSuyog Pawar 
deleteCodec()137*c83a76b0SSuyog Pawar void Codec::deleteCodec() {
138*c83a76b0SSuyog Pawar   ivd_delete_ip_t delete_ip{};
139*c83a76b0SSuyog Pawar   ivd_delete_op_t delete_op{};
140*c83a76b0SSuyog Pawar 
141*c83a76b0SSuyog Pawar   delete_ip.e_cmd = IVD_CMD_DELETE;
142*c83a76b0SSuyog Pawar   delete_ip.u4_size = sizeof(ivd_delete_ip_t);
143*c83a76b0SSuyog Pawar   delete_op.u4_size = sizeof(ivd_delete_op_t);
144*c83a76b0SSuyog Pawar 
145*c83a76b0SSuyog Pawar   ivd_api_function(mCodec, (void *)&delete_ip, (void *)&delete_op);
146*c83a76b0SSuyog Pawar }
147*c83a76b0SSuyog Pawar 
resetCodec()148*c83a76b0SSuyog Pawar void Codec::resetCodec() {
149*c83a76b0SSuyog Pawar   ivd_ctl_reset_ip_t s_ctl_ip{};
150*c83a76b0SSuyog Pawar   ivd_ctl_reset_op_t s_ctl_op{};
151*c83a76b0SSuyog Pawar 
152*c83a76b0SSuyog Pawar   s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
153*c83a76b0SSuyog Pawar   s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_RESET;
154*c83a76b0SSuyog Pawar   s_ctl_ip.u4_size = sizeof(ivd_ctl_reset_ip_t);
155*c83a76b0SSuyog Pawar   s_ctl_op.u4_size = sizeof(ivd_ctl_reset_op_t);
156*c83a76b0SSuyog Pawar 
157*c83a76b0SSuyog Pawar   ivd_api_function(mCodec, (void *)&s_ctl_ip, (void *)&s_ctl_op);
158*c83a76b0SSuyog Pawar }
159*c83a76b0SSuyog Pawar 
setCores()160*c83a76b0SSuyog Pawar void Codec::setCores() {
161*c83a76b0SSuyog Pawar   ihevcd_cxa_ctl_set_num_cores_ip_t s_ctl_ip{};
162*c83a76b0SSuyog Pawar   ihevcd_cxa_ctl_set_num_cores_op_t s_ctl_op{};
163*c83a76b0SSuyog Pawar 
164*c83a76b0SSuyog Pawar   s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
165*c83a76b0SSuyog Pawar   s_ctl_ip.e_sub_cmd =
166*c83a76b0SSuyog Pawar       (IVD_CONTROL_API_COMMAND_TYPE_T)IHEVCD_CXA_CMD_CTL_SET_NUM_CORES;
167*c83a76b0SSuyog Pawar   s_ctl_ip.u4_num_cores = mNumCores;
168*c83a76b0SSuyog Pawar   s_ctl_ip.u4_size = sizeof(ihevcd_cxa_ctl_set_num_cores_ip_t);
169*c83a76b0SSuyog Pawar   s_ctl_op.u4_size = sizeof(ihevcd_cxa_ctl_set_num_cores_op_t);
170*c83a76b0SSuyog Pawar 
171*c83a76b0SSuyog Pawar   ivd_api_function(mCodec, (void *)&s_ctl_ip, (void *)&s_ctl_op);
172*c83a76b0SSuyog Pawar }
173*c83a76b0SSuyog Pawar 
setParams(IVD_VIDEO_DECODE_MODE_T mode)174*c83a76b0SSuyog Pawar void Codec::setParams(IVD_VIDEO_DECODE_MODE_T mode) {
175*c83a76b0SSuyog Pawar   ivd_ctl_set_config_ip_t s_ctl_ip{};
176*c83a76b0SSuyog Pawar   ivd_ctl_set_config_op_t s_ctl_op{};
177*c83a76b0SSuyog Pawar 
178*c83a76b0SSuyog Pawar   s_ctl_ip.u4_disp_wd = 0;
179*c83a76b0SSuyog Pawar   s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE;
180*c83a76b0SSuyog Pawar   s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
181*c83a76b0SSuyog Pawar   s_ctl_ip.e_vid_dec_mode = mode;
182*c83a76b0SSuyog Pawar   s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
183*c83a76b0SSuyog Pawar   s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
184*c83a76b0SSuyog Pawar   s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);
185*c83a76b0SSuyog Pawar   s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t);
186*c83a76b0SSuyog Pawar 
187*c83a76b0SSuyog Pawar   ivd_api_function(mCodec, (void *)&s_ctl_ip, (void *)&s_ctl_op);
188*c83a76b0SSuyog Pawar }
189*c83a76b0SSuyog Pawar 
setArchitecture(IVD_ARCH_T arch)190*c83a76b0SSuyog Pawar void Codec::setArchitecture(IVD_ARCH_T arch) {
191*c83a76b0SSuyog Pawar   ihevcd_cxa_ctl_set_processor_ip_t s_ctl_ip{};
192*c83a76b0SSuyog Pawar   ihevcd_cxa_ctl_set_processor_op_t s_ctl_op{};
193*c83a76b0SSuyog Pawar 
194*c83a76b0SSuyog Pawar   s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
195*c83a76b0SSuyog Pawar   s_ctl_ip.e_sub_cmd =
196*c83a76b0SSuyog Pawar       (IVD_CONTROL_API_COMMAND_TYPE_T)IHEVCD_CXA_CMD_CTL_SET_PROCESSOR;
197*c83a76b0SSuyog Pawar   s_ctl_ip.u4_arch = arch;
198*c83a76b0SSuyog Pawar   s_ctl_ip.u4_soc = SOC_GENERIC;
199*c83a76b0SSuyog Pawar   s_ctl_ip.u4_size = sizeof(ihevcd_cxa_ctl_set_processor_ip_t);
200*c83a76b0SSuyog Pawar   s_ctl_op.u4_size = sizeof(ihevcd_cxa_ctl_set_processor_op_t);
201*c83a76b0SSuyog Pawar 
202*c83a76b0SSuyog Pawar   ivd_api_function(mCodec, (void *)&s_ctl_ip, (void *)&s_ctl_op);
203*c83a76b0SSuyog Pawar }
freeFrame()204*c83a76b0SSuyog Pawar void Codec::freeFrame() {
205*c83a76b0SSuyog Pawar   for (int i = 0; i < mOutBufHandle.u4_num_bufs; i++) {
206*c83a76b0SSuyog Pawar     if (mOutBufHandle.pu1_bufs[i]) {
207*c83a76b0SSuyog Pawar       free(mOutBufHandle.pu1_bufs[i]);
208*c83a76b0SSuyog Pawar       mOutBufHandle.pu1_bufs[i] = nullptr;
209*c83a76b0SSuyog Pawar     }
210*c83a76b0SSuyog Pawar   }
211*c83a76b0SSuyog Pawar }
212*c83a76b0SSuyog Pawar 
allocFrame()213*c83a76b0SSuyog Pawar void Codec::allocFrame() {
214*c83a76b0SSuyog Pawar   size_t sizes[4] = {0};
215*c83a76b0SSuyog Pawar   size_t num_bufs = 0;
216*c83a76b0SSuyog Pawar 
217*c83a76b0SSuyog Pawar   freeFrame();
218*c83a76b0SSuyog Pawar 
219*c83a76b0SSuyog Pawar   memset(&mOutBufHandle, 0, sizeof(mOutBufHandle));
220*c83a76b0SSuyog Pawar 
221*c83a76b0SSuyog Pawar   switch (mColorFormat) {
222*c83a76b0SSuyog Pawar     case IV_YUV_420SP_UV:
223*c83a76b0SSuyog Pawar       [[fallthrough]];
224*c83a76b0SSuyog Pawar     case IV_YUV_420SP_VU:
225*c83a76b0SSuyog Pawar       sizes[0] = mWidth * mHeight;
226*c83a76b0SSuyog Pawar       sizes[1] = mWidth * mHeight >> 1;
227*c83a76b0SSuyog Pawar       num_bufs = 2;
228*c83a76b0SSuyog Pawar       break;
229*c83a76b0SSuyog Pawar     case IV_YUV_422ILE:
230*c83a76b0SSuyog Pawar       sizes[0] = mWidth * mHeight * 2;
231*c83a76b0SSuyog Pawar       num_bufs = 1;
232*c83a76b0SSuyog Pawar       break;
233*c83a76b0SSuyog Pawar     case IV_RGB_565:
234*c83a76b0SSuyog Pawar       sizes[0] = mWidth * mHeight * 2;
235*c83a76b0SSuyog Pawar       num_bufs = 1;
236*c83a76b0SSuyog Pawar       break;
237*c83a76b0SSuyog Pawar     case IV_RGBA_8888:
238*c83a76b0SSuyog Pawar       sizes[0] = mWidth * mHeight * 4;
239*c83a76b0SSuyog Pawar       num_bufs = 1;
240*c83a76b0SSuyog Pawar       break;
241*c83a76b0SSuyog Pawar     case IV_YUV_420P:
242*c83a76b0SSuyog Pawar       [[fallthrough]];
243*c83a76b0SSuyog Pawar     default:
244*c83a76b0SSuyog Pawar       sizes[0] = mWidth * mHeight;
245*c83a76b0SSuyog Pawar       sizes[1] = mWidth * mHeight >> 2;
246*c83a76b0SSuyog Pawar       sizes[2] = mWidth * mHeight >> 2;
247*c83a76b0SSuyog Pawar       num_bufs = 3;
248*c83a76b0SSuyog Pawar       break;
249*c83a76b0SSuyog Pawar   }
250*c83a76b0SSuyog Pawar   mOutBufHandle.u4_num_bufs = num_bufs;
251*c83a76b0SSuyog Pawar   for (int i = 0; i < num_bufs; i++) {
252*c83a76b0SSuyog Pawar     mOutBufHandle.u4_min_out_buf_size[i] = sizes[i];
253*c83a76b0SSuyog Pawar     mOutBufHandle.pu1_bufs[i] = (UWORD8 *)iv_aligned_malloc(NULL, 16, sizes[i]);
254*c83a76b0SSuyog Pawar   }
255*c83a76b0SSuyog Pawar }
256*c83a76b0SSuyog Pawar 
decodeHeader(const uint8_t * data,size_t size)257*c83a76b0SSuyog Pawar void Codec::decodeHeader(const uint8_t *data, size_t size) {
258*c83a76b0SSuyog Pawar   setParams(IVD_DECODE_HEADER);
259*c83a76b0SSuyog Pawar 
260*c83a76b0SSuyog Pawar   size_t numDecodeCalls = 0;
261*c83a76b0SSuyog Pawar 
262*c83a76b0SSuyog Pawar   while (size > 0 && numDecodeCalls < kMaxNumDecodeCalls) {
263*c83a76b0SSuyog Pawar     IV_API_CALL_STATUS_T ret;
264*c83a76b0SSuyog Pawar     ivd_video_decode_ip_t dec_ip{};
265*c83a76b0SSuyog Pawar     ivd_video_decode_op_t dec_op{};
266*c83a76b0SSuyog Pawar     size_t bytes_consumed;
267*c83a76b0SSuyog Pawar 
268*c83a76b0SSuyog Pawar     memset(&dec_ip, 0, sizeof(dec_ip));
269*c83a76b0SSuyog Pawar     memset(&dec_op, 0, sizeof(dec_op));
270*c83a76b0SSuyog Pawar 
271*c83a76b0SSuyog Pawar     dec_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
272*c83a76b0SSuyog Pawar     dec_ip.u4_ts = 0;
273*c83a76b0SSuyog Pawar     dec_ip.pv_stream_buffer = (void *)data;
274*c83a76b0SSuyog Pawar     dec_ip.u4_num_Bytes = size;
275*c83a76b0SSuyog Pawar     dec_ip.u4_size = sizeof(ivd_video_decode_ip_t);
276*c83a76b0SSuyog Pawar     dec_op.u4_size = sizeof(ivd_video_decode_op_t);
277*c83a76b0SSuyog Pawar 
278*c83a76b0SSuyog Pawar     ret = ivd_api_function(mCodec, (void *)&dec_ip, (void *)&dec_op);
279*c83a76b0SSuyog Pawar 
280*c83a76b0SSuyog Pawar     bytes_consumed = dec_op.u4_num_bytes_consumed;
281*c83a76b0SSuyog Pawar     /* If no bytes are consumed, then consume 4 bytes to ensure fuzzer proceeds
282*c83a76b0SSuyog Pawar      * to feed next data */
283*c83a76b0SSuyog Pawar     if (!bytes_consumed) bytes_consumed = 4;
284*c83a76b0SSuyog Pawar 
285*c83a76b0SSuyog Pawar     bytes_consumed = std::min(size, bytes_consumed);
286*c83a76b0SSuyog Pawar 
287*c83a76b0SSuyog Pawar     data += bytes_consumed;
288*c83a76b0SSuyog Pawar     size -= bytes_consumed;
289*c83a76b0SSuyog Pawar     numDecodeCalls++;
290*c83a76b0SSuyog Pawar 
291*c83a76b0SSuyog Pawar     mWidth = std::min(dec_op.u4_pic_wd, (UWORD32)10240);
292*c83a76b0SSuyog Pawar     mHeight = std::min(dec_op.u4_pic_ht, (UWORD32)10240);
293*c83a76b0SSuyog Pawar 
294*c83a76b0SSuyog Pawar     /* Break after successful header decode */
295*c83a76b0SSuyog Pawar     if (mWidth && mHeight) {
296*c83a76b0SSuyog Pawar       break;
297*c83a76b0SSuyog Pawar     }
298*c83a76b0SSuyog Pawar   }
299*c83a76b0SSuyog Pawar   /* if width / height are invalid, set them to defaults */
300*c83a76b0SSuyog Pawar   if (!mWidth) mWidth = 1920;
301*c83a76b0SSuyog Pawar   if (!mHeight) mHeight = 1088;
302*c83a76b0SSuyog Pawar }
303*c83a76b0SSuyog Pawar 
decodeFrame(const uint8_t * data,size_t size,size_t * bytesConsumed)304*c83a76b0SSuyog Pawar IV_API_CALL_STATUS_T Codec::decodeFrame(const uint8_t *data, size_t size,
305*c83a76b0SSuyog Pawar                                         size_t *bytesConsumed) {
306*c83a76b0SSuyog Pawar   IV_API_CALL_STATUS_T ret;
307*c83a76b0SSuyog Pawar   ivd_video_decode_ip_t dec_ip{};
308*c83a76b0SSuyog Pawar   ivd_video_decode_op_t dec_op{};
309*c83a76b0SSuyog Pawar 
310*c83a76b0SSuyog Pawar   memset(&dec_ip, 0, sizeof(dec_ip));
311*c83a76b0SSuyog Pawar   memset(&dec_op, 0, sizeof(dec_op));
312*c83a76b0SSuyog Pawar 
313*c83a76b0SSuyog Pawar   dec_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
314*c83a76b0SSuyog Pawar   dec_ip.u4_ts = 0;
315*c83a76b0SSuyog Pawar   dec_ip.pv_stream_buffer = (void *)data;
316*c83a76b0SSuyog Pawar   dec_ip.u4_num_Bytes = size;
317*c83a76b0SSuyog Pawar   dec_ip.u4_size = sizeof(ivd_video_decode_ip_t);
318*c83a76b0SSuyog Pawar   dec_ip.s_out_buffer = mOutBufHandle;
319*c83a76b0SSuyog Pawar 
320*c83a76b0SSuyog Pawar   dec_op.u4_size = sizeof(ivd_video_decode_op_t);
321*c83a76b0SSuyog Pawar 
322*c83a76b0SSuyog Pawar   ret = ivd_api_function(mCodec, (void *)&dec_ip, (void *)&dec_op);
323*c83a76b0SSuyog Pawar 
324*c83a76b0SSuyog Pawar   /* In case of change in resolution, reset codec and feed the same data again
325*c83a76b0SSuyog Pawar    */
326*c83a76b0SSuyog Pawar   if (IVD_RES_CHANGED == (dec_op.u4_error_code & 0xFF)) {
327*c83a76b0SSuyog Pawar     resetCodec();
328*c83a76b0SSuyog Pawar     ret = ivd_api_function(mCodec, (void *)&dec_ip, (void *)&dec_op);
329*c83a76b0SSuyog Pawar   }
330*c83a76b0SSuyog Pawar   *bytesConsumed = dec_op.u4_num_bytes_consumed;
331*c83a76b0SSuyog Pawar 
332*c83a76b0SSuyog Pawar   /* If no bytes are consumed, then consume 4 bytes to ensure fuzzer proceeds
333*c83a76b0SSuyog Pawar    * to feed next data */
334*c83a76b0SSuyog Pawar   if (!*bytesConsumed) *bytesConsumed = 4;
335*c83a76b0SSuyog Pawar 
336*c83a76b0SSuyog Pawar   if (dec_op.u4_pic_wd && dec_op.u4_pic_ht &&
337*c83a76b0SSuyog Pawar       (mWidth != dec_op.u4_pic_wd || mHeight != dec_op.u4_pic_ht)) {
338*c83a76b0SSuyog Pawar     mWidth = std::min(dec_op.u4_pic_wd, (UWORD32)10240);
339*c83a76b0SSuyog Pawar     mHeight = std::min(dec_op.u4_pic_ht, (UWORD32)10240);
340*c83a76b0SSuyog Pawar     allocFrame();
341*c83a76b0SSuyog Pawar   }
342*c83a76b0SSuyog Pawar 
343*c83a76b0SSuyog Pawar   return ret;
344*c83a76b0SSuyog Pawar }
345*c83a76b0SSuyog Pawar 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)346*c83a76b0SSuyog Pawar extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
347*c83a76b0SSuyog Pawar   if (size < 1) {
348*c83a76b0SSuyog Pawar     return 0;
349*c83a76b0SSuyog Pawar   }
350*c83a76b0SSuyog Pawar   size_t colorFormatOfst = std::min((size_t)OFFSET_COLOR_FORMAT, size - 1);
351*c83a76b0SSuyog Pawar   size_t numCoresOfst = std::min((size_t)OFFSET_NUM_CORES, size - 1);
352*c83a76b0SSuyog Pawar   size_t architectureOfst = std::min((size_t)OFFSET_ARCH, size - 1);
353*c83a76b0SSuyog Pawar   size_t architectureIdx = data[architectureOfst] % kSupportedArchitectures;
354*c83a76b0SSuyog Pawar   IVD_ARCH_T arch = (IVD_ARCH_T)supportedArchitectures[architectureIdx];
355*c83a76b0SSuyog Pawar   size_t colorFormatIdx = data[colorFormatOfst] % kSupportedColorFormats;
356*c83a76b0SSuyog Pawar   IV_COLOR_FORMAT_T colorFormat =
357*c83a76b0SSuyog Pawar       (IV_COLOR_FORMAT_T)(supportedColorFormats[colorFormatIdx]);
358*c83a76b0SSuyog Pawar   uint32_t numCores = (data[numCoresOfst] % kMaxCores) + 1;
359*c83a76b0SSuyog Pawar   size_t numDecodeCalls = 0;
360*c83a76b0SSuyog Pawar   Codec *codec = new Codec(colorFormat, numCores);
361*c83a76b0SSuyog Pawar   codec->createCodec();
362*c83a76b0SSuyog Pawar   codec->setArchitecture(arch);
363*c83a76b0SSuyog Pawar   codec->setCores();
364*c83a76b0SSuyog Pawar   codec->decodeHeader(data, size);
365*c83a76b0SSuyog Pawar   codec->setParams(IVD_DECODE_FRAME);
366*c83a76b0SSuyog Pawar   codec->allocFrame();
367*c83a76b0SSuyog Pawar 
368*c83a76b0SSuyog Pawar   while (size > 0 && numDecodeCalls < kMaxNumDecodeCalls) {
369*c83a76b0SSuyog Pawar     IV_API_CALL_STATUS_T ret;
370*c83a76b0SSuyog Pawar     size_t bytesConsumed;
371*c83a76b0SSuyog Pawar     ret = codec->decodeFrame(data, size, &bytesConsumed);
372*c83a76b0SSuyog Pawar 
373*c83a76b0SSuyog Pawar     bytesConsumed = std::min(size, bytesConsumed);
374*c83a76b0SSuyog Pawar     data += bytesConsumed;
375*c83a76b0SSuyog Pawar     size -= bytesConsumed;
376*c83a76b0SSuyog Pawar     numDecodeCalls++;
377*c83a76b0SSuyog Pawar   }
378*c83a76b0SSuyog Pawar 
379*c83a76b0SSuyog Pawar   codec->freeFrame();
380*c83a76b0SSuyog Pawar   codec->deleteCodec();
381*c83a76b0SSuyog Pawar   delete codec;
382*c83a76b0SSuyog Pawar   return 0;
383*c83a76b0SSuyog Pawar }
384