Home | History | Annotate | Download | only in avcdec
      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 "SoftAVCDec"
     19 #include <utils/Log.h>
     20 
     21 #include "ih264_typedefs.h"
     22 #include "iv.h"
     23 #include "ivd.h"
     24 #include "ih264d.h"
     25 #include "SoftAVCDec.h"
     26 
     27 #include <media/stagefright/foundation/ADebug.h>
     28 #include <media/stagefright/MediaDefs.h>
     29 #include <OMX_VideoExt.h>
     30 
     31 namespace android {
     32 
     33 #define PRINT_TIME  ALOGV
     34 
     35 #define componentName                   "video_decoder.avc"
     36 #define codingType                      OMX_VIDEO_CodingAVC
     37 #define CODEC_MIME_TYPE                 MEDIA_MIMETYPE_VIDEO_AVC
     38 
     39 /** Function and structure definitions to keep code similar for each codec */
     40 #define ivdec_api_function              ih264d_api_function
     41 #define ivdext_create_ip_t              ih264d_create_ip_t
     42 #define ivdext_create_op_t              ih264d_create_op_t
     43 #define ivdext_delete_ip_t              ih264d_delete_ip_t
     44 #define ivdext_delete_op_t              ih264d_delete_op_t
     45 #define ivdext_ctl_set_num_cores_ip_t   ih264d_ctl_set_num_cores_ip_t
     46 #define ivdext_ctl_set_num_cores_op_t   ih264d_ctl_set_num_cores_op_t
     47 
     48 #define IVDEXT_CMD_CTL_SET_NUM_CORES    \
     49         (IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_SET_NUM_CORES
     50 
     51 static const CodecProfileLevel kProfileLevels[] = {
     52     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1  },
     53     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1b },
     54     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel11 },
     55     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel12 },
     56     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13 },
     57     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2  },
     58     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel21 },
     59     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel22 },
     60     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel3  },
     61     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel31 },
     62     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel32 },
     63     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel4  },
     64     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel41 },
     65     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel42 },
     66     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel5  },
     67     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel51 },
     68     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel52 },
     69 
     70     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel1  },
     71     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel1b },
     72     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel11 },
     73     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel12 },
     74     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel13 },
     75     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel2  },
     76     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel21 },
     77     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel22 },
     78     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel3  },
     79     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel31 },
     80     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel32 },
     81     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel4  },
     82     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel41 },
     83     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel42 },
     84     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel5  },
     85     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel51 },
     86     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel52 },
     87 
     88     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel1  },
     89     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel1b },
     90     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel11 },
     91     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel12 },
     92     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel13 },
     93     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel2  },
     94     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel21 },
     95     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel22 },
     96     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel3  },
     97     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel31 },
     98     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel32 },
     99     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel4  },
    100     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel41 },
    101     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel42 },
    102     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel5  },
    103     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel51 },
    104     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel52 },
    105 };
    106 
    107 SoftAVC::SoftAVC(
    108         const char *name,
    109         const OMX_CALLBACKTYPE *callbacks,
    110         OMX_PTR appData,
    111         OMX_COMPONENTTYPE **component)
    112     : SoftVideoDecoderOMXComponent(
    113             name, componentName, codingType,
    114             kProfileLevels, ARRAY_SIZE(kProfileLevels),
    115             320 /* width */, 240 /* height */, callbacks,
    116             appData, component),
    117       mCodecCtx(NULL),
    118       mFlushOutBuffer(NULL),
    119       mOmxColorFormat(OMX_COLOR_FormatYUV420Planar),
    120       mIvColorFormat(IV_YUV_420P),
    121       mChangingResolution(false),
    122       mSignalledError(false),
    123       mStride(mWidth){
    124     initPorts(
    125             1 /* numMinInputBuffers */, kNumBuffers, INPUT_BUF_SIZE,
    126             1 /* numMinOutputBuffers */, kNumBuffers, CODEC_MIME_TYPE);
    127 
    128     GETTIME(&mTimeStart, NULL);
    129 
    130     // If input dump is enabled, then open create an empty file
    131     GENERATE_FILE_NAMES();
    132     CREATE_DUMP_FILE(mInFile);
    133 }
    134 
    135 SoftAVC::~SoftAVC() {
    136     CHECK_EQ(deInitDecoder(), (status_t)OK);
    137 }
    138 
    139 static void *ivd_aligned_malloc(void *ctxt, WORD32 alignment, WORD32 size) {
    140     UNUSED(ctxt);
    141     return memalign(alignment, size);
    142 }
    143 
    144 static void ivd_aligned_free(void *ctxt, void *buf) {
    145     UNUSED(ctxt);
    146     free(buf);
    147     return;
    148 }
    149 
    150 static size_t GetCPUCoreCount() {
    151     long cpuCoreCount = 1;
    152 #if defined(_SC_NPROCESSORS_ONLN)
    153     cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
    154 #else
    155     // _SC_NPROC_ONLN must be defined...
    156     cpuCoreCount = sysconf(_SC_NPROC_ONLN);
    157 #endif
    158     CHECK(cpuCoreCount >= 1);
    159     ALOGV("Number of CPU cores: %ld", cpuCoreCount);
    160     return (size_t)cpuCoreCount;
    161 }
    162 
    163 void SoftAVC::logVersion() {
    164     ivd_ctl_getversioninfo_ip_t s_ctl_ip;
    165     ivd_ctl_getversioninfo_op_t s_ctl_op;
    166     UWORD8 au1_buf[512];
    167     IV_API_CALL_STATUS_T status;
    168 
    169     s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
    170     s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_GETVERSION;
    171     s_ctl_ip.u4_size = sizeof(ivd_ctl_getversioninfo_ip_t);
    172     s_ctl_op.u4_size = sizeof(ivd_ctl_getversioninfo_op_t);
    173     s_ctl_ip.pv_version_buffer = au1_buf;
    174     s_ctl_ip.u4_version_buffer_size = sizeof(au1_buf);
    175 
    176     status =
    177         ivdec_api_function(mCodecCtx, (void *)&s_ctl_ip, (void *)&s_ctl_op);
    178 
    179     if (status != IV_SUCCESS) {
    180         ALOGE("Error in getting version number: 0x%x",
    181                 s_ctl_op.u4_error_code);
    182     } else {
    183         ALOGV("Ittiam decoder version number: %s",
    184                 (char *)s_ctl_ip.pv_version_buffer);
    185     }
    186     return;
    187 }
    188 
    189 status_t SoftAVC::setParams(size_t stride) {
    190     ivd_ctl_set_config_ip_t s_ctl_ip;
    191     ivd_ctl_set_config_op_t s_ctl_op;
    192     IV_API_CALL_STATUS_T status;
    193     s_ctl_ip.u4_disp_wd = (UWORD32)stride;
    194     s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE;
    195 
    196     s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
    197     s_ctl_ip.e_vid_dec_mode = IVD_DECODE_FRAME;
    198     s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
    199     s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
    200     s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);
    201     s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t);
    202 
    203     ALOGV("Set the run-time (dynamic) parameters stride = %zu", stride);
    204     status = ivdec_api_function(mCodecCtx, (void *)&s_ctl_ip, (void *)&s_ctl_op);
    205 
    206     if (status != IV_SUCCESS) {
    207         ALOGE("Error in setting the run-time parameters: 0x%x",
    208                 s_ctl_op.u4_error_code);
    209 
    210         return UNKNOWN_ERROR;
    211     }
    212     return OK;
    213 }
    214 
    215 status_t SoftAVC::resetPlugin() {
    216     mIsInFlush = false;
    217     mReceivedEOS = false;
    218     memset(mTimeStamps, 0, sizeof(mTimeStamps));
    219     memset(mTimeStampsValid, 0, sizeof(mTimeStampsValid));
    220 
    221     /* Initialize both start and end times */
    222     gettimeofday(&mTimeStart, NULL);
    223     gettimeofday(&mTimeEnd, NULL);
    224 
    225     return OK;
    226 }
    227 
    228 status_t SoftAVC::resetDecoder() {
    229     ivd_ctl_reset_ip_t s_ctl_ip;
    230     ivd_ctl_reset_op_t s_ctl_op;
    231     IV_API_CALL_STATUS_T status;
    232 
    233     s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
    234     s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_RESET;
    235     s_ctl_ip.u4_size = sizeof(ivd_ctl_reset_ip_t);
    236     s_ctl_op.u4_size = sizeof(ivd_ctl_reset_op_t);
    237 
    238     status = ivdec_api_function(mCodecCtx, (void *)&s_ctl_ip, (void *)&s_ctl_op);
    239     if (IV_SUCCESS != status) {
    240         ALOGE("Error in reset: 0x%x", s_ctl_op.u4_error_code);
    241         return UNKNOWN_ERROR;
    242     }
    243     mSignalledError = false;
    244 
    245     /* Set number of cores/threads to be used by the codec */
    246     setNumCores();
    247 
    248     mStride = 0;
    249     return OK;
    250 }
    251 
    252 status_t SoftAVC::setNumCores() {
    253     ivdext_ctl_set_num_cores_ip_t s_set_cores_ip;
    254     ivdext_ctl_set_num_cores_op_t s_set_cores_op;
    255     IV_API_CALL_STATUS_T status;
    256     s_set_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL;
    257     s_set_cores_ip.e_sub_cmd = IVDEXT_CMD_CTL_SET_NUM_CORES;
    258     s_set_cores_ip.u4_num_cores = MIN(mNumCores, CODEC_MAX_NUM_CORES);
    259     s_set_cores_ip.u4_size = sizeof(ivdext_ctl_set_num_cores_ip_t);
    260     s_set_cores_op.u4_size = sizeof(ivdext_ctl_set_num_cores_op_t);
    261     status = ivdec_api_function(
    262             mCodecCtx, (void *)&s_set_cores_ip, (void *)&s_set_cores_op);
    263     if (IV_SUCCESS != status) {
    264         ALOGE("Error in setting number of cores: 0x%x",
    265                 s_set_cores_op.u4_error_code);
    266         return UNKNOWN_ERROR;
    267     }
    268     return OK;
    269 }
    270 
    271 status_t SoftAVC::setFlushMode() {
    272     IV_API_CALL_STATUS_T status;
    273     ivd_ctl_flush_ip_t s_video_flush_ip;
    274     ivd_ctl_flush_op_t s_video_flush_op;
    275 
    276     s_video_flush_ip.e_cmd = IVD_CMD_VIDEO_CTL;
    277     s_video_flush_ip.e_sub_cmd = IVD_CMD_CTL_FLUSH;
    278     s_video_flush_ip.u4_size = sizeof(ivd_ctl_flush_ip_t);
    279     s_video_flush_op.u4_size = sizeof(ivd_ctl_flush_op_t);
    280 
    281     /* Set the decoder in Flush mode, subsequent decode() calls will flush */
    282     status = ivdec_api_function(
    283             mCodecCtx, (void *)&s_video_flush_ip, (void *)&s_video_flush_op);
    284 
    285     if (status != IV_SUCCESS) {
    286         ALOGE("Error in setting the decoder in flush mode: (%d) 0x%x", status,
    287                 s_video_flush_op.u4_error_code);
    288         return UNKNOWN_ERROR;
    289     }
    290 
    291     mIsInFlush = true;
    292     return OK;
    293 }
    294 
    295 status_t SoftAVC::initDecoder() {
    296     IV_API_CALL_STATUS_T status;
    297 
    298     mNumCores = GetCPUCoreCount();
    299     mCodecCtx = NULL;
    300 
    301     mStride = outputBufferWidth();
    302 
    303     /* Initialize the decoder */
    304     {
    305         ivdext_create_ip_t s_create_ip;
    306         ivdext_create_op_t s_create_op;
    307 
    308         void *dec_fxns = (void *)ivdec_api_function;
    309 
    310         s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ivdext_create_ip_t);
    311         s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
    312         s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 0;
    313         s_create_op.s_ivd_create_op_t.u4_size = sizeof(ivdext_create_op_t);
    314         s_create_ip.s_ivd_create_ip_t.e_output_format = mIvColorFormat;
    315         s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ivd_aligned_malloc;
    316         s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ivd_aligned_free;
    317         s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = NULL;
    318 
    319         status = ivdec_api_function(mCodecCtx, (void *)&s_create_ip, (void *)&s_create_op);
    320 
    321         mCodecCtx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle;
    322         mCodecCtx->pv_fxns = dec_fxns;
    323         mCodecCtx->u4_size = sizeof(iv_obj_t);
    324 
    325         if (status != IV_SUCCESS) {
    326             ALOGE("Error in create: 0x%x",
    327                     s_create_op.s_ivd_create_op_t.u4_error_code);
    328             deInitDecoder();
    329             mCodecCtx = NULL;
    330             return UNKNOWN_ERROR;
    331         }
    332     }
    333 
    334     /* Reset the plugin state */
    335     resetPlugin();
    336 
    337     /* Set the run time (dynamic) parameters */
    338     setParams(mStride);
    339 
    340     /* Set number of cores/threads to be used by the codec */
    341     setNumCores();
    342 
    343     /* Get codec version */
    344     logVersion();
    345 
    346     mFlushNeeded = false;
    347     return OK;
    348 }
    349 
    350 status_t SoftAVC::deInitDecoder() {
    351     size_t i;
    352     IV_API_CALL_STATUS_T status;
    353 
    354     if (mCodecCtx) {
    355         ivdext_delete_ip_t s_delete_ip;
    356         ivdext_delete_op_t s_delete_op;
    357 
    358         s_delete_ip.s_ivd_delete_ip_t.u4_size = sizeof(ivdext_delete_ip_t);
    359         s_delete_ip.s_ivd_delete_ip_t.e_cmd = IVD_CMD_DELETE;
    360 
    361         s_delete_op.s_ivd_delete_op_t.u4_size = sizeof(ivdext_delete_op_t);
    362 
    363         status = ivdec_api_function(mCodecCtx, (void *)&s_delete_ip, (void *)&s_delete_op);
    364         if (status != IV_SUCCESS) {
    365             ALOGE("Error in delete: 0x%x",
    366                     s_delete_op.s_ivd_delete_op_t.u4_error_code);
    367             return UNKNOWN_ERROR;
    368         }
    369     }
    370 
    371 
    372     mChangingResolution = false;
    373 
    374     return OK;
    375 }
    376 
    377 void SoftAVC::onReset() {
    378     SoftVideoDecoderOMXComponent::onReset();
    379 
    380     mSignalledError = false;
    381     resetDecoder();
    382     resetPlugin();
    383 }
    384 
    385 bool SoftAVC::getVUIParams() {
    386     IV_API_CALL_STATUS_T status;
    387     ih264d_ctl_get_vui_params_ip_t s_ctl_get_vui_params_ip;
    388     ih264d_ctl_get_vui_params_op_t s_ctl_get_vui_params_op;
    389 
    390     s_ctl_get_vui_params_ip.e_cmd = IVD_CMD_VIDEO_CTL;
    391     s_ctl_get_vui_params_ip.e_sub_cmd =
    392         (IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_GET_VUI_PARAMS;
    393 
    394     s_ctl_get_vui_params_ip.u4_size =
    395         sizeof(ih264d_ctl_get_vui_params_ip_t);
    396 
    397     s_ctl_get_vui_params_op.u4_size = sizeof(ih264d_ctl_get_vui_params_op_t);
    398 
    399     status = ivdec_api_function(
    400             (iv_obj_t *)mCodecCtx, (void *)&s_ctl_get_vui_params_ip,
    401             (void *)&s_ctl_get_vui_params_op);
    402 
    403     if (status != IV_SUCCESS) {
    404         ALOGW("Error in getting VUI params: 0x%x",
    405                 s_ctl_get_vui_params_op.u4_error_code);
    406         return false;
    407     }
    408 
    409     int32_t primaries = s_ctl_get_vui_params_op.u1_colour_primaries;
    410     int32_t transfer = s_ctl_get_vui_params_op.u1_tfr_chars;
    411     int32_t coeffs = s_ctl_get_vui_params_op.u1_matrix_coeffs;
    412     bool fullRange = s_ctl_get_vui_params_op.u1_video_full_range_flag;
    413 
    414     ColorAspects colorAspects;
    415     ColorUtils::convertIsoColorAspectsToCodecAspects(
    416             primaries, transfer, coeffs, fullRange, colorAspects);
    417 
    418     // Update color aspects if necessary.
    419     if (colorAspectsDiffer(colorAspects, mBitstreamColorAspects)) {
    420         mBitstreamColorAspects = colorAspects;
    421         status_t err = handleColorAspectsChange();
    422         CHECK(err == OK);
    423     }
    424     return true;
    425 }
    426 
    427 bool SoftAVC::setDecodeArgs(
    428         ivd_video_decode_ip_t *ps_dec_ip,
    429         ivd_video_decode_op_t *ps_dec_op,
    430         OMX_BUFFERHEADERTYPE *inHeader,
    431         OMX_BUFFERHEADERTYPE *outHeader,
    432         size_t timeStampIx) {
    433     size_t sizeY = outputBufferWidth() * outputBufferHeight();
    434     size_t sizeUV;
    435 
    436     ps_dec_ip->u4_size = sizeof(ivd_video_decode_ip_t);
    437     ps_dec_op->u4_size = sizeof(ivd_video_decode_op_t);
    438 
    439     ps_dec_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
    440 
    441     /* When in flush and after EOS with zero byte input,
    442      * inHeader is set to zero. Hence check for non-null */
    443     if (inHeader) {
    444         ps_dec_ip->u4_ts = timeStampIx;
    445         ps_dec_ip->pv_stream_buffer =
    446             inHeader->pBuffer + inHeader->nOffset;
    447         ps_dec_ip->u4_num_Bytes = inHeader->nFilledLen;
    448     } else {
    449         ps_dec_ip->u4_ts = 0;
    450         ps_dec_ip->pv_stream_buffer = NULL;
    451         ps_dec_ip->u4_num_Bytes = 0;
    452     }
    453 
    454     sizeUV = sizeY / 4;
    455     ps_dec_ip->s_out_buffer.u4_min_out_buf_size[0] = sizeY;
    456     ps_dec_ip->s_out_buffer.u4_min_out_buf_size[1] = sizeUV;
    457     ps_dec_ip->s_out_buffer.u4_min_out_buf_size[2] = sizeUV;
    458 
    459     uint8_t *pBuf;
    460     if (outHeader) {
    461         if (outHeader->nAllocLen < sizeY + (sizeUV * 2)) {
    462             android_errorWriteLog(0x534e4554, "27833616");
    463             return false;
    464         }
    465         pBuf = outHeader->pBuffer;
    466     } else {
    467         // mFlushOutBuffer always has the right size.
    468         pBuf = mFlushOutBuffer;
    469     }
    470 
    471     ps_dec_ip->s_out_buffer.pu1_bufs[0] = pBuf;
    472     ps_dec_ip->s_out_buffer.pu1_bufs[1] = pBuf + sizeY;
    473     ps_dec_ip->s_out_buffer.pu1_bufs[2] = pBuf + sizeY + sizeUV;
    474     ps_dec_ip->s_out_buffer.u4_num_bufs = 3;
    475     return true;
    476 }
    477 void SoftAVC::onPortFlushCompleted(OMX_U32 portIndex) {
    478     /* Once the output buffers are flushed, ignore any buffers that are held in decoder */
    479     if (kOutputPortIndex == portIndex) {
    480         setFlushMode();
    481 
    482         /* Allocate a picture buffer to flushed data */
    483         uint32_t displayStride = outputBufferWidth();
    484         uint32_t displayHeight = outputBufferHeight();
    485 
    486         uint32_t bufferSize = displayStride * displayHeight * 3 / 2;
    487         mFlushOutBuffer = (uint8_t *)memalign(128, bufferSize);
    488         if (NULL == mFlushOutBuffer) {
    489             ALOGE("Could not allocate flushOutputBuffer of size %u", bufferSize);
    490             return;
    491         }
    492 
    493         while (true) {
    494             ivd_video_decode_ip_t s_dec_ip;
    495             ivd_video_decode_op_t s_dec_op;
    496             IV_API_CALL_STATUS_T status;
    497             size_t sizeY, sizeUV;
    498 
    499             setDecodeArgs(&s_dec_ip, &s_dec_op, NULL, NULL, 0);
    500 
    501             status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
    502             if (0 == s_dec_op.u4_output_present) {
    503                 resetPlugin();
    504                 break;
    505             }
    506         }
    507 
    508         if (mFlushOutBuffer) {
    509             free(mFlushOutBuffer);
    510             mFlushOutBuffer = NULL;
    511         }
    512 
    513     }
    514 }
    515 
    516 void SoftAVC::onQueueFilled(OMX_U32 portIndex) {
    517     UNUSED(portIndex);
    518 
    519     if (mSignalledError) {
    520         return;
    521     }
    522     if (mOutputPortSettingsChange != NONE) {
    523         return;
    524     }
    525 
    526     if (NULL == mCodecCtx) {
    527         if (OK != initDecoder()) {
    528             ALOGE("Failed to initialize decoder");
    529             notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
    530             mSignalledError = true;
    531             return;
    532         }
    533     }
    534     if (outputBufferWidth() != mStride) {
    535         /* Set the run-time (dynamic) parameters */
    536         mStride = outputBufferWidth();
    537         setParams(mStride);
    538     }
    539 
    540     List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
    541     List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
    542 
    543     while (!outQueue.empty()) {
    544         BufferInfo *inInfo;
    545         OMX_BUFFERHEADERTYPE *inHeader;
    546 
    547         BufferInfo *outInfo;
    548         OMX_BUFFERHEADERTYPE *outHeader;
    549         size_t timeStampIx;
    550 
    551         inInfo = NULL;
    552         inHeader = NULL;
    553 
    554         if (!mIsInFlush) {
    555             if (!inQueue.empty()) {
    556                 inInfo = *inQueue.begin();
    557                 inHeader = inInfo->mHeader;
    558                 if (inHeader == NULL) {
    559                     inQueue.erase(inQueue.begin());
    560                     inInfo->mOwnedByUs = false;
    561                     continue;
    562                 }
    563             } else {
    564                 break;
    565             }
    566         }
    567 
    568         outInfo = *outQueue.begin();
    569         outHeader = outInfo->mHeader;
    570         outHeader->nFlags = 0;
    571         outHeader->nTimeStamp = 0;
    572         outHeader->nOffset = 0;
    573 
    574         if (inHeader != NULL) {
    575             if (inHeader->nFilledLen == 0) {
    576                 inQueue.erase(inQueue.begin());
    577                 inInfo->mOwnedByUs = false;
    578                 notifyEmptyBufferDone(inHeader);
    579 
    580                 if (!(inHeader->nFlags & OMX_BUFFERFLAG_EOS)) {
    581                     continue;
    582                 }
    583 
    584                 mReceivedEOS = true;
    585                 inHeader = NULL;
    586                 setFlushMode();
    587             } else if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
    588                 mReceivedEOS = true;
    589             }
    590         }
    591 
    592         /* Get a free slot in timestamp array to hold input timestamp */
    593         {
    594             size_t i;
    595             timeStampIx = 0;
    596             for (i = 0; i < MAX_TIME_STAMPS; i++) {
    597                 if (!mTimeStampsValid[i]) {
    598                     timeStampIx = i;
    599                     break;
    600                 }
    601             }
    602             if (inHeader != NULL) {
    603                 mTimeStampsValid[timeStampIx] = true;
    604                 mTimeStamps[timeStampIx] = inHeader->nTimeStamp;
    605             }
    606         }
    607 
    608         {
    609             ivd_video_decode_ip_t s_dec_ip;
    610             ivd_video_decode_op_t s_dec_op;
    611             WORD32 timeDelay, timeTaken;
    612             size_t sizeY, sizeUV;
    613 
    614             if (!setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx)) {
    615                 ALOGE("Decoder arg setup failed");
    616                 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
    617                 mSignalledError = true;
    618                 return;
    619             }
    620             // If input dump is enabled, then write to file
    621             DUMP_TO_FILE(mInFile, s_dec_ip.pv_stream_buffer, s_dec_ip.u4_num_Bytes);
    622 
    623             GETTIME(&mTimeStart, NULL);
    624             /* Compute time elapsed between end of previous decode()
    625              * to start of current decode() */
    626             TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);
    627 
    628             IV_API_CALL_STATUS_T status;
    629             status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
    630 
    631             bool unsupportedResolution =
    632                 (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_dec_op.u4_error_code & 0xFF));
    633 
    634             /* Check for unsupported dimensions */
    635             if (unsupportedResolution) {
    636                 ALOGE("Unsupported resolution : %dx%d", mWidth, mHeight);
    637                 notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
    638                 mSignalledError = true;
    639                 return;
    640             }
    641 
    642             bool allocationFailed = (IVD_MEM_ALLOC_FAILED == (s_dec_op.u4_error_code & 0xFF));
    643             if (allocationFailed) {
    644                 ALOGE("Allocation failure in decoder");
    645                 notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
    646                 mSignalledError = true;
    647                 return;
    648             }
    649 
    650             bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF));
    651 
    652             getVUIParams();
    653 
    654             GETTIME(&mTimeEnd, NULL);
    655             /* Compute time taken for decode() */
    656             TIME_DIFF(mTimeStart, mTimeEnd, timeTaken);
    657 
    658             PRINT_TIME("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay,
    659                    s_dec_op.u4_num_bytes_consumed);
    660             if (s_dec_op.u4_frame_decoded_flag && !mFlushNeeded) {
    661                 mFlushNeeded = true;
    662             }
    663 
    664             if ((inHeader != NULL) && (1 != s_dec_op.u4_frame_decoded_flag)) {
    665                 /* If the input did not contain picture data, then ignore
    666                  * the associated timestamp */
    667                 mTimeStampsValid[timeStampIx] = false;
    668             }
    669 
    670             // If the decoder is in the changing resolution mode and there is no output present,
    671             // that means the switching is done and it's ready to reset the decoder and the plugin.
    672             if (mChangingResolution && !s_dec_op.u4_output_present) {
    673                 mChangingResolution = false;
    674                 resetDecoder();
    675                 resetPlugin();
    676                 mStride = outputBufferWidth();
    677                 setParams(mStride);
    678                 continue;
    679             }
    680 
    681             if (resChanged) {
    682                 mChangingResolution = true;
    683                 if (mFlushNeeded) {
    684                     setFlushMode();
    685                 }
    686                 continue;
    687             }
    688 
    689             // Combine the resolution change and coloraspects change in one PortSettingChange event
    690             // if necessary.
    691             if ((0 < s_dec_op.u4_pic_wd) && (0 < s_dec_op.u4_pic_ht)) {
    692                 uint32_t width = s_dec_op.u4_pic_wd;
    693                 uint32_t height = s_dec_op.u4_pic_ht;
    694                 bool portWillReset = false;
    695                 handlePortSettingsChange(&portWillReset, width, height);
    696                 if (portWillReset) {
    697                     resetDecoder();
    698                     return;
    699                 }
    700             } else if (mUpdateColorAspects) {
    701                 notify(OMX_EventPortSettingsChanged, kOutputPortIndex,
    702                     kDescribeColorAspectsIndex, NULL);
    703                 mUpdateColorAspects = false;
    704                 return;
    705             }
    706 
    707             if (s_dec_op.u4_output_present) {
    708                 outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2;
    709 
    710                 outHeader->nTimeStamp = mTimeStamps[s_dec_op.u4_ts];
    711                 mTimeStampsValid[s_dec_op.u4_ts] = false;
    712 
    713                 outInfo->mOwnedByUs = false;
    714                 outQueue.erase(outQueue.begin());
    715                 outInfo = NULL;
    716                 notifyFillBufferDone(outHeader);
    717                 outHeader = NULL;
    718             } else if (mIsInFlush) {
    719                 /* If in flush mode and no output is returned by the codec,
    720                  * then come out of flush mode */
    721                 mIsInFlush = false;
    722 
    723                 /* If EOS was recieved on input port and there is no output
    724                  * from the codec, then signal EOS on output port */
    725                 if (mReceivedEOS) {
    726                     outHeader->nFilledLen = 0;
    727                     outHeader->nFlags |= OMX_BUFFERFLAG_EOS;
    728 
    729                     outInfo->mOwnedByUs = false;
    730                     outQueue.erase(outQueue.begin());
    731                     outInfo = NULL;
    732                     notifyFillBufferDone(outHeader);
    733                     outHeader = NULL;
    734                     resetPlugin();
    735                 }
    736             }
    737         }
    738 
    739         /* If input EOS is seen and decoder is not in flush mode,
    740          * set the decoder in flush mode.
    741          * There can be a case where EOS is sent along with last picture data
    742          * In that case, only after decoding that input data, decoder has to be
    743          * put in flush. This case is handled here  */
    744 
    745         if (mReceivedEOS && !mIsInFlush) {
    746             setFlushMode();
    747         }
    748 
    749         if (inHeader != NULL) {
    750             inInfo->mOwnedByUs = false;
    751             inQueue.erase(inQueue.begin());
    752             inInfo = NULL;
    753             notifyEmptyBufferDone(inHeader);
    754             inHeader = NULL;
    755         }
    756     }
    757 }
    758 
    759 int SoftAVC::getColorAspectPreference() {
    760     return kPreferBitstream;
    761 }
    762 
    763 }  // namespace android
    764 
    765 android::SoftOMXComponent *createSoftOMXComponent(
    766         const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
    767         OMX_COMPONENTTYPE **component) {
    768     return new android::SoftAVC(name, callbacks, appData, component);
    769 }
    770