SoftAVCEnc.cpp revision d08a068bee8396b2ccdd819920b4496de2309a68
1/*
2 * Copyright 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "SoftAVCEnc"
19#include <utils/Log.h>
20#include <utils/misc.h>
21
22#include "OMX_Video.h"
23
24#include <HardwareAPI.h>
25#include <MetadataBufferType.h>
26#include <media/stagefright/foundation/ADebug.h>
27#include <media/stagefright/MediaDefs.h>
28#include <media/stagefright/MediaErrors.h>
29#include <media/stagefright/MetaData.h>
30#include <media/stagefright/Utils.h>
31#include <OMX_IndexExt.h>
32#include <OMX_VideoExt.h>
33#include <ui/Rect.h>
34
35#include "ih264_typedefs.h"
36#include "iv2.h"
37#include "ive2.h"
38#include "ih264e.h"
39#include "SoftAVCEnc.h"
40
41namespace android {
42
43    #define ive_api_function ih264e_api_function
44
45template<class T>
46static void InitOMXParams(T *params) {
47    params->nSize = sizeof(T);
48    params->nVersion.s.nVersionMajor = 1;
49    params->nVersion.s.nVersionMinor = 0;
50    params->nVersion.s.nRevision = 0;
51    params->nVersion.s.nStep = 0;
52}
53
54struct LevelConversion {
55    OMX_VIDEO_AVCLEVELTYPE omxLevel;
56    WORD32 avcLevel;
57};
58
59static LevelConversion ConversionTable[] = {
60    { OMX_VIDEO_AVCLevel1,  10 },
61    { OMX_VIDEO_AVCLevel1b, 9  },
62    { OMX_VIDEO_AVCLevel11, 11 },
63    { OMX_VIDEO_AVCLevel12, 12 },
64    { OMX_VIDEO_AVCLevel13, 13 },
65    { OMX_VIDEO_AVCLevel2,  20 },
66    { OMX_VIDEO_AVCLevel21, 21 },
67    { OMX_VIDEO_AVCLevel22, 22 },
68    { OMX_VIDEO_AVCLevel3,  30 },
69    { OMX_VIDEO_AVCLevel31, 31 },
70    { OMX_VIDEO_AVCLevel32, 32 },
71    { OMX_VIDEO_AVCLevel4,  40 },
72    { OMX_VIDEO_AVCLevel41, 41 },
73    { OMX_VIDEO_AVCLevel42, 42 },
74    { OMX_VIDEO_AVCLevel5,  50 },
75    { OMX_VIDEO_AVCLevel51, 51 },
76};
77
78static const CodecProfileLevel kProfileLevels[] = {
79    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1  },
80    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1b },
81    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel11 },
82    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel12 },
83    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13 },
84    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2  },
85    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel21 },
86    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel22 },
87    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel3  },
88    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel31 },
89    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel32 },
90    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel4  },
91    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel41 },
92    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1  },
93    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1b },
94    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel11 },
95    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel12 },
96    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel13 },
97    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel2  },
98    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel21 },
99    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel22 },
100    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel3  },
101    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel31 },
102    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel32 },
103    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel4  },
104    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel41 },
105
106};
107
108static size_t GetCPUCoreCount() {
109    long cpuCoreCount = 1;
110#if defined(_SC_NPROCESSORS_ONLN)
111    cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
112#else
113    // _SC_NPROC_ONLN must be defined...
114    cpuCoreCount = sysconf(_SC_NPROC_ONLN);
115#endif
116    CHECK(cpuCoreCount >= 1);
117    ALOGV("Number of CPU cores: %ld", cpuCoreCount);
118    return (size_t)cpuCoreCount;
119}
120
121static status_t ConvertOmxAvcLevelToAvcSpecLevel(
122        OMX_VIDEO_AVCLEVELTYPE omxLevel, WORD32 *avcLevel) {
123    for (size_t i = 0; i < NELEM(ConversionTable); ++i) {
124        if (omxLevel == ConversionTable[i].omxLevel) {
125            *avcLevel = ConversionTable[i].avcLevel;
126            return OK;
127        }
128    }
129
130    ALOGE("ConvertOmxAvcLevelToAvcSpecLevel: %d level not supported",
131            (int32_t)omxLevel);
132
133    return BAD_VALUE;
134}
135
136static status_t ConvertAvcSpecLevelToOmxAvcLevel(
137        WORD32 avcLevel, OMX_VIDEO_AVCLEVELTYPE *omxLevel) {
138    for (size_t i = 0; i < NELEM(ConversionTable); ++i) {
139        if (avcLevel == ConversionTable[i].avcLevel) {
140            *omxLevel = ConversionTable[i].omxLevel;
141            return OK;
142        }
143    }
144
145    ALOGE("ConvertAvcSpecLevelToOmxAvcLevel: %d level not supported",
146            (int32_t)avcLevel);
147
148    return BAD_VALUE;
149}
150
151
152SoftAVC::SoftAVC(
153        const char *name,
154        const OMX_CALLBACKTYPE *callbacks,
155        OMX_PTR appData,
156        OMX_COMPONENTTYPE **component)
157    : SoftVideoEncoderOMXComponent(
158            name, "video_encoder.avc", OMX_VIDEO_CodingAVC,
159            kProfileLevels, NELEM(kProfileLevels),
160            176 /* width */, 144 /* height */,
161            callbacks, appData, component),
162      mUpdateFlag(0),
163      mIvVideoColorFormat(IV_YUV_420P),
164      mAVCEncProfile(IV_PROFILE_BASE),
165      mAVCEncLevel(41),
166      mStarted(false),
167      mSawInputEOS(false),
168      mSawOutputEOS(false),
169      mSignalledError(false),
170      mCodecCtx(NULL) {
171
172    initPorts(kNumBuffers, kNumBuffers, ((mWidth * mHeight * 3) >> 1),
173            MEDIA_MIMETYPE_VIDEO_AVC, 2);
174
175    // If dump is enabled, then open create an empty file
176    GENERATE_FILE_NAMES();
177    CREATE_DUMP_FILE(mInFile);
178    CREATE_DUMP_FILE(mOutFile);
179    memset(mConversionBuffers, 0, sizeof(mConversionBuffers));
180    memset(mInputBufferInfo, 0, sizeof(mInputBufferInfo));
181
182    initEncParams();
183
184}
185
186SoftAVC::~SoftAVC() {
187    releaseEncoder();
188    List<BufferInfo *> &outQueue = getPortQueue(1);
189    List<BufferInfo *> &inQueue = getPortQueue(0);
190    CHECK(outQueue.empty());
191    CHECK(inQueue.empty());
192}
193
194void  SoftAVC::initEncParams() {
195    mCodecCtx = NULL;
196    mMemRecords = NULL;
197    mNumMemRecords = DEFAULT_MEM_REC_CNT;
198    mHeaderGenerated = 0;
199    mNumCores = GetCPUCoreCount();
200    mArch = DEFAULT_ARCH;
201    mSliceMode = DEFAULT_SLICE_MODE;
202    mSliceParam = DEFAULT_SLICE_PARAM;
203    mHalfPelEnable = DEFAULT_HPEL;
204    mIInterval = DEFAULT_I_INTERVAL;
205    mIDRInterval = DEFAULT_IDR_INTERVAL;
206    mDisableDeblkLevel = DEFAULT_DISABLE_DEBLK_LEVEL;
207    mEnableFastSad = DEFAULT_ENABLE_FAST_SAD;
208    mEnableAltRef = DEFAULT_ENABLE_ALT_REF;
209    mEncSpeed = DEFAULT_ENC_SPEED;
210    mIntra4x4 = DEFAULT_INTRA4x4;
211    mAIRMode = DEFAULT_AIR;
212    mAIRRefreshPeriod = DEFAULT_AIR_REFRESH_PERIOD;
213    mPSNREnable = DEFAULT_PSNR_ENABLE;
214    mReconEnable = DEFAULT_RECON_ENABLE;
215    mEntropyMode = DEFAULT_ENTROPY_MODE;
216    mBframes = DEFAULT_B_FRAMES;
217
218    gettimeofday(&mTimeStart, NULL);
219    gettimeofday(&mTimeEnd, NULL);
220
221}
222
223
224OMX_ERRORTYPE SoftAVC::setDimensions() {
225    ive_ctl_set_dimensions_ip_t s_dimensions_ip;
226    ive_ctl_set_dimensions_op_t s_dimensions_op;
227    IV_STATUS_T status;
228
229    s_dimensions_ip.e_cmd = IVE_CMD_VIDEO_CTL;
230    s_dimensions_ip.e_sub_cmd = IVE_CMD_CTL_SET_DIMENSIONS;
231    s_dimensions_ip.u4_ht = mHeight;
232    s_dimensions_ip.u4_wd = mWidth;
233
234    s_dimensions_ip.u4_timestamp_high = -1;
235    s_dimensions_ip.u4_timestamp_low = -1;
236
237    s_dimensions_ip.u4_size = sizeof(ive_ctl_set_dimensions_ip_t);
238    s_dimensions_op.u4_size = sizeof(ive_ctl_set_dimensions_op_t);
239
240    status = ive_api_function(mCodecCtx, &s_dimensions_ip, &s_dimensions_op);
241    if (status != IV_SUCCESS) {
242        ALOGE("Unable to set frame dimensions = 0x%x\n",
243                s_dimensions_op.u4_error_code);
244        return OMX_ErrorUndefined;
245    }
246    return OMX_ErrorNone;
247}
248
249OMX_ERRORTYPE SoftAVC::setNumCores() {
250    IV_STATUS_T status;
251    ive_ctl_set_num_cores_ip_t s_num_cores_ip;
252    ive_ctl_set_num_cores_op_t s_num_cores_op;
253    s_num_cores_ip.e_cmd = IVE_CMD_VIDEO_CTL;
254    s_num_cores_ip.e_sub_cmd = IVE_CMD_CTL_SET_NUM_CORES;
255    s_num_cores_ip.u4_num_cores = MIN(mNumCores, CODEC_MAX_CORES);
256    s_num_cores_ip.u4_timestamp_high = -1;
257    s_num_cores_ip.u4_timestamp_low = -1;
258    s_num_cores_ip.u4_size = sizeof(ive_ctl_set_num_cores_ip_t);
259
260    s_num_cores_op.u4_size = sizeof(ive_ctl_set_num_cores_op_t);
261
262    status = ive_api_function(
263            mCodecCtx, (void *) &s_num_cores_ip, (void *) &s_num_cores_op);
264    if (status != IV_SUCCESS) {
265        ALOGE("Unable to set processor params = 0x%x\n",
266                s_num_cores_op.u4_error_code);
267        return OMX_ErrorUndefined;
268    }
269    return OMX_ErrorNone;
270}
271
272OMX_ERRORTYPE SoftAVC::setFrameRate() {
273    ive_ctl_set_frame_rate_ip_t s_frame_rate_ip;
274    ive_ctl_set_frame_rate_op_t s_frame_rate_op;
275    IV_STATUS_T status;
276
277    s_frame_rate_ip.e_cmd = IVE_CMD_VIDEO_CTL;
278    s_frame_rate_ip.e_sub_cmd = IVE_CMD_CTL_SET_FRAMERATE;
279
280    s_frame_rate_ip.u4_src_frame_rate = mFramerate >> 16;
281    s_frame_rate_ip.u4_tgt_frame_rate = mFramerate >> 16;
282
283    s_frame_rate_ip.u4_timestamp_high = -1;
284    s_frame_rate_ip.u4_timestamp_low = -1;
285
286    s_frame_rate_ip.u4_size = sizeof(ive_ctl_set_frame_rate_ip_t);
287    s_frame_rate_op.u4_size = sizeof(ive_ctl_set_frame_rate_op_t);
288
289    status = ive_api_function(mCodecCtx, &s_frame_rate_ip, &s_frame_rate_op);
290    if (status != IV_SUCCESS) {
291        ALOGE("Unable to set frame rate = 0x%x\n",
292                s_frame_rate_op.u4_error_code);
293        return OMX_ErrorUndefined;
294    }
295    return OMX_ErrorNone;
296}
297
298OMX_ERRORTYPE SoftAVC::setIpeParams() {
299    ive_ctl_set_ipe_params_ip_t s_ipe_params_ip;
300    ive_ctl_set_ipe_params_op_t s_ipe_params_op;
301    IV_STATUS_T status;
302
303    s_ipe_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
304    s_ipe_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_IPE_PARAMS;
305
306    s_ipe_params_ip.u4_enable_intra_4x4 = mIntra4x4;
307    s_ipe_params_ip.u4_enc_speed_preset = mEncSpeed;
308
309    s_ipe_params_ip.u4_timestamp_high = -1;
310    s_ipe_params_ip.u4_timestamp_low = -1;
311
312    s_ipe_params_ip.u4_size = sizeof(ive_ctl_set_ipe_params_ip_t);
313    s_ipe_params_op.u4_size = sizeof(ive_ctl_set_ipe_params_op_t);
314
315    status = ive_api_function(mCodecCtx, &s_ipe_params_ip, &s_ipe_params_op);
316    if (status != IV_SUCCESS) {
317        ALOGE("Unable to set ipe params = 0x%x\n",
318                s_ipe_params_op.u4_error_code);
319        return OMX_ErrorUndefined;
320    }
321    return OMX_ErrorNone;
322}
323
324OMX_ERRORTYPE SoftAVC::setBitRate() {
325    ive_ctl_set_bitrate_ip_t s_bitrate_ip;
326    ive_ctl_set_bitrate_op_t s_bitrate_op;
327    IV_STATUS_T status;
328
329    s_bitrate_ip.e_cmd = IVE_CMD_VIDEO_CTL;
330    s_bitrate_ip.e_sub_cmd = IVE_CMD_CTL_SET_BITRATE;
331
332    s_bitrate_ip.u4_target_bitrate = mBitrate;
333
334    s_bitrate_ip.u4_timestamp_high = -1;
335    s_bitrate_ip.u4_timestamp_low = -1;
336
337    s_bitrate_ip.u4_size = sizeof(ive_ctl_set_bitrate_ip_t);
338    s_bitrate_op.u4_size = sizeof(ive_ctl_set_bitrate_op_t);
339
340    status = ive_api_function(mCodecCtx, &s_bitrate_ip, &s_bitrate_op);
341    if (status != IV_SUCCESS) {
342        ALOGE("Unable to set bit rate = 0x%x\n", s_bitrate_op.u4_error_code);
343        return OMX_ErrorUndefined;
344    }
345    return OMX_ErrorNone;
346}
347
348OMX_ERRORTYPE SoftAVC::setFrameType(IV_PICTURE_CODING_TYPE_T e_frame_type) {
349    ive_ctl_set_frame_type_ip_t s_frame_type_ip;
350    ive_ctl_set_frame_type_op_t s_frame_type_op;
351    IV_STATUS_T status;
352    s_frame_type_ip.e_cmd = IVE_CMD_VIDEO_CTL;
353    s_frame_type_ip.e_sub_cmd = IVE_CMD_CTL_SET_FRAMETYPE;
354
355    s_frame_type_ip.e_frame_type = e_frame_type;
356
357    s_frame_type_ip.u4_timestamp_high = -1;
358    s_frame_type_ip.u4_timestamp_low = -1;
359
360    s_frame_type_ip.u4_size = sizeof(ive_ctl_set_frame_type_ip_t);
361    s_frame_type_op.u4_size = sizeof(ive_ctl_set_frame_type_op_t);
362
363    status = ive_api_function(mCodecCtx, &s_frame_type_ip, &s_frame_type_op);
364    if (status != IV_SUCCESS) {
365        ALOGE("Unable to set frame type = 0x%x\n",
366                s_frame_type_op.u4_error_code);
367        return OMX_ErrorUndefined;
368    }
369    return OMX_ErrorNone;
370}
371
372OMX_ERRORTYPE SoftAVC::setQp() {
373    ive_ctl_set_qp_ip_t s_qp_ip;
374    ive_ctl_set_qp_op_t s_qp_op;
375    IV_STATUS_T status;
376
377    s_qp_ip.e_cmd = IVE_CMD_VIDEO_CTL;
378    s_qp_ip.e_sub_cmd = IVE_CMD_CTL_SET_QP;
379
380    s_qp_ip.u4_i_qp = DEFAULT_I_QP;
381    s_qp_ip.u4_i_qp_max = DEFAULT_QP_MAX;
382    s_qp_ip.u4_i_qp_min = DEFAULT_QP_MIN;
383
384    s_qp_ip.u4_p_qp = DEFAULT_P_QP;
385    s_qp_ip.u4_p_qp_max = DEFAULT_QP_MAX;
386    s_qp_ip.u4_p_qp_min = DEFAULT_QP_MIN;
387
388    s_qp_ip.u4_b_qp = DEFAULT_P_QP;
389    s_qp_ip.u4_b_qp_max = DEFAULT_QP_MAX;
390    s_qp_ip.u4_b_qp_min = DEFAULT_QP_MIN;
391
392    s_qp_ip.u4_timestamp_high = -1;
393    s_qp_ip.u4_timestamp_low = -1;
394
395    s_qp_ip.u4_size = sizeof(ive_ctl_set_qp_ip_t);
396    s_qp_op.u4_size = sizeof(ive_ctl_set_qp_op_t);
397
398    status = ive_api_function(mCodecCtx, &s_qp_ip, &s_qp_op);
399    if (status != IV_SUCCESS) {
400        ALOGE("Unable to set qp 0x%x\n", s_qp_op.u4_error_code);
401        return OMX_ErrorUndefined;
402    }
403    return OMX_ErrorNone;
404}
405
406OMX_ERRORTYPE SoftAVC::setEncMode(IVE_ENC_MODE_T e_enc_mode) {
407    IV_STATUS_T status;
408    ive_ctl_set_enc_mode_ip_t s_enc_mode_ip;
409    ive_ctl_set_enc_mode_op_t s_enc_mode_op;
410
411    s_enc_mode_ip.e_cmd = IVE_CMD_VIDEO_CTL;
412    s_enc_mode_ip.e_sub_cmd = IVE_CMD_CTL_SET_ENC_MODE;
413
414    s_enc_mode_ip.e_enc_mode = e_enc_mode;
415
416    s_enc_mode_ip.u4_timestamp_high = -1;
417    s_enc_mode_ip.u4_timestamp_low = -1;
418
419    s_enc_mode_ip.u4_size = sizeof(ive_ctl_set_enc_mode_ip_t);
420    s_enc_mode_op.u4_size = sizeof(ive_ctl_set_enc_mode_op_t);
421
422    status = ive_api_function(mCodecCtx, &s_enc_mode_ip, &s_enc_mode_op);
423    if (status != IV_SUCCESS) {
424        ALOGE("Unable to set in header encode mode = 0x%x\n",
425                s_enc_mode_op.u4_error_code);
426        return OMX_ErrorUndefined;
427    }
428    return OMX_ErrorNone;
429}
430
431OMX_ERRORTYPE SoftAVC::setVbvParams() {
432    ive_ctl_set_vbv_params_ip_t s_vbv_ip;
433    ive_ctl_set_vbv_params_op_t s_vbv_op;
434    IV_STATUS_T status;
435
436    s_vbv_ip.e_cmd = IVE_CMD_VIDEO_CTL;
437    s_vbv_ip.e_sub_cmd = IVE_CMD_CTL_SET_VBV_PARAMS;
438
439    s_vbv_ip.u4_vbv_buf_size = 0;
440    s_vbv_ip.u4_vbv_buffer_delay = 1000;
441
442    s_vbv_ip.u4_timestamp_high = -1;
443    s_vbv_ip.u4_timestamp_low = -1;
444
445    s_vbv_ip.u4_size = sizeof(ive_ctl_set_vbv_params_ip_t);
446    s_vbv_op.u4_size = sizeof(ive_ctl_set_vbv_params_op_t);
447
448    status = ive_api_function(mCodecCtx, &s_vbv_ip, &s_vbv_op);
449    if (status != IV_SUCCESS) {
450        ALOGE("Unable to set VBC params = 0x%x\n", s_vbv_op.u4_error_code);
451        return OMX_ErrorUndefined;
452    }
453    return OMX_ErrorNone;
454}
455
456OMX_ERRORTYPE SoftAVC::setAirParams() {
457    ive_ctl_set_air_params_ip_t s_air_ip;
458    ive_ctl_set_air_params_op_t s_air_op;
459    IV_STATUS_T status;
460
461    s_air_ip.e_cmd = IVE_CMD_VIDEO_CTL;
462    s_air_ip.e_sub_cmd = IVE_CMD_CTL_SET_AIR_PARAMS;
463
464    s_air_ip.e_air_mode = mAIRMode;
465    s_air_ip.u4_air_refresh_period = mAIRRefreshPeriod;
466
467    s_air_ip.u4_timestamp_high = -1;
468    s_air_ip.u4_timestamp_low = -1;
469
470    s_air_ip.u4_size = sizeof(ive_ctl_set_air_params_ip_t);
471    s_air_op.u4_size = sizeof(ive_ctl_set_air_params_op_t);
472
473    status = ive_api_function(mCodecCtx, &s_air_ip, &s_air_op);
474    if (status != IV_SUCCESS) {
475        ALOGE("Unable to set air params = 0x%x\n", s_air_op.u4_error_code);
476        return OMX_ErrorUndefined;
477    }
478    return OMX_ErrorNone;
479}
480
481OMX_ERRORTYPE SoftAVC::setMeParams() {
482    IV_STATUS_T status;
483    ive_ctl_set_me_params_ip_t s_me_params_ip;
484    ive_ctl_set_me_params_op_t s_me_params_op;
485
486    s_me_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
487    s_me_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_ME_PARAMS;
488
489    s_me_params_ip.u4_enable_fast_sad = mEnableFastSad;
490    s_me_params_ip.u4_enable_alt_ref = mEnableAltRef;
491
492    s_me_params_ip.u4_enable_hpel = mHalfPelEnable;
493    s_me_params_ip.u4_enable_qpel = DEFAULT_QPEL;
494    s_me_params_ip.u4_me_speed_preset = DEFAULT_ME_SPEED;
495    s_me_params_ip.u4_srch_rng_x = DEFAULT_SRCH_RNG_X;
496    s_me_params_ip.u4_srch_rng_y = DEFAULT_SRCH_RNG_Y;
497
498    s_me_params_ip.u4_timestamp_high = -1;
499    s_me_params_ip.u4_timestamp_low = -1;
500
501    s_me_params_ip.u4_size = sizeof(ive_ctl_set_me_params_ip_t);
502    s_me_params_op.u4_size = sizeof(ive_ctl_set_me_params_op_t);
503
504    status = ive_api_function(mCodecCtx, &s_me_params_ip, &s_me_params_op);
505    if (status != IV_SUCCESS) {
506        ALOGE("Unable to set me params = 0x%x\n", s_me_params_op.u4_error_code);
507        return OMX_ErrorUndefined;
508    }
509    return OMX_ErrorNone;
510}
511
512OMX_ERRORTYPE SoftAVC::setGopParams() {
513    IV_STATUS_T status;
514    ive_ctl_set_gop_params_ip_t s_gop_params_ip;
515    ive_ctl_set_gop_params_op_t s_gop_params_op;
516
517    s_gop_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
518    s_gop_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_GOP_PARAMS;
519
520    s_gop_params_ip.u4_i_frm_interval = mIInterval;
521    s_gop_params_ip.u4_idr_frm_interval = mIDRInterval;
522
523    s_gop_params_ip.u4_timestamp_high = -1;
524    s_gop_params_ip.u4_timestamp_low = -1;
525
526    s_gop_params_ip.u4_size = sizeof(ive_ctl_set_gop_params_ip_t);
527    s_gop_params_op.u4_size = sizeof(ive_ctl_set_gop_params_op_t);
528
529    status = ive_api_function(mCodecCtx, &s_gop_params_ip, &s_gop_params_op);
530    if (status != IV_SUCCESS) {
531        ALOGE("Unable to set ME params = 0x%x\n",
532                s_gop_params_op.u4_error_code);
533        return OMX_ErrorUndefined;
534    }
535    return OMX_ErrorNone;
536}
537
538OMX_ERRORTYPE SoftAVC::setProfileParams() {
539    IV_STATUS_T status;
540    ive_ctl_set_profile_params_ip_t s_profile_params_ip;
541    ive_ctl_set_profile_params_op_t s_profile_params_op;
542
543    s_profile_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
544    s_profile_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_PROFILE_PARAMS;
545
546    s_profile_params_ip.e_profile = DEFAULT_EPROFILE;
547    s_profile_params_ip.u4_entropy_coding_mode = mEntropyMode;
548    s_profile_params_ip.u4_timestamp_high = -1;
549    s_profile_params_ip.u4_timestamp_low = -1;
550
551    s_profile_params_ip.u4_size = sizeof(ive_ctl_set_profile_params_ip_t);
552    s_profile_params_op.u4_size = sizeof(ive_ctl_set_profile_params_op_t);
553
554    status = ive_api_function(mCodecCtx, &s_profile_params_ip, &s_profile_params_op);
555    if (status != IV_SUCCESS) {
556        ALOGE("Unable to set profile params = 0x%x\n",
557                s_profile_params_op.u4_error_code);
558        return OMX_ErrorUndefined;
559    }
560    return OMX_ErrorNone;
561}
562
563OMX_ERRORTYPE SoftAVC::setDeblockParams() {
564    IV_STATUS_T status;
565    ive_ctl_set_deblock_params_ip_t s_deblock_params_ip;
566    ive_ctl_set_deblock_params_op_t s_deblock_params_op;
567
568    s_deblock_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
569    s_deblock_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_DEBLOCK_PARAMS;
570
571    s_deblock_params_ip.u4_disable_deblock_level = mDisableDeblkLevel;
572
573    s_deblock_params_ip.u4_timestamp_high = -1;
574    s_deblock_params_ip.u4_timestamp_low = -1;
575
576    s_deblock_params_ip.u4_size = sizeof(ive_ctl_set_deblock_params_ip_t);
577    s_deblock_params_op.u4_size = sizeof(ive_ctl_set_deblock_params_op_t);
578
579    status = ive_api_function(mCodecCtx, &s_deblock_params_ip, &s_deblock_params_op);
580    if (status != IV_SUCCESS) {
581        ALOGE("Unable to enable/disable deblock params = 0x%x\n",
582                s_deblock_params_op.u4_error_code);
583        return OMX_ErrorUndefined;
584    }
585    return OMX_ErrorNone;
586}
587
588void SoftAVC::logVersion() {
589    ive_ctl_getversioninfo_ip_t s_ctl_ip;
590    ive_ctl_getversioninfo_op_t s_ctl_op;
591    UWORD8 au1_buf[512];
592    IV_STATUS_T status;
593
594    s_ctl_ip.e_cmd = IVE_CMD_VIDEO_CTL;
595    s_ctl_ip.e_sub_cmd = IVE_CMD_CTL_GETVERSION;
596    s_ctl_ip.u4_size = sizeof(ive_ctl_getversioninfo_ip_t);
597    s_ctl_op.u4_size = sizeof(ive_ctl_getversioninfo_op_t);
598    s_ctl_ip.pu1_version = au1_buf;
599    s_ctl_ip.u4_version_bufsize = sizeof(au1_buf);
600
601    status = ive_api_function(mCodecCtx, (void *) &s_ctl_ip, (void *) &s_ctl_op);
602
603    if (status != IV_SUCCESS) {
604        ALOGE("Error in getting version: 0x%x", s_ctl_op.u4_error_code);
605    } else {
606        ALOGV("Ittiam encoder version: %s", (char *)s_ctl_ip.pu1_version);
607    }
608    return;
609}
610
611OMX_ERRORTYPE SoftAVC::initEncoder() {
612    IV_STATUS_T status;
613    WORD32 level;
614    uint32_t displaySizeY;
615    CHECK(!mStarted);
616
617    OMX_ERRORTYPE errType = OMX_ErrorNone;
618
619    displaySizeY = mWidth * mHeight;
620    if (displaySizeY > (1920 * 1088)) {
621        level = 50;
622    } else if (displaySizeY > (1280 * 720)) {
623        level = 40;
624    } else if (displaySizeY > (720 * 576)) {
625        level = 31;
626    } else if (displaySizeY > (624 * 320)) {
627        level = 30;
628    } else if (displaySizeY > (352 * 288)) {
629        level = 21;
630    } else {
631        level = 20;
632    }
633    mAVCEncLevel = MAX(level, mAVCEncLevel);
634
635    mStride = mWidth;
636
637    if (mInputDataIsMeta) {
638        for (size_t i = 0; i < MAX_CONVERSION_BUFFERS; i++) {
639            if (mConversionBuffers[i] != NULL) {
640                free(mConversionBuffers[i]);
641                mConversionBuffers[i] = 0;
642            }
643
644            if (((uint64_t)mStride * mHeight) > ((uint64_t)INT32_MAX / 3)) {
645                ALOGE("Buffer size is too big.");
646                return OMX_ErrorUndefined;
647            }
648            mConversionBuffers[i] = (uint8_t *)malloc(mStride * mHeight * 3 / 2);
649
650            if (mConversionBuffers[i] == NULL) {
651                ALOGE("Allocating conversion buffer failed.");
652                return OMX_ErrorUndefined;
653            }
654
655            mConversionBuffersFree[i] = 1;
656        }
657    }
658
659    switch (mColorFormat) {
660        case OMX_COLOR_FormatYUV420SemiPlanar:
661            mIvVideoColorFormat = IV_YUV_420SP_UV;
662            ALOGV("colorFormat YUV_420SP");
663            break;
664        default:
665        case OMX_COLOR_FormatYUV420Planar:
666            mIvVideoColorFormat = IV_YUV_420P;
667            ALOGV("colorFormat YUV_420P");
668            break;
669    }
670
671    ALOGD("Params width %d height %d level %d colorFormat %d", mWidth,
672            mHeight, mAVCEncLevel, mIvVideoColorFormat);
673
674    /* Getting Number of MemRecords */
675    {
676        iv_num_mem_rec_ip_t s_num_mem_rec_ip;
677        iv_num_mem_rec_op_t s_num_mem_rec_op;
678
679        s_num_mem_rec_ip.u4_size = sizeof(iv_num_mem_rec_ip_t);
680        s_num_mem_rec_op.u4_size = sizeof(iv_num_mem_rec_op_t);
681
682        s_num_mem_rec_ip.e_cmd = IV_CMD_GET_NUM_MEM_REC;
683
684        status = ive_api_function(0, &s_num_mem_rec_ip, &s_num_mem_rec_op);
685
686        if (status != IV_SUCCESS) {
687            ALOGE("Get number of memory records failed = 0x%x\n",
688                    s_num_mem_rec_op.u4_error_code);
689            return OMX_ErrorUndefined;
690        }
691
692        mNumMemRecords = s_num_mem_rec_op.u4_num_mem_rec;
693    }
694
695    /* Allocate array to hold memory records */
696    if (mNumMemRecords > SIZE_MAX / sizeof(iv_mem_rec_t)) {
697        ALOGE("requested memory size is too big.");
698        return OMX_ErrorUndefined;
699    }
700    mMemRecords = (iv_mem_rec_t *)malloc(mNumMemRecords * sizeof(iv_mem_rec_t));
701    if (NULL == mMemRecords) {
702        ALOGE("Unable to allocate memory for hold memory records: Size %zu",
703                mNumMemRecords * sizeof(iv_mem_rec_t));
704        mSignalledError = true;
705        notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
706        return OMX_ErrorUndefined;
707    }
708
709    {
710        iv_mem_rec_t *ps_mem_rec;
711        ps_mem_rec = mMemRecords;
712        for (size_t i = 0; i < mNumMemRecords; i++) {
713            ps_mem_rec->u4_size = sizeof(iv_mem_rec_t);
714            ps_mem_rec->pv_base = NULL;
715            ps_mem_rec->u4_mem_size = 0;
716            ps_mem_rec->u4_mem_alignment = 0;
717            ps_mem_rec->e_mem_type = IV_NA_MEM_TYPE;
718
719            ps_mem_rec++;
720        }
721    }
722
723    /* Getting MemRecords Attributes */
724    {
725        iv_fill_mem_rec_ip_t s_fill_mem_rec_ip;
726        iv_fill_mem_rec_op_t s_fill_mem_rec_op;
727
728        s_fill_mem_rec_ip.u4_size = sizeof(iv_fill_mem_rec_ip_t);
729        s_fill_mem_rec_op.u4_size = sizeof(iv_fill_mem_rec_op_t);
730
731        s_fill_mem_rec_ip.e_cmd = IV_CMD_FILL_NUM_MEM_REC;
732        s_fill_mem_rec_ip.ps_mem_rec = mMemRecords;
733        s_fill_mem_rec_ip.u4_num_mem_rec = mNumMemRecords;
734        s_fill_mem_rec_ip.u4_max_wd = mWidth;
735        s_fill_mem_rec_ip.u4_max_ht = mHeight;
736        s_fill_mem_rec_ip.u4_max_level = mAVCEncLevel;
737        s_fill_mem_rec_ip.e_color_format = DEFAULT_INP_COLOR_FORMAT;
738        s_fill_mem_rec_ip.u4_max_ref_cnt = DEFAULT_MAX_REF_FRM;
739        s_fill_mem_rec_ip.u4_max_reorder_cnt = DEFAULT_MAX_REORDER_FRM;
740        s_fill_mem_rec_ip.u4_max_srch_rng_x = DEFAULT_MAX_SRCH_RANGE_X;
741        s_fill_mem_rec_ip.u4_max_srch_rng_y = DEFAULT_MAX_SRCH_RANGE_Y;
742
743        status = ive_api_function(0, &s_fill_mem_rec_ip, &s_fill_mem_rec_op);
744
745        if (status != IV_SUCCESS) {
746            ALOGE("Fill memory records failed = 0x%x\n",
747                    s_fill_mem_rec_op.u4_error_code);
748            mSignalledError = true;
749            notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
750            return OMX_ErrorUndefined;
751        }
752    }
753
754    /* Allocating Memory for Mem Records */
755    {
756        WORD32 total_size;
757        iv_mem_rec_t *ps_mem_rec;
758        total_size = 0;
759        ps_mem_rec = mMemRecords;
760
761        for (size_t i = 0; i < mNumMemRecords; i++) {
762            ps_mem_rec->pv_base = ive_aligned_malloc(
763                    ps_mem_rec->u4_mem_alignment, ps_mem_rec->u4_mem_size);
764            if (ps_mem_rec->pv_base == NULL) {
765                ALOGE("Allocation failure for mem record id %zu size %u\n", i,
766                        ps_mem_rec->u4_mem_size);
767                mSignalledError = true;
768                notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
769                return OMX_ErrorUndefined;
770
771            }
772            total_size += ps_mem_rec->u4_mem_size;
773
774            ps_mem_rec++;
775        }
776    }
777
778    /* Codec Instance Creation */
779    {
780        ive_init_ip_t s_init_ip;
781        ive_init_op_t s_init_op;
782
783        mCodecCtx = (iv_obj_t *)mMemRecords[0].pv_base;
784        mCodecCtx->u4_size = sizeof(iv_obj_t);
785        mCodecCtx->pv_fxns = (void *)ive_api_function;
786
787        s_init_ip.u4_size = sizeof(ive_init_ip_t);
788        s_init_op.u4_size = sizeof(ive_init_op_t);
789
790        s_init_ip.e_cmd = IV_CMD_INIT;
791        s_init_ip.u4_num_mem_rec = mNumMemRecords;
792        s_init_ip.ps_mem_rec = mMemRecords;
793        s_init_ip.u4_max_wd = mWidth;
794        s_init_ip.u4_max_ht = mHeight;
795        s_init_ip.u4_max_ref_cnt = DEFAULT_MAX_REF_FRM;
796        s_init_ip.u4_max_reorder_cnt = DEFAULT_MAX_REORDER_FRM;
797        s_init_ip.u4_max_level = mAVCEncLevel;
798        s_init_ip.e_inp_color_fmt = mIvVideoColorFormat;
799
800        if (mReconEnable || mPSNREnable) {
801            s_init_ip.u4_enable_recon = 1;
802        } else {
803            s_init_ip.u4_enable_recon = 0;
804        }
805        s_init_ip.e_recon_color_fmt = DEFAULT_RECON_COLOR_FORMAT;
806        s_init_ip.e_rc_mode = DEFAULT_RC_MODE;
807        s_init_ip.u4_max_framerate = DEFAULT_MAX_FRAMERATE;
808        s_init_ip.u4_max_bitrate = DEFAULT_MAX_BITRATE;
809        s_init_ip.u4_num_bframes = mBframes;
810        s_init_ip.e_content_type = IV_PROGRESSIVE;
811        s_init_ip.u4_max_srch_rng_x = DEFAULT_MAX_SRCH_RANGE_X;
812        s_init_ip.u4_max_srch_rng_y = DEFAULT_MAX_SRCH_RANGE_Y;
813        s_init_ip.e_slice_mode = mSliceMode;
814        s_init_ip.u4_slice_param = mSliceParam;
815        s_init_ip.e_arch = mArch;
816        s_init_ip.e_soc = DEFAULT_SOC;
817
818        status = ive_api_function(mCodecCtx, &s_init_ip, &s_init_op);
819
820        if (status != IV_SUCCESS) {
821            ALOGE("Init memory records failed = 0x%x\n",
822                    s_init_op.u4_error_code);
823            mSignalledError = true;
824            notify(OMX_EventError, OMX_ErrorUndefined, 0 /* arg2 */, NULL /* data */);
825            return OMX_ErrorUndefined;
826        }
827    }
828
829    /* Get Codec Version */
830    logVersion();
831
832    /* set processor details */
833    setNumCores();
834
835    /* Video control Set Frame dimensions */
836    setDimensions();
837
838    /* Video control Set Frame rates */
839    setFrameRate();
840
841    /* Video control Set IPE Params */
842    setIpeParams();
843
844    /* Video control Set Bitrate */
845    setBitRate();
846
847    /* Video control Set QP */
848    setQp();
849
850    /* Video control Set AIR params */
851    setAirParams();
852
853    /* Video control Set VBV params */
854    setVbvParams();
855
856    /* Video control Set Motion estimation params */
857    setMeParams();
858
859    /* Video control Set GOP params */
860    setGopParams();
861
862    /* Video control Set Deblock params */
863    setDeblockParams();
864
865    /* Video control Set Profile params */
866    setProfileParams();
867
868    /* Video control Set in Encode header mode */
869    setEncMode(IVE_ENC_MODE_HEADER);
870
871    ALOGV("init_codec successfull");
872
873    mSpsPpsHeaderReceived = false;
874    mStarted = true;
875
876    return OMX_ErrorNone;
877}
878
879OMX_ERRORTYPE SoftAVC::releaseEncoder() {
880    IV_STATUS_T status = IV_SUCCESS;
881    iv_retrieve_mem_rec_ip_t s_retrieve_mem_ip;
882    iv_retrieve_mem_rec_op_t s_retrieve_mem_op;
883    iv_mem_rec_t *ps_mem_rec;
884
885    if (!mStarted) {
886        return OMX_ErrorNone;
887    }
888
889    s_retrieve_mem_ip.u4_size = sizeof(iv_retrieve_mem_rec_ip_t);
890    s_retrieve_mem_op.u4_size = sizeof(iv_retrieve_mem_rec_op_t);
891    s_retrieve_mem_ip.e_cmd = IV_CMD_RETRIEVE_MEMREC;
892    s_retrieve_mem_ip.ps_mem_rec = mMemRecords;
893
894    status = ive_api_function(mCodecCtx, &s_retrieve_mem_ip, &s_retrieve_mem_op);
895
896    if (status != IV_SUCCESS) {
897        ALOGE("Unable to retrieve memory records = 0x%x\n",
898                s_retrieve_mem_op.u4_error_code);
899        return OMX_ErrorUndefined;
900    }
901
902    /* Free memory records */
903    ps_mem_rec = mMemRecords;
904    for (size_t i = 0; i < s_retrieve_mem_op.u4_num_mem_rec_filled; i++) {
905        ive_aligned_free(ps_mem_rec->pv_base);
906        ps_mem_rec++;
907    }
908
909    free(mMemRecords);
910
911    for (size_t i = 0; i < MAX_CONVERSION_BUFFERS; i++) {
912        if (mConversionBuffers[i]) {
913            free(mConversionBuffers[i]);
914            mConversionBuffers[i] = NULL;
915        }
916    }
917
918    mStarted = false;
919
920    return OMX_ErrorNone;
921}
922
923OMX_ERRORTYPE SoftAVC::internalGetParameter(OMX_INDEXTYPE index, OMX_PTR params) {
924    switch (index) {
925        case OMX_IndexParamVideoBitrate:
926        {
927            OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
928                (OMX_VIDEO_PARAM_BITRATETYPE *)params;
929
930            if (!isValidOMXParam(bitRate)) {
931                return OMX_ErrorBadParameter;
932            }
933
934            if (bitRate->nPortIndex != 1) {
935                return OMX_ErrorUndefined;
936            }
937
938            bitRate->eControlRate = OMX_Video_ControlRateVariable;
939            bitRate->nTargetBitrate = mBitrate;
940            return OMX_ErrorNone;
941        }
942
943        case OMX_IndexParamVideoAvc:
944        {
945            OMX_VIDEO_PARAM_AVCTYPE *avcParams = (OMX_VIDEO_PARAM_AVCTYPE *)params;
946
947            if (!isValidOMXParam(avcParams)) {
948                return OMX_ErrorBadParameter;
949            }
950
951            if (avcParams->nPortIndex != 1) {
952                return OMX_ErrorUndefined;
953            }
954
955            OMX_VIDEO_AVCLEVELTYPE omxLevel = OMX_VIDEO_AVCLevel41;
956            if (OMX_ErrorNone
957                    != ConvertAvcSpecLevelToOmxAvcLevel(mAVCEncLevel, &omxLevel)) {
958                return OMX_ErrorUndefined;
959            }
960
961            avcParams->eProfile = OMX_VIDEO_AVCProfileBaseline;
962            avcParams->eLevel = omxLevel;
963            avcParams->nRefFrames = 1;
964            avcParams->bUseHadamard = OMX_TRUE;
965            avcParams->nAllowedPictureTypes = (OMX_VIDEO_PictureTypeI
966                    | OMX_VIDEO_PictureTypeP | OMX_VIDEO_PictureTypeB);
967            avcParams->nRefIdx10ActiveMinus1 = 0;
968            avcParams->nRefIdx11ActiveMinus1 = 0;
969            avcParams->bWeightedPPrediction = OMX_FALSE;
970            avcParams->bconstIpred = OMX_FALSE;
971            avcParams->bDirect8x8Inference = OMX_FALSE;
972            avcParams->bDirectSpatialTemporal = OMX_FALSE;
973            avcParams->nCabacInitIdc = 0;
974            return OMX_ErrorNone;
975        }
976
977        default:
978            return SoftVideoEncoderOMXComponent::internalGetParameter(index, params);
979    }
980}
981
982OMX_ERRORTYPE SoftAVC::internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR params) {
983    int32_t indexFull = index;
984
985    switch (indexFull) {
986        case OMX_IndexParamVideoBitrate:
987        {
988            OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
989                (OMX_VIDEO_PARAM_BITRATETYPE *)params;
990
991            if (!isValidOMXParam(bitRate)) {
992                return OMX_ErrorBadParameter;
993            }
994
995            return internalSetBitrateParams(bitRate);
996        }
997
998        case OMX_IndexParamVideoAvc:
999        {
1000            OMX_VIDEO_PARAM_AVCTYPE *avcType = (OMX_VIDEO_PARAM_AVCTYPE *)params;
1001
1002            if (!isValidOMXParam(avcType)) {
1003                return OMX_ErrorBadParameter;
1004            }
1005
1006            if (avcType->nPortIndex != 1) {
1007                return OMX_ErrorUndefined;
1008            }
1009
1010            mEntropyMode = 0;
1011
1012            if (OMX_TRUE == avcType->bEntropyCodingCABAC)
1013                mEntropyMode = 1;
1014
1015            if ((avcType->nAllowedPictureTypes & OMX_VIDEO_PictureTypeB) &&
1016                    avcType->nPFrames) {
1017                mBframes = avcType->nBFrames / avcType->nPFrames;
1018            }
1019
1020            mIInterval = avcType->nPFrames + avcType->nBFrames;
1021
1022            if (OMX_VIDEO_AVCLoopFilterDisable == avcType->eLoopFilterMode)
1023                mDisableDeblkLevel = 4;
1024
1025            if (avcType->nRefFrames != 1
1026                    || avcType->bUseHadamard != OMX_TRUE
1027                    || avcType->nRefIdx10ActiveMinus1 != 0
1028                    || avcType->nRefIdx11ActiveMinus1 != 0
1029                    || avcType->bWeightedPPrediction != OMX_FALSE
1030                    || avcType->bconstIpred != OMX_FALSE
1031                    || avcType->bDirect8x8Inference != OMX_FALSE
1032                    || avcType->bDirectSpatialTemporal != OMX_FALSE
1033                    || avcType->nCabacInitIdc != 0) {
1034                return OMX_ErrorUndefined;
1035            }
1036
1037            if (OK != ConvertOmxAvcLevelToAvcSpecLevel(avcType->eLevel, &mAVCEncLevel)) {
1038                return OMX_ErrorUndefined;
1039            }
1040
1041            return OMX_ErrorNone;
1042        }
1043
1044        default:
1045            return SoftVideoEncoderOMXComponent::internalSetParameter(index, params);
1046    }
1047}
1048
1049OMX_ERRORTYPE SoftAVC::getConfig(
1050        OMX_INDEXTYPE index, OMX_PTR _params) {
1051    switch ((int)index) {
1052        case OMX_IndexConfigAndroidIntraRefresh:
1053        {
1054            OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE *intraRefreshParams =
1055                (OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE *)_params;
1056
1057            if (!isValidOMXParam(intraRefreshParams)) {
1058                return OMX_ErrorBadParameter;
1059            }
1060
1061            if (intraRefreshParams->nPortIndex != kOutputPortIndex) {
1062                return OMX_ErrorUndefined;
1063            }
1064
1065            intraRefreshParams->nRefreshPeriod =
1066                    (mAIRMode == IVE_AIR_MODE_NONE) ? 0 : mAIRRefreshPeriod;
1067            return OMX_ErrorNone;
1068        }
1069
1070        default:
1071            return SoftVideoEncoderOMXComponent::getConfig(index, _params);
1072    }
1073}
1074
1075OMX_ERRORTYPE SoftAVC::setConfig(
1076        OMX_INDEXTYPE index, const OMX_PTR _params) {
1077    switch ((int)index) {
1078        case OMX_IndexConfigVideoIntraVOPRefresh:
1079        {
1080            OMX_CONFIG_INTRAREFRESHVOPTYPE *params =
1081                (OMX_CONFIG_INTRAREFRESHVOPTYPE *)_params;
1082
1083            if (!isValidOMXParam(params)) {
1084                return OMX_ErrorBadParameter;
1085            }
1086
1087            if (params->nPortIndex != kOutputPortIndex) {
1088                return OMX_ErrorBadPortIndex;
1089            }
1090
1091            if (params->IntraRefreshVOP) {
1092                mUpdateFlag |= kRequestKeyFrame;
1093            }
1094            return OMX_ErrorNone;
1095        }
1096
1097        case OMX_IndexConfigVideoBitrate:
1098        {
1099            OMX_VIDEO_CONFIG_BITRATETYPE *params =
1100                (OMX_VIDEO_CONFIG_BITRATETYPE *)_params;
1101
1102            if (!isValidOMXParam(params)) {
1103                return OMX_ErrorBadParameter;
1104            }
1105
1106            if (params->nPortIndex != kOutputPortIndex) {
1107                return OMX_ErrorBadPortIndex;
1108            }
1109
1110            if (mBitrate != params->nEncodeBitrate) {
1111                mBitrate = params->nEncodeBitrate;
1112                mUpdateFlag |= kUpdateBitrate;
1113            }
1114            return OMX_ErrorNone;
1115        }
1116
1117        case OMX_IndexConfigAndroidIntraRefresh:
1118        {
1119            const OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE *intraRefreshParams =
1120                (const OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE *)_params;
1121
1122            if (!isValidOMXParam(intraRefreshParams)) {
1123                return OMX_ErrorBadParameter;
1124            }
1125
1126            if (intraRefreshParams->nPortIndex != kOutputPortIndex) {
1127                return OMX_ErrorUndefined;
1128            }
1129
1130            if (intraRefreshParams->nRefreshPeriod == 0) {
1131                mAIRMode = IVE_AIR_MODE_NONE;
1132                mAIRRefreshPeriod = 0;
1133            } else if (intraRefreshParams->nRefreshPeriod > 0) {
1134                mAIRMode = IVE_AIR_MODE_CYCLIC;
1135                mAIRRefreshPeriod = intraRefreshParams->nRefreshPeriod;
1136            }
1137            mUpdateFlag |= kUpdateAIRMode;
1138            return OMX_ErrorNone;
1139        }
1140
1141        default:
1142            return SimpleSoftOMXComponent::setConfig(index, _params);
1143    }
1144}
1145
1146OMX_ERRORTYPE SoftAVC::internalSetBitrateParams(
1147        const OMX_VIDEO_PARAM_BITRATETYPE *bitrate) {
1148    if (bitrate->nPortIndex != kOutputPortIndex) {
1149        return OMX_ErrorUnsupportedIndex;
1150    }
1151
1152    mBitrate = bitrate->nTargetBitrate;
1153    mUpdateFlag |= kUpdateBitrate;
1154
1155    return OMX_ErrorNone;
1156}
1157
1158OMX_ERRORTYPE SoftAVC::setEncodeArgs(
1159        ive_video_encode_ip_t *ps_encode_ip,
1160        ive_video_encode_op_t *ps_encode_op,
1161        OMX_BUFFERHEADERTYPE *inputBufferHeader,
1162        OMX_BUFFERHEADERTYPE *outputBufferHeader) {
1163    iv_raw_buf_t *ps_inp_raw_buf;
1164    const uint8_t *source;
1165    UWORD8 *pu1_buf;
1166
1167    ps_inp_raw_buf = &ps_encode_ip->s_inp_buf;
1168    ps_encode_ip->s_out_buf.pv_buf = outputBufferHeader->pBuffer;
1169    ps_encode_ip->s_out_buf.u4_bytes = 0;
1170    ps_encode_ip->s_out_buf.u4_bufsize = outputBufferHeader->nAllocLen;
1171    ps_encode_ip->u4_size = sizeof(ive_video_encode_ip_t);
1172    ps_encode_op->u4_size = sizeof(ive_video_encode_op_t);
1173
1174    ps_encode_ip->e_cmd = IVE_CMD_VIDEO_ENCODE;
1175    ps_encode_ip->pv_bufs = NULL;
1176    ps_encode_ip->pv_mb_info = NULL;
1177    ps_encode_ip->pv_pic_info = NULL;
1178    ps_encode_ip->u4_mb_info_type = 0;
1179    ps_encode_ip->u4_pic_info_type = 0;
1180    ps_encode_op->s_out_buf.pv_buf = NULL;
1181
1182    /* Initialize color formats */
1183    ps_inp_raw_buf->e_color_fmt = mIvVideoColorFormat;
1184    source = NULL;
1185    if ((inputBufferHeader != NULL) && inputBufferHeader->nFilledLen) {
1186        source = inputBufferHeader->pBuffer + inputBufferHeader->nOffset;
1187
1188        if (mInputDataIsMeta) {
1189            uint8_t *conversionBuffer = NULL;
1190            for (size_t i = 0; i < MAX_CONVERSION_BUFFERS; i++) {
1191                if (mConversionBuffersFree[i]) {
1192                    mConversionBuffersFree[i] = 0;
1193                    conversionBuffer = mConversionBuffers[i];
1194                    break;
1195                }
1196            }
1197
1198            if (NULL == conversionBuffer) {
1199                ALOGE("No free buffers to hold conversion data");
1200                return OMX_ErrorUndefined;
1201            }
1202
1203            source = extractGraphicBuffer(
1204                    conversionBuffer, (mWidth * mHeight * 3 / 2), source,
1205                    inputBufferHeader->nFilledLen, mWidth, mHeight);
1206
1207            if (source == NULL) {
1208                ALOGE("Error in extractGraphicBuffer");
1209                notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
1210                return OMX_ErrorUndefined;
1211            }
1212        }
1213        ps_encode_ip->u4_is_last = 0;
1214        ps_encode_ip->u4_timestamp_high = (inputBufferHeader->nTimeStamp) >> 32;
1215        ps_encode_ip->u4_timestamp_low = (inputBufferHeader->nTimeStamp) & 0xFFFFFFFF;
1216    }
1217    else {
1218        if (mSawInputEOS){
1219            ps_encode_ip->u4_is_last = 1;
1220        }
1221        memset(ps_inp_raw_buf, 0, sizeof(iv_raw_buf_t));
1222        ps_inp_raw_buf->e_color_fmt = mIvVideoColorFormat;
1223        ps_inp_raw_buf->u4_size = sizeof(iv_raw_buf_t);
1224        return OMX_ErrorNone;
1225    }
1226
1227    pu1_buf = (UWORD8 *)source;
1228    switch (mIvVideoColorFormat) {
1229        case IV_YUV_420P:
1230        {
1231            ps_inp_raw_buf->apv_bufs[0] = pu1_buf;
1232            pu1_buf += (mStride) * mHeight;
1233            ps_inp_raw_buf->apv_bufs[1] = pu1_buf;
1234            pu1_buf += (mStride / 2) * mHeight / 2;
1235            ps_inp_raw_buf->apv_bufs[2] = pu1_buf;
1236
1237            ps_inp_raw_buf->au4_wd[0] = mWidth;
1238            ps_inp_raw_buf->au4_wd[1] = mWidth / 2;
1239            ps_inp_raw_buf->au4_wd[2] = mWidth / 2;
1240
1241            ps_inp_raw_buf->au4_ht[0] = mHeight;
1242            ps_inp_raw_buf->au4_ht[1] = mHeight / 2;
1243            ps_inp_raw_buf->au4_ht[2] = mHeight / 2;
1244
1245            ps_inp_raw_buf->au4_strd[0] = mStride;
1246            ps_inp_raw_buf->au4_strd[1] = (mStride / 2);
1247            ps_inp_raw_buf->au4_strd[2] = (mStride / 2);
1248            break;
1249        }
1250
1251        case IV_YUV_422ILE:
1252        {
1253            ps_inp_raw_buf->apv_bufs[0] = pu1_buf;
1254            ps_inp_raw_buf->au4_wd[0] = mWidth * 2;
1255            ps_inp_raw_buf->au4_ht[0] = mHeight;
1256            ps_inp_raw_buf->au4_strd[0] = mStride * 2;
1257            break;
1258        }
1259
1260        case IV_YUV_420SP_UV:
1261        case IV_YUV_420SP_VU:
1262        default:
1263        {
1264            ps_inp_raw_buf->apv_bufs[0] = pu1_buf;
1265            pu1_buf += (mStride) * mHeight;
1266            ps_inp_raw_buf->apv_bufs[1] = pu1_buf;
1267
1268            ps_inp_raw_buf->au4_wd[0] = mWidth;
1269            ps_inp_raw_buf->au4_wd[1] = mWidth;
1270
1271            ps_inp_raw_buf->au4_ht[0] = mHeight;
1272            ps_inp_raw_buf->au4_ht[1] = mHeight / 2;
1273
1274            ps_inp_raw_buf->au4_strd[0] = mStride;
1275            ps_inp_raw_buf->au4_strd[1] = mStride;
1276            break;
1277        }
1278    }
1279    return OMX_ErrorNone;
1280}
1281
1282void SoftAVC::onQueueFilled(OMX_U32 portIndex) {
1283    IV_STATUS_T status;
1284    WORD32 timeDelay, timeTaken;
1285
1286    UNUSED(portIndex);
1287
1288    // Initialize encoder if not already initialized
1289    if (mCodecCtx == NULL) {
1290        if (OMX_ErrorNone != initEncoder()) {
1291            ALOGE("Failed to initialize encoder");
1292            notify(OMX_EventError, OMX_ErrorUndefined, 0 /* arg2 */, NULL /* data */);
1293            return;
1294        }
1295    }
1296    if (mSignalledError) {
1297        return;
1298    }
1299
1300    List<BufferInfo *> &inQueue = getPortQueue(0);
1301    List<BufferInfo *> &outQueue = getPortQueue(1);
1302
1303    while (!mSawOutputEOS && !outQueue.empty()) {
1304
1305        OMX_ERRORTYPE error;
1306        ive_video_encode_ip_t s_encode_ip;
1307        ive_video_encode_op_t s_encode_op;
1308        BufferInfo *outputBufferInfo = *outQueue.begin();
1309        OMX_BUFFERHEADERTYPE *outputBufferHeader = outputBufferInfo->mHeader;
1310
1311        BufferInfo *inputBufferInfo;
1312        OMX_BUFFERHEADERTYPE *inputBufferHeader;
1313
1314        if (mSawInputEOS) {
1315            inputBufferHeader = NULL;
1316            inputBufferInfo = NULL;
1317        } else if (!inQueue.empty()) {
1318            inputBufferInfo = *inQueue.begin();
1319            inputBufferHeader = inputBufferInfo->mHeader;
1320        } else {
1321            return;
1322        }
1323
1324        outputBufferHeader->nTimeStamp = 0;
1325        outputBufferHeader->nFlags = 0;
1326        outputBufferHeader->nOffset = 0;
1327        outputBufferHeader->nFilledLen = 0;
1328        outputBufferHeader->nOffset = 0;
1329
1330        if (inputBufferHeader != NULL) {
1331            outputBufferHeader->nFlags = inputBufferHeader->nFlags;
1332        }
1333
1334        uint8_t *outPtr = (uint8_t *)outputBufferHeader->pBuffer;
1335
1336        if (!mSpsPpsHeaderReceived) {
1337            error = setEncodeArgs(&s_encode_ip, &s_encode_op, NULL, outputBufferHeader);
1338            if (error != OMX_ErrorNone) {
1339                mSignalledError = true;
1340                notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
1341                return;
1342            }
1343            status = ive_api_function(mCodecCtx, &s_encode_ip, &s_encode_op);
1344
1345            if (IV_SUCCESS != status) {
1346                ALOGE("Encode Frame failed = 0x%x\n",
1347                        s_encode_op.u4_error_code);
1348            } else {
1349                ALOGV("Bytes Generated in header %d\n",
1350                        s_encode_op.s_out_buf.u4_bytes);
1351            }
1352
1353            mSpsPpsHeaderReceived = true;
1354
1355            outputBufferHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
1356            outputBufferHeader->nFilledLen = s_encode_op.s_out_buf.u4_bytes;
1357            if (inputBufferHeader != NULL) {
1358                outputBufferHeader->nTimeStamp = inputBufferHeader->nTimeStamp;
1359            }
1360
1361            outQueue.erase(outQueue.begin());
1362            outputBufferInfo->mOwnedByUs = false;
1363
1364            DUMP_TO_FILE(
1365                    mOutFile, outputBufferHeader->pBuffer,
1366                    outputBufferHeader->nFilledLen);
1367            notifyFillBufferDone(outputBufferHeader);
1368
1369            setEncMode(IVE_ENC_MODE_PICTURE);
1370            return;
1371        }
1372
1373        if (mUpdateFlag) {
1374            if (mUpdateFlag & kUpdateBitrate) {
1375                setBitRate();
1376            }
1377            if (mUpdateFlag & kRequestKeyFrame) {
1378                setFrameType(IV_IDR_FRAME);
1379            }
1380            if (mUpdateFlag & kUpdateAIRMode) {
1381                setAirParams();
1382                notify(OMX_EventPortSettingsChanged, kOutputPortIndex,
1383                        OMX_IndexConfigAndroidIntraRefresh, NULL);
1384            }
1385            mUpdateFlag = 0;
1386        }
1387
1388        if ((inputBufferHeader != NULL)
1389                && (inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS)) {
1390            mSawInputEOS = true;
1391        }
1392
1393        /* In normal mode, store inputBufferInfo and this will be returned
1394           when encoder consumes this input */
1395        if (!mInputDataIsMeta && (inputBufferInfo != NULL)) {
1396            for (size_t i = 0; i < MAX_INPUT_BUFFER_HEADERS; i++) {
1397                if (NULL == mInputBufferInfo[i]) {
1398                    mInputBufferInfo[i] = inputBufferInfo;
1399                    break;
1400                }
1401            }
1402        }
1403        error = setEncodeArgs(
1404                &s_encode_ip, &s_encode_op, inputBufferHeader, outputBufferHeader);
1405
1406        if (error != OMX_ErrorNone) {
1407            mSignalledError = true;
1408            notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
1409            return;
1410        }
1411
1412        DUMP_TO_FILE(
1413                mInFile, s_encode_ip.s_inp_buf.apv_bufs[0],
1414                (mHeight * mStride * 3 / 2));
1415
1416        GETTIME(&mTimeStart, NULL);
1417        /* Compute time elapsed between end of previous decode()
1418         * to start of current decode() */
1419        TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);
1420        status = ive_api_function(mCodecCtx, &s_encode_ip, &s_encode_op);
1421
1422        if (IV_SUCCESS != status) {
1423            ALOGE("Encode Frame failed = 0x%x\n",
1424                    s_encode_op.u4_error_code);
1425            mSignalledError = true;
1426            notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
1427            return;
1428        }
1429
1430        GETTIME(&mTimeEnd, NULL);
1431        /* Compute time taken for decode() */
1432        TIME_DIFF(mTimeStart, mTimeEnd, timeTaken);
1433
1434        ALOGV("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay,
1435                s_encode_op.s_out_buf.u4_bytes);
1436
1437        /* In encoder frees up an input buffer, mark it as free */
1438        if (s_encode_op.s_inp_buf.apv_bufs[0] != NULL) {
1439            if (mInputDataIsMeta) {
1440                for (size_t i = 0; i < MAX_CONVERSION_BUFFERS; i++) {
1441                    if (mConversionBuffers[i] == s_encode_op.s_inp_buf.apv_bufs[0]) {
1442                        mConversionBuffersFree[i] = 1;
1443                        break;
1444                    }
1445                }
1446            } else {
1447                /* In normal mode, call EBD on inBuffeHeader that is freed by the codec */
1448                for (size_t i = 0; i < MAX_INPUT_BUFFER_HEADERS; i++) {
1449                    uint8_t *buf = NULL;
1450                    OMX_BUFFERHEADERTYPE *bufHdr = NULL;
1451                    if (mInputBufferInfo[i] != NULL) {
1452                        bufHdr = mInputBufferInfo[i]->mHeader;
1453                        buf = bufHdr->pBuffer + bufHdr->nOffset;
1454                    }
1455                    if (s_encode_op.s_inp_buf.apv_bufs[0] == buf) {
1456                        mInputBufferInfo[i]->mOwnedByUs = false;
1457                        notifyEmptyBufferDone(bufHdr);
1458                        mInputBufferInfo[i] = NULL;
1459                        break;
1460                    }
1461                }
1462            }
1463        }
1464
1465        outputBufferHeader->nFilledLen = s_encode_op.s_out_buf.u4_bytes;
1466
1467        if (IV_IDR_FRAME == s_encode_op.u4_encoded_frame_type) {
1468            outputBufferHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
1469        }
1470
1471        if (inputBufferHeader != NULL) {
1472            inQueue.erase(inQueue.begin());
1473
1474            /* If in meta data, call EBD on input */
1475            /* In case of normal mode, EBD will be done once encoder
1476            releases the input buffer */
1477            if (mInputDataIsMeta) {
1478                inputBufferInfo->mOwnedByUs = false;
1479                notifyEmptyBufferDone(inputBufferHeader);
1480            }
1481        }
1482
1483        if (s_encode_op.u4_is_last) {
1484            outputBufferHeader->nFlags |= OMX_BUFFERFLAG_EOS;
1485            mSawOutputEOS = true;
1486        } else {
1487            outputBufferHeader->nFlags &= ~OMX_BUFFERFLAG_EOS;
1488        }
1489
1490        if (outputBufferHeader->nFilledLen || s_encode_op.u4_is_last) {
1491            outputBufferHeader->nTimeStamp = s_encode_op.u4_timestamp_high;
1492            outputBufferHeader->nTimeStamp <<= 32;
1493            outputBufferHeader->nTimeStamp |= s_encode_op.u4_timestamp_low;
1494            outputBufferInfo->mOwnedByUs = false;
1495            outQueue.erase(outQueue.begin());
1496            DUMP_TO_FILE(mOutFile, outputBufferHeader->pBuffer,
1497                    outputBufferHeader->nFilledLen);
1498            notifyFillBufferDone(outputBufferHeader);
1499        }
1500
1501        if (s_encode_op.u4_is_last == 1) {
1502            return;
1503        }
1504    }
1505    return;
1506}
1507
1508}  // namespace android
1509
1510android::SoftOMXComponent *createSoftOMXComponent(
1511        const char *name, const OMX_CALLBACKTYPE *callbacks,
1512        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
1513    return new android::SoftAVC(name, callbacks, appData, component);
1514}
1515