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