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 18 #define LOG_NDEBUG 0 19 #define LOG_TAG "OMXVideoDecoderVP9HWR" 20 #include <wrs_omxil_core/log.h> 21 #include "OMXVideoDecoderVP9HWR.h" 22 23 #include <system/window.h> 24 #include <ui/GraphicBufferMapper.h> 25 #include <ui/Rect.h> 26 #include <HardwareAPI.h> 27 #include <hardware/hardware.h> 28 #include <hardware/gralloc.h> 29 #include <system/graphics.h> 30 31 static const char* VP9_MIME_TYPE = "video/x-vnd.on2.vp9"; 32 33 static int GetCPUCoreCount() 34 { 35 int cpuCoreCount = 1; 36 #if defined(_SC_NPROCESSORS_ONLN) 37 cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN); 38 #else 39 // _SC_NPROC_ONLN must be defined... 40 cpuCoreCount = sysconf(_SC_NPROC_ONLN); 41 #endif 42 if (cpuCoreCount < 1) { 43 LOGW("Get CPU Core Count error."); 44 cpuCoreCount = 1; 45 } 46 LOGV("Number of CPU cores: %d", cpuCoreCount); 47 return cpuCoreCount; 48 } 49 50 51 OMXVideoDecoderVP9HWR::OMXVideoDecoderVP9HWR() 52 { 53 LOGV("OMXVideoDecoderVP9HWR is constructed."); 54 55 mNumFrameBuffer = 0; 56 mCtx = NULL; 57 58 mNativeBufferCount = OUTPORT_NATIVE_BUFFER_COUNT; 59 extUtilBufferCount = 0; 60 extMappedNativeBufferCount = 0; 61 BuildHandlerList(); 62 63 mDecodedImageWidth = 0; 64 mDecodedImageHeight = 0; 65 mDecodedImageNewWidth = 0; 66 mDecodedImageNewHeight = 0; 67 68 #ifdef DECODE_WITH_GRALLOC_BUFFER 69 // setup va 70 VAStatus vaStatus = VA_STATUS_SUCCESS; 71 mDisplay = new Display; 72 *mDisplay = ANDROID_DISPLAY_HANDLE; 73 74 mVADisplay = vaGetDisplay(mDisplay); 75 if (mVADisplay == NULL) { 76 LOGE("vaGetDisplay failed."); 77 } 78 79 int majorVersion, minorVersion; 80 vaStatus = vaInitialize(mVADisplay, &majorVersion, &minorVersion); 81 if (vaStatus != VA_STATUS_SUCCESS) { 82 LOGE("vaInitialize failed."); 83 } else { 84 LOGV("va majorVersion=%d, minorVersion=%d", majorVersion, minorVersion); 85 } 86 #endif 87 } 88 89 OMXVideoDecoderVP9HWR::~OMXVideoDecoderVP9HWR() 90 { 91 LOGV("OMXVideoDecoderVP9HWR is destructed."); 92 93 unsigned int i = 0; 94 95 if (mVADisplay) { 96 vaTerminate(mVADisplay); 97 mVADisplay = NULL; 98 } 99 } 100 101 102 // Callback func for vpx decoder to get decode buffer 103 // Now we map from the vaSurface to deploy gralloc buffer 104 // as decode buffer 105 int getVP9FrameBuffer(void *user_priv, 106 unsigned int new_size, 107 vpx_codec_frame_buffer_t *fb) 108 { 109 OMXVideoDecoderVP9HWR * p = (OMXVideoDecoderVP9HWR *)user_priv; 110 if (fb == NULL) { 111 return -1; 112 } 113 114 // TODO: Adaptive playback case needs to reconsider 115 if (p->extNativeBufferSize < new_size) { 116 LOGE("Provided frame buffer size < requesting min size."); 117 return -1; 118 } 119 120 int i; 121 for (i = 0; i < p->extMappedNativeBufferCount; i++ ) { 122 if ((p->extMIDs[i]->m_render_done == true) && 123 (p->extMIDs[i]->m_released == true)) { 124 fb->data = p->extMIDs[i]->m_usrAddr; 125 fb->size = p->extNativeBufferSize; 126 fb->fb_stride = p->extActualBufferStride; 127 fb->fb_height_stride = p->extActualBufferHeightStride; 128 fb->fb_index = i; 129 p->extMIDs[i]->m_released = false; 130 break; 131 } 132 } 133 134 if (i == p->extMappedNativeBufferCount) { 135 LOGE("No available frame buffer in pool."); 136 return -1; 137 } 138 return 0; 139 } 140 141 // call back function from libvpx to inform frame buffer 142 // not used anymore. 143 int releaseVP9FrameBuffer(void *user_priv, vpx_codec_frame_buffer_t *fb) 144 { 145 int i; 146 OMXVideoDecoderVP9HWR * p = (OMXVideoDecoderVP9HWR *)user_priv; 147 if (fb == NULL) { 148 return -1; 149 } 150 for (i = 0; i < p->extMappedNativeBufferCount; i++ ) { 151 if (fb->data == p->extMIDs[i]->m_usrAddr) { 152 p->extMIDs[i]->m_released = true; 153 break; 154 } 155 } 156 157 if (i == p->extMappedNativeBufferCount) { 158 LOGE("Not found matching frame buffer in pool, libvpx's wrong?"); 159 return -1; 160 } 161 return 0; 162 } 163 164 165 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::initDecoder() 166 { 167 mCtx = new vpx_codec_ctx_t; 168 vpx_codec_err_t vpx_err; 169 vpx_codec_dec_cfg_t cfg; 170 memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t)); 171 cfg.threads = GetCPUCoreCount(); 172 if ((vpx_err = vpx_codec_dec_init( 173 (vpx_codec_ctx_t *)mCtx, 174 &vpx_codec_vp9_dx_algo, 175 &cfg, 0))) { 176 LOGE("on2 decoder failed to initialize. (%d)", vpx_err); 177 return OMX_ErrorNotReady; 178 } 179 180 mNumFrameBuffer = OUTPORT_NATIVE_BUFFER_COUNT; 181 182 if (vpx_codec_set_frame_buffer_functions((vpx_codec_ctx_t *)mCtx, 183 getVP9FrameBuffer, 184 releaseVP9FrameBuffer, 185 this)) { 186 LOGE("Failed to configure external frame buffers"); 187 return OMX_ErrorNotReady; 188 } 189 190 return OMX_ErrorNone; 191 } 192 193 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::destroyDecoder() 194 { 195 vpx_codec_destroy((vpx_codec_ctx_t *)mCtx); 196 delete (vpx_codec_ctx_t *)mCtx; 197 mCtx = NULL; 198 return OMX_ErrorNone; 199 } 200 201 202 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::InitInputPortFormatSpecific( 203 OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput) 204 { 205 paramPortDefinitionInput->nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT; 206 paramPortDefinitionInput->nBufferCountMin = INPORT_MIN_BUFFER_COUNT; 207 paramPortDefinitionInput->nBufferSize = INPORT_BUFFER_SIZE; 208 paramPortDefinitionInput->format.video.cMIMEType = (OMX_STRING)VP9_MIME_TYPE; 209 paramPortDefinitionInput->format.video.eCompressionFormat = OMX_VIDEO_CodingVP9; 210 211 return OMX_ErrorNone; 212 } 213 214 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorInit(void) 215 { 216 unsigned int i = 0; 217 218 for (i = 0; i < MAX_NATIVE_BUFFER_COUNT; i++) { 219 extMIDs[i] = (vaapiMemId*)malloc(sizeof(vaapiMemId)); 220 extMIDs[i]->m_usrAddr = NULL; 221 extMIDs[i]->m_surface = new VASurfaceID; 222 } 223 224 initDecoder(); 225 226 if (RAWDATA_MODE == mWorkingMode) { 227 OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput; 228 229 memcpy(¶mPortDefinitionInput, 230 this->ports[INPORT_INDEX]->GetPortDefinition(), 231 sizeof(paramPortDefinitionInput)); 232 233 extNativeBufferSize = INTERNAL_MAX_FRAME_WIDTH * 234 INTERNAL_MAX_FRAME_HEIGHT * 1.5; 235 extActualBufferStride = INTERNAL_MAX_FRAME_WIDTH; 236 extActualBufferHeightStride = INTERNAL_MAX_FRAME_HEIGHT; 237 238 for (i = 0; i < OUTPORT_ACTUAL_BUFFER_COUNT; i++ ) { 239 extMIDs[i]->m_usrAddr = (unsigned char*)malloc(sizeof(unsigned char) * 240 extNativeBufferSize); 241 extMIDs[i]->m_render_done = true; 242 extMIDs[i]->m_released = true; 243 } 244 extMappedNativeBufferCount = OUTPORT_ACTUAL_BUFFER_COUNT; 245 return OMX_ErrorNone; 246 } 247 248 #ifdef DECODE_WITH_GRALLOC_BUFFER 249 if (mOMXBufferHeaderTypePtrNum > MAX_NATIVE_BUFFER_COUNT) { 250 LOGE("Actual OMX outport buffer header type num (%d) > MAX_NATIVE_BUFFER_COUNT (%d)", 251 mOMXBufferHeaderTypePtrNum, MAX_NATIVE_BUFFER_COUNT); 252 return OMX_ErrorOverflow; 253 } 254 255 OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput; 256 257 memcpy(¶mPortDefinitionInput, 258 this->ports[INPORT_INDEX]->GetPortDefinition(), 259 sizeof(paramPortDefinitionInput)); 260 261 int surfaceWidth = mGraphicBufferParam.graphicBufferWidth; 262 int surfaceHeight = mGraphicBufferParam.graphicBufferHeight; 263 int surfaceStride = mGraphicBufferParam.graphicBufferStride; 264 extNativeBufferSize = mGraphicBufferParam.graphicBufferStride * 265 mGraphicBufferParam.graphicBufferHeight * 1.5; 266 extActualBufferStride = surfaceStride; 267 extActualBufferHeightStride = surfaceHeight; 268 269 for (i = 0; i < mOMXBufferHeaderTypePtrNum; i++) { 270 OMX_BUFFERHEADERTYPE *buf_hdr = mOMXBufferHeaderTypePtrArray[i]; 271 272 extMIDs[i]->m_key = (unsigned int)(buf_hdr->pBuffer); 273 extMIDs[i]->m_render_done = false; 274 extMIDs[i]->m_released = true; 275 276 VAStatus va_res; 277 unsigned int buffer; 278 VASurfaceAttrib attribs[2]; 279 VASurfaceAttribExternalBuffers* surfExtBuf = new VASurfaceAttribExternalBuffers; 280 int32_t format = VA_RT_FORMAT_YUV420; 281 282 surfExtBuf->buffers= (unsigned long *)&buffer; 283 surfExtBuf->num_buffers = 1; 284 surfExtBuf->pixel_format = VA_FOURCC_NV12; 285 surfExtBuf->width = surfaceWidth; 286 surfExtBuf->height = surfaceHeight; 287 surfExtBuf->data_size = surfaceStride * surfaceHeight * 1.5; 288 surfExtBuf->num_planes = 2; 289 surfExtBuf->pitches[0] = surfaceStride; 290 surfExtBuf->pitches[1] = surfaceStride; 291 surfExtBuf->pitches[2] = 0; 292 surfExtBuf->pitches[3] = 0; 293 surfExtBuf->offsets[0] = 0; 294 surfExtBuf->offsets[1] = surfaceStride * surfaceHeight; 295 surfExtBuf->offsets[2] = 0; 296 surfExtBuf->offsets[3] = 0; 297 surfExtBuf->flags = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC; 298 299 surfExtBuf->buffers[0] = (unsigned int)buf_hdr->pBuffer; 300 301 attribs[0].type = (VASurfaceAttribType)VASurfaceAttribMemoryType; 302 attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE; 303 attribs[0].value.type = VAGenericValueTypeInteger; 304 attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC; 305 306 attribs[1].type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor; 307 attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE; 308 attribs[1].value.type = VAGenericValueTypePointer; 309 attribs[1].value.value.p = (void *)surfExtBuf; 310 311 va_res = vaCreateSurfaces(mVADisplay, 312 format, 313 surfaceWidth, 314 surfaceHeight, 315 extMIDs[i]->m_surface, 316 1, 317 attribs, 318 2); 319 320 if (va_res != VA_STATUS_SUCCESS) { 321 LOGE("Failed to create vaSurface!"); 322 return OMX_ErrorUndefined; 323 } 324 325 delete surfExtBuf; 326 327 VAImage image; 328 unsigned char* usrptr; 329 330 va_res = vaDeriveImage(mVADisplay, *(extMIDs[i]->m_surface), &image); 331 if (VA_STATUS_SUCCESS == va_res) { 332 va_res = vaMapBuffer(mVADisplay, image.buf, (void **) &usrptr); 333 if (VA_STATUS_SUCCESS == va_res) { 334 extMIDs[i]->m_usrAddr = usrptr; 335 vaUnmapBuffer(mVADisplay, image.buf); 336 } 337 vaDestroyImage(mVADisplay, image.image_id); 338 } 339 extMappedNativeBufferCount++; 340 } 341 return OMX_ErrorNone; 342 #endif 343 } 344 345 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorDeinit(void) 346 { 347 destroyDecoder(); 348 unsigned int i = 0; 349 if (mWorkingMode == GRAPHICBUFFER_MODE) { 350 for (i = 0; i < mOMXBufferHeaderTypePtrNum; i++) { 351 if (extMIDs[i]->m_surface != NULL) { 352 vaDestroySurfaces(mVADisplay, extMIDs[i]->m_surface, 1); 353 } 354 } 355 356 } else if (mWorkingMode == RAWDATA_MODE) { 357 for (i = 0; i < OUTPORT_ACTUAL_BUFFER_COUNT; i++ ) { 358 if (extMIDs[i]->m_usrAddr != NULL) { 359 free(extMIDs[i]->m_usrAddr); 360 extMIDs[i]->m_usrAddr = NULL; 361 } 362 } 363 } 364 mOMXBufferHeaderTypePtrNum = 0; 365 memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam)); 366 for (i = 0; i < MAX_NATIVE_BUFFER_COUNT; i++) { 367 delete extMIDs[i]->m_surface; 368 free(extMIDs[i]); 369 } 370 return OMXComponentCodecBase::ProcessorDeinit(); 371 } 372 373 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorStop(void) 374 { 375 return OMXComponentCodecBase::ProcessorStop(); 376 } 377 378 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorFlush(OMX_U32) 379 { 380 return OMX_ErrorNone; 381 } 382 383 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE* buffer) 384 { 385 unsigned int handle = (unsigned int)buffer->pBuffer; 386 unsigned int i = 0; 387 388 if (buffer->nOutputPortIndex == OUTPORT_INDEX){ 389 for (i = 0; i < mOMXBufferHeaderTypePtrNum; i++) { 390 if (handle == extMIDs[i]->m_key) { 391 extMIDs[i]->m_render_done = true; 392 break; 393 } 394 } 395 } 396 return OMX_ErrorNone; 397 } 398 399 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorProcess( 400 OMX_BUFFERHEADERTYPE ***pBuffers, 401 buffer_retain_t *retains, 402 OMX_U32) 403 { 404 OMX_ERRORTYPE ret; 405 OMX_BUFFERHEADERTYPE *inBuffer = *pBuffers[INPORT_INDEX]; 406 OMX_BUFFERHEADERTYPE *outBuffer = *pBuffers[OUTPORT_INDEX]; 407 OMX_BOOL isResolutionChange = OMX_FALSE; 408 409 if (inBuffer->pBuffer == NULL) { 410 LOGE("Buffer to decode is empty."); 411 return OMX_ErrorBadParameter; 412 } 413 414 if (inBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 415 LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag."); 416 } 417 418 if (inBuffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) { 419 LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag."); 420 } 421 422 if (inBuffer->nFlags & OMX_BUFFERFLAG_EOS) { 423 if (inBuffer->nFilledLen == 0) { 424 (*pBuffers[OUTPORT_INDEX])->nFilledLen = 0; 425 (*pBuffers[OUTPORT_INDEX])->nFlags = OMX_BUFFERFLAG_EOS; 426 return OMX_ErrorNone; 427 } 428 } 429 430 if (vpx_codec_decode((vpx_codec_ctx_t *)mCtx, 431 inBuffer->pBuffer + inBuffer->nOffset, 432 inBuffer->nFilledLen, 433 NULL, 434 0)) { 435 LOGE("on2 decoder failed to decode frame."); 436 return OMX_ErrorBadParameter; 437 } 438 439 ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], 440 &retains[OUTPORT_INDEX], 441 ((*pBuffers[INPORT_INDEX]))->nFlags, 442 &isResolutionChange); 443 444 if (ret == OMX_ErrorNone) { 445 (*pBuffers[OUTPORT_INDEX])->nTimeStamp = inBuffer->nTimeStamp; 446 } 447 448 if (isResolutionChange) { 449 HandleFormatChange(); 450 } 451 452 bool inputEoS = ((*pBuffers[INPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS); 453 bool outputEoS = ((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS); 454 // if output port is not eos, retain the input buffer 455 // until all the output buffers are drained. 456 if (inputEoS && !outputEoS) { 457 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 458 // the input buffer is retained for draining purpose. 459 // Set nFilledLen to 0 so buffer will not be decoded again. 460 (*pBuffers[INPORT_INDEX])->nFilledLen = 0; 461 } 462 463 if (ret == OMX_ErrorNotReady) { 464 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 465 ret = OMX_ErrorNone; 466 } 467 468 return ret; 469 } 470 471 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorReset(void) 472 { 473 return OMX_ErrorNone; 474 } 475 476 static int ALIGN(int x, int y) 477 { 478 // y must be a power of 2. 479 return (x + y - 1) & ~(y - 1); 480 } 481 482 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::HandleFormatChange(void) 483 { 484 mDecodedImageWidth = mDecodedImageNewWidth; 485 mDecodedImageHeight = mDecodedImageNewHeight; 486 487 // Sync port definition as it may change. 488 OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput, paramPortDefinitionOutput; 489 490 memcpy(¶mPortDefinitionInput, 491 this->ports[INPORT_INDEX]->GetPortDefinition(), 492 sizeof(paramPortDefinitionInput)); 493 494 memcpy(¶mPortDefinitionOutput, 495 this->ports[OUTPORT_INDEX]->GetPortDefinition(), 496 sizeof(paramPortDefinitionOutput)); 497 498 uint32_t width = mDecodedImageWidth; 499 uint32_t height = mDecodedImageHeight; 500 uint32_t stride = mDecodedImageWidth; 501 uint32_t sliceHeight = mDecodedImageHeight; 502 503 uint32_t widthCropped = mDecodedImageWidth; 504 uint32_t heightCropped = mDecodedImageHeight; 505 uint32_t strideCropped = widthCropped; 506 uint32_t sliceHeightCropped = heightCropped; 507 508 if (widthCropped == paramPortDefinitionOutput.format.video.nFrameWidth && 509 heightCropped == paramPortDefinitionOutput.format.video.nFrameHeight) { 510 if (mWorkingMode == RAWDATA_MODE) { 511 LOGW("Change of portsetting is not reported as size is not changed."); 512 return OMX_ErrorNone; 513 } 514 } 515 516 paramPortDefinitionInput.format.video.nFrameWidth = width; 517 paramPortDefinitionInput.format.video.nFrameHeight = height; 518 paramPortDefinitionInput.format.video.nStride = stride; 519 paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight; 520 521 if (mWorkingMode == RAWDATA_MODE) { 522 paramPortDefinitionOutput.format.video.nFrameWidth = widthCropped; 523 paramPortDefinitionOutput.format.video.nFrameHeight = heightCropped; 524 paramPortDefinitionOutput.format.video.nStride = strideCropped; 525 paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeightCropped; 526 } else if (mWorkingMode == GRAPHICBUFFER_MODE) { 527 // when the width and height ES parse are not larger than allocated graphic buffer in outport, 528 // there is no need to reallocate graphic buffer,just report the crop info to omx client 529 if (width <= mGraphicBufferParam.graphicBufferWidth && 530 height <= mGraphicBufferParam.graphicBufferHeight) { 531 this->ports[INPORT_INDEX]->SetPortDefinition(¶mPortDefinitionInput, true); 532 this->ports[OUTPORT_INDEX]->ReportOutputCrop(); 533 return OMX_ErrorNone; 534 } 535 536 if (width > mGraphicBufferParam.graphicBufferWidth || 537 height > mGraphicBufferParam.graphicBufferHeight) { 538 // update the real decoded resolution to outport instead of display resolution 539 // for graphic buffer reallocation 540 // when the width and height parsed from ES are larger than allocated graphic buffer in outport, 541 paramPortDefinitionOutput.format.video.nFrameWidth = width; 542 paramPortDefinitionOutput.format.video.nFrameHeight = (height + 0x1f) & ~0x1f; 543 paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat( 544 paramPortDefinitionOutput.format.video.nFrameWidth); 545 paramPortDefinitionOutput.format.video.nStride = stride; 546 paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight; 547 } 548 } 549 550 paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false; 551 mOMXBufferHeaderTypePtrNum = 0; 552 memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam)); 553 554 this->ports[INPORT_INDEX]->SetPortDefinition(¶mPortDefinitionInput, true); 555 this->ports[OUTPORT_INDEX]->SetPortDefinition(¶mPortDefinitionOutput, true); 556 557 this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged(); 558 return OMX_ErrorNone; 559 } 560 561 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::FillRenderBuffer(OMX_BUFFERHEADERTYPE **pBuffer, 562 buffer_retain_t *retain, 563 OMX_U32 inportBufferFlags, 564 OMX_BOOL *isResolutionChange) 565 { 566 OMX_BUFFERHEADERTYPE *buffer = *pBuffer; 567 OMX_BUFFERHEADERTYPE *buffer_orign = buffer; 568 569 OMX_ERRORTYPE ret = OMX_ErrorNone; 570 571 vpx_codec_iter_t iter = NULL; 572 vpx_image_t *img = NULL; 573 img = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter); 574 575 if (img != NULL) { 576 if ((mDecodedImageWidth == 0) && (mDecodedImageHeight == 0)) { // init value 577 mDecodedImageWidth = img->d_w; 578 mDecodedImageHeight = img->d_h; 579 } 580 if ((mDecodedImageWidth != img->d_w) && (mDecodedImageHeight != img->d_h)) { 581 mDecodedImageNewWidth = img->d_w; 582 mDecodedImageNewHeight = img->d_h; 583 *isResolutionChange = OMX_TRUE; 584 } 585 } 586 587 if (mWorkingMode == RAWDATA_MODE) { 588 if (img == NULL) { 589 LOGE("vpx_codec_get_frame return NULL."); 590 return OMX_ErrorNotReady; 591 } 592 593 // in Raw data mode, this flag should be always true 594 extMIDs[img->fb_index]->m_render_done = true; 595 596 void *dst = buffer->pBuffer; 597 uint8_t *dst_y = (uint8_t *)dst; 598 const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput 599 = this->ports[INPORT_INDEX]->GetPortDefinition(); 600 601 size_t inBufferWidth = paramPortDefinitionInput->format.video.nFrameWidth; 602 size_t inBufferHeight = paramPortDefinitionInput->format.video.nFrameHeight; 603 604 const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionOutput 605 = this->ports[OUTPORT_INDEX]->GetPortDefinition(); 606 607 size_t dst_y_size = paramPortDefinitionOutput->format.video.nStride * 608 paramPortDefinitionOutput->format.video.nFrameHeight; 609 size_t dst_c_stride = ALIGN(paramPortDefinitionOutput->format.video.nStride / 2, 16); 610 size_t dst_c_size = dst_c_stride * paramPortDefinitionOutput->format.video.nFrameHeight / 2; 611 uint8_t *dst_v = dst_y + dst_y_size; 612 uint8_t *dst_u = dst_v + dst_c_size; 613 614 //test border 615 dst_y += VPX_DECODE_BORDER * paramPortDefinitionOutput->format.video.nStride + VPX_DECODE_BORDER; 616 dst_v += (VPX_DECODE_BORDER/2) * dst_c_stride + (VPX_DECODE_BORDER/2); 617 dst_u += (VPX_DECODE_BORDER/2) * dst_c_stride + (VPX_DECODE_BORDER/2); 618 619 const uint8_t *srcLine = (const uint8_t *)img->planes[PLANE_Y]; 620 621 for (size_t i = 0; i < img->d_h; ++i) { 622 memcpy(dst_y, srcLine, img->d_w); 623 624 srcLine += img->stride[PLANE_Y]; 625 dst_y += paramPortDefinitionOutput->format.video.nStride; 626 } 627 628 srcLine = (const uint8_t *)img->planes[PLANE_U]; 629 for (size_t i = 0; i < img->d_h / 2; ++i) { 630 memcpy(dst_u, srcLine, img->d_w / 2); 631 632 srcLine += img->stride[PLANE_U]; 633 dst_u += dst_c_stride; 634 } 635 636 srcLine = (const uint8_t *)img->planes[PLANE_V]; 637 for (size_t i = 0; i < img->d_h / 2; ++i) { 638 memcpy(dst_v, srcLine, img->d_w / 2); 639 640 srcLine += img->stride[PLANE_V]; 641 dst_v += dst_c_stride; 642 } 643 644 buffer->nOffset = 0; 645 buffer->nFilledLen = dst_y_size + dst_c_size * 2; 646 if (inportBufferFlags & OMX_BUFFERFLAG_EOS) { 647 buffer->nFlags = OMX_BUFFERFLAG_EOS; 648 } 649 650 if (buffer_orign != buffer) { 651 *retain = BUFFER_RETAIN_OVERRIDDEN; 652 } 653 ret = OMX_ErrorNone; 654 655 return ret; 656 657 } 658 659 #ifdef DECODE_WITH_GRALLOC_BUFFER 660 if (NULL != img) { 661 buffer = *pBuffer = mOMXBufferHeaderTypePtrArray[img->fb_index]; 662 663 if ((unsigned int)(buffer->pBuffer) != extMIDs[img->fb_index]->m_key) { 664 LOGE("There is gralloc handle mismatching between pool\ 665 and mOMXBufferHeaderTypePtrArray."); 666 return OMX_ErrorNotReady; 667 } 668 669 extMIDs[img->fb_index]->m_render_done = false; 670 671 buffer->nOffset = 0; 672 673 size_t dst_y_size = img->d_w * img->d_h; 674 675 buffer->nFilledLen = dst_y_size * 1.5; // suport only 4:2:0 for now 676 677 if (inportBufferFlags & OMX_BUFFERFLAG_EOS) { 678 buffer->nFlags = OMX_BUFFERFLAG_EOS; 679 } 680 681 if (buffer_orign != buffer) { 682 *retain = BUFFER_RETAIN_OVERRIDDEN; 683 } 684 685 return OMX_ErrorNone; 686 } else { 687 LOGE("vpx_codec_get_frame return NULL."); 688 return OMX_ErrorNotReady; 689 } 690 #endif 691 } 692 693 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::PrepareConfigBuffer(VideoConfigBuffer *) 694 { 695 return OMX_ErrorNone; 696 } 697 698 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *, 699 buffer_retain_t *, 700 VideoDecodeBuffer *) 701 { 702 return OMX_ErrorNone; 703 } 704 705 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::BuildHandlerList(void) 706 { 707 OMXVideoDecoderBase::BuildHandlerList(); 708 return OMX_ErrorNone; 709 } 710 711 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::GetParamVideoVp9(OMX_PTR) 712 { 713 return OMX_ErrorNone; 714 } 715 716 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::SetParamVideoVp9(OMX_PTR) 717 { 718 return OMX_ErrorNone; 719 } 720 721 OMX_COLOR_FORMATTYPE OMXVideoDecoderVP9HWR::GetOutputColorFormat(int) 722 { 723 LOGV("Output color format is OMX_INTEL_COLOR_FormatHalYV12."); 724 return (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YV12; 725 } 726 727 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::GetDecoderOutputCropSpecific(OMX_PTR pStructure) 728 { 729 OMX_ERRORTYPE ret = OMX_ErrorNone; 730 OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)pStructure; 731 732 CHECK_TYPE_HEADER(rectParams); 733 734 if (rectParams->nPortIndex != OUTPORT_INDEX) { 735 return OMX_ErrorUndefined; 736 } 737 738 const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput 739 = this->ports[INPORT_INDEX]->GetPortDefinition(); 740 741 rectParams->nLeft = VPX_DECODE_BORDER; 742 rectParams->nTop = VPX_DECODE_BORDER; 743 rectParams->nWidth = paramPortDefinitionInput->format.video.nFrameWidth; 744 rectParams->nHeight = paramPortDefinitionInput->format.video.nFrameHeight; 745 746 return ret; 747 } 748 749 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::GetNativeBufferUsageSpecific(OMX_PTR pStructure) 750 { 751 OMX_ERRORTYPE ret; 752 android::GetAndroidNativeBufferUsageParams *param = 753 (android::GetAndroidNativeBufferUsageParams*)pStructure; 754 CHECK_TYPE_HEADER(param); 755 756 param->nUsage |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER \ 757 | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_EXTERNAL_DISP); 758 return OMX_ErrorNone; 759 760 } 761 762 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::SetNativeBufferModeSpecific(OMX_PTR pStructure) 763 { 764 OMX_ERRORTYPE ret; 765 EnableAndroidNativeBuffersParams *param = 766 (EnableAndroidNativeBuffersParams*)pStructure; 767 768 CHECK_TYPE_HEADER(param); 769 CHECK_PORT_INDEX_RANGE(param); 770 CHECK_SET_PARAM_STATE(); 771 772 if (!param->enable) { 773 mWorkingMode = RAWDATA_MODE; 774 return OMX_ErrorNone; 775 } 776 mWorkingMode = GRAPHICBUFFER_MODE; 777 PortVideo *port = NULL; 778 port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]); 779 780 781 OMX_PARAM_PORTDEFINITIONTYPE port_def; 782 memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def)); 783 port_def.nBufferCountMin = mNativeBufferCount; 784 port_def.nBufferCountActual = mNativeBufferCount; 785 port_def.format.video.cMIMEType = (OMX_STRING)VA_VED_RAW_MIME_TYPE; 786 port_def.format.video.eColorFormat = OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar; 787 788 // add borders for libvpx decode need. 789 port_def.format.video.nFrameHeight += VPX_DECODE_BORDER * 2; 790 port_def.format.video.nFrameWidth += VPX_DECODE_BORDER * 2; 791 // make heigth 32bit align 792 port_def.format.video.nFrameHeight = (port_def.format.video.nFrameHeight + 0x1f) & ~0x1f; 793 port_def.format.video.eColorFormat = GetOutputColorFormat( 794 port_def.format.video.nFrameWidth); 795 port->SetPortDefinition(&port_def,true); 796 797 return OMX_ErrorNone; 798 } 799 800 801 bool OMXVideoDecoderVP9HWR::IsAllBufferAvailable(void) 802 { 803 bool b = ComponentBase::IsAllBufferAvailable(); 804 if (b == false) { 805 return false; 806 } 807 808 PortVideo *port = NULL; 809 port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]); 810 const OMX_PARAM_PORTDEFINITIONTYPE* port_def = port->GetPortDefinition(); 811 // if output port is disabled, retain the input buffer 812 if (!port_def->bEnabled) { 813 return false; 814 } 815 816 unsigned int i = 0; 817 int found = 0; 818 819 if (RAWDATA_MODE == mWorkingMode) { 820 for (i = 0; i < OUTPORT_ACTUAL_BUFFER_COUNT; i++) { 821 if (extMIDs[i]->m_released == true) { 822 found ++; 823 if (found > 1) { //libvpx sometimes needs 2 buffer when calling decode once. 824 return true; 825 } 826 } 827 } 828 } else { // graphic buffer mode 829 for (i = 0; i < mOMXBufferHeaderTypePtrNum; i++) { 830 if ((extMIDs[i]->m_render_done == true) && (extMIDs[i]->m_released == true)) { 831 found ++; 832 if (found > 1) { //libvpx sometimes needs 2 buffer when calling decode once. 833 return true; 834 } 835 } 836 } 837 } 838 839 b = false; 840 841 return b; 842 } 843 844 DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.VP9.hwr", "video_decoder.vp9", OMXVideoDecoderVP9HWR); 845 846