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