SoftAVCEnc.cpp revision b3d9f56313f1838649712297ebc8205c4ec14870
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                mConversionBuffers[i] = 0;
641            }
642
643            if (((uint64_t)mStride * mHeight) > ((uint64_t)INT32_MAX / 3)) {
644                ALOGE("Buffer size is too big.");
645                return OMX_ErrorUndefined;
646            }
647            mConversionBuffers[i] = (uint8_t *)malloc(mStride * mHeight * 3 / 2);
648
649            if (mConversionBuffers[i] == NULL) {
650                ALOGE("Allocating conversion buffer failed.");
651                return OMX_ErrorUndefined;
652            }
653
654            mConversionBuffersFree[i] = 1;
655        }
656    }
657
658    switch (mColorFormat) {
659        case OMX_COLOR_FormatYUV420SemiPlanar:
660            mIvVideoColorFormat = IV_YUV_420SP_UV;
661            ALOGV("colorFormat YUV_420SP");
662            break;
663        default:
664        case OMX_COLOR_FormatYUV420Planar:
665            mIvVideoColorFormat = IV_YUV_420P;
666            ALOGV("colorFormat YUV_420P");
667            break;
668    }
669
670    ALOGD("Params width %d height %d level %d colorFormat %d", mWidth,
671            mHeight, mAVCEncLevel, mIvVideoColorFormat);
672
673    /* Getting Number of MemRecords */
674    {
675        iv_num_mem_rec_ip_t s_num_mem_rec_ip;
676        iv_num_mem_rec_op_t s_num_mem_rec_op;
677
678        s_num_mem_rec_ip.u4_size = sizeof(iv_num_mem_rec_ip_t);
679        s_num_mem_rec_op.u4_size = sizeof(iv_num_mem_rec_op_t);
680
681        s_num_mem_rec_ip.e_cmd = IV_CMD_GET_NUM_MEM_REC;
682
683        status = ive_api_function(0, &s_num_mem_rec_ip, &s_num_mem_rec_op);
684
685        if (status != IV_SUCCESS) {
686            ALOGE("Get number of memory records failed = 0x%x\n",
687                    s_num_mem_rec_op.u4_error_code);
688            return OMX_ErrorUndefined;
689        }
690
691        mNumMemRecords = s_num_mem_rec_op.u4_num_mem_rec;
692    }
693
694    /* Allocate array to hold memory records */
695    if (mNumMemRecords > SIZE_MAX / sizeof(iv_mem_rec_t)) {
696        ALOGE("requested memory size is too big.");
697        return OMX_ErrorUndefined;
698    }
699    mMemRecords = (iv_mem_rec_t *)malloc(mNumMemRecords * sizeof(iv_mem_rec_t));
700    if (NULL == mMemRecords) {
701        ALOGE("Unable to allocate memory for hold memory records: Size %zu",
702                mNumMemRecords * sizeof(iv_mem_rec_t));
703        mSignalledError = true;
704        notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
705        return OMX_ErrorUndefined;
706    }
707
708    {
709        iv_mem_rec_t *ps_mem_rec;
710        ps_mem_rec = mMemRecords;
711        for (size_t i = 0; i < mNumMemRecords; i++) {
712            ps_mem_rec->u4_size = sizeof(iv_mem_rec_t);
713            ps_mem_rec->pv_base = NULL;
714            ps_mem_rec->u4_mem_size = 0;
715            ps_mem_rec->u4_mem_alignment = 0;
716            ps_mem_rec->e_mem_type = IV_NA_MEM_TYPE;
717
718            ps_mem_rec++;
719        }
720    }
721
722    /* Getting MemRecords Attributes */
723    {
724        iv_fill_mem_rec_ip_t s_fill_mem_rec_ip;
725        iv_fill_mem_rec_op_t s_fill_mem_rec_op;
726
727        s_fill_mem_rec_ip.u4_size = sizeof(iv_fill_mem_rec_ip_t);
728        s_fill_mem_rec_op.u4_size = sizeof(iv_fill_mem_rec_op_t);
729
730        s_fill_mem_rec_ip.e_cmd = IV_CMD_FILL_NUM_MEM_REC;
731        s_fill_mem_rec_ip.ps_mem_rec = mMemRecords;
732        s_fill_mem_rec_ip.u4_num_mem_rec = mNumMemRecords;
733        s_fill_mem_rec_ip.u4_max_wd = mWidth;
734        s_fill_mem_rec_ip.u4_max_ht = mHeight;
735        s_fill_mem_rec_ip.u4_max_level = mAVCEncLevel;
736        s_fill_mem_rec_ip.e_color_format = DEFAULT_INP_COLOR_FORMAT;
737        s_fill_mem_rec_ip.u4_max_ref_cnt = DEFAULT_MAX_REF_FRM;
738        s_fill_mem_rec_ip.u4_max_reorder_cnt = DEFAULT_MAX_REORDER_FRM;
739        s_fill_mem_rec_ip.u4_max_srch_rng_x = DEFAULT_MAX_SRCH_RANGE_X;
740        s_fill_mem_rec_ip.u4_max_srch_rng_y = DEFAULT_MAX_SRCH_RANGE_Y;
741
742        status = ive_api_function(0, &s_fill_mem_rec_ip, &s_fill_mem_rec_op);
743
744        if (status != IV_SUCCESS) {
745            ALOGE("Fill memory records failed = 0x%x\n",
746                    s_fill_mem_rec_op.u4_error_code);
747            mSignalledError = true;
748            notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
749            return OMX_ErrorUndefined;
750        }
751    }
752
753    /* Allocating Memory for Mem Records */
754    {
755        WORD32 total_size;
756        iv_mem_rec_t *ps_mem_rec;
757        total_size = 0;
758        ps_mem_rec = mMemRecords;
759
760        for (size_t i = 0; i < mNumMemRecords; i++) {
761            ps_mem_rec->pv_base = ive_aligned_malloc(
762                    ps_mem_rec->u4_mem_alignment, ps_mem_rec->u4_mem_size);
763            if (ps_mem_rec->pv_base == NULL) {
764                ALOGE("Allocation failure for mem record id %zu size %u\n", i,
765                        ps_mem_rec->u4_mem_size);
766                mSignalledError = true;
767                notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
768                return OMX_ErrorUndefined;
769
770            }
771            total_size += ps_mem_rec->u4_mem_size;
772
773            ps_mem_rec++;
774        }
775    }
776
777    /* Codec Instance Creation */
778    {
779        ive_init_ip_t s_init_ip;
780        ive_init_op_t s_init_op;
781
782        mCodecCtx = (iv_obj_t *)mMemRecords[0].pv_base;
783        mCodecCtx->u4_size = sizeof(iv_obj_t);
784        mCodecCtx->pv_fxns = (void *)ive_api_function;
785
786        s_init_ip.u4_size = sizeof(ive_init_ip_t);
787        s_init_op.u4_size = sizeof(ive_init_op_t);
788
789        s_init_ip.e_cmd = IV_CMD_INIT;
790        s_init_ip.u4_num_mem_rec = mNumMemRecords;
791        s_init_ip.ps_mem_rec = mMemRecords;
792        s_init_ip.u4_max_wd = mWidth;
793        s_init_ip.u4_max_ht = mHeight;
794        s_init_ip.u4_max_ref_cnt = DEFAULT_MAX_REF_FRM;
795        s_init_ip.u4_max_reorder_cnt = DEFAULT_MAX_REORDER_FRM;
796        s_init_ip.u4_max_level = mAVCEncLevel;
797        s_init_ip.e_inp_color_fmt = mIvVideoColorFormat;
798
799        if (mReconEnable || mPSNREnable) {
800            s_init_ip.u4_enable_recon = 1;
801        } else {
802            s_init_ip.u4_enable_recon = 0;
803        }
804        s_init_ip.e_recon_color_fmt = DEFAULT_RECON_COLOR_FORMAT;
805        s_init_ip.e_rc_mode = DEFAULT_RC_MODE;
806        s_init_ip.u4_max_framerate = DEFAULT_MAX_FRAMERATE;
807        s_init_ip.u4_max_bitrate = DEFAULT_MAX_BITRATE;
808        s_init_ip.u4_num_bframes = mBframes;
809        s_init_ip.e_content_type = IV_PROGRESSIVE;
810        s_init_ip.u4_max_srch_rng_x = DEFAULT_MAX_SRCH_RANGE_X;
811        s_init_ip.u4_max_srch_rng_y = DEFAULT_MAX_SRCH_RANGE_Y;
812        s_init_ip.e_slice_mode = mSliceMode;
813        s_init_ip.u4_slice_param = mSliceParam;
814        s_init_ip.e_arch = mArch;
815        s_init_ip.e_soc = DEFAULT_SOC;
816
817        status = ive_api_function(mCodecCtx, &s_init_ip, &s_init_op);
818
819        if (status != IV_SUCCESS) {
820            ALOGE("Init memory records failed = 0x%x\n",
821                    s_init_op.u4_error_code);
822            mSignalledError = true;
823            notify(OMX_EventError, OMX_ErrorUndefined, 0 /* arg2 */, NULL /* data */);
824            return OMX_ErrorUndefined;
825        }
826    }
827
828    /* Get Codec Version */
829    logVersion();
830
831    /* set processor details */
832    setNumCores();
833
834    /* Video control Set Frame dimensions */
835    setDimensions();
836
837    /* Video control Set Frame rates */
838    setFrameRate();
839
840    /* Video control Set IPE Params */
841    setIpeParams();
842
843    /* Video control Set Bitrate */
844    setBitRate();
845
846    /* Video control Set QP */
847    setQp();
848
849    /* Video control Set AIR params */
850    setAirParams();
851
852    /* Video control Set VBV params */
853    setVbvParams();
854
855    /* Video control Set Motion estimation params */
856    setMeParams();
857
858    /* Video control Set GOP params */
859    setGopParams();
860
861    /* Video control Set Deblock params */
862    setDeblockParams();
863
864    /* Video control Set Profile params */
865    setProfileParams();
866
867    /* Video control Set in Encode header mode */
868    setEncMode(IVE_ENC_MODE_HEADER);
869
870    ALOGV("init_codec successfull");
871
872    mSpsPpsHeaderReceived = false;
873    mStarted = true;
874
875    return OMX_ErrorNone;
876}
877
878OMX_ERRORTYPE SoftAVC::releaseEncoder() {
879    IV_STATUS_T status = IV_SUCCESS;
880    iv_retrieve_mem_rec_ip_t s_retrieve_mem_ip;
881    iv_retrieve_mem_rec_op_t s_retrieve_mem_op;
882    iv_mem_rec_t *ps_mem_rec;
883
884    if (!mStarted) {
885        return OMX_ErrorNone;
886    }
887
888    s_retrieve_mem_ip.u4_size = sizeof(iv_retrieve_mem_rec_ip_t);
889    s_retrieve_mem_op.u4_size = sizeof(iv_retrieve_mem_rec_op_t);
890    s_retrieve_mem_ip.e_cmd = IV_CMD_RETRIEVE_MEMREC;
891    s_retrieve_mem_ip.ps_mem_rec = mMemRecords;
892
893    status = ive_api_function(mCodecCtx, &s_retrieve_mem_ip, &s_retrieve_mem_op);
894
895    if (status != IV_SUCCESS) {
896        ALOGE("Unable to retrieve memory records = 0x%x\n",
897                s_retrieve_mem_op.u4_error_code);
898        return OMX_ErrorUndefined;
899    }
900
901    /* Free memory records */
902    ps_mem_rec = mMemRecords;
903    for (size_t i = 0; i < s_retrieve_mem_op.u4_num_mem_rec_filled; i++) {
904        ive_aligned_free(ps_mem_rec->pv_base);
905        ps_mem_rec++;
906    }
907
908    free(mMemRecords);
909
910    for (size_t i = 0; i < MAX_CONVERSION_BUFFERS; i++) {
911        if (mConversionBuffers[i]) {
912            free(mConversionBuffers[i]);
913            mConversionBuffers[i] = NULL;
914        }
915    }
916
917    mStarted = false;
918
919    return OMX_ErrorNone;
920}
921
922OMX_ERRORTYPE SoftAVC::internalGetParameter(OMX_INDEXTYPE index, OMX_PTR params) {
923    switch (index) {
924        case OMX_IndexParamVideoBitrate:
925        {
926            OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
927                (OMX_VIDEO_PARAM_BITRATETYPE *)params;
928
929            if (bitRate->nPortIndex != 1) {
930                return OMX_ErrorUndefined;
931            }
932
933            bitRate->eControlRate = OMX_Video_ControlRateVariable;
934            bitRate->nTargetBitrate = mBitrate;
935            return OMX_ErrorNone;
936        }
937
938        case OMX_IndexParamVideoAvc:
939        {
940            OMX_VIDEO_PARAM_AVCTYPE *avcParams = (OMX_VIDEO_PARAM_AVCTYPE *)params;
941
942            if (avcParams->nPortIndex != 1) {
943                return OMX_ErrorUndefined;
944            }
945
946            OMX_VIDEO_AVCLEVELTYPE omxLevel = OMX_VIDEO_AVCLevel41;
947            if (OMX_ErrorNone
948                    != ConvertAvcSpecLevelToOmxAvcLevel(mAVCEncLevel, &omxLevel)) {
949                return OMX_ErrorUndefined;
950            }
951
952            avcParams->eProfile = OMX_VIDEO_AVCProfileBaseline;
953            avcParams->eLevel = omxLevel;
954            avcParams->nRefFrames = 1;
955            avcParams->bUseHadamard = OMX_TRUE;
956            avcParams->nAllowedPictureTypes = (OMX_VIDEO_PictureTypeI
957                    | OMX_VIDEO_PictureTypeP | OMX_VIDEO_PictureTypeB);
958            avcParams->nRefIdx10ActiveMinus1 = 0;
959            avcParams->nRefIdx11ActiveMinus1 = 0;
960            avcParams->bWeightedPPrediction = OMX_FALSE;
961            avcParams->bconstIpred = OMX_FALSE;
962            avcParams->bDirect8x8Inference = OMX_FALSE;
963            avcParams->bDirectSpatialTemporal = OMX_FALSE;
964            avcParams->nCabacInitIdc = 0;
965            return OMX_ErrorNone;
966        }
967
968        default:
969            return SoftVideoEncoderOMXComponent::internalGetParameter(index, params);
970    }
971}
972
973OMX_ERRORTYPE SoftAVC::internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR params) {
974    int32_t indexFull = index;
975
976    switch (indexFull) {
977        case OMX_IndexParamVideoBitrate:
978        {
979            return internalSetBitrateParams(
980                    (const OMX_VIDEO_PARAM_BITRATETYPE *)params);
981        }
982
983        case OMX_IndexParamVideoAvc:
984        {
985            OMX_VIDEO_PARAM_AVCTYPE *avcType = (OMX_VIDEO_PARAM_AVCTYPE *)params;
986
987            if (avcType->nPortIndex != 1) {
988                return OMX_ErrorUndefined;
989            }
990
991            mEntropyMode = 0;
992
993            if (OMX_TRUE == avcType->bEntropyCodingCABAC)
994                mEntropyMode = 1;
995
996            if ((avcType->nAllowedPictureTypes & OMX_VIDEO_PictureTypeB) &&
997                    avcType->nPFrames) {
998                mBframes = avcType->nBFrames / avcType->nPFrames;
999            }
1000
1001            mIInterval = avcType->nPFrames + avcType->nBFrames;
1002
1003            if (OMX_VIDEO_AVCLoopFilterDisable == avcType->eLoopFilterMode)
1004                mDisableDeblkLevel = 4;
1005
1006            if (avcType->nRefFrames != 1
1007                    || avcType->bUseHadamard != OMX_TRUE
1008                    || avcType->nRefIdx10ActiveMinus1 != 0
1009                    || avcType->nRefIdx11ActiveMinus1 != 0
1010                    || avcType->bWeightedPPrediction != OMX_FALSE
1011                    || avcType->bconstIpred != OMX_FALSE
1012                    || avcType->bDirect8x8Inference != OMX_FALSE
1013                    || avcType->bDirectSpatialTemporal != OMX_FALSE
1014                    || avcType->nCabacInitIdc != 0) {
1015                return OMX_ErrorUndefined;
1016            }
1017
1018            if (OK != ConvertOmxAvcLevelToAvcSpecLevel(avcType->eLevel, &mAVCEncLevel)) {
1019                return OMX_ErrorUndefined;
1020            }
1021
1022            return OMX_ErrorNone;
1023        }
1024
1025        default:
1026            return SoftVideoEncoderOMXComponent::internalSetParameter(index, params);
1027    }
1028}
1029
1030OMX_ERRORTYPE SoftAVC::setConfig(
1031        OMX_INDEXTYPE index, const OMX_PTR _params) {
1032    switch (index) {
1033        case OMX_IndexConfigVideoIntraVOPRefresh:
1034        {
1035            OMX_CONFIG_INTRAREFRESHVOPTYPE *params =
1036                (OMX_CONFIG_INTRAREFRESHVOPTYPE *)_params;
1037
1038            if (params->nPortIndex != kOutputPortIndex) {
1039                return OMX_ErrorBadPortIndex;
1040            }
1041
1042            mKeyFrameRequested = params->IntraRefreshVOP;
1043            return OMX_ErrorNone;
1044        }
1045
1046        case OMX_IndexConfigVideoBitrate:
1047        {
1048            OMX_VIDEO_CONFIG_BITRATETYPE *params =
1049                (OMX_VIDEO_CONFIG_BITRATETYPE *)_params;
1050
1051            if (params->nPortIndex != kOutputPortIndex) {
1052                return OMX_ErrorBadPortIndex;
1053            }
1054
1055            if (mBitrate != params->nEncodeBitrate) {
1056                mBitrate = params->nEncodeBitrate;
1057                mBitrateUpdated = true;
1058            }
1059            return OMX_ErrorNone;
1060        }
1061
1062        default:
1063            return SimpleSoftOMXComponent::setConfig(index, _params);
1064    }
1065}
1066
1067OMX_ERRORTYPE SoftAVC::internalSetBitrateParams(
1068        const OMX_VIDEO_PARAM_BITRATETYPE *bitrate) {
1069    if (bitrate->nPortIndex != kOutputPortIndex) {
1070        return OMX_ErrorUnsupportedIndex;
1071    }
1072
1073    mBitrate = bitrate->nTargetBitrate;
1074    mBitrateUpdated = true;
1075
1076    return OMX_ErrorNone;
1077}
1078
1079OMX_ERRORTYPE SoftAVC::setEncodeArgs(
1080        ive_video_encode_ip_t *ps_encode_ip,
1081        ive_video_encode_op_t *ps_encode_op,
1082        OMX_BUFFERHEADERTYPE *inputBufferHeader,
1083        OMX_BUFFERHEADERTYPE *outputBufferHeader) {
1084    iv_raw_buf_t *ps_inp_raw_buf;
1085    const uint8_t *source;
1086    UWORD8 *pu1_buf;
1087
1088    ps_inp_raw_buf = &ps_encode_ip->s_inp_buf;
1089    ps_encode_ip->s_out_buf.pv_buf = outputBufferHeader->pBuffer;
1090    ps_encode_ip->s_out_buf.u4_bytes = 0;
1091    ps_encode_ip->s_out_buf.u4_bufsize = outputBufferHeader->nAllocLen;
1092    ps_encode_ip->u4_size = sizeof(ive_video_encode_ip_t);
1093    ps_encode_op->u4_size = sizeof(ive_video_encode_op_t);
1094
1095    ps_encode_ip->e_cmd = IVE_CMD_VIDEO_ENCODE;
1096    ps_encode_ip->pv_bufs = NULL;
1097    ps_encode_ip->pv_mb_info = NULL;
1098    ps_encode_ip->pv_pic_info = NULL;
1099    ps_encode_ip->u4_mb_info_type = 0;
1100    ps_encode_ip->u4_pic_info_type = 0;
1101    ps_encode_op->s_out_buf.pv_buf = NULL;
1102
1103    /* Initialize color formats */
1104    ps_inp_raw_buf->e_color_fmt = mIvVideoColorFormat;
1105    source = NULL;
1106    if ((inputBufferHeader != NULL) && inputBufferHeader->nFilledLen) {
1107        source = inputBufferHeader->pBuffer + inputBufferHeader->nOffset;
1108
1109        if (mInputDataIsMeta) {
1110            uint8_t *conversionBuffer = NULL;
1111            for (size_t i = 0; i < MAX_CONVERSION_BUFFERS; i++) {
1112                if (mConversionBuffersFree[i]) {
1113                    mConversionBuffersFree[i] = 0;
1114                    conversionBuffer = mConversionBuffers[i];
1115                    break;
1116                }
1117            }
1118
1119            if (NULL == conversionBuffer) {
1120                ALOGE("No free buffers to hold conversion data");
1121                return OMX_ErrorUndefined;
1122            }
1123
1124            source = extractGraphicBuffer(
1125                    conversionBuffer, (mWidth * mHeight * 3 / 2), source,
1126                    inputBufferHeader->nFilledLen, mWidth, mHeight);
1127
1128            if (source == NULL) {
1129                ALOGE("Error in extractGraphicBuffer");
1130                notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
1131                return OMX_ErrorUndefined;
1132            }
1133        }
1134        ps_encode_ip->u4_is_last = 0;
1135        ps_encode_ip->u4_timestamp_high = (inputBufferHeader->nTimeStamp) >> 32;
1136        ps_encode_ip->u4_timestamp_low = (inputBufferHeader->nTimeStamp) & 0xFFFFFFFF;
1137    }
1138    else {
1139        if (mSawInputEOS){
1140            ps_encode_ip->u4_is_last = 1;
1141        }
1142        memset(ps_inp_raw_buf, 0, sizeof(iv_raw_buf_t));
1143        ps_inp_raw_buf->e_color_fmt = mIvVideoColorFormat;
1144        ps_inp_raw_buf->u4_size = sizeof(iv_raw_buf_t);
1145        return OMX_ErrorNone;
1146    }
1147
1148    pu1_buf = (UWORD8 *)source;
1149    switch (mIvVideoColorFormat) {
1150        case IV_YUV_420P:
1151        {
1152            ps_inp_raw_buf->apv_bufs[0] = pu1_buf;
1153            pu1_buf += (mStride) * mHeight;
1154            ps_inp_raw_buf->apv_bufs[1] = pu1_buf;
1155            pu1_buf += (mStride / 2) * mHeight / 2;
1156            ps_inp_raw_buf->apv_bufs[2] = pu1_buf;
1157
1158            ps_inp_raw_buf->au4_wd[0] = mWidth;
1159            ps_inp_raw_buf->au4_wd[1] = mWidth / 2;
1160            ps_inp_raw_buf->au4_wd[2] = mWidth / 2;
1161
1162            ps_inp_raw_buf->au4_ht[0] = mHeight;
1163            ps_inp_raw_buf->au4_ht[1] = mHeight / 2;
1164            ps_inp_raw_buf->au4_ht[2] = mHeight / 2;
1165
1166            ps_inp_raw_buf->au4_strd[0] = mStride;
1167            ps_inp_raw_buf->au4_strd[1] = (mStride / 2);
1168            ps_inp_raw_buf->au4_strd[2] = (mStride / 2);
1169            break;
1170        }
1171
1172        case IV_YUV_422ILE:
1173        {
1174            ps_inp_raw_buf->apv_bufs[0] = pu1_buf;
1175            ps_inp_raw_buf->au4_wd[0] = mWidth * 2;
1176            ps_inp_raw_buf->au4_ht[0] = mHeight;
1177            ps_inp_raw_buf->au4_strd[0] = mStride * 2;
1178            break;
1179        }
1180
1181        case IV_YUV_420SP_UV:
1182        case IV_YUV_420SP_VU:
1183        default:
1184        {
1185            ps_inp_raw_buf->apv_bufs[0] = pu1_buf;
1186            pu1_buf += (mStride) * mHeight;
1187            ps_inp_raw_buf->apv_bufs[1] = pu1_buf;
1188
1189            ps_inp_raw_buf->au4_wd[0] = mWidth;
1190            ps_inp_raw_buf->au4_wd[1] = mWidth;
1191
1192            ps_inp_raw_buf->au4_ht[0] = mHeight;
1193            ps_inp_raw_buf->au4_ht[1] = mHeight / 2;
1194
1195            ps_inp_raw_buf->au4_strd[0] = mStride;
1196            ps_inp_raw_buf->au4_strd[1] = mStride;
1197            break;
1198        }
1199    }
1200    return OMX_ErrorNone;
1201}
1202
1203void SoftAVC::onQueueFilled(OMX_U32 portIndex) {
1204    IV_STATUS_T status;
1205    WORD32 timeDelay, timeTaken;
1206
1207    UNUSED(portIndex);
1208
1209    // Initialize encoder if not already initialized
1210    if (mCodecCtx == NULL) {
1211        if (OMX_ErrorNone != initEncoder()) {
1212            ALOGE("Failed to initialize encoder");
1213            notify(OMX_EventError, OMX_ErrorUndefined, 0 /* arg2 */, NULL /* data */);
1214            return;
1215        }
1216    }
1217    if (mSignalledError) {
1218        return;
1219    }
1220
1221    List<BufferInfo *> &inQueue = getPortQueue(0);
1222    List<BufferInfo *> &outQueue = getPortQueue(1);
1223
1224    while (!mSawOutputEOS && !outQueue.empty()) {
1225
1226        OMX_ERRORTYPE error;
1227        ive_video_encode_ip_t s_encode_ip;
1228        ive_video_encode_op_t s_encode_op;
1229        BufferInfo *outputBufferInfo = *outQueue.begin();
1230        OMX_BUFFERHEADERTYPE *outputBufferHeader = outputBufferInfo->mHeader;
1231
1232        BufferInfo *inputBufferInfo;
1233        OMX_BUFFERHEADERTYPE *inputBufferHeader;
1234
1235        if (mSawInputEOS) {
1236            inputBufferHeader = NULL;
1237            inputBufferInfo = NULL;
1238        } else if (!inQueue.empty()) {
1239            inputBufferInfo = *inQueue.begin();
1240            inputBufferHeader = inputBufferInfo->mHeader;
1241        } else {
1242            return;
1243        }
1244
1245        outputBufferHeader->nTimeStamp = 0;
1246        outputBufferHeader->nFlags = 0;
1247        outputBufferHeader->nOffset = 0;
1248        outputBufferHeader->nFilledLen = 0;
1249        outputBufferHeader->nOffset = 0;
1250
1251        if (inputBufferHeader != NULL) {
1252            outputBufferHeader->nFlags = inputBufferHeader->nFlags;
1253        }
1254
1255        uint8_t *outPtr = (uint8_t *)outputBufferHeader->pBuffer;
1256
1257        if (!mSpsPpsHeaderReceived) {
1258            error = setEncodeArgs(&s_encode_ip, &s_encode_op, NULL, outputBufferHeader);
1259            if (error != OMX_ErrorNone) {
1260                mSignalledError = true;
1261                notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
1262                return;
1263            }
1264            status = ive_api_function(mCodecCtx, &s_encode_ip, &s_encode_op);
1265
1266            if (IV_SUCCESS != status) {
1267                ALOGE("Encode Frame failed = 0x%x\n",
1268                        s_encode_op.u4_error_code);
1269            } else {
1270                ALOGV("Bytes Generated in header %d\n",
1271                        s_encode_op.s_out_buf.u4_bytes);
1272            }
1273
1274            mSpsPpsHeaderReceived = true;
1275
1276            outputBufferHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
1277            outputBufferHeader->nFilledLen = s_encode_op.s_out_buf.u4_bytes;
1278            if (inputBufferHeader != NULL) {
1279                outputBufferHeader->nTimeStamp = inputBufferHeader->nTimeStamp;
1280            }
1281
1282            outQueue.erase(outQueue.begin());
1283            outputBufferInfo->mOwnedByUs = false;
1284
1285            DUMP_TO_FILE(
1286                    mOutFile, outputBufferHeader->pBuffer,
1287                    outputBufferHeader->nFilledLen);
1288            notifyFillBufferDone(outputBufferHeader);
1289
1290            setEncMode(IVE_ENC_MODE_PICTURE);
1291            return;
1292        }
1293
1294        if (mBitrateUpdated) {
1295            setBitRate();
1296        }
1297
1298        if (mKeyFrameRequested) {
1299            setFrameType(IV_IDR_FRAME);
1300        }
1301
1302        if ((inputBufferHeader != NULL)
1303                && (inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS)) {
1304            mSawInputEOS = true;
1305        }
1306
1307        /* In normal mode, store inputBufferInfo and this will be returned
1308           when encoder consumes this input */
1309        if (!mInputDataIsMeta && (inputBufferInfo != NULL)) {
1310            for (size_t i = 0; i < MAX_INPUT_BUFFER_HEADERS; i++) {
1311                if (NULL == mInputBufferInfo[i]) {
1312                    mInputBufferInfo[i] = inputBufferInfo;
1313                    break;
1314                }
1315            }
1316        }
1317        error = setEncodeArgs(
1318                &s_encode_ip, &s_encode_op, inputBufferHeader, outputBufferHeader);
1319
1320        if (error != OMX_ErrorNone) {
1321            mSignalledError = true;
1322            notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
1323            return;
1324        }
1325
1326        DUMP_TO_FILE(
1327                mInFile, s_encode_ip.s_inp_buf.apv_bufs[0],
1328                (mHeight * mStride * 3 / 2));
1329
1330        GETTIME(&mTimeStart, NULL);
1331        /* Compute time elapsed between end of previous decode()
1332         * to start of current decode() */
1333        TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);
1334        status = ive_api_function(mCodecCtx, &s_encode_ip, &s_encode_op);
1335
1336        if (IV_SUCCESS != status) {
1337            ALOGE("Encode Frame failed = 0x%x\n",
1338                    s_encode_op.u4_error_code);
1339            mSignalledError = true;
1340            notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
1341            return;
1342        }
1343
1344        GETTIME(&mTimeEnd, NULL);
1345        /* Compute time taken for decode() */
1346        TIME_DIFF(mTimeStart, mTimeEnd, timeTaken);
1347
1348        ALOGV("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay,
1349                s_encode_op.s_out_buf.u4_bytes);
1350
1351        /* In encoder frees up an input buffer, mark it as free */
1352        if (s_encode_op.s_inp_buf.apv_bufs[0] != NULL) {
1353            if (mInputDataIsMeta) {
1354                for (size_t i = 0; i < MAX_CONVERSION_BUFFERS; i++) {
1355                    if (mConversionBuffers[i] == s_encode_op.s_inp_buf.apv_bufs[0]) {
1356                        mConversionBuffersFree[i] = 1;
1357                        break;
1358                    }
1359                }
1360            } else {
1361                /* In normal mode, call EBD on inBuffeHeader that is freed by the codec */
1362                for (size_t i = 0; i < MAX_INPUT_BUFFER_HEADERS; i++) {
1363                    uint8_t *buf = NULL;
1364                    OMX_BUFFERHEADERTYPE *bufHdr = NULL;
1365                    if (mInputBufferInfo[i] != NULL) {
1366                        bufHdr = mInputBufferInfo[i]->mHeader;
1367                        buf = bufHdr->pBuffer + bufHdr->nOffset;
1368                    }
1369                    if (s_encode_op.s_inp_buf.apv_bufs[0] == buf) {
1370                        mInputBufferInfo[i]->mOwnedByUs = false;
1371                        notifyEmptyBufferDone(bufHdr);
1372                        mInputBufferInfo[i] = NULL;
1373                        break;
1374                    }
1375                }
1376            }
1377        }
1378
1379        outputBufferHeader->nFilledLen = s_encode_op.s_out_buf.u4_bytes;
1380
1381        if (IV_IDR_FRAME == s_encode_op.u4_encoded_frame_type) {
1382            outputBufferHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
1383        }
1384
1385        if (inputBufferHeader != NULL) {
1386            inQueue.erase(inQueue.begin());
1387
1388            /* If in meta data, call EBD on input */
1389            /* In case of normal mode, EBD will be done once encoder
1390            releases the input buffer */
1391            if (mInputDataIsMeta) {
1392                inputBufferInfo->mOwnedByUs = false;
1393                notifyEmptyBufferDone(inputBufferHeader);
1394            }
1395        }
1396
1397        if (s_encode_op.u4_is_last) {
1398            outputBufferHeader->nFlags |= OMX_BUFFERFLAG_EOS;
1399            mSawOutputEOS = true;
1400        } else {
1401            outputBufferHeader->nFlags &= ~OMX_BUFFERFLAG_EOS;
1402        }
1403
1404        if (outputBufferHeader->nFilledLen || s_encode_op.u4_is_last) {
1405            outputBufferHeader->nTimeStamp = s_encode_op.u4_timestamp_high;
1406            outputBufferHeader->nTimeStamp <<= 32;
1407            outputBufferHeader->nTimeStamp |= s_encode_op.u4_timestamp_low;
1408            outputBufferInfo->mOwnedByUs = false;
1409            outQueue.erase(outQueue.begin());
1410            DUMP_TO_FILE(mOutFile, outputBufferHeader->pBuffer,
1411                    outputBufferHeader->nFilledLen);
1412            notifyFillBufferDone(outputBufferHeader);
1413        }
1414
1415        if (s_encode_op.u4_is_last == 1) {
1416            return;
1417        }
1418    }
1419    return;
1420}
1421
1422}  // namespace android
1423
1424android::SoftOMXComponent *createSoftOMXComponent(
1425        const char *name, const OMX_CALLBACKTYPE *callbacks,
1426        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
1427    return new android::SoftAVC(name, callbacks, appData, component);
1428}
1429