Home | History | Annotate | Download | only in videocodec
      1 /*
      2 * Copyright (c) 2009-2011 Intel Corporation.  All rights reserved.
      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 
     18 // #define LOG_NDEBUG 0
     19 #define LOG_TAG "OMXVideoDecoder"
     20 #include <wrs_omxil_core/log.h>
     21 #include "OMXVideoDecoderAVC.h"
     22 
     23 
     24 // Be sure to have an equal string in VideoDecoderHost.cpp (libmix)
     25 static const char* AVC_MIME_TYPE = "video/h264";
     26 #define INVALID_PTS (OMX_S64)-1
     27 
     28 
     29 OMXVideoDecoderAVC::OMXVideoDecoderAVC()
     30     : mAccumulateBuffer(NULL),
     31       mBufferSize(0),
     32       mFilledLen(0),
     33       mTimeStamp(INVALID_PTS) {
     34     LOGV("OMXVideoDecoderAVC is constructed.");
     35     mVideoDecoder = createVideoDecoder(AVC_MIME_TYPE);
     36     if (!mVideoDecoder) {
     37         LOGE("createVideoDecoder failed for \"%s\"", AVC_MIME_TYPE);
     38     }
     39     // Override default native buffer count defined in the base class
     40     mNativeBufferCount = OUTPORT_NATIVE_BUFFER_COUNT;
     41     BuildHandlerList();
     42 }
     43 
     44 OMXVideoDecoderAVC::~OMXVideoDecoderAVC() {
     45     LOGV("OMXVideoDecoderAVC is destructed.");
     46 }
     47 
     48 OMX_ERRORTYPE OMXVideoDecoderAVC::InitInputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput) {
     49     //OMX_VIDEO_PARAM_INTEL_AVC_DECODE_SETTINGS
     50     memset(&mDecodeSettings, 0, sizeof(mDecodeSettings));
     51     SetTypeHeader(&mDecodeSettings, sizeof(mDecodeSettings));
     52     mDecodeSettings.nMaxNumberOfReferenceFrame = NUM_REFERENCE_FRAME;
     53 
     54     // OMX_PARAM_PORTDEFINITIONTYPE
     55     paramPortDefinitionInput->nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT;
     56     paramPortDefinitionInput->nBufferCountMin = INPORT_MIN_BUFFER_COUNT;
     57     paramPortDefinitionInput->nBufferSize = INPORT_BUFFER_SIZE;
     58     paramPortDefinitionInput->format.video.cMIMEType = (OMX_STRING)AVC_MIME_TYPE;
     59     paramPortDefinitionInput->format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
     60 
     61     // OMX_VIDEO_PARAM_AVCTYPE
     62     memset(&mParamAvc, 0, sizeof(mParamAvc));
     63     SetTypeHeader(&mParamAvc, sizeof(mParamAvc));
     64     mParamAvc.nPortIndex = INPORT_INDEX;
     65     // TODO: check eProfile/eLevel
     66     mParamAvc.eProfile = OMX_VIDEO_AVCProfileHigh; //OMX_VIDEO_AVCProfileBaseline;
     67     mParamAvc.eLevel = OMX_VIDEO_AVCLevel41; //OMX_VIDEO_AVCLevel1;
     68 
     69     return OMX_ErrorNone;
     70 }
     71 
     72 OMX_ERRORTYPE OMXVideoDecoderAVC::ProcessorInit(void) {
     73     return OMXVideoDecoderBase::ProcessorInit();
     74 }
     75 
     76 OMX_ERRORTYPE OMXVideoDecoderAVC::ProcessorDeinit(void) {
     77     if (mAccumulateBuffer) {
     78         delete mAccumulateBuffer;
     79     }
     80     mAccumulateBuffer = NULL;
     81     mBufferSize = 0;
     82     mFilledLen = 0;
     83     mTimeStamp = INVALID_PTS;
     84 
     85     return OMXVideoDecoderBase::ProcessorDeinit();
     86 }
     87 
     88 OMX_ERRORTYPE OMXVideoDecoderAVC::ProcessorFlush(OMX_U32 portIndex) {
     89     mFilledLen = 0;
     90     mTimeStamp = INVALID_PTS;
     91     return OMXVideoDecoderBase::ProcessorFlush(portIndex);
     92 }
     93 
     94 OMX_ERRORTYPE OMXVideoDecoderAVC::ProcessorProcess(
     95         OMX_BUFFERHEADERTYPE ***pBuffers,
     96         buffer_retain_t *retains,
     97         OMX_U32 numberBuffers) {
     98 
     99     return OMXVideoDecoderBase::ProcessorProcess(pBuffers, retains, numberBuffers);
    100 }
    101 
    102 OMX_ERRORTYPE OMXVideoDecoderAVC::PrepareConfigBuffer(VideoConfigBuffer *p) {
    103     OMX_ERRORTYPE ret;
    104 
    105     ret = OMXVideoDecoderBase::PrepareConfigBuffer(p);
    106     CHECK_RETURN_VALUE("OMXVideoDecoderBase::PrepareConfigBuffer");
    107 
    108     if (mParamAvc.eProfile == OMX_VIDEO_AVCProfileBaseline) {
    109         p->flag |= WANT_LOW_DELAY;
    110     }
    111 
    112     if (mDecodeSettings.nMaxWidth == 0 ||
    113         mDecodeSettings.nMaxHeight == 0) {
    114         return OMX_ErrorNone;
    115     }
    116 
    117     LOGW("AVC Video decoder used in Video Conferencing Mode.");
    118 
    119     // For video conferencing application
    120     p->width = mDecodeSettings.nMaxWidth;
    121     p->height = mDecodeSettings.nMaxHeight;
    122     p->profile = VAProfileH264ConstrainedBaseline;
    123     if(!(p->flag & USE_NATIVE_GRAPHIC_BUFFER)) {
    124         p->surfaceNumber = mDecodeSettings.nMaxNumberOfReferenceFrame + EXTRA_REFERENCE_FRAME;
    125         p->flag = WANT_ERROR_CONCEALMENT | WANT_LOW_DELAY | HAS_SURFACE_NUMBER | HAS_VA_PROFILE;
    126     } else {
    127         p->flag |= WANT_ERROR_CONCEALMENT | WANT_LOW_DELAY | HAS_SURFACE_NUMBER | HAS_VA_PROFILE;
    128     }
    129 
    130     return OMX_ErrorNone;
    131 }
    132 
    133 OMX_ERRORTYPE OMXVideoDecoderAVC::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) {
    134     OMX_ERRORTYPE ret;
    135     ret = OMXVideoDecoderBase::PrepareDecodeBuffer(buffer, retain, p);
    136     CHECK_RETURN_VALUE("OMXVideoDecoderBase::PrepareDecodeBuffer");
    137 
    138     // OMX_BUFFERFLAG_CODECCONFIG is an optional flag
    139     // if flag is set, buffer will only contain codec data.
    140     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
    141         LOGV("Received AVC codec data.");
    142         return ret;
    143     }
    144 
    145     // OMX_BUFFERFLAG_ENDOFFRAME is an optional flag
    146     if (buffer->nFlags & (OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS)) {
    147         // TODO: if OMX_BUFFERFLAG_ENDOFFRAME indicates end of a NAL unit and in OMXVideoDecodeBase
    148         // we set buffer flag to HAS_COMPLETE_FRAME,  corruption will happen
    149         mTimeStamp = buffer->nTimeStamp;
    150         if (mFilledLen == 0) {
    151             // buffer is not accumulated and it contains a complete frame
    152             return ret;
    153         }
    154         // buffer contains  the last part of fragmented frame
    155         ret = AccumulateBuffer(buffer);
    156         CHECK_RETURN_VALUE("AccumulateBuffer");
    157         ret = FillDecodeBuffer(p);
    158         CHECK_RETURN_VALUE("FillDecodeBuffer");
    159         return ret;
    160     }
    161 
    162     LOGW("Received fragmented buffer.");
    163     // use time stamp to determine frame boundary
    164     if (mTimeStamp == INVALID_PTS) {
    165         // first ever buffer
    166         mTimeStamp = buffer->nTimeStamp;
    167     }
    168 
    169     if (mTimeStamp != buffer->nTimeStamp && mFilledLen != 0) {
    170         // buffer accumulated contains a complete frame
    171         ret = FillDecodeBuffer(p);
    172         CHECK_RETURN_VALUE("FillDecodeBuffer");
    173         // retain the current buffer
    174         *retain = BUFFER_RETAIN_GETAGAIN;
    175     } else {
    176         // buffer accumulation for beginning of fragmented buffer (mFilledLen == 0) or
    177         // middle/end of fragmented buffer (mFilledLen != 0)
    178         ret = AccumulateBuffer(buffer);
    179         CHECK_RETURN_VALUE("AccumulateBuffer");
    180         ret = OMX_ErrorNotReady;
    181     }
    182 
    183     if (buffer->nFilledLen != 0) {
    184         mTimeStamp = buffer->nTimeStamp;
    185     }
    186     return ret;
    187 }
    188 
    189 OMX_ERRORTYPE OMXVideoDecoderAVC::AccumulateBuffer(OMX_BUFFERHEADERTYPE *buffer) {
    190     // check if allocated buffer is big enough
    191     if (mFilledLen + buffer->nFilledLen > mBufferSize) {
    192         mBufferSize = mFilledLen + buffer->nFilledLen;
    193         if (mBufferSize < INPORT_BUFFER_SIZE) {
    194             mBufferSize = INPORT_BUFFER_SIZE;
    195         }
    196         if (mBufferSize == 0) {
    197             return OMX_ErrorBadParameter;
    198         }
    199         OMX_U8 *temp = new OMX_U8 [mBufferSize];
    200         if (temp == NULL) {
    201             mBufferSize = 0;
    202             return OMX_ErrorInsufficientResources;
    203         }
    204         if (mFilledLen != 0) {
    205             memcpy(temp, mAccumulateBuffer, mFilledLen);
    206         }
    207         if (mAccumulateBuffer) {
    208             delete [] mAccumulateBuffer;
    209         }
    210         mAccumulateBuffer = temp;
    211     }
    212     if (buffer->nFilledLen != 0) {
    213         memcpy(mAccumulateBuffer + mFilledLen, buffer->pBuffer + buffer->nOffset, buffer->nFilledLen);
    214     }
    215     mFilledLen += buffer->nFilledLen;
    216     return OMX_ErrorNone;
    217 }
    218 
    219 OMX_ERRORTYPE OMXVideoDecoderAVC::FillDecodeBuffer(VideoDecodeBuffer *p) {
    220     p->data = mAccumulateBuffer;
    221     p->size = mFilledLen;
    222     p->timeStamp = mTimeStamp;
    223     p->flag = HAS_COMPLETE_FRAME;
    224 
    225     mFilledLen = 0;
    226     return OMX_ErrorNone;
    227 }
    228 
    229 OMX_ERRORTYPE OMXVideoDecoderAVC::BuildHandlerList(void) {
    230     OMXVideoDecoderBase::BuildHandlerList();
    231     AddHandler(OMX_IndexParamVideoAvc, GetParamVideoAvc, SetParamVideoAvc);
    232     AddHandler((OMX_INDEXTYPE)OMX_IndexParamIntelAVCDecodeSettings, GetParamIntelAVCDecodeSettings, SetParamIntelAVCDecodeSettings);
    233     AddHandler(OMX_IndexParamVideoProfileLevelQuerySupported, GetParamVideoAVCProfileLevel, SetParamVideoAVCProfileLevel);
    234     return OMX_ErrorNone;
    235 }
    236 
    237 OMX_ERRORTYPE OMXVideoDecoderAVC::GetParamVideoAvc(OMX_PTR pStructure) {
    238     OMX_ERRORTYPE ret;
    239     OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure;
    240     CHECK_TYPE_HEADER(p);
    241     CHECK_PORT_INDEX(p, INPORT_INDEX);
    242 
    243     memcpy(p, &mParamAvc, sizeof(*p));
    244     return OMX_ErrorNone;
    245 }
    246 
    247 OMX_ERRORTYPE OMXVideoDecoderAVC::SetParamVideoAvc(OMX_PTR pStructure) {
    248     OMX_ERRORTYPE ret;
    249     OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure;
    250     CHECK_TYPE_HEADER(p);
    251     CHECK_PORT_INDEX(p, INPORT_INDEX);
    252     CHECK_SET_PARAM_STATE();
    253 
    254     // TODO: do we need to check if port is enabled?
    255     // TODO: see SetPortAvcParam implementation - Can we make simple copy????
    256     memcpy(&mParamAvc, p, sizeof(mParamAvc));
    257 
    258     return OMX_ErrorNone;
    259 }
    260 
    261 OMX_ERRORTYPE OMXVideoDecoderAVC::GetParamIntelAVCDecodeSettings(OMX_PTR) {
    262     return OMX_ErrorNotImplemented;
    263 }
    264 
    265 OMX_ERRORTYPE OMXVideoDecoderAVC::SetParamIntelAVCDecodeSettings(OMX_PTR pStructure) {
    266     LOGW("SetParamIntelAVCDecodeSettings");
    267 
    268     OMX_ERRORTYPE ret;
    269     OMX_VIDEO_PARAM_INTEL_AVC_DECODE_SETTINGS *p = (OMX_VIDEO_PARAM_INTEL_AVC_DECODE_SETTINGS *)pStructure;
    270 
    271     CHECK_TYPE_HEADER(p);
    272     CHECK_PORT_INDEX(p, INPORT_INDEX);
    273     CHECK_SET_PARAM_STATE();
    274 
    275     if(p->nMaxNumberOfReferenceFrame == 0) {
    276         // TODO: check if we just return in this case.
    277         p->nMaxNumberOfReferenceFrame = NUM_REFERENCE_FRAME;
    278     }
    279     LOGI("Maximum width = %u, height = %u, dpb = %u", p->nMaxWidth, p->nMaxHeight, p->nMaxNumberOfReferenceFrame);
    280     mDecodeSettings = *p;
    281 
    282     return OMX_ErrorNone;
    283 }
    284 
    285 OMX_ERRORTYPE OMXVideoDecoderAVC::GetParamVideoAVCProfileLevel(OMX_PTR pStructure) {
    286     OMX_ERRORTYPE ret;
    287     OMX_VIDEO_PARAM_PROFILELEVELTYPE *p = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pStructure;
    288     CHECK_TYPE_HEADER(p);
    289     CHECK_PORT_INDEX(p, INPORT_INDEX);
    290 
    291     struct ProfileLevelTable {
    292         OMX_U32 profile;
    293         OMX_U32 level;
    294     } plTable[] = {
    295         {OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel42},
    296         {OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel42},
    297         {OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel42}
    298     };
    299 
    300     OMX_U32 count = sizeof(plTable)/sizeof(ProfileLevelTable);
    301     CHECK_ENUMERATION_RANGE(p->nProfileIndex,count);
    302 
    303     p->eProfile = plTable[p->nProfileIndex].profile;
    304     p->eLevel = plTable[p->nProfileIndex].level;
    305 
    306     return OMX_ErrorNone;
    307 }
    308 
    309 OMX_ERRORTYPE OMXVideoDecoderAVC::SetParamVideoAVCProfileLevel(OMX_PTR) {
    310     LOGW("SetParamVideoAVCProfileLevel is not supported.");
    311     return OMX_ErrorUnsupportedSetting;
    312 }
    313 
    314 OMX_COLOR_FORMATTYPE OMXVideoDecoderAVC::GetOutputColorFormat(int width)
    315 {
    316 #ifdef USE_GEN_HW
    317     return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled;
    318 #else
    319     return OMXVideoDecoderBase::GetOutputColorFormat(width);
    320 #endif
    321 }
    322 
    323 OMX_ERRORTYPE OMXVideoDecoderAVC::SetMaxOutputBufferCount(OMX_PARAM_PORTDEFINITIONTYPE *p) {
    324     OMX_ERRORTYPE ret;
    325     CHECK_TYPE_HEADER(p);
    326     CHECK_PORT_INDEX(p, OUTPORT_INDEX);
    327 
    328     p->nBufferCountActual = MAX_OUTPORT_BUFFER_COUNT;
    329     return OMXVideoDecoderBase::SetMaxOutputBufferCount(p);
    330 }
    331 
    332 DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.AVC", "video_decoder.avc", OMXVideoDecoderAVC);
    333