• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright (C) 2020 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************
18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19  */
20 #include <malloc.h>
21 #include <algorithm>
22 #include <string.h>
23 #include <vector>
24 
25 #include "ih264_defs.h"
26 #include "ih264_typedefs.h"
27 #include "ih264e.h"
28 #include "ih264e_error.h"
29 #define ive_api_function ih264e_api_function
30 typedef std::tuple<uint8_t *, uint8_t *, uint8_t *> bufferPtrs;
31 
32 constexpr static int kMaxNumEncodeCalls = 100;
33 constexpr uint32_t kHeaderLength = 0x800;
34 constexpr int16_t kCompressionRatio = 1;
35 
36 constexpr int kMeSpeedPreset[] = {0, 50, 75, 100};
37 constexpr IVE_AIR_MODE_T kAirMode[] = {IVE_AIR_MODE_NONE, IVE_AIR_MODE_CYCLIC, IVE_AIR_MODE_RANDOM};
38 constexpr IVE_SPEED_CONFIG kEncSpeed[] = {IVE_CONFIG, IVE_SLOWEST,    IVE_NORMAL,
39                                           IVE_FAST,   IVE_HIGH_SPEED, IVE_FASTEST};
40 constexpr IV_PROFILE_T kProfle[] = {IV_PROFILE_BASE, IV_PROFILE_MAIN};
41 constexpr IVE_RC_MODE_T kRCMode[] = {IVE_RC_NONE, IVE_RC_STORAGE, IVE_RC_CBR_NON_LOW_DELAY,
42                                      IVE_RC_CBR_LOW_DELAY};
43 constexpr IV_COLOR_FORMAT_T kSupportedColorFormats[] = {IV_YUV_420P, IV_YUV_420SP_UV, IV_YUV_422ILE,
44                                                         IV_YUV_420SP_VU};
45 
46 constexpr size_t kAirModeNum = std::size(kAirMode);
47 constexpr size_t kEncSpeedNum = std::size(kEncSpeed);
48 constexpr size_t kMeSpeedPresetNum = std::size(kMeSpeedPreset);
49 constexpr size_t kProfleNum = std::size(kProfle);
50 constexpr size_t kRCModeNum = std::size(kRCMode);
51 constexpr size_t kSupportedColorFormatsNum = std::size(kSupportedColorFormats);
52 constexpr size_t kMinQP = 4;
53 constexpr size_t kMaxWidth = 10240;
54 constexpr size_t kMaxHeight = 10240;
55 constexpr size_t kMaxBitrate = 500000000;
56 
57 enum {
58     IDX_WD_BYTE_1,
59     IDX_WD_BYTE_2,
60     IDX_HT_BYTE_1,
61     IDX_HT_BYTE_2,
62     IDX_COLOR_FORMAT,
63     IDX_ARCH_TYPE,
64     IDX_RC_MODE,
65     IDX_NUM_CORES,
66     IDX_NUM_B_FRAMES,
67     IDX_ENC_SPEED,
68     IDX_CONSTRAINED_INTRA_FLAG,
69     IDX_INTRA_4x4,
70     IDX_I_FRAME_QP,
71     IDX_P_FRAME_QP,
72     IDX_B_FRAME_QP,
73     IDX_BITRATE_BYTE_1,
74     IDX_BITRATE_BYTE_2,
75     IDX_FRAME_RATE,
76     IDX_INTRA_REFRESH,
77     IDX_ENABLE_HALF_PEL,
78     IDX_ENABLE_Q_PEL,
79     IDX_ME_SPEED_PRESET,
80     IDX_AIR_MODE,
81     IDX_DISABLE_DEBLOCK_LEVEL,
82     IDX_SEARCH_RANGE_X,
83     IDX_SEARCH_RANGE_Y,
84     IDX_I_INTERVAL,
85     IDX_IDR_INTERVAL,
86     IDX_SEI_MDCV_FLAG,
87     IDX_SEI_CLL_FLAG,
88     IDX_SEI_AVE_FLAG,
89     IDX_SEI_CCV_FLAG,
90     IDX_PROFILE,
91     IDX_ASPECT_RATIO_FLAG,
92     IDX_NAL_HRD_FLAG,
93     IDX_VCL_HRD_FLAG,
94     IDX_ENABLE_FORCE_IDR,
95     IDX_ENABLE_DYNAMIC_BITRATE,
96     IDX_ENABLE_DYNAMIC_FRAME_RATE,
97     IDX_FORCE_IDR_INTERVAL,
98     IDX_DYNAMIC_BITRATE_INTERVAL,
99     IDX_DYNAMIC_FRAME_RATE_INTERVAL,
100     IDX_SEND_EOS_WITH_LAST_FRAME,
101     IDX_LAST
102 };
103 
104 class Codec {
105    public:
106     Codec() = default;
~Codec()107     ~Codec() { deInitEncoder(); }
108     bool initEncoder(const uint8_t **pdata, size_t *psize);
109     void encodeFrames(const uint8_t *data, size_t size);
110     void deInitEncoder();
111 
112    private:
113     bufferPtrs setEncParams(iv_raw_buf_t *psInpRawBuf, const uint8_t *data, size_t frameSize);
114     void setFrameType(IV_PICTURE_CODING_TYPE_T eFrameType);
115     void setQp();
116     void setEncMode(IVE_ENC_MODE_T eEncMode);
117     void setDimensions();
118     void setNumCores();
119     void setFrameRate();
120     void setIpeParams();
121     void setBitRate();
122     void setAirParams();
123     void setMeParams();
124     void setGopParams();
125     void setProfileParams();
126     void setDeblockParams();
127     void setVbvParams();
128     void setDefault();
129     void setVuiParams();
130     void getBufInfo();
131     void setSeiMdcvParams();
132     void setSeiCllParams();
133     void setSeiAveParams();
134     void setSeiCcvParams();
135     void logVersion();
136     bool mHalfPelEnable = 1;
137     bool mQPelEnable = 1;
138     bool mIntra4x4 = 0;
139     bool mEnableFastSad = 0;
140     bool mEnableAltRef = 0;
141     bool mConstrainedIntraFlag = 0;
142     bool mSeiCllFlag = 1;
143     bool mSeiAveFlag = 1;
144     bool mSeiCcvFlag = 1;
145     bool mSeiMdcvFlag = 1;
146     bool mAspectRatioFlag = 0;
147     bool mNalHrdFlag = 0;
148     bool mVclHrdFlag = 0;
149     bool mIsForceIdrEnabled = false;
150     bool mIsDynamicBitRateChangeEnabled = false;
151     bool mIsDynamicFrameRateChangeEnabled = false;
152     bool mSendEosWithLastFrame = false;
153     uint32_t mWidth = 2560;
154     uint32_t mHeight = 2560;
155     uint32_t mAvcEncLevel = 41;
156     uint32_t mNumMemRecords = 0;
157     uint32_t mNumCores = 1;
158     uint32_t mBframes = 0;
159     uint32_t mSliceParam = 256;
160     uint32_t mMeSpeedPreset = 100;
161     uint32_t mIInterval = 60;
162     uint32_t mIDRInterval = 60;
163     uint32_t mDisableDeblockLevel = 0;
164     uint32_t m_I_QP = 22;
165     uint32_t m_P_QP = 28;
166     uint32_t m_B_QP = 22;
167     uint32_t mIntraRefresh = 30;
168     uint32_t mSearchRangeX = 64;
169     uint32_t mSearchRangeY = 48;
170     uint32_t mForceIdrInterval = 0;          // in number of frames
171     uint32_t mDynamicBitRateInterval = 0;    // in number of frames
172     uint32_t mDynamicFrameRateInterval = 0;  // in number of frames
173     uint64_t mBitrate = 6000000;
174     float mFrameRate = 30;
175     iv_obj_t *mCodecCtx = nullptr;
176     iv_mem_rec_t *mMemRecords = nullptr;
177     IVE_AIR_MODE_T mAirMode = IVE_AIR_MODE_NONE;
178     IVE_SPEED_CONFIG mEncSpeed = IVE_NORMAL;
179     IVE_RC_MODE_T mRCMode = IVE_RC_STORAGE;
180     IV_ARCH_T mArch = ARCH_NA;
181     IVE_SLICE_MODE_T mSliceMode = IVE_SLICE_MODE_NONE;
182     IV_COLOR_FORMAT_T mIvVideoColorFormat = IV_YUV_420P;
183     IV_COLOR_FORMAT_T mReconFormat = IV_YUV_420P;
184     IV_PROFILE_T mProfile = IV_PROFILE_BASE;
185 };
186 
initEncoder(const uint8_t ** pdata,size_t * psize)187 bool Codec::initEncoder(const uint8_t **pdata, size_t *psize) {
188     uint8_t *data = const_cast<uint8_t *>(*pdata);
189     mWidth = ((data[IDX_WD_BYTE_1] << 8) | data[IDX_WD_BYTE_2]) % kMaxWidth;
190     mHeight = ((data[IDX_HT_BYTE_1] << 8) | data[IDX_HT_BYTE_2]) % kMaxHeight;
191 
192     mIvVideoColorFormat =
193         kSupportedColorFormats[data[IDX_COLOR_FORMAT] % kSupportedColorFormatsNum];
194     mArch = ((data[IDX_ARCH_TYPE] & 0x03) == 0x00) ? ARCH_ARM_NONEON : ARCH_NA;
195     mRCMode = kRCMode[data[IDX_RC_MODE] % kRCModeNum];
196     mNumCores = (data[IDX_NUM_CORES] & 0x07) + 1;
197     mBframes = data[IDX_NUM_B_FRAMES] & 0x07;
198     mEncSpeed = kEncSpeed[data[IDX_ENC_SPEED] % kEncSpeedNum];
199     mConstrainedIntraFlag = data[IDX_CONSTRAINED_INTRA_FLAG] & 0x01;
200     mIntra4x4 = data[IDX_INTRA_4x4] & 0x01;
201     m_I_QP = (data[IDX_I_FRAME_QP] % (MAX_H264_QP - kMinQP)) + kMinQP;
202     m_P_QP = (data[IDX_P_FRAME_QP] % (MAX_H264_QP - kMinQP)) + kMinQP;
203     m_B_QP = (data[IDX_B_FRAME_QP] % (MAX_H264_QP - kMinQP)) + kMinQP;
204     mBitrate = (((data[IDX_BITRATE_BYTE_1] << 8) | data[IDX_BITRATE_BYTE_2]) * 1000) % kMaxBitrate;
205     mFrameRate = data[IDX_FRAME_RATE];
206     mIntraRefresh = data[IDX_INTRA_REFRESH] + 1;
207     mHalfPelEnable = data[IDX_ENABLE_HALF_PEL] & 0x01;
208     mQPelEnable = data[IDX_ENABLE_Q_PEL] & 0x01;
209     mMeSpeedPreset = kMeSpeedPreset[data[IDX_ME_SPEED_PRESET] % kMeSpeedPresetNum];
210     mAirMode = kAirMode[data[IDX_AIR_MODE] % kAirModeNum];
211     mDisableDeblockLevel = data[IDX_DISABLE_DEBLOCK_LEVEL] & 0x03;
212     mSearchRangeX = data[IDX_SEARCH_RANGE_X];
213     mSearchRangeY = data[IDX_SEARCH_RANGE_Y];
214     mIInterval = data[IDX_I_INTERVAL] + 1;
215     mIDRInterval = data[IDX_IDR_INTERVAL] + 1;
216     mSeiMdcvFlag = data[IDX_SEI_MDCV_FLAG] & 0x01;
217     mSeiCllFlag = data[IDX_SEI_CLL_FLAG] & 0x01;
218     mSeiAveFlag = data[IDX_SEI_AVE_FLAG] & 0x01;
219     mSeiCcvFlag = data[IDX_SEI_CCV_FLAG] & 0x01;
220     mProfile = kProfle[data[IDX_PROFILE] % kProfleNum];
221     mAspectRatioFlag = data[IDX_ASPECT_RATIO_FLAG] & 0x01;
222     mNalHrdFlag = data[IDX_NAL_HRD_FLAG] & 0x01;
223     mVclHrdFlag = data[IDX_VCL_HRD_FLAG] & 0x01;
224     mIsForceIdrEnabled = data[IDX_ENABLE_FORCE_IDR] & 0x01;
225     mIsDynamicBitRateChangeEnabled = data[IDX_ENABLE_DYNAMIC_BITRATE] & 0x01;
226     mIsDynamicFrameRateChangeEnabled = data[IDX_ENABLE_DYNAMIC_FRAME_RATE] & 0x01;
227     mSendEosWithLastFrame = data[IDX_SEND_EOS_WITH_LAST_FRAME] & 0x01;
228     mForceIdrInterval = data[IDX_FORCE_IDR_INTERVAL] & 0x07;
229     mDynamicBitRateInterval = data[IDX_DYNAMIC_BITRATE_INTERVAL] & 0x07;
230     mDynamicFrameRateInterval = data[IDX_DYNAMIC_FRAME_RATE_INTERVAL] & 0x07;
231 
232     /* Getting Number of MemRecords */
233     iv_num_mem_rec_ip_t sNumMemRecIp{};
234     iv_num_mem_rec_op_t sNumMemRecOp{};
235 
236     sNumMemRecIp.u4_size = sizeof(iv_num_mem_rec_ip_t);
237     sNumMemRecOp.u4_size = sizeof(iv_num_mem_rec_op_t);
238     sNumMemRecIp.e_cmd = IV_CMD_GET_NUM_MEM_REC;
239 
240     if (IV_SUCCESS != ive_api_function(nullptr, &sNumMemRecIp, &sNumMemRecOp)) {
241         return false;
242     }
243     mNumMemRecords = sNumMemRecOp.u4_num_mem_rec;
244     mMemRecords = (iv_mem_rec_t *)malloc(mNumMemRecords * sizeof(iv_mem_rec_t));
245     if (!mMemRecords) {
246         return false;
247     }
248     iv_mem_rec_t *psMemRec;
249     psMemRec = mMemRecords;
250     for (size_t i = 0; i < mNumMemRecords; ++i) {
251         psMemRec->u4_size = sizeof(iv_mem_rec_t);
252         psMemRec->pv_base = nullptr;
253         psMemRec->u4_mem_size = 0;
254         psMemRec->u4_mem_alignment = 0;
255         psMemRec->e_mem_type = IV_NA_MEM_TYPE;
256         ++psMemRec;
257     }
258 
259     /* Getting MemRecords Attributes */
260     iv_fill_mem_rec_ip_t sFillMemRecIp{};
261     iv_fill_mem_rec_op_t sFillMemRecOp{};
262 
263     sFillMemRecIp.u4_size = sizeof(iv_fill_mem_rec_ip_t);
264     sFillMemRecOp.u4_size = sizeof(iv_fill_mem_rec_op_t);
265 
266     sFillMemRecIp.e_cmd = IV_CMD_FILL_NUM_MEM_REC;
267     sFillMemRecIp.ps_mem_rec = mMemRecords;
268     sFillMemRecIp.u4_num_mem_rec = mNumMemRecords;
269     sFillMemRecIp.u4_max_wd = mWidth;
270     sFillMemRecIp.u4_max_ht = mHeight;
271     sFillMemRecIp.u4_max_level = mAvcEncLevel;
272     sFillMemRecIp.e_color_format = IV_YUV_420SP_VU;
273     sFillMemRecIp.u4_max_ref_cnt = 2;
274     sFillMemRecIp.u4_max_reorder_cnt = 0;
275     sFillMemRecIp.u4_max_srch_rng_x = 256;
276     sFillMemRecIp.u4_max_srch_rng_y = 256;
277 
278     if (IV_SUCCESS != ive_api_function(nullptr, &sFillMemRecIp, &sFillMemRecOp)) {
279         return false;
280     }
281     /* Allocating Memory for Mem Records */
282     psMemRec = mMemRecords;
283     for (size_t i = 0; i < mNumMemRecords; ++i) {
284         posix_memalign(&psMemRec->pv_base, psMemRec->u4_mem_alignment, psMemRec->u4_mem_size);
285         if (!psMemRec->pv_base) {
286             return false;
287         }
288         ++psMemRec;
289     }
290 
291     /* Codec Instance Creation */
292     ive_init_ip_t sInitIp{};
293     ive_init_op_t sInitOp{};
294 
295     mCodecCtx = (iv_obj_t *)mMemRecords[0].pv_base;
296     mCodecCtx->u4_size = sizeof(iv_obj_t);
297     mCodecCtx->pv_fxns = (void *)ive_api_function;
298 
299     sInitIp.u4_size = sizeof(ive_init_ip_t);
300     sInitOp.u4_size = sizeof(ive_init_op_t);
301 
302     sInitIp.e_cmd = IV_CMD_INIT;
303     sInitIp.u4_num_mem_rec = mNumMemRecords;
304     sInitIp.ps_mem_rec = mMemRecords;
305     sInitIp.u4_max_wd = mWidth;
306     sInitIp.u4_max_ht = mHeight;
307     sInitIp.u4_max_ref_cnt = 2;
308     sInitIp.u4_max_reorder_cnt = 0;
309     sInitIp.u4_max_level = mAvcEncLevel;
310     sInitIp.e_inp_color_fmt = mIvVideoColorFormat;
311     sInitIp.u4_enable_recon = 0;
312     sInitIp.e_recon_color_fmt = mReconFormat;
313     sInitIp.e_rc_mode = mRCMode;
314     sInitIp.u4_max_framerate = 120000;
315     sInitIp.u4_max_bitrate = 240000000;
316     sInitIp.u4_num_bframes = mBframes;
317     sInitIp.e_content_type = IV_PROGRESSIVE;
318     sInitIp.u4_max_srch_rng_x = 256;
319     sInitIp.u4_max_srch_rng_y = 256;
320     sInitIp.e_slice_mode = mSliceMode;
321     sInitIp.u4_slice_param = mSliceParam;
322     sInitIp.e_arch = mArch;
323     sInitIp.e_soc = SOC_GENERIC;
324 
325     if (IV_SUCCESS != ive_api_function(mCodecCtx, &sInitIp, &sInitOp)) {
326         return false;
327     }
328 
329     logVersion();
330     setDefault();
331     getBufInfo();
332     setNumCores();
333     setDimensions();
334     setFrameRate();
335     setIpeParams();
336     setBitRate();
337     setQp();
338     setAirParams();
339     setVbvParams();
340     setMeParams();
341     setGopParams();
342     setDeblockParams();
343     setVuiParams();
344     setSeiMdcvParams();
345     setSeiCllParams();
346     setSeiAveParams();
347     setSeiCcvParams();
348     setProfileParams();
349     setEncMode(IVE_ENC_MODE_HEADER);
350 
351     *pdata += IDX_LAST;
352     *psize -= IDX_LAST;
353     return true;
354 }
355 
setDimensions()356 void Codec::setDimensions() {
357     ive_ctl_set_dimensions_ip_t sDimensionsIp{};
358     ive_ctl_set_dimensions_op_t sDimensionsOp{};
359 
360     sDimensionsIp.e_cmd = IVE_CMD_VIDEO_CTL;
361     sDimensionsIp.e_sub_cmd = IVE_CMD_CTL_SET_DIMENSIONS;
362     sDimensionsIp.u4_ht = mHeight;
363     sDimensionsIp.u4_wd = mWidth;
364 
365     sDimensionsIp.u4_timestamp_high = -1;
366     sDimensionsIp.u4_timestamp_low = -1;
367 
368     sDimensionsIp.u4_size = sizeof(ive_ctl_set_dimensions_ip_t);
369     sDimensionsOp.u4_size = sizeof(ive_ctl_set_dimensions_op_t);
370 
371     ive_api_function(mCodecCtx, &sDimensionsIp, &sDimensionsOp);
372     return;
373 }
374 
setNumCores()375 void Codec::setNumCores() {
376     ive_ctl_set_num_cores_ip_t sNumCoresIp{};
377     ive_ctl_set_num_cores_op_t sNumCoresOp{};
378 
379     sNumCoresIp.e_cmd = IVE_CMD_VIDEO_CTL;
380     sNumCoresIp.e_sub_cmd = IVE_CMD_CTL_SET_NUM_CORES;
381     sNumCoresIp.u4_num_cores = mNumCores;
382 
383     sNumCoresIp.u4_timestamp_high = -1;
384     sNumCoresIp.u4_timestamp_low = -1;
385 
386     sNumCoresIp.u4_size = sizeof(ive_ctl_set_num_cores_ip_t);
387     sNumCoresOp.u4_size = sizeof(ive_ctl_set_num_cores_op_t);
388 
389     ive_api_function(mCodecCtx, (void *)&sNumCoresIp, (void *)&sNumCoresOp);
390     return;
391 }
392 
setDefault()393 void Codec::setDefault() {
394     ive_ctl_setdefault_ip_t sDefaultIp{};
395     ive_ctl_setdefault_op_t sDefaultOp{};
396 
397     sDefaultIp.e_cmd = IVE_CMD_VIDEO_CTL;
398     sDefaultIp.e_sub_cmd = IVE_CMD_CTL_SETDEFAULT;
399 
400     sDefaultIp.u4_timestamp_high = -1;
401     sDefaultIp.u4_timestamp_low = -1;
402 
403     sDefaultIp.u4_size = sizeof(ive_ctl_setdefault_ip_t);
404     sDefaultOp.u4_size = sizeof(ive_ctl_setdefault_op_t);
405 
406     ive_api_function(mCodecCtx, &sDefaultIp, &sDefaultOp);
407     return;
408 }
409 
getBufInfo()410 void Codec::getBufInfo() {
411     ih264e_ctl_getbufinfo_ip_t sGetBufInfoIp{};
412     ih264e_ctl_getbufinfo_op_t sGetBufInfoOp{};
413 
414     sGetBufInfoIp.s_ive_ip.u4_size = sizeof(ih264e_ctl_getbufinfo_ip_t);
415     sGetBufInfoOp.s_ive_op.u4_size = sizeof(ih264e_ctl_getbufinfo_op_t);
416 
417     sGetBufInfoIp.s_ive_ip.e_cmd = IVE_CMD_VIDEO_CTL;
418     sGetBufInfoIp.s_ive_ip.e_sub_cmd = IVE_CMD_CTL_GETBUFINFO;
419     sGetBufInfoIp.s_ive_ip.u4_max_ht = mHeight;
420     sGetBufInfoIp.s_ive_ip.u4_max_wd = mWidth;
421     sGetBufInfoIp.s_ive_ip.e_inp_color_fmt = mIvVideoColorFormat;
422 
423     ih264e_api_function(mCodecCtx, &sGetBufInfoIp, &sGetBufInfoOp);
424     return;
425 }
426 
setFrameRate()427 void Codec::setFrameRate() {
428     ive_ctl_set_frame_rate_ip_t sFrameRateIp{};
429     ive_ctl_set_frame_rate_op_t sFrameRateOp{};
430 
431     sFrameRateIp.e_cmd = IVE_CMD_VIDEO_CTL;
432     sFrameRateIp.e_sub_cmd = IVE_CMD_CTL_SET_FRAMERATE;
433     sFrameRateIp.u4_src_frame_rate = mFrameRate;
434     sFrameRateIp.u4_tgt_frame_rate = mFrameRate;
435 
436     sFrameRateIp.u4_timestamp_high = -1;
437     sFrameRateIp.u4_timestamp_low = -1;
438 
439     sFrameRateIp.u4_size = sizeof(ive_ctl_set_frame_rate_ip_t);
440     sFrameRateOp.u4_size = sizeof(ive_ctl_set_frame_rate_op_t);
441 
442     ive_api_function(mCodecCtx, &sFrameRateIp, &sFrameRateOp);
443     return;
444 }
445 
setIpeParams()446 void Codec::setIpeParams() {
447     ive_ctl_set_ipe_params_ip_t sIpeParamsIp{};
448     ive_ctl_set_ipe_params_op_t sIpeParamsOp{};
449 
450     sIpeParamsIp.e_cmd = IVE_CMD_VIDEO_CTL;
451     sIpeParamsIp.e_sub_cmd = IVE_CMD_CTL_SET_IPE_PARAMS;
452     sIpeParamsIp.u4_enable_intra_4x4 = mIntra4x4;
453     sIpeParamsIp.u4_enc_speed_preset = mEncSpeed;
454     sIpeParamsIp.u4_constrained_intra_pred = mConstrainedIntraFlag;
455 
456     sIpeParamsIp.u4_timestamp_high = -1;
457     sIpeParamsIp.u4_timestamp_low = -1;
458 
459     sIpeParamsIp.u4_size = sizeof(ive_ctl_set_ipe_params_ip_t);
460     sIpeParamsOp.u4_size = sizeof(ive_ctl_set_ipe_params_op_t);
461 
462     ive_api_function(mCodecCtx, &sIpeParamsIp, &sIpeParamsOp);
463     return;
464 }
465 
setBitRate()466 void Codec::setBitRate() {
467     ive_ctl_set_bitrate_ip_t sBitrateIp{};
468     ive_ctl_set_bitrate_op_t sBitrateOp{};
469 
470     sBitrateIp.e_cmd = IVE_CMD_VIDEO_CTL;
471     sBitrateIp.e_sub_cmd = IVE_CMD_CTL_SET_BITRATE;
472     sBitrateIp.u4_target_bitrate = mBitrate;
473 
474     sBitrateIp.u4_timestamp_high = -1;
475     sBitrateIp.u4_timestamp_low = -1;
476 
477     sBitrateIp.u4_size = sizeof(ive_ctl_set_bitrate_ip_t);
478     sBitrateOp.u4_size = sizeof(ive_ctl_set_bitrate_op_t);
479 
480     ive_api_function(mCodecCtx, &sBitrateIp, &sBitrateOp);
481     return;
482 }
483 
setFrameType(IV_PICTURE_CODING_TYPE_T eFrameType)484 void Codec::setFrameType(IV_PICTURE_CODING_TYPE_T eFrameType) {
485     ive_ctl_set_frame_type_ip_t sFrameTypeIp{};
486     ive_ctl_set_frame_type_op_t sFrameTypeOp{};
487 
488     sFrameTypeIp.e_cmd = IVE_CMD_VIDEO_CTL;
489     sFrameTypeIp.e_sub_cmd = IVE_CMD_CTL_SET_FRAMETYPE;
490     sFrameTypeIp.e_frame_type = eFrameType;
491 
492     sFrameTypeIp.u4_timestamp_high = -1;
493     sFrameTypeIp.u4_timestamp_low = -1;
494 
495     sFrameTypeIp.u4_size = sizeof(ive_ctl_set_frame_type_ip_t);
496     sFrameTypeOp.u4_size = sizeof(ive_ctl_set_frame_type_op_t);
497 
498     ive_api_function(mCodecCtx, &sFrameTypeIp, &sFrameTypeOp);
499     return;
500 }
501 
setQp()502 void Codec::setQp() {
503     ive_ctl_set_qp_ip_t s_QpIp{};
504     ive_ctl_set_qp_op_t s_QpOp{};
505 
506     s_QpIp.e_cmd = IVE_CMD_VIDEO_CTL;
507     s_QpIp.e_sub_cmd = IVE_CMD_CTL_SET_QP;
508 
509     s_QpIp.u4_i_qp = m_I_QP;
510     s_QpIp.u4_i_qp_max = MAX_H264_QP;
511     s_QpIp.u4_i_qp_min = kMinQP;
512 
513     s_QpIp.u4_p_qp = m_P_QP;
514     s_QpIp.u4_p_qp_max = MAX_H264_QP;
515     s_QpIp.u4_p_qp_min = kMinQP;
516 
517     s_QpIp.u4_b_qp = m_B_QP;
518     s_QpIp.u4_b_qp_max = MAX_H264_QP;
519     s_QpIp.u4_b_qp_min = kMinQP;
520 
521     s_QpIp.u4_timestamp_high = -1;
522     s_QpIp.u4_timestamp_low = -1;
523 
524     s_QpIp.u4_size = sizeof(ive_ctl_set_qp_ip_t);
525     s_QpOp.u4_size = sizeof(ive_ctl_set_qp_op_t);
526 
527     ive_api_function(mCodecCtx, &s_QpIp, &s_QpOp);
528     return;
529 }
530 
setEncMode(IVE_ENC_MODE_T eEncMode)531 void Codec::setEncMode(IVE_ENC_MODE_T eEncMode) {
532     ive_ctl_set_enc_mode_ip_t sEncModeIp{};
533     ive_ctl_set_enc_mode_op_t sEncModeOp{};
534 
535     sEncModeIp.e_cmd = IVE_CMD_VIDEO_CTL;
536     sEncModeIp.e_sub_cmd = IVE_CMD_CTL_SET_ENC_MODE;
537     sEncModeIp.e_enc_mode = eEncMode;
538 
539     sEncModeIp.u4_timestamp_high = -1;
540     sEncModeIp.u4_timestamp_low = -1;
541 
542     sEncModeIp.u4_size = sizeof(ive_ctl_set_enc_mode_ip_t);
543     sEncModeOp.u4_size = sizeof(ive_ctl_set_enc_mode_op_t);
544 
545     ive_api_function(mCodecCtx, &sEncModeIp, &sEncModeOp);
546     return;
547 }
548 
setVbvParams()549 void Codec::setVbvParams() {
550     ive_ctl_set_vbv_params_ip_t sVbvIp{};
551     ive_ctl_set_vbv_params_op_t sVbvOp{};
552 
553     sVbvIp.e_cmd = IVE_CMD_VIDEO_CTL;
554     sVbvIp.e_sub_cmd = IVE_CMD_CTL_SET_VBV_PARAMS;
555     sVbvIp.u4_vbv_buf_size = 0;
556     sVbvIp.u4_vbv_buffer_delay = 1000;
557 
558     sVbvIp.u4_timestamp_high = -1;
559     sVbvIp.u4_timestamp_low = -1;
560 
561     sVbvIp.u4_size = sizeof(ive_ctl_set_vbv_params_ip_t);
562     sVbvOp.u4_size = sizeof(ive_ctl_set_vbv_params_op_t);
563 
564     ive_api_function(mCodecCtx, &sVbvIp, &sVbvOp);
565     return;
566 }
567 
setAirParams()568 void Codec::setAirParams() {
569     ive_ctl_set_air_params_ip_t sAirIp{};
570     ive_ctl_set_air_params_op_t sAirOp{};
571 
572     sAirIp.e_cmd = IVE_CMD_VIDEO_CTL;
573     sAirIp.e_sub_cmd = IVE_CMD_CTL_SET_AIR_PARAMS;
574     sAirIp.e_air_mode = mAirMode;
575     sAirIp.u4_air_refresh_period = mIntraRefresh;
576 
577     sAirIp.u4_timestamp_high = -1;
578     sAirIp.u4_timestamp_low = -1;
579 
580     sAirIp.u4_size = sizeof(ive_ctl_set_air_params_ip_t);
581     sAirOp.u4_size = sizeof(ive_ctl_set_air_params_op_t);
582 
583     ive_api_function(mCodecCtx, &sAirIp, &sAirOp);
584     return;
585 }
586 
setMeParams()587 void Codec::setMeParams() {
588     ive_ctl_set_me_params_ip_t sMeParamsIp{};
589     ive_ctl_set_me_params_op_t sMeParamsOp{};
590 
591     sMeParamsIp.e_cmd = IVE_CMD_VIDEO_CTL;
592     sMeParamsIp.e_sub_cmd = IVE_CMD_CTL_SET_ME_PARAMS;
593     sMeParamsIp.u4_enable_fast_sad = mEnableFastSad;
594     sMeParamsIp.u4_enable_alt_ref = mEnableAltRef;
595 
596     sMeParamsIp.u4_enable_hpel = mHalfPelEnable;
597     sMeParamsIp.u4_enable_qpel = mQPelEnable;
598     sMeParamsIp.u4_me_speed_preset = mMeSpeedPreset;
599     sMeParamsIp.u4_srch_rng_x = mSearchRangeX;
600     sMeParamsIp.u4_srch_rng_y = mSearchRangeY;
601 
602     sMeParamsIp.u4_timestamp_high = -1;
603     sMeParamsIp.u4_timestamp_low = -1;
604 
605     sMeParamsIp.u4_size = sizeof(ive_ctl_set_me_params_ip_t);
606     sMeParamsOp.u4_size = sizeof(ive_ctl_set_me_params_op_t);
607 
608     ive_api_function(mCodecCtx, &sMeParamsIp, &sMeParamsOp);
609     return;
610 }
611 
setGopParams()612 void Codec::setGopParams() {
613     ive_ctl_set_gop_params_ip_t sGopParamsIp{};
614     ive_ctl_set_gop_params_op_t sGopParamsOp{};
615 
616     sGopParamsIp.e_cmd = IVE_CMD_VIDEO_CTL;
617     sGopParamsIp.e_sub_cmd = IVE_CMD_CTL_SET_GOP_PARAMS;
618 
619     sGopParamsIp.u4_i_frm_interval = mIInterval;
620     sGopParamsIp.u4_idr_frm_interval = mIDRInterval;
621 
622     sGopParamsIp.u4_timestamp_high = -1;
623     sGopParamsIp.u4_timestamp_low = -1;
624 
625     sGopParamsIp.u4_size = sizeof(ive_ctl_set_gop_params_ip_t);
626     sGopParamsOp.u4_size = sizeof(ive_ctl_set_gop_params_op_t);
627 
628     ive_api_function(mCodecCtx, &sGopParamsIp, &sGopParamsOp);
629     return;
630 }
631 
setProfileParams()632 void Codec::setProfileParams() {
633     ive_ctl_set_profile_params_ip_t sProfileParamsIp{};
634     ive_ctl_set_profile_params_op_t sProfileParamsOp{};
635 
636     sProfileParamsIp.e_cmd = IVE_CMD_VIDEO_CTL;
637     sProfileParamsIp.e_sub_cmd = IVE_CMD_CTL_SET_PROFILE_PARAMS;
638 
639     sProfileParamsIp.e_profile = mProfile;
640     if (sProfileParamsIp.e_profile == IV_PROFILE_BASE) {
641         sProfileParamsIp.u4_entropy_coding_mode = 0;
642     } else {
643         sProfileParamsIp.u4_entropy_coding_mode = 1;
644     }
645     sProfileParamsIp.u4_timestamp_high = -1;
646     sProfileParamsIp.u4_timestamp_low = -1;
647 
648     sProfileParamsIp.u4_size = sizeof(ive_ctl_set_profile_params_ip_t);
649     sProfileParamsOp.u4_size = sizeof(ive_ctl_set_profile_params_op_t);
650 
651     ive_api_function(mCodecCtx, &sProfileParamsIp, &sProfileParamsOp);
652     return;
653 }
654 
setDeblockParams()655 void Codec::setDeblockParams() {
656     ive_ctl_set_deblock_params_ip_t sDeblockParamsIp{};
657     ive_ctl_set_deblock_params_op_t sDeblockParamsOp{};
658 
659     sDeblockParamsIp.e_cmd = IVE_CMD_VIDEO_CTL;
660     sDeblockParamsIp.e_sub_cmd = IVE_CMD_CTL_SET_DEBLOCK_PARAMS;
661 
662     sDeblockParamsIp.u4_disable_deblock_level = mDisableDeblockLevel;
663 
664     sDeblockParamsIp.u4_timestamp_high = -1;
665     sDeblockParamsIp.u4_timestamp_low = -1;
666 
667     sDeblockParamsIp.u4_size = sizeof(ive_ctl_set_deblock_params_ip_t);
668     sDeblockParamsOp.u4_size = sizeof(ive_ctl_set_deblock_params_op_t);
669 
670     ive_api_function(mCodecCtx, &sDeblockParamsIp, &sDeblockParamsOp);
671     return;
672 }
673 
setVuiParams()674 void Codec::setVuiParams() {
675     ih264e_vui_ip_t sVuiParamsIp{};
676     ih264e_vui_op_t sVuiParamsOp{};
677 
678     sVuiParamsIp.e_cmd = IVE_CMD_VIDEO_CTL;
679     sVuiParamsIp.e_sub_cmd = IVE_CMD_CTL_SET_VUI_PARAMS;
680 
681     sVuiParamsIp.u1_aspect_ratio_info_present_flag = mAspectRatioFlag;
682     sVuiParamsIp.u1_aspect_ratio_idc = 0;
683     sVuiParamsIp.u2_sar_width = 0;
684     sVuiParamsIp.u2_sar_height = 0;
685     sVuiParamsIp.u1_overscan_info_present_flag = 0;
686     sVuiParamsIp.u1_overscan_appropriate_flag = 0;
687     sVuiParamsIp.u1_video_signal_type_present_flag = 1;
688     sVuiParamsIp.u1_video_format = 0;
689     sVuiParamsIp.u1_video_full_range_flag = 0;
690     sVuiParamsIp.u1_colour_description_present_flag = 1;
691     sVuiParamsIp.u1_colour_primaries = 0;
692     sVuiParamsIp.u1_transfer_characteristics = 0;
693     sVuiParamsIp.u1_matrix_coefficients = 0;
694     sVuiParamsIp.u1_chroma_loc_info_present_flag = 0;
695     sVuiParamsIp.u1_chroma_sample_loc_type_top_field = 0;
696     sVuiParamsIp.u1_chroma_sample_loc_type_bottom_field = 0;
697     sVuiParamsIp.u1_vui_timing_info_present_flag = 0;
698     sVuiParamsIp.u4_vui_num_units_in_tick = 0;
699     sVuiParamsIp.u4_vui_time_scale = 0;
700     sVuiParamsIp.u1_fixed_frame_rate_flag = 0;
701     sVuiParamsIp.u1_nal_hrd_parameters_present_flag = mNalHrdFlag;
702     sVuiParamsIp.u1_vcl_hrd_parameters_present_flag = mVclHrdFlag;
703     sVuiParamsIp.u1_low_delay_hrd_flag = 0;
704     sVuiParamsIp.u1_pic_struct_present_flag = 0;
705     sVuiParamsIp.u1_bitstream_restriction_flag = 0;
706     sVuiParamsIp.u1_motion_vectors_over_pic_boundaries_flag = 0;
707     sVuiParamsIp.u1_max_bytes_per_pic_denom = 0;
708     sVuiParamsIp.u1_max_bits_per_mb_denom = 0;
709     sVuiParamsIp.u1_log2_max_mv_length_horizontal = 0;
710     sVuiParamsIp.u1_log2_max_mv_length_vertical = 0;
711     sVuiParamsIp.u1_num_reorder_frames = 0;
712     sVuiParamsIp.u1_max_dec_frame_buffering = 0;
713 
714     sVuiParamsIp.u4_size = sizeof(ih264e_vui_ip_t);
715     sVuiParamsOp.u4_size = sizeof(ih264e_vui_op_t);
716 
717     ive_api_function(mCodecCtx, &sVuiParamsIp, &sVuiParamsOp);
718     return;
719 }
720 
setSeiMdcvParams()721 void Codec::setSeiMdcvParams() {
722     ih264e_ctl_set_sei_mdcv_params_ip_t sSeiMdcvParamsIp{};
723     ih264e_ctl_set_sei_mdcv_params_op_t sSeiMdcvParamsOp{};
724 
725     sSeiMdcvParamsIp.e_cmd = IVE_CMD_VIDEO_CTL;
726     sSeiMdcvParamsIp.e_sub_cmd = IVE_CMD_CTL_SET_SEI_MDCV_PARAMS;
727     sSeiMdcvParamsIp.u1_sei_mdcv_params_present_flag = mSeiMdcvFlag;
728     if (mSeiMdcvFlag) {
729         for (int i4_count = 0; i4_count < NUM_SEI_MDCV_PRIMARIES; ++i4_count) {
730             sSeiMdcvParamsIp.au2_display_primaries_x[i4_count] = 30000;
731             sSeiMdcvParamsIp.au2_display_primaries_y[i4_count] = 35000;
732         }
733         sSeiMdcvParamsIp.u2_white_point_x = 30000;
734         sSeiMdcvParamsIp.u2_white_point_y = 35000;
735         sSeiMdcvParamsIp.u4_max_display_mastering_luminance = 100000000;
736         sSeiMdcvParamsIp.u4_min_display_mastering_luminance = 50000;
737     }
738 
739     sSeiMdcvParamsIp.u4_timestamp_high = -1;
740     sSeiMdcvParamsIp.u4_timestamp_low = -1;
741 
742     sSeiMdcvParamsIp.u4_size = sizeof(ih264e_ctl_set_sei_mdcv_params_ip_t);
743     sSeiMdcvParamsOp.u4_size = sizeof(ih264e_ctl_set_sei_mdcv_params_op_t);
744     ih264e_api_function(mCodecCtx, &sSeiMdcvParamsIp, &sSeiMdcvParamsOp);
745     return;
746 }
747 
setSeiCllParams()748 void Codec::setSeiCllParams() {
749     ih264e_ctl_set_sei_cll_params_ip_t sSeiCllParamsIp{};
750     ih264e_ctl_set_sei_cll_params_op_t sSeiCllParamsOp{};
751 
752     sSeiCllParamsIp.e_cmd = IVE_CMD_VIDEO_CTL;
753     sSeiCllParamsIp.e_sub_cmd = IVE_CMD_CTL_SET_SEI_CLL_PARAMS;
754     sSeiCllParamsIp.u1_sei_cll_params_present_flag = mSeiCllFlag;
755     if (mSeiCllFlag) {
756         sSeiCllParamsIp.u2_max_content_light_level = 0;
757         sSeiCllParamsIp.u2_max_pic_average_light_level = 0;
758     }
759 
760     sSeiCllParamsIp.u4_timestamp_high = -1;
761     sSeiCllParamsIp.u4_timestamp_low = -1;
762 
763     sSeiCllParamsIp.u4_size = sizeof(ih264e_ctl_set_sei_cll_params_ip_t);
764     sSeiCllParamsOp.u4_size = sizeof(ih264e_ctl_set_sei_cll_params_op_t);
765 
766     ih264e_api_function(mCodecCtx, &sSeiCllParamsIp, &sSeiCllParamsOp);
767     return;
768 }
769 
setSeiAveParams()770 void Codec::setSeiAveParams() {
771     ih264e_ctl_set_sei_ave_params_ip_t sSeiAveParamsIp{};
772     ih264e_ctl_set_sei_ave_params_op_t sSeiAveParamsOp{};
773 
774     sSeiAveParamsIp.e_cmd = IVE_CMD_VIDEO_CTL;
775     sSeiAveParamsIp.e_sub_cmd = IVE_CMD_CTL_SET_SEI_AVE_PARAMS;
776     sSeiAveParamsIp.u1_sei_ave_params_present_flag = mSeiAveFlag;
777     if (mSeiAveFlag) {
778         sSeiAveParamsIp.u4_ambient_illuminance = 1;
779         sSeiAveParamsIp.u2_ambient_light_x = 0;
780         sSeiAveParamsIp.u2_ambient_light_y = 0;
781     }
782 
783     sSeiAveParamsIp.u4_timestamp_high = -1;
784     sSeiAveParamsIp.u4_timestamp_low = -1;
785 
786     sSeiAveParamsIp.u4_size = sizeof(ih264e_ctl_set_sei_ave_params_ip_t);
787     sSeiAveParamsOp.u4_size = sizeof(ih264e_ctl_set_sei_ave_params_op_t);
788 
789     ih264e_api_function(mCodecCtx, &sSeiAveParamsIp, &sSeiAveParamsOp);
790     return;
791 }
792 
setSeiCcvParams()793 void Codec::setSeiCcvParams() {
794     ih264e_ctl_set_sei_ccv_params_ip_t sSeiCcvParamsIp{};
795     ih264e_ctl_set_sei_ccv_params_op_t sSeiCcvParamsOp{};
796 
797     sSeiCcvParamsIp.e_cmd = IVE_CMD_VIDEO_CTL;
798     sSeiCcvParamsIp.e_sub_cmd = IVE_CMD_CTL_SET_SEI_CCV_PARAMS;
799     sSeiCcvParamsIp.u1_sei_ccv_params_present_flag = mSeiCcvFlag;
800     if (mSeiCcvFlag) {
801         sSeiCcvParamsIp.u1_ccv_cancel_flag = 0;
802         sSeiCcvParamsIp.u1_ccv_persistence_flag = 1;
803         sSeiCcvParamsIp.u1_ccv_primaries_present_flag = 1;
804         sSeiCcvParamsIp.u1_ccv_min_luminance_value_present_flag = 1;
805         sSeiCcvParamsIp.u1_ccv_max_luminance_value_present_flag = 1;
806         sSeiCcvParamsIp.u1_ccv_avg_luminance_value_present_flag = 1;
807         sSeiCcvParamsIp.u1_ccv_reserved_zero_2bits = 0;
808         for (int i4_count = 0; i4_count < NUM_SEI_CCV_PRIMARIES; ++i4_count) {
809             sSeiCcvParamsIp.ai4_ccv_primaries_x[i4_count] = 1;
810             sSeiCcvParamsIp.ai4_ccv_primaries_y[i4_count] = 1;
811         }
812         sSeiCcvParamsIp.u4_ccv_min_luminance_value = 1;
813         sSeiCcvParamsIp.u4_ccv_max_luminance_value = 1;
814         sSeiCcvParamsIp.u4_ccv_avg_luminance_value = 1;
815     }
816 
817     sSeiCcvParamsIp.u4_timestamp_high = -1;
818     sSeiCcvParamsIp.u4_timestamp_low = -1;
819 
820     sSeiCcvParamsIp.u4_size = sizeof(ih264e_ctl_set_sei_ccv_params_ip_t);
821     sSeiCcvParamsOp.u4_size = sizeof(ih264e_ctl_set_sei_ccv_params_op_t);
822 
823     ih264e_api_function(mCodecCtx, &sSeiCcvParamsIp, &sSeiCcvParamsOp);
824     return;
825 }
826 
logVersion()827 void Codec::logVersion() {
828     ive_ctl_getversioninfo_ip_t sCtlIp{};
829     ive_ctl_getversioninfo_op_t sCtlOp{};
830     UWORD8 au1Buf[512];
831 
832     sCtlIp.e_cmd = IVE_CMD_VIDEO_CTL;
833     sCtlIp.e_sub_cmd = IVE_CMD_CTL_GETVERSION;
834 
835     sCtlIp.u4_size = sizeof(ive_ctl_getversioninfo_ip_t);
836     sCtlOp.u4_size = sizeof(ive_ctl_getversioninfo_op_t);
837     sCtlIp.pu1_version = au1Buf;
838     sCtlIp.u4_version_bufsize = sizeof(au1Buf);
839 
840     ive_api_function(mCodecCtx, (void *)&sCtlIp, (void *)&sCtlOp);
841     return;
842 }
843 
encodeFrames(const uint8_t * data,size_t size)844 void Codec::encodeFrames(const uint8_t *data, size_t size) {
845     size_t frameSize = (mIvVideoColorFormat == IV_YUV_422ILE) ? (mWidth * mHeight * 2)
846                                                               : ((mWidth * mHeight * 3) / 2);
847     ive_video_encode_ip_t sEncodeIp{};
848     ive_video_encode_op_t sEncodeOp{};
849     uint8_t header[kHeaderLength];
850     int32_t numEncodeCalls = 0;
851     iv_raw_buf_t *psInpRawBuf = &sEncodeIp.s_inp_buf;
852     sEncodeIp.s_out_buf.pv_buf = header;
853     sEncodeIp.s_out_buf.u4_bytes = 0;
854     sEncodeIp.s_out_buf.u4_bufsize = kHeaderLength;
855     sEncodeIp.u4_size = sizeof(ive_video_encode_ip_t);
856     sEncodeOp.u4_size = sizeof(ive_video_encode_op_t);
857 
858     sEncodeIp.e_cmd = IVE_CMD_VIDEO_ENCODE;
859     sEncodeIp.pv_bufs = nullptr;
860     sEncodeIp.pv_mb_info = nullptr;
861     sEncodeIp.pv_pic_info = nullptr;
862     sEncodeIp.u4_mb_info_type = 0;
863     sEncodeIp.u4_pic_info_type = 0;
864     sEncodeOp.s_out_buf.pv_buf = nullptr;
865 
866     /* Initialize color formats */
867     memset(psInpRawBuf, 0, sizeof(iv_raw_buf_t));
868     psInpRawBuf->u4_size = sizeof(iv_raw_buf_t);
869     psInpRawBuf->e_color_fmt = mIvVideoColorFormat;
870 
871     ive_api_function(mCodecCtx, &sEncodeIp, &sEncodeOp);
872     size_t numFrame = 0;
873     std::vector<bufferPtrs> inBuffers;
874     uint64_t outputBufferSize = (frameSize / kCompressionRatio);
875     while (!sEncodeOp.u4_is_last && numEncodeCalls < kMaxNumEncodeCalls) {
876         uint8_t *outputBuffer = (uint8_t *)malloc(outputBufferSize);
877         sEncodeIp.s_out_buf.pv_buf = outputBuffer;
878         sEncodeIp.s_out_buf.u4_bufsize = outputBufferSize;
879         if (size > 0) {
880             uint8_t *tmpData = (uint8_t *)malloc(frameSize);
881             size_t bytesConsumed = std::min(size, frameSize);
882             if (bytesConsumed < frameSize) {
883                 memset(&tmpData[bytesConsumed], data[0], frameSize - bytesConsumed);
884             }
885             memcpy(tmpData, data, bytesConsumed);
886             bufferPtrs inBuffer = setEncParams(psInpRawBuf, tmpData, frameSize);
887             inBuffers.push_back(inBuffer);
888             free(tmpData);
889             sEncodeIp.u4_is_last = 0;
890             if (mSendEosWithLastFrame && size == bytesConsumed) {
891                 sEncodeIp.u4_is_last = 1;
892             }
893             if (mIsForceIdrEnabled) {
894                 if (numFrame == mForceIdrInterval) {
895                     setFrameType(IV_IDR_FRAME);
896                 }
897             }
898             if (mIsDynamicBitRateChangeEnabled) {
899                 if (numFrame == mDynamicBitRateInterval) {
900                     if (data[0] & 0x01) {
901                         mBitrate *= 2;
902                     } else {
903                         mBitrate /= 2;
904                     }
905                     setBitRate();
906                 }
907             }
908             if (mIsDynamicFrameRateChangeEnabled) {
909                 if (numFrame == mDynamicFrameRateInterval) {
910                     if (size > 1 && data[1] & 0x01) {
911                         mFrameRate *= 2;
912                     } else {
913                         mFrameRate /= 2;
914                     }
915                     setFrameRate();
916                 }
917             }
918             ++numFrame;
919             data += bytesConsumed;
920             size -= bytesConsumed;
921         } else {
922             sEncodeIp.u4_is_last = 1;
923             psInpRawBuf->apv_bufs[0] = nullptr;
924             psInpRawBuf->apv_bufs[1] = nullptr;
925             psInpRawBuf->apv_bufs[2] = nullptr;
926         }
927         ive_api_function(mCodecCtx, &sEncodeIp, &sEncodeOp);
928         if (sEncodeOp.s_inp_buf.apv_bufs[0]) {
929             std::vector<bufferPtrs>::iterator iter;
930             uint8_t *inputbuf = (uint8_t *)sEncodeOp.s_inp_buf.apv_bufs[0];
931             iter = std::find_if(
932                 inBuffers.begin(), inBuffers.end(),
933                 [=, &inputbuf](const bufferPtrs &buf) { return std::get<0>(buf) == inputbuf; });
934             if (iter != inBuffers.end()) {
935                 inBuffers.erase(iter);
936                 free(sEncodeOp.s_inp_buf.apv_bufs[0]);
937                 if (sEncodeOp.s_inp_buf.apv_bufs[1]) {
938                     free(sEncodeOp.s_inp_buf.apv_bufs[1]);
939                 }
940                 if (sEncodeOp.s_inp_buf.apv_bufs[2]) {
941                     free(sEncodeOp.s_inp_buf.apv_bufs[2]);
942                 }
943             }
944         }
945         ++numEncodeCalls;
946         free(outputBuffer);
947     }
948     for (const auto &buffer : inBuffers) {
949         free(std::get<0>(buffer));
950         if (std::get<1>(buffer)) {
951             free(std::get<1>(buffer));
952         }
953         if (std::get<2>(buffer)) {
954             free(std::get<2>(buffer));
955         }
956     }
957     inBuffers.clear();
958 }
959 
setEncParams(iv_raw_buf_t * psInpRawBuf,const uint8_t * data,size_t frameSize)960 bufferPtrs Codec::setEncParams(iv_raw_buf_t *psInpRawBuf, const uint8_t *data, size_t frameSize) {
961     bufferPtrs inBuffer;
962     switch (mIvVideoColorFormat) {
963         case IV_YUV_420SP_UV:
964             [[fallthrough]];
965         case IV_YUV_420SP_VU: {
966             uint8_t *yPlane = (uint8_t *)malloc(mWidth * mHeight);
967             uint8_t *uPlane = (uint8_t *)malloc(frameSize - (mWidth * mHeight));
968             memcpy(yPlane, data, mWidth * mHeight);
969             memcpy(uPlane, data + (mWidth * mHeight), frameSize - (mWidth * mHeight));
970             int32_t yStride = mWidth;
971             int32_t uStride = mWidth / 2;
972             psInpRawBuf->apv_bufs[0] = yPlane;
973             psInpRawBuf->apv_bufs[1] = uPlane;
974 
975             psInpRawBuf->au4_wd[0] = mWidth;
976             psInpRawBuf->au4_wd[1] = mWidth;
977 
978             psInpRawBuf->au4_ht[0] = mHeight;
979             psInpRawBuf->au4_ht[1] = mHeight / 2;
980 
981             psInpRawBuf->au4_strd[0] = yStride;
982             psInpRawBuf->au4_strd[1] = uStride;
983             inBuffer = std::make_tuple(yPlane, uPlane, nullptr);
984             break;
985         }
986         case IV_YUV_422ILE: {
987             uint8_t *yPlane = (uint8_t *)malloc(frameSize);
988             memcpy(yPlane, data, frameSize);
989             psInpRawBuf->apv_bufs[0] = yPlane;
990 
991             psInpRawBuf->au4_wd[0] = mWidth * 2;
992 
993             psInpRawBuf->au4_ht[0] = mHeight;
994 
995             psInpRawBuf->au4_strd[0] = mWidth * 2;
996             inBuffer = std::make_tuple(yPlane, nullptr, nullptr);
997             break;
998         }
999         case IV_YUV_420P:
1000             [[fallthrough]];
1001         default: {
1002             uint8_t *yPlane = (uint8_t *)malloc(mWidth * mHeight);
1003             uint8_t *uPlane = (uint8_t *)malloc((mWidth * mHeight) / 4);
1004             uint8_t *vPlane = (uint8_t *)malloc(frameSize - ((mWidth * mHeight) * 5) / 4);
1005             memcpy(yPlane, data, mWidth * mHeight);
1006             memcpy(uPlane, data + (mWidth * mHeight), (mWidth * mHeight) / 4);
1007             memcpy(vPlane, data + ((mWidth * mHeight) * 5) / 4,
1008                    frameSize - ((mWidth * mHeight) * 5) / 4);
1009             int32_t yStride = mWidth;
1010             int32_t uStride = mWidth / 2;
1011             int32_t vStride = mWidth / 2;
1012 
1013             psInpRawBuf->apv_bufs[0] = yPlane;
1014             psInpRawBuf->apv_bufs[1] = uPlane;
1015             psInpRawBuf->apv_bufs[2] = vPlane;
1016 
1017             psInpRawBuf->au4_wd[0] = mWidth;
1018             psInpRawBuf->au4_wd[1] = mWidth / 2;
1019             psInpRawBuf->au4_wd[2] = mWidth / 2;
1020 
1021             psInpRawBuf->au4_ht[0] = mHeight;
1022             psInpRawBuf->au4_ht[1] = mHeight / 2;
1023             psInpRawBuf->au4_ht[2] = mHeight / 2;
1024 
1025             psInpRawBuf->au4_strd[0] = yStride;
1026             psInpRawBuf->au4_strd[1] = uStride;
1027             psInpRawBuf->au4_strd[2] = vStride;
1028             inBuffer = std::make_tuple(yPlane, uPlane, vPlane);
1029             break;
1030         }
1031     }
1032     return inBuffer;
1033 }
1034 
deInitEncoder()1035 void Codec::deInitEncoder() {
1036     iv_mem_rec_t *ps_mem_rec = mMemRecords;
1037     for (size_t i = 0; i < mNumMemRecords; ++i) {
1038         if (ps_mem_rec) {
1039             free(ps_mem_rec->pv_base);
1040         }
1041         ++ps_mem_rec;
1042     }
1043     if (mMemRecords) {
1044         free(mMemRecords);
1045     }
1046     mCodecCtx = nullptr;
1047     return;
1048 }
1049 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)1050 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
1051     if (size < IDX_LAST) {
1052         return 0;
1053     }
1054     Codec *codec = new Codec();
1055     if (codec->initEncoder(&data, &size)) {
1056         codec->encodeFrames(data, size);
1057     }
1058     delete codec;
1059     return 0;
1060 }
1061