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