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