1*a97c2a1fSXin Li /******************************************************************************
2*a97c2a1fSXin Li *
3*a97c2a1fSXin Li * Copyright (C) 2019 The Android Open Source Project
4*a97c2a1fSXin Li *
5*a97c2a1fSXin Li * Licensed under the Apache License, Version 2.0 (the "License");
6*a97c2a1fSXin Li * you may not use this file except in compliance with the License.
7*a97c2a1fSXin Li * You may obtain a copy of the License at:
8*a97c2a1fSXin Li *
9*a97c2a1fSXin Li * http://www.apache.org/licenses/LICENSE-2.0
10*a97c2a1fSXin Li *
11*a97c2a1fSXin Li * Unless required by applicable law or agreed to in writing, software
12*a97c2a1fSXin Li * distributed under the License is distributed on an "AS IS" BASIS,
13*a97c2a1fSXin Li * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*a97c2a1fSXin Li * See the License for the specific language governing permissions and
15*a97c2a1fSXin Li * limitations under the License.
16*a97c2a1fSXin Li *
17*a97c2a1fSXin Li *****************************************************************************
18*a97c2a1fSXin Li * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19*a97c2a1fSXin Li */
20*a97c2a1fSXin Li
21*a97c2a1fSXin Li #include <stddef.h>
22*a97c2a1fSXin Li #include <stdint.h>
23*a97c2a1fSXin Li #include <stdio.h>
24*a97c2a1fSXin Li #include <stdlib.h>
25*a97c2a1fSXin Li #include <string.h>
26*a97c2a1fSXin Li #include <algorithm>
27*a97c2a1fSXin Li #include <memory>
28*a97c2a1fSXin Li
29*a97c2a1fSXin Li #include "iv_datatypedef.h"
30*a97c2a1fSXin Li #include "iv.h"
31*a97c2a1fSXin Li #include "ivd.h"
32*a97c2a1fSXin Li #include "impeg2d.h"
33*a97c2a1fSXin Li
34*a97c2a1fSXin Li #define ALIGN2(x) ((((x) + 1) >> 1) << 1)
35*a97c2a1fSXin Li #define MAX_FRAME_WIDTH 3840
36*a97c2a1fSXin Li #define MAX_FRAME_HEIGHT 2160
37*a97c2a1fSXin Li #define NELEMENTS(x) (sizeof(x) / sizeof(x[0]))
38*a97c2a1fSXin Li #define ivd_api_function impeg2d_api_function
39*a97c2a1fSXin Li const IV_COLOR_FORMAT_T supportedColorFormats[] = {IV_YUV_420P, IV_YUV_420SP_UV,
40*a97c2a1fSXin Li IV_YUV_420SP_VU};
41*a97c2a1fSXin Li
42*a97c2a1fSXin Li /* Decoder ignores invalid arch, i.e. for arm build, if SSSE3 is requested,
43*a97c2a1fSXin Li * decoder defaults to a supported configuration. So same set of supported
44*a97c2a1fSXin Li * architectures can be used in arm/arm64/x86 builds */
45*a97c2a1fSXin Li const IVD_ARCH_T supportedArchitectures[] = {
46*a97c2a1fSXin Li ARCH_ARM_NONEON, ARCH_ARM_A9Q, ARCH_ARM_NEONINTR, ARCH_ARMV8_GENERIC,
47*a97c2a1fSXin Li ARCH_X86_GENERIC, ARCH_X86_SSSE3, ARCH_X86_SSE42};
48*a97c2a1fSXin Li
49*a97c2a1fSXin Li enum {
50*a97c2a1fSXin Li OFFSET_COLOR_FORMAT = 6,
51*a97c2a1fSXin Li OFFSET_NUM_CORES,
52*a97c2a1fSXin Li OFFSET_ARCH,
53*a97c2a1fSXin Li /* Should be the last entry */
54*a97c2a1fSXin Li OFFSET_MAX,
55*a97c2a1fSXin Li };
56*a97c2a1fSXin Li
57*a97c2a1fSXin Li const static int kMaxNumDecodeCalls = 100;
58*a97c2a1fSXin Li const static int kSupportedColorFormats = NELEMENTS(supportedColorFormats);
59*a97c2a1fSXin Li const static int kSupportedArchitectures = NELEMENTS(supportedArchitectures);
60*a97c2a1fSXin Li const static int kMaxCores = 4;
61*a97c2a1fSXin Li
62*a97c2a1fSXin Li class Codec {
63*a97c2a1fSXin Li public:
64*a97c2a1fSXin Li Codec(IV_COLOR_FORMAT_T colorFormat, size_t numCores);
65*a97c2a1fSXin Li ~Codec();
66*a97c2a1fSXin Li
67*a97c2a1fSXin Li void createCodec();
68*a97c2a1fSXin Li void deleteCodec();
69*a97c2a1fSXin Li void resetCodec();
70*a97c2a1fSXin Li void setCores();
71*a97c2a1fSXin Li void allocFrame();
72*a97c2a1fSXin Li void freeFrame();
73*a97c2a1fSXin Li void decodeHeader(const uint8_t *data, size_t size);
74*a97c2a1fSXin Li IV_API_CALL_STATUS_T decodeFrame(const uint8_t *data, size_t size,
75*a97c2a1fSXin Li size_t *bytesConsumed);
76*a97c2a1fSXin Li void setParams(IVD_VIDEO_DECODE_MODE_T mode);
77*a97c2a1fSXin Li void setArchitecture(IVD_ARCH_T arch);
78*a97c2a1fSXin Li
79*a97c2a1fSXin Li private:
80*a97c2a1fSXin Li IV_COLOR_FORMAT_T mColorFormat;
81*a97c2a1fSXin Li size_t mNumCores;
82*a97c2a1fSXin Li iv_obj_t *mCodec;
83*a97c2a1fSXin Li ivd_out_bufdesc_t mOutBufHandle;
84*a97c2a1fSXin Li uint32_t mWidth;
85*a97c2a1fSXin Li uint32_t mHeight;
86*a97c2a1fSXin Li uint32_t mDeinterlace;
87*a97c2a1fSXin Li uint32_t mKeepThreadsActive;
88*a97c2a1fSXin Li iv_mem_rec_t *mMemRecords;
89*a97c2a1fSXin Li };
90*a97c2a1fSXin Li
Codec(IV_COLOR_FORMAT_T colorFormat,size_t numCores)91*a97c2a1fSXin Li Codec::Codec(IV_COLOR_FORMAT_T colorFormat, size_t numCores) {
92*a97c2a1fSXin Li mColorFormat = colorFormat;
93*a97c2a1fSXin Li mNumCores = numCores;
94*a97c2a1fSXin Li mCodec = nullptr;
95*a97c2a1fSXin Li mWidth = 0;
96*a97c2a1fSXin Li mHeight = 0;
97*a97c2a1fSXin Li mDeinterlace = 1;
98*a97c2a1fSXin Li mKeepThreadsActive = 1;
99*a97c2a1fSXin Li memset(&mOutBufHandle, 0, sizeof(mOutBufHandle));
100*a97c2a1fSXin Li }
101*a97c2a1fSXin Li
~Codec()102*a97c2a1fSXin Li Codec::~Codec() {}
103*a97c2a1fSXin Li
createCodec()104*a97c2a1fSXin Li void Codec::createCodec() {
105*a97c2a1fSXin Li IV_API_CALL_STATUS_T ret;
106*a97c2a1fSXin Li UWORD32 numMemRecords;
107*a97c2a1fSXin Li size_t i;
108*a97c2a1fSXin Li void *fxns = (void *)&ivd_api_function;
109*a97c2a1fSXin Li
110*a97c2a1fSXin Li iv_num_mem_rec_ip_t get_mem_ip;
111*a97c2a1fSXin Li iv_num_mem_rec_op_t get_mem_op;
112*a97c2a1fSXin Li
113*a97c2a1fSXin Li get_mem_ip.u4_size = sizeof(get_mem_ip);
114*a97c2a1fSXin Li get_mem_op.u4_size = sizeof(get_mem_op);
115*a97c2a1fSXin Li get_mem_ip.e_cmd = IV_CMD_GET_NUM_MEM_REC;
116*a97c2a1fSXin Li
117*a97c2a1fSXin Li ret = ivd_api_function(NULL, (void *)&get_mem_ip, (void *)&get_mem_op);
118*a97c2a1fSXin Li if (ret != IV_SUCCESS) {
119*a97c2a1fSXin Li return;
120*a97c2a1fSXin Li }
121*a97c2a1fSXin Li
122*a97c2a1fSXin Li numMemRecords = get_mem_op.u4_num_mem_rec;
123*a97c2a1fSXin Li
124*a97c2a1fSXin Li mMemRecords = (iv_mem_rec_t *)malloc(numMemRecords * sizeof(iv_mem_rec_t));
125*a97c2a1fSXin Li if (mMemRecords == NULL) {
126*a97c2a1fSXin Li return;
127*a97c2a1fSXin Li }
128*a97c2a1fSXin Li
129*a97c2a1fSXin Li impeg2d_fill_mem_rec_ip_t fill_mem_ip;
130*a97c2a1fSXin Li impeg2d_fill_mem_rec_op_t fill_mem_op;
131*a97c2a1fSXin Li
132*a97c2a1fSXin Li fill_mem_ip.s_ivd_fill_mem_rec_ip_t.e_cmd = IV_CMD_FILL_NUM_MEM_REC;
133*a97c2a1fSXin Li fill_mem_ip.s_ivd_fill_mem_rec_ip_t.pv_mem_rec_location =
134*a97c2a1fSXin Li (iv_mem_rec_t *)mMemRecords;
135*a97c2a1fSXin Li fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_wd = MAX_FRAME_WIDTH;
136*a97c2a1fSXin Li fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_ht = MAX_FRAME_HEIGHT;
137*a97c2a1fSXin Li fill_mem_ip.u4_share_disp_buf = 0;
138*a97c2a1fSXin Li fill_mem_ip.u4_deinterlace = mDeinterlace;
139*a97c2a1fSXin Li fill_mem_ip.u4_keep_threads_active = mKeepThreadsActive;
140*a97c2a1fSXin Li fill_mem_ip.e_output_format = mColorFormat;
141*a97c2a1fSXin Li
142*a97c2a1fSXin Li fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_size =
143*a97c2a1fSXin Li sizeof(impeg2d_fill_mem_rec_ip_t);
144*a97c2a1fSXin Li fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_size =
145*a97c2a1fSXin Li sizeof(impeg2d_fill_mem_rec_op_t);
146*a97c2a1fSXin Li
147*a97c2a1fSXin Li for (i = 0; i < numMemRecords; i++)
148*a97c2a1fSXin Li mMemRecords[i].u4_size = sizeof(iv_mem_rec_t);
149*a97c2a1fSXin Li
150*a97c2a1fSXin Li ret = ivd_api_function(NULL, (void *)&fill_mem_ip, (void *)&fill_mem_op);
151*a97c2a1fSXin Li
152*a97c2a1fSXin Li if (ret != IV_SUCCESS) {
153*a97c2a1fSXin Li return;
154*a97c2a1fSXin Li }
155*a97c2a1fSXin Li numMemRecords = fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_num_mem_rec_filled;
156*a97c2a1fSXin Li
157*a97c2a1fSXin Li iv_mem_rec_t *ps_mem_rec = (iv_mem_rec_t *)mMemRecords;
158*a97c2a1fSXin Li
159*a97c2a1fSXin Li for (i = 0; i < numMemRecords; i++) {
160*a97c2a1fSXin Li if (0 != posix_memalign(&ps_mem_rec->pv_base, ps_mem_rec->u4_mem_alignment,
161*a97c2a1fSXin Li ps_mem_rec->u4_mem_size)) {
162*a97c2a1fSXin Li return;
163*a97c2a1fSXin Li }
164*a97c2a1fSXin Li
165*a97c2a1fSXin Li if (ps_mem_rec->pv_base == NULL) {
166*a97c2a1fSXin Li return;
167*a97c2a1fSXin Li }
168*a97c2a1fSXin Li
169*a97c2a1fSXin Li ps_mem_rec++;
170*a97c2a1fSXin Li }
171*a97c2a1fSXin Li
172*a97c2a1fSXin Li mCodec = (iv_obj_t *)(iv_obj_t *)mMemRecords[0].pv_base;
173*a97c2a1fSXin Li mCodec->pv_fxns = fxns;
174*a97c2a1fSXin Li mCodec->u4_size = sizeof(iv_obj_t);
175*a97c2a1fSXin Li
176*a97c2a1fSXin Li impeg2d_init_ip_t init_ip;
177*a97c2a1fSXin Li impeg2d_init_op_t init_op;
178*a97c2a1fSXin Li
179*a97c2a1fSXin Li init_ip.s_ivd_init_ip_t.e_cmd = (IVD_API_COMMAND_TYPE_T)IV_CMD_INIT;
180*a97c2a1fSXin Li init_ip.s_ivd_init_ip_t.pv_mem_rec_location = mMemRecords;
181*a97c2a1fSXin Li init_ip.s_ivd_init_ip_t.u4_frm_max_wd = MAX_FRAME_WIDTH;
182*a97c2a1fSXin Li init_ip.s_ivd_init_ip_t.u4_frm_max_ht = MAX_FRAME_HEIGHT;
183*a97c2a1fSXin Li
184*a97c2a1fSXin Li init_ip.u4_share_disp_buf = 0;
185*a97c2a1fSXin Li init_ip.u4_deinterlace = mDeinterlace;
186*a97c2a1fSXin Li init_ip.u4_keep_threads_active = mKeepThreadsActive;
187*a97c2a1fSXin Li init_ip.s_ivd_init_ip_t.u4_num_mem_rec = numMemRecords;
188*a97c2a1fSXin Li init_ip.s_ivd_init_ip_t.e_output_format = mColorFormat;
189*a97c2a1fSXin Li init_ip.s_ivd_init_ip_t.u4_size = sizeof(impeg2d_init_ip_t);
190*a97c2a1fSXin Li init_op.s_ivd_init_op_t.u4_size = sizeof(impeg2d_init_op_t);
191*a97c2a1fSXin Li
192*a97c2a1fSXin Li ret = ivd_api_function(mCodec, (void *)&init_ip, (void *)&init_op);
193*a97c2a1fSXin Li if (ret != IV_SUCCESS) {
194*a97c2a1fSXin Li return;
195*a97c2a1fSXin Li }
196*a97c2a1fSXin Li }
197*a97c2a1fSXin Li
deleteCodec()198*a97c2a1fSXin Li void Codec::deleteCodec() {
199*a97c2a1fSXin Li IV_API_CALL_STATUS_T ret;
200*a97c2a1fSXin Li iv_retrieve_mem_rec_ip_t retrieve_ip;
201*a97c2a1fSXin Li iv_retrieve_mem_rec_op_t retrieve_op;
202*a97c2a1fSXin Li retrieve_ip.pv_mem_rec_location = (iv_mem_rec_t *)mMemRecords;
203*a97c2a1fSXin Li
204*a97c2a1fSXin Li retrieve_ip.e_cmd = IV_CMD_RETRIEVE_MEMREC;
205*a97c2a1fSXin Li retrieve_ip.u4_size = sizeof(iv_retrieve_mem_rec_ip_t);
206*a97c2a1fSXin Li retrieve_op.u4_size = sizeof(iv_retrieve_mem_rec_op_t);
207*a97c2a1fSXin Li
208*a97c2a1fSXin Li ret = ivd_api_function(mCodec, (void *)&retrieve_ip, (void *)&retrieve_op);
209*a97c2a1fSXin Li
210*a97c2a1fSXin Li if (ret != IV_SUCCESS) {
211*a97c2a1fSXin Li return;
212*a97c2a1fSXin Li }
213*a97c2a1fSXin Li
214*a97c2a1fSXin Li iv_mem_rec_t *ps_mem_rec = retrieve_ip.pv_mem_rec_location;
215*a97c2a1fSXin Li for (size_t i = 0; i < retrieve_op.u4_num_mem_rec_filled; i++) {
216*a97c2a1fSXin Li free(ps_mem_rec->pv_base);
217*a97c2a1fSXin Li ps_mem_rec++;
218*a97c2a1fSXin Li }
219*a97c2a1fSXin Li free(retrieve_ip.pv_mem_rec_location);
220*a97c2a1fSXin Li }
221*a97c2a1fSXin Li
resetCodec()222*a97c2a1fSXin Li void Codec::resetCodec() {
223*a97c2a1fSXin Li ivd_ctl_reset_ip_t s_ctl_ip;
224*a97c2a1fSXin Li ivd_ctl_reset_op_t s_ctl_op;
225*a97c2a1fSXin Li
226*a97c2a1fSXin Li s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
227*a97c2a1fSXin Li s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_RESET;
228*a97c2a1fSXin Li s_ctl_ip.u4_size = sizeof(ivd_ctl_reset_ip_t);
229*a97c2a1fSXin Li s_ctl_op.u4_size = sizeof(ivd_ctl_reset_op_t);
230*a97c2a1fSXin Li
231*a97c2a1fSXin Li ivd_api_function(mCodec, (void *)&s_ctl_ip, (void *)&s_ctl_op);
232*a97c2a1fSXin Li }
233*a97c2a1fSXin Li
setCores()234*a97c2a1fSXin Li void Codec::setCores() {
235*a97c2a1fSXin Li impeg2d_ctl_set_num_cores_ip_t s_ctl_ip;
236*a97c2a1fSXin Li impeg2d_ctl_set_num_cores_op_t s_ctl_op;
237*a97c2a1fSXin Li
238*a97c2a1fSXin Li s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
239*a97c2a1fSXin Li s_ctl_ip.e_sub_cmd =
240*a97c2a1fSXin Li (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_SET_NUM_CORES;
241*a97c2a1fSXin Li s_ctl_ip.u4_num_cores = mNumCores;
242*a97c2a1fSXin Li s_ctl_ip.u4_size = sizeof(impeg2d_ctl_set_num_cores_ip_t);
243*a97c2a1fSXin Li s_ctl_op.u4_size = sizeof(impeg2d_ctl_set_num_cores_op_t);
244*a97c2a1fSXin Li
245*a97c2a1fSXin Li ivd_api_function(mCodec, (void *)&s_ctl_ip, (void *)&s_ctl_op);
246*a97c2a1fSXin Li }
247*a97c2a1fSXin Li
setParams(IVD_VIDEO_DECODE_MODE_T mode)248*a97c2a1fSXin Li void Codec::setParams(IVD_VIDEO_DECODE_MODE_T mode) {
249*a97c2a1fSXin Li ivd_ctl_set_config_ip_t s_ctl_ip;
250*a97c2a1fSXin Li ivd_ctl_set_config_op_t s_ctl_op;
251*a97c2a1fSXin Li
252*a97c2a1fSXin Li s_ctl_ip.u4_disp_wd = 0;
253*a97c2a1fSXin Li s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE;
254*a97c2a1fSXin Li s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
255*a97c2a1fSXin Li s_ctl_ip.e_vid_dec_mode = mode;
256*a97c2a1fSXin Li s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
257*a97c2a1fSXin Li s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
258*a97c2a1fSXin Li s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);
259*a97c2a1fSXin Li s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t);
260*a97c2a1fSXin Li
261*a97c2a1fSXin Li ivd_api_function(mCodec, (void *)&s_ctl_ip, (void *)&s_ctl_op);
262*a97c2a1fSXin Li }
263*a97c2a1fSXin Li
setArchitecture(IVD_ARCH_T arch)264*a97c2a1fSXin Li void Codec::setArchitecture(IVD_ARCH_T arch) {
265*a97c2a1fSXin Li impeg2d_ctl_set_processor_ip_t s_ctl_ip;
266*a97c2a1fSXin Li impeg2d_ctl_set_processor_op_t s_ctl_op;
267*a97c2a1fSXin Li
268*a97c2a1fSXin Li s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
269*a97c2a1fSXin Li s_ctl_ip.e_sub_cmd =
270*a97c2a1fSXin Li (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_SET_PROCESSOR;
271*a97c2a1fSXin Li s_ctl_ip.u4_arch = arch;
272*a97c2a1fSXin Li s_ctl_ip.u4_soc = SOC_GENERIC;
273*a97c2a1fSXin Li s_ctl_ip.u4_size = sizeof(impeg2d_ctl_set_processor_ip_t);
274*a97c2a1fSXin Li s_ctl_op.u4_size = sizeof(impeg2d_ctl_set_processor_op_t);
275*a97c2a1fSXin Li
276*a97c2a1fSXin Li ivd_api_function(mCodec, (void *)&s_ctl_ip, (void *)&s_ctl_op);
277*a97c2a1fSXin Li }
freeFrame()278*a97c2a1fSXin Li void Codec::freeFrame() {
279*a97c2a1fSXin Li for (int i = 0; i < mOutBufHandle.u4_num_bufs; i++) {
280*a97c2a1fSXin Li if (mOutBufHandle.pu1_bufs[i]) {
281*a97c2a1fSXin Li free(mOutBufHandle.pu1_bufs[i]);
282*a97c2a1fSXin Li mOutBufHandle.pu1_bufs[i] = nullptr;
283*a97c2a1fSXin Li }
284*a97c2a1fSXin Li }
285*a97c2a1fSXin Li }
286*a97c2a1fSXin Li
allocFrame()287*a97c2a1fSXin Li void Codec::allocFrame() {
288*a97c2a1fSXin Li size_t sizes[4] = {0};
289*a97c2a1fSXin Li size_t num_bufs = 0;
290*a97c2a1fSXin Li
291*a97c2a1fSXin Li freeFrame();
292*a97c2a1fSXin Li
293*a97c2a1fSXin Li memset(&mOutBufHandle, 0, sizeof(mOutBufHandle));
294*a97c2a1fSXin Li
295*a97c2a1fSXin Li switch (mColorFormat) {
296*a97c2a1fSXin Li case IV_YUV_420SP_UV:
297*a97c2a1fSXin Li [[fallthrough]];
298*a97c2a1fSXin Li case IV_YUV_420SP_VU:
299*a97c2a1fSXin Li sizes[0] = mWidth * mHeight;
300*a97c2a1fSXin Li sizes[1] = ALIGN2(mWidth) * ALIGN2(mHeight) >> 1;
301*a97c2a1fSXin Li num_bufs = 2;
302*a97c2a1fSXin Li break;
303*a97c2a1fSXin Li case IV_YUV_422ILE:
304*a97c2a1fSXin Li sizes[0] = mWidth * mHeight * 2;
305*a97c2a1fSXin Li num_bufs = 1;
306*a97c2a1fSXin Li break;
307*a97c2a1fSXin Li case IV_RGB_565:
308*a97c2a1fSXin Li sizes[0] = mWidth * mHeight * 2;
309*a97c2a1fSXin Li num_bufs = 1;
310*a97c2a1fSXin Li break;
311*a97c2a1fSXin Li case IV_RGBA_8888:
312*a97c2a1fSXin Li sizes[0] = mWidth * mHeight * 4;
313*a97c2a1fSXin Li num_bufs = 1;
314*a97c2a1fSXin Li break;
315*a97c2a1fSXin Li case IV_YUV_420P:
316*a97c2a1fSXin Li [[fallthrough]];
317*a97c2a1fSXin Li default:
318*a97c2a1fSXin Li sizes[0] = mWidth * mHeight;
319*a97c2a1fSXin Li sizes[1] = ALIGN2(mWidth) * ALIGN2(mHeight) >> 2;
320*a97c2a1fSXin Li sizes[2] = ALIGN2(mWidth) * ALIGN2(mHeight) >> 2;
321*a97c2a1fSXin Li num_bufs = 3;
322*a97c2a1fSXin Li break;
323*a97c2a1fSXin Li }
324*a97c2a1fSXin Li mOutBufHandle.u4_num_bufs = num_bufs;
325*a97c2a1fSXin Li for (int i = 0; i < num_bufs; i++) {
326*a97c2a1fSXin Li mOutBufHandle.u4_min_out_buf_size[i] = sizes[i];
327*a97c2a1fSXin Li void *buf = NULL;
328*a97c2a1fSXin Li if (0 != posix_memalign(&buf, 16, sizes[i])) {
329*a97c2a1fSXin Li return;
330*a97c2a1fSXin Li }
331*a97c2a1fSXin Li mOutBufHandle.pu1_bufs[i] = (UWORD8 *)buf;
332*a97c2a1fSXin Li }
333*a97c2a1fSXin Li }
334*a97c2a1fSXin Li
decodeHeader(const uint8_t * data,size_t size)335*a97c2a1fSXin Li void Codec::decodeHeader(const uint8_t *data, size_t size) {
336*a97c2a1fSXin Li setParams(IVD_DECODE_HEADER);
337*a97c2a1fSXin Li
338*a97c2a1fSXin Li size_t numDecodeCalls = 0;
339*a97c2a1fSXin Li
340*a97c2a1fSXin Li while (size > 0 && numDecodeCalls < kMaxNumDecodeCalls) {
341*a97c2a1fSXin Li IV_API_CALL_STATUS_T ret;
342*a97c2a1fSXin Li ivd_video_decode_ip_t dec_ip;
343*a97c2a1fSXin Li ivd_video_decode_op_t dec_op;
344*a97c2a1fSXin Li size_t bytes_consumed;
345*a97c2a1fSXin Li
346*a97c2a1fSXin Li memset(&dec_ip, 0, sizeof(dec_ip));
347*a97c2a1fSXin Li memset(&dec_op, 0, sizeof(dec_op));
348*a97c2a1fSXin Li
349*a97c2a1fSXin Li dec_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
350*a97c2a1fSXin Li dec_ip.u4_ts = 0;
351*a97c2a1fSXin Li dec_ip.pv_stream_buffer = (void *)data;
352*a97c2a1fSXin Li dec_ip.u4_num_Bytes = size;
353*a97c2a1fSXin Li dec_ip.u4_size = sizeof(ivd_video_decode_ip_t);
354*a97c2a1fSXin Li dec_op.u4_size = sizeof(ivd_video_decode_op_t);
355*a97c2a1fSXin Li
356*a97c2a1fSXin Li ret = ivd_api_function(mCodec, (void *)&dec_ip, (void *)&dec_op);
357*a97c2a1fSXin Li
358*a97c2a1fSXin Li bytes_consumed = dec_op.u4_num_bytes_consumed;
359*a97c2a1fSXin Li /* If no bytes are consumed, then consume 4 bytes to ensure fuzzer proceeds
360*a97c2a1fSXin Li * to feed next data */
361*a97c2a1fSXin Li if (!bytes_consumed) bytes_consumed = 4;
362*a97c2a1fSXin Li
363*a97c2a1fSXin Li bytes_consumed = std::min(size, bytes_consumed);
364*a97c2a1fSXin Li
365*a97c2a1fSXin Li data += bytes_consumed;
366*a97c2a1fSXin Li size -= bytes_consumed;
367*a97c2a1fSXin Li numDecodeCalls++;
368*a97c2a1fSXin Li
369*a97c2a1fSXin Li mWidth = std::min(dec_op.u4_pic_wd, (UWORD32)10240);
370*a97c2a1fSXin Li mHeight = std::min(dec_op.u4_pic_ht, (UWORD32)10240);
371*a97c2a1fSXin Li
372*a97c2a1fSXin Li /* Break after successful header decode */
373*a97c2a1fSXin Li if (mWidth && mHeight) {
374*a97c2a1fSXin Li break;
375*a97c2a1fSXin Li }
376*a97c2a1fSXin Li }
377*a97c2a1fSXin Li /* if width / height are invalid, set them to defaults */
378*a97c2a1fSXin Li if (!mWidth) mWidth = 1920;
379*a97c2a1fSXin Li if (!mHeight) mHeight = 1088;
380*a97c2a1fSXin Li }
381*a97c2a1fSXin Li
decodeFrame(const uint8_t * data,size_t size,size_t * bytesConsumed)382*a97c2a1fSXin Li IV_API_CALL_STATUS_T Codec::decodeFrame(const uint8_t *data, size_t size,
383*a97c2a1fSXin Li size_t *bytesConsumed) {
384*a97c2a1fSXin Li IV_API_CALL_STATUS_T ret;
385*a97c2a1fSXin Li ivd_video_decode_ip_t dec_ip;
386*a97c2a1fSXin Li ivd_video_decode_op_t dec_op;
387*a97c2a1fSXin Li
388*a97c2a1fSXin Li memset(&dec_ip, 0, sizeof(dec_ip));
389*a97c2a1fSXin Li memset(&dec_op, 0, sizeof(dec_op));
390*a97c2a1fSXin Li
391*a97c2a1fSXin Li dec_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
392*a97c2a1fSXin Li dec_ip.u4_ts = 0;
393*a97c2a1fSXin Li dec_ip.pv_stream_buffer = (void *)data;
394*a97c2a1fSXin Li dec_ip.u4_num_Bytes = size;
395*a97c2a1fSXin Li dec_ip.u4_size = sizeof(ivd_video_decode_ip_t);
396*a97c2a1fSXin Li dec_ip.s_out_buffer = mOutBufHandle;
397*a97c2a1fSXin Li
398*a97c2a1fSXin Li dec_op.u4_size = sizeof(ivd_video_decode_op_t);
399*a97c2a1fSXin Li
400*a97c2a1fSXin Li ret = ivd_api_function(mCodec, (void *)&dec_ip, (void *)&dec_op);
401*a97c2a1fSXin Li if (IMPEG2D_UNSUPPORTED_DIMENSIONS == dec_op.u4_error_code) {
402*a97c2a1fSXin Li /* In case of unsupported resolution, reset codec */
403*a97c2a1fSXin Li resetCodec();
404*a97c2a1fSXin Li } else if (IVD_RES_CHANGED == (dec_op.u4_error_code & 0xFF)) {
405*a97c2a1fSXin Li /* In case of change in resolution, reset codec and feed the same data
406*a97c2a1fSXin Li * again */
407*a97c2a1fSXin Li resetCodec();
408*a97c2a1fSXin Li ret = ivd_api_function(mCodec, (void *)&dec_ip, (void *)&dec_op);
409*a97c2a1fSXin Li }
410*a97c2a1fSXin Li *bytesConsumed = dec_op.u4_num_bytes_consumed;
411*a97c2a1fSXin Li
412*a97c2a1fSXin Li /* If no bytes are consumed, then consume 4 bytes to ensure fuzzer proceeds
413*a97c2a1fSXin Li * to feed next data */
414*a97c2a1fSXin Li if (!*bytesConsumed) *bytesConsumed = 4;
415*a97c2a1fSXin Li
416*a97c2a1fSXin Li if (dec_op.u4_pic_wd && dec_op.u4_pic_ht &&
417*a97c2a1fSXin Li (mWidth != dec_op.u4_pic_wd || mHeight != dec_op.u4_pic_ht)) {
418*a97c2a1fSXin Li mWidth = std::min(dec_op.u4_pic_wd, (UWORD32)10240);
419*a97c2a1fSXin Li mHeight = std::min(dec_op.u4_pic_ht, (UWORD32)10240);
420*a97c2a1fSXin Li allocFrame();
421*a97c2a1fSXin Li }
422*a97c2a1fSXin Li
423*a97c2a1fSXin Li return ret;
424*a97c2a1fSXin Li }
425*a97c2a1fSXin Li
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)426*a97c2a1fSXin Li extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
427*a97c2a1fSXin Li if (size < 1) {
428*a97c2a1fSXin Li return 0;
429*a97c2a1fSXin Li }
430*a97c2a1fSXin Li size_t colorFormatOfst = std::min((size_t)OFFSET_COLOR_FORMAT, size - 1);
431*a97c2a1fSXin Li size_t numCoresOfst = std::min((size_t)OFFSET_NUM_CORES, size - 1);
432*a97c2a1fSXin Li size_t architectureOfst = std::min((size_t)OFFSET_ARCH, size - 1);
433*a97c2a1fSXin Li size_t architectureIdx = data[architectureOfst] % kSupportedArchitectures;
434*a97c2a1fSXin Li IVD_ARCH_T arch = (IVD_ARCH_T)supportedArchitectures[architectureIdx];
435*a97c2a1fSXin Li size_t colorFormatIdx = data[colorFormatOfst] % kSupportedColorFormats;
436*a97c2a1fSXin Li IV_COLOR_FORMAT_T colorFormat =
437*a97c2a1fSXin Li (IV_COLOR_FORMAT_T)(supportedColorFormats[colorFormatIdx]);
438*a97c2a1fSXin Li uint32_t numCores = (data[numCoresOfst] % kMaxCores) + 1;
439*a97c2a1fSXin Li size_t numDecodeCalls = 0;
440*a97c2a1fSXin Li Codec *codec = new Codec(colorFormat, numCores);
441*a97c2a1fSXin Li codec->createCodec();
442*a97c2a1fSXin Li codec->setArchitecture(arch);
443*a97c2a1fSXin Li codec->setCores();
444*a97c2a1fSXin Li codec->decodeHeader(data, size);
445*a97c2a1fSXin Li codec->setParams(IVD_DECODE_FRAME);
446*a97c2a1fSXin Li codec->allocFrame();
447*a97c2a1fSXin Li
448*a97c2a1fSXin Li while (size > 0 && numDecodeCalls < kMaxNumDecodeCalls) {
449*a97c2a1fSXin Li IV_API_CALL_STATUS_T ret;
450*a97c2a1fSXin Li size_t bytesConsumed;
451*a97c2a1fSXin Li ret = codec->decodeFrame(data, size, &bytesConsumed);
452*a97c2a1fSXin Li
453*a97c2a1fSXin Li bytesConsumed = std::min(size, bytesConsumed);
454*a97c2a1fSXin Li data += bytesConsumed;
455*a97c2a1fSXin Li size -= bytesConsumed;
456*a97c2a1fSXin Li numDecodeCalls++;
457*a97c2a1fSXin Li }
458*a97c2a1fSXin Li
459*a97c2a1fSXin Li codec->freeFrame();
460*a97c2a1fSXin Li codec->deleteCodec();
461*a97c2a1fSXin Li delete codec;
462*a97c2a1fSXin Li return 0;
463*a97c2a1fSXin Li }
464