1 /* 2 * Copyright (c) 2012 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 #define LOG_TIME 0 18 //#define LOG_NDEBUG 0 19 #define LOG_TAG "OMXVideoDecoderVP9Hybrid" 20 #include <wrs_omxil_core/log.h> 21 #include "OMXVideoDecoderVP9Hybrid.h" 22 23 #include <hardware/hardware.h> 24 #include <hardware/gralloc.h> 25 #include <system/graphics.h> 26 27 #include <hal_public.h> 28 29 #define VP9_YV12_ALIGN (128-1) 30 static const char* VP9_MIME_TYPE = "video/x-vnd.on2.vp9"; 31 32 OMXVideoDecoderVP9Hybrid::OMXVideoDecoderVP9Hybrid() { 33 LOGV("OMXVideoDecoderVP9Hybrid is constructed."); 34 mNativeBufferCount = OUTPORT_NATIVE_BUFFER_COUNT; 35 BuildHandlerList(); 36 mLibHandle = NULL; 37 mOpenDecoder = NULL; 38 mInitDecoder = NULL; 39 mCloseDecoder = NULL; 40 mSingalRenderDone = NULL; 41 mDecoderDecode = NULL; 42 mCheckBufferAvailable = NULL; 43 mGetOutput = NULL; 44 mGetRawDataOutput = NULL; 45 mGetFrameResolution = NULL; 46 mDeinitDecoder = NULL; 47 mLastTimeStamp = 0; 48 mWorkingMode = RAWDATA_MODE; 49 mDecodedImageWidth = 0; 50 mDecodedImageHeight = 0; 51 mDecodedImageNewWidth = 0; 52 mDecodedImageNewHeight = 0; 53 } 54 55 OMXVideoDecoderVP9Hybrid::~OMXVideoDecoderVP9Hybrid() { 56 LOGV("OMXVideoDecoderVP9Hybrid is destructed."); 57 } 58 59 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::InitInputPortFormatSpecific( 60 OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput) { 61 // OMX_PARAM_PORTDEFINITIONTYPE 62 paramPortDefinitionInput->nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT; 63 paramPortDefinitionInput->nBufferCountMin = INPORT_MIN_BUFFER_COUNT; 64 paramPortDefinitionInput->nBufferSize = INPORT_BUFFER_SIZE; 65 paramPortDefinitionInput->format.video.cMIMEType = (OMX_STRING)VP9_MIME_TYPE; 66 paramPortDefinitionInput->format.video.eCompressionFormat = OMX_VIDEO_CodingVP9; 67 return OMX_ErrorNone; 68 } 69 70 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorInit(void) { 71 uint32_t buff[MAX_GRAPHIC_BUFFER_NUM]; 72 uint32_t i, bufferCount; 73 bool gralloc_mode = (mWorkingMode == GRAPHICBUFFER_MODE); 74 uint32_t bufferSize, bufferHStride, bufferHeight, bufferVStride, bufferWidth; 75 if (!gralloc_mode) { 76 bufferHStride = 1920; 77 bufferVStride = 1088; 78 bufferWidth = 1920; 79 bufferHeight = 1080; 80 bufferCount = 12; 81 } else { 82 if (mAPMode == METADATA_MODE) { 83 const OMX_PARAM_PORTDEFINITIONTYPE *def_output = this->ports[OUTPORT_INDEX]->GetPortDefinition(); 84 if (def_output == NULL) { 85 return OMX_ErrorBadParameter; 86 } 87 bufferCount = mMetaDataBuffersNum = def_output->nBufferCountActual; 88 mOMXBufferHeaderTypePtrNum = 0; 89 90 mGraphicBufferParam.graphicBufferColorFormat = def_output->format.video.eColorFormat; 91 mGraphicBufferParam.graphicBufferHStride = (def_output->format.video.nFrameWidth + VP9_YV12_ALIGN) & ~VP9_YV12_ALIGN; 92 mGraphicBufferParam.graphicBufferVStride = (def_output->format.video.nFrameHeight + 0x1f) & ~0x1f; 93 mGraphicBufferParam.graphicBufferWidth = def_output->format.video.nFrameWidth; 94 mGraphicBufferParam.graphicBufferHeight = def_output->format.video.nFrameHeight; 95 mDecodedImageWidth = def_output->format.video.nFrameWidth; 96 mDecodedImageHeight = def_output->format.video.nFrameHeight; 97 } else{ 98 bufferCount = mOMXBufferHeaderTypePtrNum; 99 100 for (i = 0; i < bufferCount; i++ ) { 101 OMX_BUFFERHEADERTYPE *buf_hdr = mOMXBufferHeaderTypePtrArray[i]; 102 buff[i] = (uint32_t)(buf_hdr->pBuffer); 103 } 104 } 105 106 bufferHStride = mGraphicBufferParam.graphicBufferHStride; 107 bufferVStride = mGraphicBufferParam.graphicBufferVStride; 108 bufferWidth = mGraphicBufferParam.graphicBufferWidth; 109 bufferHeight = mGraphicBufferParam.graphicBufferHeight; 110 } 111 112 bufferSize = bufferHStride * bufferVStride * 1.5; 113 114 mLibHandle = dlopen("libDecoderVP9Hybrid.so", RTLD_NOW); 115 if (mLibHandle == NULL) { 116 LOGE("dlopen libDecoderVP9Hybrid.so fail\n"); 117 return OMX_ErrorBadParameter; 118 } else { 119 LOGI("dlopen libDecoderVP9Hybrid.so successfully\n"); 120 } 121 mOpenDecoder = (OpenFunc)dlsym(mLibHandle, "Decoder_Open"); 122 mCloseDecoder = (CloseFunc)dlsym(mLibHandle, "Decoder_Close"); 123 mInitDecoder = (InitFunc)dlsym(mLibHandle, "Decoder_Init"); 124 mSingalRenderDone = (SingalRenderDoneFunc)dlsym(mLibHandle, "Decoder_SingalRenderDone"); 125 mDecoderDecode = (DecodeFunc)dlsym(mLibHandle, "Decoder_Decode"); 126 mCheckBufferAvailable = (IsBufferAvailableFunc)dlsym(mLibHandle, "Decoder_IsBufferAvailable"); 127 mGetOutput = (GetOutputFunc)dlsym(mLibHandle, "Decoder_GetOutput"); 128 mGetRawDataOutput = (GetRawDataOutputFunc)dlsym(mLibHandle, "Decoder_GetRawDataOutput"); 129 mGetFrameResolution = (GetFrameResolutionFunc)dlsym(mLibHandle, "Decoder_GetFrameResolution"); 130 mDeinitDecoder = (DeinitFunc)dlsym(mLibHandle, "Decoder_Deinit"); 131 if (mOpenDecoder == NULL || mCloseDecoder == NULL 132 || mInitDecoder == NULL || mSingalRenderDone == NULL 133 || mDecoderDecode == NULL || mCheckBufferAvailable == NULL 134 || mGetOutput == NULL || mGetRawDataOutput == NULL 135 || mGetFrameResolution == NULL || mDeinitDecoder == NULL) { 136 return OMX_ErrorBadParameter; 137 } 138 139 if (mOpenDecoder(&mCtx,&mHybridCtx) == false) { 140 LOGE("open hybrid Decoder fail\n"); 141 return OMX_ErrorBadParameter; 142 } 143 144 // FIXME: The proprietary part of the vp9hybrid decoder should be updated 145 // to take VStride as well as Height. For now it's convenient to 146 // use VStride as that was effectively what was done before.. 147 mInitDecoder(mHybridCtx, bufferSize, bufferHStride, bufferWidth, 148 bufferHeight, bufferCount, gralloc_mode, buff, (uint32_t)mAPMode); 149 return OMX_ErrorNone; 150 } 151 152 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorReset(void) 153 { 154 uint32_t buff[MAX_GRAPHIC_BUFFER_NUM]; 155 uint32_t i, bufferCount; 156 bool gralloc_mode = (mWorkingMode == GRAPHICBUFFER_MODE); 157 uint32_t bufferSize, bufferHStride, bufferHeight, bufferVStride, bufferWidth; 158 if (!gralloc_mode) { 159 bufferHStride = mDecodedImageWidth; 160 bufferVStride = mDecodedImageHeight; 161 bufferWidth = mDecodedImageWidth; 162 bufferHeight = mDecodedImageHeight; 163 bufferSize = bufferHStride * bufferVStride * 1.5; 164 bufferCount = 12; 165 } else { 166 if (mAPMode == METADATA_MODE) { 167 const OMX_PARAM_PORTDEFINITIONTYPE *def_output = this->ports[OUTPORT_INDEX]->GetPortDefinition(); 168 if (def_output == NULL) { 169 return OMX_ErrorBadParameter; 170 } 171 bufferCount = mMetaDataBuffersNum = def_output->nBufferCountActual; 172 mOMXBufferHeaderTypePtrNum = 0; 173 174 mGraphicBufferParam.graphicBufferColorFormat = def_output->format.video.eColorFormat; 175 mGraphicBufferParam.graphicBufferHStride = (def_output->format.video.nFrameWidth + VP9_YV12_ALIGN) & ~VP9_YV12_ALIGN; 176 mGraphicBufferParam.graphicBufferVStride = (def_output->format.video.nFrameHeight + 0x1f) & ~0x1f; 177 mGraphicBufferParam.graphicBufferWidth = def_output->format.video.nFrameWidth; 178 mGraphicBufferParam.graphicBufferHeight = def_output->format.video.nFrameHeight; 179 } else{ 180 bufferCount = mOMXBufferHeaderTypePtrNum; 181 182 for (i = 0; i < bufferCount; i++ ) { 183 OMX_BUFFERHEADERTYPE *buf_hdr = mOMXBufferHeaderTypePtrArray[i]; 184 buff[i] = (uint32_t)(buf_hdr->pBuffer); 185 } 186 } 187 bufferHStride = mGraphicBufferParam.graphicBufferHStride; 188 bufferVStride = mGraphicBufferParam.graphicBufferVStride; 189 bufferWidth = mGraphicBufferParam.graphicBufferWidth; 190 bufferHeight = mGraphicBufferParam.graphicBufferHeight; 191 } 192 193 bufferSize = bufferHStride * bufferVStride * 1.5; 194 195 // FIXME: The proprietary part of the vp9hybrid decoder should be updated 196 // to take VStride as well as Height. For now it's convenient to 197 // use VStride as that was effectively what was done before.. 198 mInitDecoder(mHybridCtx, bufferSize, bufferHStride, bufferWidth, 199 bufferHeight, bufferCount, gralloc_mode, buff, (uint32_t)mAPMode); 200 mFormatChanged = false; 201 return OMX_ErrorNone; 202 } 203 204 bool OMXVideoDecoderVP9Hybrid::isReallocateNeeded(const uint8_t * data,uint32_t data_sz) 205 { 206 bool gralloc_mode = (mWorkingMode == GRAPHICBUFFER_MODE); 207 uint32_t width, height; 208 bool ret = true; 209 if (gralloc_mode) { 210 ret = mGetFrameResolution(data,data_sz, &width, &height); 211 if (width == 0 || height == 0) 212 return false; 213 214 if (ret) { 215 if (mAPMode == METADATA_MODE) { 216 ret = (width != mDecodedImageWidth) 217 || (height != mDecodedImageHeight); 218 } else { 219 ret = width > mGraphicBufferParam.graphicBufferWidth 220 || height > mGraphicBufferParam.graphicBufferHeight; 221 } 222 if (ret) { 223 mDecodedImageNewWidth = width; 224 mDecodedImageNewHeight = height; 225 return true; 226 } 227 } 228 } 229 230 return ret; 231 } 232 233 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorDeinit(void) { 234 mCloseDecoder(mCtx,mHybridCtx); 235 mOMXBufferHeaderTypePtrNum = 0; 236 if (mLibHandle != NULL) { 237 dlclose(mLibHandle); 238 mLibHandle = NULL; 239 } 240 return OMX_ErrorNone; 241 } 242 243 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorStop(void) { 244 return OMXComponentCodecBase::ProcessorStop(); 245 } 246 247 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorFlush(OMX_U32 portIndex) { 248 if (portIndex == INPORT_INDEX || portIndex == OMX_ALL) { 249 // end the last frame 250 unsigned int width, height; 251 mDecoderDecode(mCtx,mHybridCtx,NULL,0,true); 252 mGetOutput(mCtx,mHybridCtx, &width, &height); 253 } 254 return OMX_ErrorNone; 255 } 256 257 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE* buffer) { 258 if (buffer->nOutputPortIndex == OUTPORT_INDEX){ 259 unsigned int handle; 260 if (mAPMode == METADATA_MODE) { 261 bool found = false; 262 if (mOMXBufferHeaderTypePtrNum < mMetaDataBuffersNum) { 263 for (uint32_t i = 0; i < mOMXBufferHeaderTypePtrNum; i++) { 264 if (mOMXBufferHeaderTypePtrArray[i] == buffer) { 265 found = true; 266 break; 267 } 268 } 269 if (!found) { 270 mOMXBufferHeaderTypePtrArray[mOMXBufferHeaderTypePtrNum] = buffer; 271 mOMXBufferHeaderTypePtrNum++; 272 } 273 } else { 274 found = true; 275 } 276 277 android::VideoGrallocMetadata *metadata = (android::VideoGrallocMetadata *)(buffer->pBuffer); 278 handle = (unsigned int)metadata->pHandle; 279 mSingalRenderDone(mHybridCtx, handle, !found); 280 } else { 281 handle = (unsigned int)buffer->pBuffer; 282 mSingalRenderDone(mHybridCtx, handle, false); 283 } 284 } 285 return OMX_ErrorNone; 286 } 287 288 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorProcess( 289 OMX_BUFFERHEADERTYPE ***pBuffers, 290 buffer_retain_t *retains, 291 OMX_U32) 292 { 293 OMX_ERRORTYPE ret; 294 OMX_BUFFERHEADERTYPE *inBuffer = *pBuffers[INPORT_INDEX]; 295 OMX_BUFFERHEADERTYPE *outBuffer = *pBuffers[OUTPORT_INDEX]; 296 OMX_BOOL isResolutionChange = OMX_FALSE; 297 bool eos = (inBuffer->nFlags & OMX_BUFFERFLAG_EOS)? true : false; 298 eos = eos && (inBuffer->nFilledLen == 0); 299 static unsigned char *firstFrame = NULL; 300 static uint32_t firstFrameSize = 0; 301 302 if (inBuffer->pBuffer == NULL) { 303 LOGE("Buffer to decode is empty."); 304 return OMX_ErrorBadParameter; 305 } 306 307 if (inBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 308 LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag."); 309 } 310 311 if (inBuffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) { 312 LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag."); 313 } 314 315 if (firstFrameSize == 0 && inBuffer->nFilledLen != 0 && inBuffer->nTimeStamp != 0) { 316 if (firstFrame != NULL) { 317 free(firstFrame); 318 firstFrame = NULL; 319 } 320 321 firstFrame = (unsigned char *)malloc(inBuffer->nFilledLen); 322 memcpy(firstFrame, inBuffer->pBuffer + inBuffer->nOffset, inBuffer->nFilledLen); 323 firstFrameSize = inBuffer->nFilledLen; 324 } 325 326 if ((mWorkingMode == GRAPHICBUFFER_MODE) && (mAPMode == METADATA_MODE) && (!mFormatChanged)) { 327 bool mRet = mGetFrameResolution(inBuffer->pBuffer + inBuffer->nOffset, inBuffer->nFilledLen, 328 &mDecodedImageNewWidth,&mDecodedImageNewHeight); 329 330 if (mRet && ((mDecodedImageNewWidth != 0) && (mDecodedImageNewHeight != 0)) && 331 ((mDecodedImageWidth != 0) && (mDecodedImageHeight != 0)) && 332 ((mDecodedImageNewWidth != mDecodedImageWidth || mDecodedImageNewHeight != mDecodedImageHeight))) { 333 if (mLastTimeStamp == 0) { 334 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 335 HandleFormatChange(); 336 return OMX_ErrorNone; 337 } else { 338 // Detected format change in time. 339 // drain the last frame, keep the current input buffer 340 mDecoderDecode(mCtx, mHybridCtx, firstFrame, firstFrameSize, false); 341 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 342 343 mFormatChanged = true; 344 345 ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX], 346 eos ? OMX_BUFFERFLAG_EOS : 0, &isResolutionChange); 347 348 if (ret == OMX_ErrorNone) 349 (*pBuffers[OUTPORT_INDEX])->nTimeStamp = mLastTimeStamp; 350 351 mLastTimeStamp = inBuffer->nTimeStamp; 352 353 free(firstFrame); 354 firstFrame = NULL; 355 firstFrameSize = 0; 356 return ret; 357 } 358 } else if (!mRet && (mDecodedImageNewWidth == 0 || mDecodedImageNewHeight == 0)) { 359 retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; 360 return OMX_ErrorBadParameter; 361 } 362 } 363 364 #if LOG_TIME == 1 365 struct timeval tv_start, tv_end; 366 int32_t time_ms; 367 gettimeofday(&tv_start,NULL); 368 #endif 369 int res = mDecoderDecode(mCtx,mHybridCtx,inBuffer->pBuffer + inBuffer->nOffset,inBuffer->nFilledLen, eos); 370 if (res != 0) { 371 if (res == -2) { 372 if (isReallocateNeeded(inBuffer->pBuffer + inBuffer->nOffset,inBuffer->nFilledLen)) { 373 if (mAPMode == METADATA_MODE) { 374 mFormatChanged = true; 375 } else { 376 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 377 HandleFormatChange(); 378 return OMX_ErrorNone; 379 } 380 } 381 // drain the last frame, keep the current input buffer 382 res = mDecoderDecode(mCtx,mHybridCtx,NULL,0,true); 383 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 384 } else if (res == -3) { 385 LOGW("on2 decoder skipped to decode the frame."); 386 (*pBuffers[OUTPORT_INDEX])->nOffset = 0; 387 (*pBuffers[OUTPORT_INDEX])->nFilledLen = 0; 388 return OMX_ErrorNone; 389 } else { 390 LOGE("on2 decoder failed to decode frame."); 391 return OMX_ErrorBadParameter; 392 } 393 } 394 395 #if LOG_TIME == 1 396 gettimeofday(&tv_end,NULL); 397 time_ms = (int32_t)(tv_end.tv_sec - tv_start.tv_sec) * 1000 + (int32_t)(tv_end.tv_usec - tv_start.tv_usec)/1000; 398 LOGI("vpx_codec_decode: %d ms", time_ms); 399 #endif 400 401 ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], 402 &retains[OUTPORT_INDEX], 403 eos? OMX_BUFFERFLAG_EOS:0, 404 &isResolutionChange); 405 406 if (ret == OMX_ErrorNone) { 407 (*pBuffers[OUTPORT_INDEX])->nTimeStamp = mLastTimeStamp; 408 } 409 mLastTimeStamp = inBuffer->nTimeStamp; 410 411 if (isResolutionChange == OMX_TRUE) { 412 HandleFormatChange(); 413 } 414 bool inputEoS = ((*pBuffers[INPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS); 415 bool outputEoS = ((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS); 416 // if output port is not eos, retain the input buffer 417 // until all the output buffers are drained. 418 if (inputEoS && !outputEoS && retains[INPORT_INDEX] != BUFFER_RETAIN_GETAGAIN) { 419 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 420 // the input buffer is retained for draining purpose. 421 // Set nFilledLen to 0 so buffer will not be decoded again. 422 (*pBuffers[INPORT_INDEX])->nFilledLen = 0; 423 } 424 425 if (ret == OMX_ErrorNotReady) { 426 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 427 ret = OMX_ErrorNone; 428 } 429 430 return ret; 431 } 432 433 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::FillRenderBuffer(OMX_BUFFERHEADERTYPE **pBuffer, 434 buffer_retain_t *retain, 435 OMX_U32 inportBufferFlags, 436 OMX_BOOL *isResolutionChange) 437 { 438 OMX_BUFFERHEADERTYPE *buffer = *pBuffer; 439 OMX_BUFFERHEADERTYPE *buffer_orign = buffer; 440 441 OMX_ERRORTYPE ret = OMX_ErrorNone; 442 443 int fb_index; 444 if (mWorkingMode == RAWDATA_MODE) { 445 const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionOutput 446 = this->ports[OUTPORT_INDEX]->GetPortDefinition(); 447 int32_t stride = paramPortDefinitionOutput->format.video.nStride; 448 int32_t height = paramPortDefinitionOutput->format.video.nFrameHeight; 449 int32_t width = paramPortDefinitionOutput->format.video.nFrameWidth; 450 unsigned char *dst = buffer->pBuffer; 451 fb_index = mGetRawDataOutput(mCtx,mHybridCtx,dst,height,stride); 452 if (fb_index == -1) { 453 if (inportBufferFlags & OMX_BUFFERFLAG_EOS) { 454 // eos frame is non-shown frame 455 buffer->nFlags = OMX_BUFFERFLAG_EOS; 456 buffer->nOffset = 0; 457 buffer->nFilledLen = 0; 458 return OMX_ErrorNone; 459 } 460 LOGV("vpx_codec_get_frame return NULL."); 461 return OMX_ErrorNotReady; 462 } 463 buffer->nOffset = 0; 464 buffer->nFilledLen = stride*height*3/2; 465 if (inportBufferFlags & OMX_BUFFERFLAG_EOS) { 466 buffer->nFlags = OMX_BUFFERFLAG_EOS; 467 } 468 return OMX_ErrorNone; 469 } 470 471 if (mFormatChanged && mAPMode == METADATA_MODE) { 472 fb_index = mGetOutput(mCtx,mHybridCtx, &mDecodedImageWidth, &mDecodedImageHeight); 473 } else { 474 fb_index = mGetOutput(mCtx,mHybridCtx, &mDecodedImageNewWidth, &mDecodedImageNewHeight); 475 } 476 if (fb_index == -1) { 477 if (mFormatChanged && mAPMode == METADATA_MODE) { 478 *isResolutionChange = OMX_TRUE; 479 return OMX_ErrorNone; 480 } 481 482 if (inportBufferFlags & OMX_BUFFERFLAG_EOS) { 483 // eos frame is no-shown frame 484 buffer->nFlags = OMX_BUFFERFLAG_EOS; 485 buffer->nOffset = 0; 486 buffer->nFilledLen = 0; 487 return OMX_ErrorNone; 488 } 489 LOGV("vpx_codec_get_frame return NULL."); 490 return OMX_ErrorNotReady; 491 } 492 if (mDecodedImageHeight == 0 && mDecodedImageWidth == 0) { 493 mDecodedImageWidth = mDecodedImageNewWidth; 494 mDecodedImageHeight = mDecodedImageNewHeight; 495 if (mAPMode == LEGACY_MODE) 496 *isResolutionChange = OMX_TRUE; 497 } 498 499 if (mAPMode == LEGACY_MODE) { 500 if ((mDecodedImageNewWidth != mDecodedImageWidth) 501 || (mDecodedImageNewHeight!= mDecodedImageHeight)) 502 *isResolutionChange = OMX_TRUE; 503 } else { 504 if (mFormatChanged && ((mDecodedImageNewWidth != mDecodedImageWidth) 505 || (mDecodedImageNewHeight!= mDecodedImageHeight))) 506 *isResolutionChange = OMX_TRUE; 507 } 508 buffer = *pBuffer = mOMXBufferHeaderTypePtrArray[fb_index]; 509 buffer->nOffset = 0; 510 buffer->nFilledLen = sizeof(OMX_U8*); 511 if (inportBufferFlags & OMX_BUFFERFLAG_EOS) { 512 buffer->nFlags = OMX_BUFFERFLAG_EOS; 513 } 514 515 if (buffer_orign != buffer) { 516 *retain = BUFFER_RETAIN_OVERRIDDEN; 517 } 518 519 ret = OMX_ErrorNone; 520 521 return ret; 522 523 } 524 525 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::PrepareConfigBuffer(VideoConfigBuffer *) { 526 return OMX_ErrorNone; 527 } 528 529 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *, 530 buffer_retain_t *, 531 VideoDecodeBuffer *) { 532 return OMX_ErrorNone; 533 } 534 535 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::BuildHandlerList(void) { 536 OMXVideoDecoderBase::BuildHandlerList(); 537 return OMX_ErrorNone; 538 } 539 540 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::GetParamVideoVp9(OMX_PTR) { 541 return OMX_ErrorNone; 542 } 543 544 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::SetParamVideoVp9(OMX_PTR) { 545 return OMX_ErrorNone; 546 } 547 548 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::HandleFormatChange(void) 549 { 550 ALOGE("handle format change from %dx%d to %dx%d", 551 mDecodedImageWidth,mDecodedImageHeight,mDecodedImageNewWidth,mDecodedImageNewHeight); 552 mDecodedImageWidth = mDecodedImageNewWidth; 553 mDecodedImageHeight = mDecodedImageNewHeight; 554 // Sync port definition as it may change. 555 OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput, paramPortDefinitionOutput; 556 557 memcpy(¶mPortDefinitionInput, 558 this->ports[INPORT_INDEX]->GetPortDefinition(), 559 sizeof(paramPortDefinitionInput)); 560 561 memcpy(¶mPortDefinitionOutput, 562 this->ports[OUTPORT_INDEX]->GetPortDefinition(), 563 sizeof(paramPortDefinitionOutput)); 564 565 unsigned int width = mDecodedImageWidth; 566 unsigned int height = mDecodedImageHeight; 567 unsigned int stride = mDecodedImageWidth; 568 unsigned int sliceHeight = mDecodedImageHeight; 569 570 unsigned int widthCropped = mDecodedImageWidth; 571 unsigned int heightCropped = mDecodedImageHeight; 572 unsigned int strideCropped = widthCropped; 573 unsigned int sliceHeightCropped = heightCropped; 574 575 if (widthCropped == paramPortDefinitionOutput.format.video.nFrameWidth && 576 heightCropped == paramPortDefinitionOutput.format.video.nFrameHeight) { 577 if (mWorkingMode == RAWDATA_MODE) { 578 LOGW("Change of portsetting is not reported as size is not changed."); 579 return OMX_ErrorNone; 580 } 581 } 582 583 if (mAPMode == METADATA_MODE) { 584 paramPortDefinitionOutput.nBufferCountActual = mNativeBufferCount; 585 paramPortDefinitionOutput.nBufferCountMin = mNativeBufferCount - 4; 586 } 587 paramPortDefinitionInput.format.video.nFrameWidth = width; 588 paramPortDefinitionInput.format.video.nFrameHeight = height; 589 paramPortDefinitionInput.format.video.nStride = stride; 590 paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight; 591 592 if (mWorkingMode == RAWDATA_MODE) { 593 paramPortDefinitionOutput.format.video.nFrameWidth = widthCropped; 594 paramPortDefinitionOutput.format.video.nFrameHeight = heightCropped; 595 paramPortDefinitionOutput.format.video.nStride = strideCropped; 596 paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeightCropped; 597 } else if (mWorkingMode == GRAPHICBUFFER_MODE) { 598 // when the width and height ES parse are not larger than allocated graphic buffer in outport, 599 // there is no need to reallocate graphic buffer,just report the crop info to omx client 600 if (mAPMode == LEGACY_MODE && 601 width <= mGraphicBufferParam.graphicBufferWidth && 602 height <= mGraphicBufferParam.graphicBufferHeight) { 603 this->ports[INPORT_INDEX]->SetPortDefinition(¶mPortDefinitionInput, true); 604 this->ports[OUTPORT_INDEX]->ReportOutputCrop(); 605 return OMX_ErrorNone; 606 } 607 608 if (mAPMode == METADATA_MODE || 609 width > mGraphicBufferParam.graphicBufferWidth || 610 height > mGraphicBufferParam.graphicBufferHeight) { 611 // update the real decoded resolution to outport instead of display resolution 612 // for graphic buffer reallocation 613 // when the width and height parsed from ES are larger than allocated graphic buffer in outport, 614 paramPortDefinitionOutput.format.video.nFrameWidth = width; 615 paramPortDefinitionOutput.format.video.nFrameHeight = height; 616 paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat( 617 paramPortDefinitionOutput.format.video.nFrameWidth); 618 paramPortDefinitionOutput.format.video.nStride = stride; 619 paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight; 620 } 621 } 622 623 paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false; 624 mOMXBufferHeaderTypePtrNum = 0; 625 mMetaDataBuffersNum = 0; 626 memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam)); 627 mDeinitDecoder(mHybridCtx); 628 629 this->ports[INPORT_INDEX]->SetPortDefinition(¶mPortDefinitionInput, true); 630 this->ports[OUTPORT_INDEX]->SetPortDefinition(¶mPortDefinitionOutput, true); 631 632 this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged(); 633 return OMX_ErrorNone; 634 } 635 636 637 OMX_COLOR_FORMATTYPE OMXVideoDecoderVP9Hybrid::GetOutputColorFormat(int) { 638 LOGV("Output color format is HAL_PIXEL_FORMAT_INTEL_YV12."); 639 return (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_INTEL_YV12; 640 } 641 642 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::GetDecoderOutputCropSpecific(OMX_PTR pStructure) { 643 644 OMX_ERRORTYPE ret = OMX_ErrorNone; 645 OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)pStructure; 646 647 CHECK_TYPE_HEADER(rectParams); 648 649 if (rectParams->nPortIndex != OUTPORT_INDEX) { 650 return OMX_ErrorUndefined; 651 } 652 653 const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput 654 = this->ports[INPORT_INDEX]->GetPortDefinition(); 655 656 rectParams->nLeft = VPX_DECODE_BORDER; 657 rectParams->nTop = VPX_DECODE_BORDER; 658 rectParams->nWidth = paramPortDefinitionInput->format.video.nFrameWidth; 659 rectParams->nHeight = paramPortDefinitionInput->format.video.nFrameHeight; 660 661 return ret; 662 } 663 664 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::GetNativeBufferUsageSpecific(OMX_PTR pStructure) { 665 OMX_ERRORTYPE ret; 666 android::GetAndroidNativeBufferUsageParams *param = 667 (android::GetAndroidNativeBufferUsageParams*)pStructure; 668 CHECK_TYPE_HEADER(param); 669 670 param->nUsage |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN 671 | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_EXTERNAL_DISP); 672 return OMX_ErrorNone; 673 674 } 675 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::SetNativeBufferModeSpecific(OMX_PTR pStructure) { 676 OMX_ERRORTYPE ret; 677 android::EnableAndroidNativeBuffersParams *param = 678 (android::EnableAndroidNativeBuffersParams*)pStructure; 679 680 CHECK_TYPE_HEADER(param); 681 CHECK_PORT_INDEX_RANGE(param); 682 CHECK_SET_PARAM_STATE(); 683 684 PortVideo *port = NULL; 685 port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]); 686 OMX_PARAM_PORTDEFINITIONTYPE port_def; 687 memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def)); 688 689 if (!param->enable) { 690 mWorkingMode = RAWDATA_MODE; 691 LOGI("Raw data mode is used"); 692 // If it is fallback from native mode the color format has been 693 // already set to INTEL format. 694 // We need to set back the default color format and Native stuff. 695 port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; 696 port_def.format.video.pNativeRender = NULL; 697 port_def.format.video.pNativeWindow = NULL; 698 port->SetPortDefinition(&port_def,true); 699 return OMX_ErrorNone; 700 } 701 702 mWorkingMode = GRAPHICBUFFER_MODE; 703 port_def.nBufferCountMin = mNativeBufferCount - 4; 704 port_def.nBufferCountActual = mNativeBufferCount; 705 port_def.format.video.cMIMEType = (OMX_STRING)VA_VED_RAW_MIME_TYPE; 706 // add borders for libvpx decode need. 707 port_def.format.video.nFrameWidth += VPX_DECODE_BORDER * 2; 708 port_def.format.video.nFrameHeight += VPX_DECODE_BORDER * 2; 709 mDecodedImageWidth = port_def.format.video.nFrameWidth; 710 mDecodedImageHeight = port_def.format.video.nFrameHeight; 711 port_def.format.video.eColorFormat = GetOutputColorFormat(port_def.format.video.nFrameWidth); 712 port->SetPortDefinition(&port_def,true); 713 714 return OMX_ErrorNone; 715 } 716 717 718 bool OMXVideoDecoderVP9Hybrid::IsAllBufferAvailable(void) { 719 bool b = ComponentBase::IsAllBufferAvailable(); 720 if (b == false) { 721 return false; 722 } 723 724 PortVideo *port = NULL; 725 port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]); 726 const OMX_PARAM_PORTDEFINITIONTYPE* port_def = port->GetPortDefinition(); 727 // if output port is disabled, retain the input buffer 728 if (!port_def->bEnabled) { 729 return false; 730 } 731 return mCheckBufferAvailable(mHybridCtx); 732 } 733 734 DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.VP9.hybrid", "video_decoder.vp9", OMXVideoDecoderVP9Hybrid); 735