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