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