summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
diff options
context:
space:
mode:
authorVenkatarama Avadhani <venkatarama.avadhani@ittiam.com>2015-04-03 16:43:22 +0530
committerLajos Molnar <lajos@google.com>2015-04-15 15:47:42 -0700
commit22b3b44ae459974794403ed0f76d95ae43d92985 (patch)
treed0106f34b424e57efa5fee36a0767d939fc0c53e /media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
parente5b9b3db87a55d3430f881ba59ba95f7d6ae41d0 (diff)
downloadframeworks_av-22b3b44ae459974794403ed0f76d95ae43d92985.zip
frameworks_av-22b3b44ae459974794403ed0f76d95ae43d92985.tar.gz
frameworks_av-22b3b44ae459974794403ed0f76d95ae43d92985.tar.bz2
stagefright: add SoftAVCEnc using libavc
Change-Id: Ic51e92e9d86db21109b8714e822697869e184cd1
Diffstat (limited to 'media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp')
-rw-r--r--media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp1335
1 files changed, 1335 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
new file mode 100644
index 0000000..bf5e353
--- /dev/null
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
@@ -0,0 +1,1335 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SoftAVCEnc"
+#include <utils/Log.h>
+#include <utils/misc.h>
+
+#include "OMX_Video.h"
+
+#include <HardwareAPI.h>
+#include <MetadataBufferType.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+#include <ui/Rect.h>
+
+#include "ih264_typedefs.h"
+#include "iv2.h"
+#include "ive2.h"
+#include "ih264e.h"
+#include "SoftAVCEnc.h"
+
+namespace android {
+
+ #define ive_api_function ih264e_api_function
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+typedef struct LevelConversion {
+ OMX_VIDEO_AVCLEVELTYPE omxLevel;
+ WORD32 avcLevel;
+} LevelConcersion;
+
+static LevelConversion ConversionTable[] = {
+ { OMX_VIDEO_AVCLevel1, 10 },
+ { OMX_VIDEO_AVCLevel1b, 9 },
+ { OMX_VIDEO_AVCLevel11, 11 },
+ { OMX_VIDEO_AVCLevel12, 12 },
+ { OMX_VIDEO_AVCLevel13, 13 },
+ { OMX_VIDEO_AVCLevel2, 20 },
+ { OMX_VIDEO_AVCLevel21, 21 },
+ { OMX_VIDEO_AVCLevel22, 22 },
+ { OMX_VIDEO_AVCLevel3, 30 },
+ { OMX_VIDEO_AVCLevel31, 31 },
+ { OMX_VIDEO_AVCLevel32, 32 },
+ { OMX_VIDEO_AVCLevel4, 40 },
+ { OMX_VIDEO_AVCLevel41, 41 },
+ { OMX_VIDEO_AVCLevel42, 42 },
+ { OMX_VIDEO_AVCLevel5, 50 },
+ { OMX_VIDEO_AVCLevel51, 51 },
+};
+
+static const CodecProfileLevel kProfileLevels[] = {
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1b },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel11 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel12 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel21 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel22 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel3 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel31 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel32 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel4 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel41 },
+};
+
+
+static size_t GetCPUCoreCount() {
+ long cpuCoreCount = 1;
+#if defined(_SC_NPROCESSORS_ONLN)
+ cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
+#else
+ // _SC_NPROC_ONLN must be defined...
+ cpuCoreCount = sysconf(_SC_NPROC_ONLN);
+#endif
+ CHECK(cpuCoreCount >= 1);
+ ALOGD("Number of CPU cores: %ld", cpuCoreCount);
+ return (size_t)cpuCoreCount;
+}
+
+static status_t ConvertOmxAvcLevelToAvcSpecLevel(
+ OMX_VIDEO_AVCLEVELTYPE omxLevel, WORD32 *avcLevel) {
+ for (size_t i = 0; i < NELEM(ConversionTable); ++i) {
+ if (omxLevel == ConversionTable[i].omxLevel) {
+ *avcLevel = ConversionTable[i].avcLevel;
+ return OK;
+ }
+ }
+
+ ALOGE("ConvertOmxAvcLevelToAvcSpecLevel: %d level not supported",
+ (int32_t)omxLevel);
+
+ return BAD_VALUE;
+}
+
+static status_t ConvertAvcSpecLevelToOmxAvcLevel(
+ WORD32 avcLevel, OMX_VIDEO_AVCLEVELTYPE *omxLevel) {
+ for (size_t i = 0; i < NELEM(ConversionTable); ++i) {
+ if (avcLevel == ConversionTable[i].avcLevel) {
+ *omxLevel = ConversionTable[i].omxLevel;
+ return OK;
+ }
+ }
+
+ ALOGE("ConvertAvcSpecLevelToOmxAvcLevel: %d level not supported",
+ (int32_t)avcLevel);
+
+ return BAD_VALUE;
+}
+
+
+SoftAVC::SoftAVC(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SoftVideoEncoderOMXComponent(
+ name, "video_encoder.avc", OMX_VIDEO_CodingAVC,
+ kProfileLevels, NELEM(kProfileLevels),
+ 176 /* width */, 144 /* height */,
+ callbacks, appData, component),
+ mIvVideoColorFormat(IV_YUV_420P),
+ mIDRFrameRefreshIntervalInSec(1),
+ mAVCEncProfile(IV_PROFILE_BASE),
+ mAVCEncLevel(31),
+ mPrevTimestampUs(-1),
+ mStarted(false),
+ mSawInputEOS(false),
+ mSignalledError(false),
+ mConversionBuffer(NULL),
+ mCodecCtx(NULL) {
+
+ initPorts(kNumBuffers, kNumBuffers, ((mWidth * mHeight * 3) >> 1),
+ MEDIA_MIMETYPE_VIDEO_AVC, 2);
+
+ // If dump is enabled, then open create an empty file
+ GENERATE_FILE_NAMES();
+ CREATE_DUMP_FILE(mInFile);
+ CREATE_DUMP_FILE(mOutFile);
+
+}
+
+SoftAVC::~SoftAVC() {
+ releaseEncoder();
+ List<BufferInfo *> &outQueue = getPortQueue(1);
+ List<BufferInfo *> &inQueue = getPortQueue(0);
+ CHECK(outQueue.empty());
+ CHECK(inQueue.empty());
+}
+
+OMX_ERRORTYPE SoftAVC::initEncParams() {
+ mCodecCtx = NULL;
+ mMemRecords = NULL;
+ mNumMemRecords = DEFAULT_MEM_REC_CNT;
+ mHeaderGenerated = 0;
+ mNumCores = GetCPUCoreCount();
+ mArch = DEFAULT_ARCH;
+ mSliceMode = DEFAULT_SLICE_MODE;
+ mSliceParam = DEFAULT_SLICE_PARAM;
+ mHalfPelEnable = DEFAULT_HPEL;
+ mIInterval = DEFAULT_I_INTERVAL;
+ mIDRInterval = DEFAULT_IDR_INTERVAL;
+ mDisableDeblkLevel = DEFAULT_DISABLE_DEBLK_LEVEL;
+ mFrameRate = DEFAULT_SRC_FRAME_RATE;
+ mEnableFastSad = DEFAULT_ENABLE_FAST_SAD;
+ mEnableAltRef = DEFAULT_ENABLE_ALT_REF;
+ mEncSpeed = DEFAULT_ENC_SPEED;
+ mIntra4x4 = DEFAULT_INTRA4x4;
+ mAIRMode = DEFAULT_AIR;
+ mAIRRefreshPeriod = DEFAULT_AIR_REFRESH_PERIOD;
+ mPSNREnable = DEFAULT_PSNR_ENABLE;
+ mReconEnable = DEFAULT_RECON_ENABLE;
+
+ gettimeofday(&mTimeStart, NULL);
+ gettimeofday(&mTimeEnd, NULL);
+
+ return OMX_ErrorNone;
+}
+
+
+OMX_ERRORTYPE SoftAVC::setDimensions() {
+ ive_ctl_set_dimensions_ip_t s_dimensions_ip;
+ ive_ctl_set_dimensions_op_t s_dimensions_op;
+ IV_STATUS_T status;
+
+ s_dimensions_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_dimensions_ip.e_sub_cmd = IVE_CMD_CTL_SET_DIMENSIONS;
+ s_dimensions_ip.u4_ht = mHeight;
+ s_dimensions_ip.u4_wd = mWidth;
+ s_dimensions_ip.u4_strd = mStride;
+
+ s_dimensions_ip.u4_timestamp_high = -1;
+ s_dimensions_ip.u4_timestamp_low = -1;
+
+ s_dimensions_ip.u4_size = sizeof(ive_ctl_set_dimensions_ip_t);
+ s_dimensions_op.u4_size = sizeof(ive_ctl_set_dimensions_op_t);
+
+ status = ive_api_function(mCodecCtx, &s_dimensions_ip, &s_dimensions_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("Unable to set frame dimensions = 0x%x\n",
+ s_dimensions_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::setNumCores() {
+ IV_STATUS_T status;
+ ive_ctl_set_num_cores_ip_t s_num_cores_ip;
+ ive_ctl_set_num_cores_op_t s_num_cores_op;
+ s_num_cores_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_num_cores_ip.e_sub_cmd = IVE_CMD_CTL_SET_NUM_CORES;
+ s_num_cores_ip.u4_num_cores = MIN(mNumCores, CODEC_MAX_CORES);
+ s_num_cores_ip.u4_timestamp_high = -1;
+ s_num_cores_ip.u4_timestamp_low = -1;
+ s_num_cores_ip.u4_size = sizeof(ive_ctl_set_num_cores_ip_t);
+
+ s_num_cores_op.u4_size = sizeof(ive_ctl_set_num_cores_op_t);
+
+ status = ive_api_function(
+ mCodecCtx, (void *) &s_num_cores_ip, (void *) &s_num_cores_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("Unable to set processor params = 0x%x\n",
+ s_num_cores_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::setFrameRate() {
+ ive_ctl_set_frame_rate_ip_t s_frame_rate_ip;
+ ive_ctl_set_frame_rate_op_t s_frame_rate_op;
+ IV_STATUS_T status;
+
+ s_frame_rate_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_frame_rate_ip.e_sub_cmd = IVE_CMD_CTL_SET_FRAMERATE;
+
+ s_frame_rate_ip.u4_src_frame_rate = mFrameRate;
+ s_frame_rate_ip.u4_tgt_frame_rate = mFrameRate;
+
+ s_frame_rate_ip.u4_timestamp_high = -1;
+ s_frame_rate_ip.u4_timestamp_low = -1;
+
+ s_frame_rate_ip.u4_size = sizeof(ive_ctl_set_frame_rate_ip_t);
+ s_frame_rate_op.u4_size = sizeof(ive_ctl_set_frame_rate_op_t);
+
+ status = ive_api_function(mCodecCtx, &s_frame_rate_ip, &s_frame_rate_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("Unable to set frame rate = 0x%x\n",
+ s_frame_rate_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::setIpeParams() {
+ ive_ctl_set_ipe_params_ip_t s_ipe_params_ip;
+ ive_ctl_set_ipe_params_op_t s_ipe_params_op;
+ IV_STATUS_T status;
+
+ s_ipe_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_ipe_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_IPE_PARAMS;
+
+ s_ipe_params_ip.u4_enable_intra_4x4 = mIntra4x4;
+ s_ipe_params_ip.u4_enc_speed_preset = mEncSpeed;
+
+ s_ipe_params_ip.u4_timestamp_high = -1;
+ s_ipe_params_ip.u4_timestamp_low = -1;
+
+ s_ipe_params_ip.u4_size = sizeof(ive_ctl_set_ipe_params_ip_t);
+ s_ipe_params_op.u4_size = sizeof(ive_ctl_set_ipe_params_op_t);
+
+ status = ive_api_function(mCodecCtx, &s_ipe_params_ip, &s_ipe_params_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("Unable to set ipe params = 0x%x\n",
+ s_ipe_params_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::setBitRate() {
+ ive_ctl_set_bitrate_ip_t s_bitrate_ip;
+ ive_ctl_set_bitrate_op_t s_bitrate_op;
+ IV_STATUS_T status;
+
+ s_bitrate_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_bitrate_ip.e_sub_cmd = IVE_CMD_CTL_SET_BITRATE;
+
+ s_bitrate_ip.u4_target_bitrate = mBitrate;
+
+ s_bitrate_ip.u4_timestamp_high = -1;
+ s_bitrate_ip.u4_timestamp_low = -1;
+
+ s_bitrate_ip.u4_size = sizeof(ive_ctl_set_bitrate_ip_t);
+ s_bitrate_op.u4_size = sizeof(ive_ctl_set_bitrate_op_t);
+
+ status = ive_api_function(mCodecCtx, &s_bitrate_ip, &s_bitrate_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("Unable to set bit rate = 0x%x\n", s_bitrate_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::setFrameType(IV_PICTURE_CODING_TYPE_T e_frame_type) {
+ ive_ctl_set_frame_type_ip_t s_frame_type_ip;
+ ive_ctl_set_frame_type_op_t s_frame_type_op;
+ IV_STATUS_T status;
+
+ s_frame_type_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_frame_type_ip.e_sub_cmd = IVE_CMD_CTL_SET_FRAMETYPE;
+
+ s_frame_type_ip.e_frame_type = e_frame_type;
+
+ s_frame_type_ip.u4_timestamp_high = -1;
+ s_frame_type_ip.u4_timestamp_low = -1;
+
+ s_frame_type_ip.u4_size = sizeof(ive_ctl_set_frame_type_ip_t);
+ s_frame_type_op.u4_size = sizeof(ive_ctl_set_frame_type_op_t);
+
+ status = ive_api_function(mCodecCtx, &s_frame_type_ip, &s_frame_type_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("Unable to set frame type = 0x%x\n",
+ s_frame_type_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::setQp() {
+ ive_ctl_set_qp_ip_t s_qp_ip;
+ ive_ctl_set_qp_op_t s_qp_op;
+ IV_STATUS_T status;
+
+ s_qp_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_qp_ip.e_sub_cmd = IVE_CMD_CTL_SET_QP;
+
+ s_qp_ip.u4_i_qp = DEFAULT_I_QP;
+ s_qp_ip.u4_i_qp_max = DEFAULT_QP_MAX;
+ s_qp_ip.u4_i_qp_min = DEFAULT_QP_MIN;
+
+ s_qp_ip.u4_p_qp = DEFAULT_P_QP;
+ s_qp_ip.u4_p_qp_max = DEFAULT_QP_MAX;
+ s_qp_ip.u4_p_qp_min = DEFAULT_QP_MIN;
+
+ s_qp_ip.u4_b_qp = DEFAULT_P_QP;
+ s_qp_ip.u4_b_qp_max = DEFAULT_QP_MAX;
+ s_qp_ip.u4_b_qp_min = DEFAULT_QP_MIN;
+
+ s_qp_ip.u4_timestamp_high = -1;
+ s_qp_ip.u4_timestamp_low = -1;
+
+ s_qp_ip.u4_size = sizeof(ive_ctl_set_qp_ip_t);
+ s_qp_op.u4_size = sizeof(ive_ctl_set_qp_op_t);
+
+ status = ive_api_function(mCodecCtx, &s_qp_ip, &s_qp_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("Unable to set qp 0x%x\n", s_qp_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::setEncMode(IVE_ENC_MODE_T e_enc_mode) {
+ IV_STATUS_T status;
+ ive_ctl_set_enc_mode_ip_t s_enc_mode_ip;
+ ive_ctl_set_enc_mode_op_t s_enc_mode_op;
+
+ s_enc_mode_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_enc_mode_ip.e_sub_cmd = IVE_CMD_CTL_SET_ENC_MODE;
+
+ s_enc_mode_ip.e_enc_mode = e_enc_mode;
+
+ s_enc_mode_ip.u4_timestamp_high = -1;
+ s_enc_mode_ip.u4_timestamp_low = -1;
+
+ s_enc_mode_ip.u4_size = sizeof(ive_ctl_set_enc_mode_ip_t);
+ s_enc_mode_op.u4_size = sizeof(ive_ctl_set_enc_mode_op_t);
+
+ status = ive_api_function(mCodecCtx, &s_enc_mode_ip, &s_enc_mode_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("Unable to set in header encode mode = 0x%x\n",
+ s_enc_mode_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::setVbvParams() {
+ ive_ctl_set_vbv_params_ip_t s_vbv_ip;
+ ive_ctl_set_vbv_params_op_t s_vbv_op;
+ IV_STATUS_T status;
+
+ s_vbv_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_vbv_ip.e_sub_cmd = IVE_CMD_CTL_SET_VBV_PARAMS;
+
+ s_vbv_ip.u4_vbv_buf_size = 0;
+ s_vbv_ip.u4_vbv_buffer_delay = 1000;
+
+ s_vbv_ip.u4_timestamp_high = -1;
+ s_vbv_ip.u4_timestamp_low = -1;
+
+ s_vbv_ip.u4_size = sizeof(ive_ctl_set_vbv_params_ip_t);
+ s_vbv_op.u4_size = sizeof(ive_ctl_set_vbv_params_op_t);
+
+ status = ive_api_function(mCodecCtx, &s_vbv_ip, &s_vbv_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("Unable to set VBC params = 0x%x\n", s_vbv_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::setAirParams() {
+ ive_ctl_set_air_params_ip_t s_air_ip;
+ ive_ctl_set_air_params_op_t s_air_op;
+ IV_STATUS_T status;
+
+ s_air_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_air_ip.e_sub_cmd = IVE_CMD_CTL_SET_AIR_PARAMS;
+
+ s_air_ip.e_air_mode = mAIRMode;
+ s_air_ip.u4_air_refresh_period = mAIRRefreshPeriod;
+
+ s_air_ip.u4_timestamp_high = -1;
+ s_air_ip.u4_timestamp_low = -1;
+
+ s_air_ip.u4_size = sizeof(ive_ctl_set_air_params_ip_t);
+ s_air_op.u4_size = sizeof(ive_ctl_set_air_params_op_t);
+
+ status = ive_api_function(mCodecCtx, &s_air_ip, &s_air_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("Unable to set air params = 0x%x\n", s_air_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::setMeParams() {
+ IV_STATUS_T status;
+ ive_ctl_set_me_params_ip_t s_me_params_ip;
+ ive_ctl_set_me_params_op_t s_me_params_op;
+
+ s_me_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_me_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_ME_PARAMS;
+
+ s_me_params_ip.u4_enable_fast_sad = mEnableFastSad;
+ s_me_params_ip.u4_enable_alt_ref = mEnableAltRef;
+
+ s_me_params_ip.u4_enable_hpel = mHalfPelEnable;
+ s_me_params_ip.u4_enable_qpel = DEFAULT_QPEL;
+ s_me_params_ip.u4_me_speed_preset = DEFAULT_ME_SPEED;
+ s_me_params_ip.u4_srch_rng_x = DEFAULT_SRCH_RNG_X;
+ s_me_params_ip.u4_srch_rng_y = DEFAULT_SRCH_RNG_Y;
+
+ s_me_params_ip.u4_timestamp_high = -1;
+ s_me_params_ip.u4_timestamp_low = -1;
+
+ s_me_params_ip.u4_size = sizeof(ive_ctl_set_me_params_ip_t);
+ s_me_params_op.u4_size = sizeof(ive_ctl_set_me_params_op_t);
+
+ status = ive_api_function(mCodecCtx, &s_me_params_ip, &s_me_params_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("Unable to set me params = 0x%x\n", s_me_params_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::setGopParams() {
+ IV_STATUS_T status;
+ ive_ctl_set_gop_params_ip_t s_gop_params_ip;
+ ive_ctl_set_gop_params_op_t s_gop_params_op;
+
+ s_gop_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_gop_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_GOP_PARAMS;
+
+ s_gop_params_ip.u4_i_frm_interval = mIInterval;
+ s_gop_params_ip.u4_idr_frm_interval = mIDRInterval;
+ s_gop_params_ip.u4_num_b_frames = DEFAULT_B_FRAMES;
+
+ s_gop_params_ip.u4_timestamp_high = -1;
+ s_gop_params_ip.u4_timestamp_low = -1;
+
+ s_gop_params_ip.u4_size = sizeof(ive_ctl_set_gop_params_ip_t);
+ s_gop_params_op.u4_size = sizeof(ive_ctl_set_gop_params_op_t);
+
+ status = ive_api_function(mCodecCtx, &s_gop_params_ip, &s_gop_params_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("Unable to set ME params = 0x%x\n",
+ s_gop_params_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::setProfileParams() {
+ IV_STATUS_T status;
+ ive_ctl_set_profile_params_ip_t s_profile_params_ip;
+ ive_ctl_set_profile_params_op_t s_profile_params_op;
+
+ s_profile_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_profile_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_PROFILE_PARAMS;
+
+ s_profile_params_ip.e_profile = DEFAULT_EPROFILE;
+
+ s_profile_params_ip.u4_timestamp_high = -1;
+ s_profile_params_ip.u4_timestamp_low = -1;
+
+ s_profile_params_ip.u4_size = sizeof(ive_ctl_set_profile_params_ip_t);
+ s_profile_params_op.u4_size = sizeof(ive_ctl_set_profile_params_op_t);
+
+ status = ive_api_function(mCodecCtx, &s_profile_params_ip, &s_profile_params_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("Unable to set profile params = 0x%x\n",
+ s_profile_params_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::setDeblockParams() {
+ IV_STATUS_T status;
+ ive_ctl_set_deblock_params_ip_t s_deblock_params_ip;
+ ive_ctl_set_deblock_params_op_t s_deblock_params_op;
+
+ s_deblock_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_deblock_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_DEBLOCK_PARAMS;
+
+ s_deblock_params_ip.u4_disable_deblock_level = mDisableDeblkLevel;
+
+ s_deblock_params_ip.u4_timestamp_high = -1;
+ s_deblock_params_ip.u4_timestamp_low = -1;
+
+ s_deblock_params_ip.u4_size = sizeof(ive_ctl_set_deblock_params_ip_t);
+ s_deblock_params_op.u4_size = sizeof(ive_ctl_set_deblock_params_op_t);
+
+ status = ive_api_function(mCodecCtx, &s_deblock_params_ip, &s_deblock_params_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("Unable to enable/disable deblock params = 0x%x\n",
+ s_deblock_params_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+ return OMX_ErrorNone;
+}
+
+void SoftAVC::logVersion() {
+ ive_ctl_getversioninfo_ip_t s_ctl_ip;
+ ive_ctl_getversioninfo_op_t s_ctl_op;
+ UWORD8 au1_buf[512];
+ IV_STATUS_T status;
+
+ s_ctl_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+ s_ctl_ip.e_sub_cmd = IVE_CMD_CTL_GETVERSION;
+ s_ctl_ip.u4_size = sizeof(ive_ctl_getversioninfo_ip_t);
+ s_ctl_op.u4_size = sizeof(ive_ctl_getversioninfo_op_t);
+ s_ctl_ip.pu1_version = au1_buf;
+ s_ctl_ip.u4_version_bufsize = sizeof(au1_buf);
+
+ status = ive_api_function(mCodecCtx, (void *) &s_ctl_ip, (void *) &s_ctl_op);
+
+ if (status != IV_SUCCESS) {
+ ALOGE("Error in getting version: 0x%x", s_ctl_op.u4_error_code);
+ } else {
+ ALOGV("Ittiam encoder version: %s", (char *)s_ctl_ip.pu1_version);
+ }
+ return;
+}
+
+OMX_ERRORTYPE SoftAVC::initEncoder() {
+ IV_STATUS_T status;
+ size_t i;
+ WORD32 level;
+ uint32_t displaySizeY;
+ CHECK(!mStarted);
+
+ OMX_ERRORTYPE errType = OMX_ErrorNone;
+
+ displaySizeY = mWidth * mHeight;
+ if (displaySizeY > (1920 * 1088)) {
+ level = 50;
+ } else if (displaySizeY > (1280 * 720)) {
+ level = 40;
+ } else if (displaySizeY > (720 * 576)) {
+ level = 31;
+ } else if (displaySizeY > (624 * 320)) {
+ level = 30;
+ } else if (displaySizeY > (352 * 288)) {
+ level = 21;
+ } else {
+ level = 20;
+ }
+ mAVCEncLevel = MAX(level, mAVCEncLevel);
+
+ if (OMX_ErrorNone != (errType = initEncParams())) {
+ ALOGE("Failed to initialize encoder params");
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
+ return errType;
+ }
+
+ mStride = ALIGN16(mWidth);
+
+ if (mInputDataIsMeta) {
+ if (mConversionBuffer) {
+ free(mConversionBuffer);
+ mConversionBuffer = NULL;
+ }
+
+ if (mConversionBuffer == NULL) {
+ mConversionBuffer = (uint8_t *)malloc(mStride * mHeight * 3 / 2);
+ if (mConversionBuffer == NULL) {
+ ALOGE("Allocating conversion buffer failed.");
+ return OMX_ErrorUndefined;
+ }
+ }
+ }
+
+ switch (mColorFormat) {
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+ mIvVideoColorFormat = IV_YUV_420SP_UV;
+ ALOGV("colorFormat YUV_420SP");
+ break;
+ default:
+ case OMX_COLOR_FormatYUV420Planar:
+ mIvVideoColorFormat = IV_YUV_420P;
+ ALOGV("colorFormat YUV_420P");
+ break;
+ }
+
+ ALOGV("Params width %d height %d level %d colorFormat %d", mWidth,
+ mHeight, mAVCEncLevel, mIvVideoColorFormat);
+
+ /* Getting Number of MemRecords */
+ {
+ iv_num_mem_rec_ip_t s_num_mem_rec_ip;
+ iv_num_mem_rec_op_t s_num_mem_rec_op;
+
+ s_num_mem_rec_ip.u4_size = sizeof(iv_num_mem_rec_ip_t);
+ s_num_mem_rec_op.u4_size = sizeof(iv_num_mem_rec_op_t);
+
+ s_num_mem_rec_ip.e_cmd = IV_CMD_GET_NUM_MEM_REC;
+
+ status = ive_api_function(0, &s_num_mem_rec_ip, &s_num_mem_rec_op);
+
+ if (status != IV_SUCCESS) {
+ ALOGE("Get number of memory records failed = 0x%x\n",
+ s_num_mem_rec_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+
+ mNumMemRecords = s_num_mem_rec_op.u4_num_mem_rec;
+ }
+
+ /* Allocate array to hold memory records */
+ mMemRecords = (iv_mem_rec_t *)malloc(mNumMemRecords * sizeof(iv_mem_rec_t));
+ if (NULL == mMemRecords) {
+ ALOGE("Unable to allocate memory for hold memory records: Size %d",
+ mNumMemRecords * sizeof(iv_mem_rec_t));
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
+ return OMX_ErrorUndefined;
+ }
+
+ {
+ iv_mem_rec_t *ps_mem_rec;
+ ps_mem_rec = mMemRecords;
+ for (i = 0; i < mNumMemRecords; i++) {
+ ps_mem_rec->u4_size = sizeof(iv_mem_rec_t);
+ ps_mem_rec->pv_base = NULL;
+ ps_mem_rec->u4_mem_size = 0;
+ ps_mem_rec->u4_mem_alignment = 0;
+ ps_mem_rec->e_mem_type = IV_NA_MEM_TYPE;
+
+ ps_mem_rec++;
+ }
+ }
+
+ /* Getting MemRecords Attributes */
+ {
+ iv_fill_mem_rec_ip_t s_fill_mem_rec_ip;
+ iv_fill_mem_rec_op_t s_fill_mem_rec_op;
+
+ s_fill_mem_rec_ip.u4_size = sizeof(iv_fill_mem_rec_ip_t);
+ s_fill_mem_rec_op.u4_size = sizeof(iv_fill_mem_rec_op_t);
+
+ s_fill_mem_rec_ip.e_cmd = IV_CMD_FILL_NUM_MEM_REC;
+ s_fill_mem_rec_ip.ps_mem_rec = mMemRecords;
+ s_fill_mem_rec_ip.u4_num_mem_rec = mNumMemRecords;
+ s_fill_mem_rec_ip.u4_max_wd = mWidth;
+ s_fill_mem_rec_ip.u4_max_ht = mHeight;
+ s_fill_mem_rec_ip.u4_max_level = mAVCEncLevel;
+ s_fill_mem_rec_ip.e_color_format = DEFAULT_INP_COLOR_FORMAT;
+ s_fill_mem_rec_ip.u4_max_ref_cnt = DEFAULT_MAX_REF_FRM;
+ s_fill_mem_rec_ip.u4_max_reorder_cnt = DEFAULT_MAX_REORDER_FRM;
+ s_fill_mem_rec_ip.u4_max_srch_rng_x = DEFAULT_MAX_SRCH_RANGE_X;
+ s_fill_mem_rec_ip.u4_max_srch_rng_y = DEFAULT_MAX_SRCH_RANGE_Y;
+
+ status = ive_api_function(0, &s_fill_mem_rec_ip, &s_fill_mem_rec_op);
+
+ if (status != IV_SUCCESS) {
+ ALOGE("Fill memory records failed = 0x%x\n",
+ s_fill_mem_rec_op.u4_error_code);
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
+ return OMX_ErrorUndefined;
+ }
+ }
+
+ /* Allocating Memory for Mem Records */
+ {
+ WORD32 total_size;
+ iv_mem_rec_t *ps_mem_rec;
+ total_size = 0;
+
+ ps_mem_rec = mMemRecords;
+ for (i = 0; i < mNumMemRecords; i++) {
+ ps_mem_rec->pv_base = ive_aligned_malloc(
+ ps_mem_rec->u4_mem_alignment, ps_mem_rec->u4_mem_size);
+ if (ps_mem_rec->pv_base == NULL) {
+ ALOGE("Allocation failure for mem record id %d size %d\n", i,
+ ps_mem_rec->u4_mem_size);
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
+ return OMX_ErrorUndefined;
+
+ }
+ total_size += ps_mem_rec->u4_mem_size;
+
+ ps_mem_rec++;
+ }
+ printf("\nTotal memory for codec %d\n", total_size);
+ }
+
+ /* Codec Instance Creation */
+ {
+ ive_init_ip_t s_init_ip;
+ ive_init_op_t s_init_op;
+
+ mCodecCtx = (iv_obj_t *)mMemRecords[0].pv_base;
+ mCodecCtx->u4_size = sizeof(iv_obj_t);
+ mCodecCtx->pv_fxns = (void *)ive_api_function;
+
+ s_init_ip.u4_size = sizeof(ive_init_ip_t);
+ s_init_op.u4_size = sizeof(ive_init_op_t);
+
+ s_init_ip.e_cmd = IV_CMD_INIT;
+ s_init_ip.u4_num_mem_rec = mNumMemRecords;
+ s_init_ip.ps_mem_rec = mMemRecords;
+ s_init_ip.u4_max_wd = mWidth;
+ s_init_ip.u4_max_ht = mHeight;
+ s_init_ip.u4_max_ref_cnt = DEFAULT_MAX_REF_FRM;
+ s_init_ip.u4_max_reorder_cnt = DEFAULT_MAX_REORDER_FRM;
+ s_init_ip.u4_max_level = mAVCEncLevel;
+ s_init_ip.e_inp_color_fmt = mIvVideoColorFormat;
+
+ if (mReconEnable || mPSNREnable) {
+ s_init_ip.u4_enable_recon = 1;
+ } else {
+ s_init_ip.u4_enable_recon = 0;
+ }
+ s_init_ip.e_recon_color_fmt = DEFAULT_RECON_COLOR_FORMAT;
+ s_init_ip.e_rc_mode = DEFAULT_RC_MODE;
+ s_init_ip.u4_max_framerate = DEFAULT_MAX_FRAMERATE;
+ s_init_ip.u4_max_bitrate = DEFAULT_MAX_BITRATE;
+ s_init_ip.u4_max_num_bframes = DEFAULT_B_FRAMES;
+ s_init_ip.e_content_type = IV_PROGRESSIVE;
+ s_init_ip.u4_max_srch_rng_x = DEFAULT_MAX_SRCH_RANGE_X;
+ s_init_ip.u4_max_srch_rng_y = DEFAULT_MAX_SRCH_RANGE_Y;
+ s_init_ip.e_slice_mode = mSliceMode;
+ s_init_ip.u4_slice_param = mSliceParam;
+ s_init_ip.e_arch = mArch;
+ s_init_ip.e_soc = DEFAULT_SOC;
+
+ status = ive_api_function(mCodecCtx, &s_init_ip, &s_init_op);
+
+ if (status != IV_SUCCESS) {
+ ALOGE("Init memory records failed = 0x%x\n",
+ s_init_op.u4_error_code);
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0 /* arg2 */, NULL /* data */);
+ return OMX_ErrorUndefined;
+ }
+ }
+
+ /* Get Codec Version */
+ logVersion();
+
+ /* set processor details */
+ setNumCores();
+
+ /* Video control Set Frame dimensions */
+ setDimensions();
+
+ /* Video control Set Frame rates */
+ setFrameRate();
+
+ /* Video control Set IPE Params */
+ setIpeParams();
+
+ /* Video control Set Bitrate */
+ setBitRate();
+
+ /* Video control Set QP */
+ setQp();
+
+ /* Video control Set AIR params */
+ setAirParams();
+
+ /* Video control Set VBV params */
+ setVbvParams();
+
+ /* Video control Set Motion estimation params */
+ setMeParams();
+
+ /* Video control Set GOP params */
+ setGopParams();
+
+ /* Video control Set Deblock params */
+ setDeblockParams();
+
+ /* Video control Set Profile params */
+ setProfileParams();
+
+ /* Video control Set in Encode header mode */
+ setEncMode(IVE_ENC_MODE_HEADER);
+
+ ALOGV("init_codec successfull");
+
+ mSpsPpsHeaderReceived = false;
+ mStarted = true;
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::releaseEncoder() {
+ IV_STATUS_T status = IV_SUCCESS;
+ iv_retrieve_mem_rec_ip_t s_retrieve_mem_ip;
+ iv_retrieve_mem_rec_op_t s_retrieve_mem_op;
+ iv_mem_rec_t *ps_mem_rec;
+ UWORD32 i;
+
+ if (!mStarted) {
+ return OMX_ErrorNone;
+ }
+
+ s_retrieve_mem_ip.u4_size = sizeof(iv_retrieve_mem_rec_ip_t);
+ s_retrieve_mem_op.u4_size = sizeof(iv_retrieve_mem_rec_op_t);
+ s_retrieve_mem_ip.e_cmd = IV_CMD_RETRIEVE_MEMREC;
+ s_retrieve_mem_ip.ps_mem_rec = mMemRecords;
+
+ status = ive_api_function(mCodecCtx, &s_retrieve_mem_ip, &s_retrieve_mem_op);
+
+ if (status != IV_SUCCESS) {
+ ALOGE("Unable to retrieve memory records = 0x%x\n",
+ s_retrieve_mem_op.u4_error_code);
+ return OMX_ErrorUndefined;
+ }
+
+ /* Free memory records */
+ ps_mem_rec = mMemRecords;
+ for (i = 0; i < s_retrieve_mem_op.u4_num_mem_rec_filled; i++) {
+ ive_aligned_free(ps_mem_rec->pv_base);
+ ps_mem_rec++;
+ }
+
+ free(mMemRecords);
+
+ if (mConversionBuffer != NULL) {
+ free(mConversionBuffer);
+ mConversionBuffer = NULL;
+ }
+
+ mStarted = false;
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::internalGetParameter(OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamVideoBitrate:
+ {
+ OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
+ (OMX_VIDEO_PARAM_BITRATETYPE *)params;
+
+ if (bitRate->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ bitRate->eControlRate = OMX_Video_ControlRateVariable;
+ bitRate->nTargetBitrate = mBitrate;
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamVideoAvc:
+ {
+ OMX_VIDEO_PARAM_AVCTYPE *avcParams = (OMX_VIDEO_PARAM_AVCTYPE *)params;
+
+ if (avcParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ avcParams->eProfile = OMX_VIDEO_AVCProfileBaseline;
+ OMX_VIDEO_AVCLEVELTYPE omxLevel = OMX_VIDEO_AVCLevel31;
+ if (OMX_ErrorNone
+ != ConvertAvcSpecLevelToOmxAvcLevel(mAVCEncLevel, &omxLevel)) {
+ return OMX_ErrorUndefined;
+ }
+
+ avcParams->eLevel = omxLevel;
+ avcParams->nRefFrames = 1;
+ avcParams->nBFrames = 0;
+ avcParams->bUseHadamard = OMX_TRUE;
+ avcParams->nAllowedPictureTypes = (OMX_VIDEO_PictureTypeI
+ | OMX_VIDEO_PictureTypeP);
+ avcParams->nRefIdx10ActiveMinus1 = 0;
+ avcParams->nRefIdx11ActiveMinus1 = 0;
+ avcParams->bWeightedPPrediction = OMX_FALSE;
+ avcParams->bEntropyCodingCABAC = OMX_FALSE;
+ avcParams->bconstIpred = OMX_FALSE;
+ avcParams->bDirect8x8Inference = OMX_FALSE;
+ avcParams->bDirectSpatialTemporal = OMX_FALSE;
+ avcParams->nCabacInitIdc = 0;
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SoftVideoEncoderOMXComponent::internalGetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftAVC::internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR params) {
+ int32_t indexFull = index;
+
+ switch (indexFull) {
+ case OMX_IndexParamVideoBitrate:
+ {
+ return internalSetBitrateParams(
+ (const OMX_VIDEO_PARAM_BITRATETYPE *)params);
+ }
+
+ case OMX_IndexParamVideoAvc:
+ {
+ OMX_VIDEO_PARAM_AVCTYPE *avcType = (OMX_VIDEO_PARAM_AVCTYPE *)params;
+
+ if (avcType->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (avcType->eProfile != OMX_VIDEO_AVCProfileBaseline
+ || avcType->nRefFrames != 1 || avcType->nBFrames != 0
+ || avcType->bUseHadamard != OMX_TRUE
+ || (avcType->nAllowedPictureTypes & OMX_VIDEO_PictureTypeB) != 0
+ || avcType->nRefIdx10ActiveMinus1 != 0
+ || avcType->nRefIdx11ActiveMinus1 != 0
+ || avcType->bWeightedPPrediction != OMX_FALSE
+ || avcType->bEntropyCodingCABAC != OMX_FALSE
+ || avcType->bconstIpred != OMX_FALSE
+ || avcType->bDirect8x8Inference != OMX_FALSE
+ || avcType->bDirectSpatialTemporal != OMX_FALSE
+ || avcType->nCabacInitIdc != 0) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (OK != ConvertOmxAvcLevelToAvcSpecLevel(avcType->eLevel, &mAVCEncLevel)) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SoftVideoEncoderOMXComponent::internalSetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftAVC::setConfig(
+ OMX_INDEXTYPE index, const OMX_PTR _params) {
+ switch (index) {
+ case OMX_IndexConfigVideoIntraVOPRefresh:
+ {
+ OMX_CONFIG_INTRAREFRESHVOPTYPE *params =
+ (OMX_CONFIG_INTRAREFRESHVOPTYPE *)_params;
+
+ if (params->nPortIndex != kOutputPortIndex) {
+ return OMX_ErrorBadPortIndex;
+ }
+
+ mKeyFrameRequested = params->IntraRefreshVOP;
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexConfigVideoBitrate:
+ {
+ OMX_VIDEO_CONFIG_BITRATETYPE *params =
+ (OMX_VIDEO_CONFIG_BITRATETYPE *)_params;
+
+ if (params->nPortIndex != kOutputPortIndex) {
+ return OMX_ErrorBadPortIndex;
+ }
+
+ if (mBitrate != params->nEncodeBitrate) {
+ mBitrate = params->nEncodeBitrate;
+ mBitrateUpdated = true;
+ }
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::setConfig(index, _params);
+ }
+}
+
+OMX_ERRORTYPE SoftAVC::internalSetBitrateParams(
+ const OMX_VIDEO_PARAM_BITRATETYPE *bitrate) {
+ if (bitrate->nPortIndex != kOutputPortIndex) {
+ return OMX_ErrorUnsupportedIndex;
+ }
+
+ mBitrate = bitrate->nTargetBitrate;
+ mBitrateUpdated = true;
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftAVC::setEncodeArgs(
+ ive_video_encode_ip_t *ps_encode_ip,
+ ive_video_encode_op_t *ps_encode_op,
+ OMX_BUFFERHEADERTYPE *inputBufferHeader,
+ OMX_BUFFERHEADERTYPE *outputBufferHeader) {
+ iv_raw_buf_t *ps_inp_raw_buf;
+ const uint8_t *source;
+ UWORD8 *pu1_buf;
+
+ ps_inp_raw_buf = &ps_encode_ip->s_inp_buf;
+ ps_encode_ip->s_out_buf.pv_buf = outputBufferHeader->pBuffer;
+ ps_encode_ip->s_out_buf.u4_bytes = 0;
+ ps_encode_ip->s_out_buf.u4_bufsize = outputBufferHeader->nAllocLen;
+ ps_encode_ip->u4_size = sizeof(ive_video_encode_ip_t);
+ ps_encode_op->u4_size = sizeof(ive_video_encode_op_t);
+
+ ps_encode_ip->e_cmd = IVE_CMD_VIDEO_ENCODE;
+ ps_encode_ip->pv_bufs = NULL;
+ ps_encode_ip->pv_mb_info = NULL;
+ ps_encode_ip->pv_pic_info = NULL;
+ ps_encode_ip->u4_mb_info_type = 0;
+ ps_encode_ip->u4_pic_info_type = 0;
+ ps_encode_op->s_out_buf.pv_buf = NULL;
+
+ /* Initialize color formats */
+ ps_inp_raw_buf->e_color_fmt = mIvVideoColorFormat;
+
+ source = NULL;
+ if (inputBufferHeader) {
+ source = inputBufferHeader->pBuffer + inputBufferHeader->nOffset;
+
+ if (mInputDataIsMeta) {
+ source = extractGraphicBuffer(
+ mConversionBuffer, (mWidth * mHeight * 3 / 2), source,
+ inputBufferHeader->nFilledLen, mWidth, mHeight);
+
+ if (source == NULL) {
+ ALOGE("Error in extractGraphicBuffer");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
+ return OMX_ErrorUndefined;
+ }
+ }
+ }
+
+ pu1_buf = (UWORD8 *)source;
+ switch (mIvVideoColorFormat) {
+ case IV_YUV_420P:
+ {
+ ps_inp_raw_buf->apv_bufs[0] = pu1_buf;
+ pu1_buf += (mStride) * mHeight;
+ ps_inp_raw_buf->apv_bufs[1] = pu1_buf;
+ pu1_buf += (mStride / 2) * mHeight / 2;
+ ps_inp_raw_buf->apv_bufs[2] = pu1_buf;
+
+ ps_inp_raw_buf->au4_wd[0] = mWidth;
+ ps_inp_raw_buf->au4_wd[1] = mWidth / 2;
+ ps_inp_raw_buf->au4_wd[2] = mWidth / 2;
+
+ ps_inp_raw_buf->au4_ht[0] = mHeight;
+ ps_inp_raw_buf->au4_ht[1] = mHeight / 2;
+ ps_inp_raw_buf->au4_ht[2] = mHeight / 2;
+
+ ps_inp_raw_buf->au4_strd[0] = mStride;
+ ps_inp_raw_buf->au4_strd[1] = (mStride / 2);
+ ps_inp_raw_buf->au4_strd[2] = (mStride / 2);
+ break;
+ }
+
+ case IV_YUV_422ILE:
+ {
+ ps_inp_raw_buf->apv_bufs[0] = pu1_buf;
+ ps_inp_raw_buf->au4_wd[0] = mWidth * 2;
+ ps_inp_raw_buf->au4_ht[0] = mHeight;
+ ps_inp_raw_buf->au4_strd[0] = mStride * 2;
+ break;
+ }
+
+ case IV_YUV_420SP_UV:
+ case IV_YUV_420SP_VU:
+ default:
+ {
+ ps_inp_raw_buf->apv_bufs[0] = pu1_buf;
+ pu1_buf += (mStride) * mHeight;
+ ps_inp_raw_buf->apv_bufs[1] = pu1_buf;
+
+ ps_inp_raw_buf->au4_wd[0] = mWidth;
+ ps_inp_raw_buf->au4_wd[1] = mWidth;
+
+ ps_inp_raw_buf->au4_ht[0] = mHeight;
+ ps_inp_raw_buf->au4_ht[1] = mHeight / 2;
+
+ ps_inp_raw_buf->au4_strd[0] = mStride;
+ ps_inp_raw_buf->au4_strd[1] = mStride;
+ break;
+ }
+ }
+
+ ps_encode_ip->u4_is_last = 0;
+
+ if (inputBufferHeader) {
+ ps_encode_ip->u4_timestamp_high = (inputBufferHeader->nTimeStamp) >> 32;
+ ps_encode_ip->u4_timestamp_low = (inputBufferHeader->nTimeStamp) & 0xFFFFFFFF;
+ }
+
+ return OMX_ErrorNone;
+}
+
+void SoftAVC::onQueueFilled(OMX_U32 portIndex) {
+ IV_STATUS_T status;
+ WORD32 timeDelay, timeTaken;
+
+ UNUSED(portIndex);
+
+ // Initialize encoder if not already initialized
+ if (mCodecCtx == NULL) {
+ if (OMX_ErrorNone != initEncoder()) {
+ ALOGE("Failed to initialize encoder");
+ notify(OMX_EventError, OMX_ErrorUndefined, 0 /* arg2 */, NULL /* data */);
+ return;
+ }
+ }
+ if (mSignalledError || mSawInputEOS) {
+ return;
+ }
+
+ List<BufferInfo *> &inQueue = getPortQueue(0);
+ List<BufferInfo *> &outQueue = getPortQueue(1);
+
+ while (!mSawInputEOS && !inQueue.empty() && !outQueue.empty()) {
+ OMX_ERRORTYPE error;
+ ive_video_encode_ip_t s_encode_ip;
+ ive_video_encode_op_t s_encode_op;
+
+ BufferInfo *inputBufferInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inputBufferHeader = inputBufferInfo->mHeader;
+
+ BufferInfo *outputBufferInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outputBufferHeader = outputBufferInfo->mHeader;
+
+ if (inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ inQueue.erase(inQueue.begin());
+ inputBufferInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inputBufferHeader);
+
+ outputBufferHeader->nFilledLen = 0;
+ outputBufferHeader->nFlags = OMX_BUFFERFLAG_EOS;
+
+ outQueue.erase(outQueue.begin());
+ outputBufferInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outputBufferHeader);
+ return;
+ }
+
+ outputBufferHeader->nTimeStamp = 0;
+ outputBufferHeader->nFlags = 0;
+ outputBufferHeader->nOffset = 0;
+ outputBufferHeader->nFilledLen = 0;
+ outputBufferHeader->nOffset = 0;
+
+ uint8_t *outPtr = (uint8_t *)outputBufferHeader->pBuffer;
+
+ if (!mSpsPpsHeaderReceived) {
+ error = setEncodeArgs(&s_encode_ip, &s_encode_op, NULL, outputBufferHeader);
+ if (error != OMX_ErrorNone) {
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
+ return;
+ }
+ status = ive_api_function(mCodecCtx, &s_encode_ip, &s_encode_op);
+
+ if (IV_SUCCESS != status) {
+ ALOGE("Encode Frame failed = 0x%x\n",
+ s_encode_op.u4_error_code);
+ } else {
+ ALOGV("Bytes Generated in header %d\n",
+ s_encode_op.s_out_buf.u4_bytes);
+ }
+
+ mSpsPpsHeaderReceived = true;
+
+ outputBufferHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
+ outputBufferHeader->nFilledLen = s_encode_op.s_out_buf.u4_bytes;
+ outputBufferHeader->nTimeStamp = inputBufferHeader->nTimeStamp;
+
+ outQueue.erase(outQueue.begin());
+ outputBufferInfo->mOwnedByUs = false;
+ DUMP_TO_FILE(
+ mOutFile, outputBufferHeader->pBuffer,
+ outputBufferHeader->nFilledLen);
+ notifyFillBufferDone(outputBufferHeader);
+
+ setEncMode(IVE_ENC_MODE_PICTURE);
+ return;
+ }
+
+ if (mBitrateUpdated) {
+ setBitRate();
+ }
+
+ if (mKeyFrameRequested) {
+ setFrameType(IV_IDR_FRAME);
+ }
+
+ mPrevTimestampUs = inputBufferHeader->nTimeStamp;
+
+ if (inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ mSawInputEOS = true;
+ }
+
+ error = setEncodeArgs(
+ &s_encode_ip, &s_encode_op, inputBufferHeader, outputBufferHeader);
+ if (error != OMX_ErrorNone) {
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
+ return;
+ }
+
+ DUMP_TO_FILE(
+ mInFile, s_encode_ip.s_inp_buf.apv_bufs[0],
+ (mHeight * mStride * 3 / 2));
+ //DUMP_TO_FILE(mInFile, inputBufferHeader->pBuffer + inputBufferHeader->nOffset,
+ // inputBufferHeader->nFilledLen);
+
+ GETTIME(&mTimeStart, NULL);
+ /* Compute time elapsed between end of previous decode()
+ * to start of current decode() */
+ TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);
+
+ status = ive_api_function(mCodecCtx, &s_encode_ip, &s_encode_op);
+
+ if (IV_SUCCESS != status) {
+ ALOGE("Encode Frame failed = 0x%x\n",
+ s_encode_op.u4_error_code);
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
+ return;
+ }
+
+ GETTIME(&mTimeEnd, NULL);
+ /* Compute time taken for decode() */
+ TIME_DIFF(mTimeStart, mTimeEnd, timeTaken);
+
+ ALOGV("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay,
+ s_encode_op.s_out_buf.u4_bytes);
+
+
+ outputBufferHeader->nFlags = inputBufferHeader->nFlags;
+ outputBufferHeader->nFilledLen = s_encode_op.s_out_buf.u4_bytes;
+ outputBufferHeader->nTimeStamp = inputBufferHeader->nTimeStamp;
+
+ if (IV_IDR_FRAME
+ == s_encode_op.u4_encoded_frame_type) {
+ outputBufferHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
+ }
+
+ inQueue.erase(inQueue.begin());
+ inputBufferInfo->mOwnedByUs = false;
+
+ notifyEmptyBufferDone(inputBufferHeader);
+
+ if (mSawInputEOS) {
+ outputBufferHeader->nFlags |= OMX_BUFFERFLAG_EOS;
+ }
+
+ outputBufferInfo->mOwnedByUs = false;
+ outQueue.erase(outQueue.begin());
+
+ DUMP_TO_FILE(
+ mOutFile, outputBufferHeader->pBuffer,
+ outputBufferHeader->nFilledLen);
+ notifyFillBufferDone(outputBufferHeader);
+
+ }
+ return;
+}
+
+
+} // namespace android
+
+android::SoftOMXComponent *createSoftOMXComponent(
+ const char *name, const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData, OMX_COMPONENTTYPE **component) {
+ return new android::SoftAVC(name, callbacks, appData, component);
+}