1 /* 2 * Copyright (C) 2014 The Android Open Source Project 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_NDEBUG 0 18 #define LOG_TAG "SoftHEVC" 19 #include <utils/Log.h> 20 21 #include "ihevc_typedefs.h" 22 #include "iv.h" 23 #include "ivd.h" 24 #include "ihevcd_cxa.h" 25 #include "SoftHEVC.h" 26 27 #include <media/stagefright/foundation/ADebug.h> 28 #include <media/stagefright/foundation/AUtils.h> 29 #include <media/stagefright/MediaDefs.h> 30 #include <OMX_VideoExt.h> 31 32 namespace android { 33 34 #define componentName "video_decoder.hevc" 35 #define codingType OMX_VIDEO_CodingHEVC 36 #define CODEC_MIME_TYPE MEDIA_MIMETYPE_VIDEO_HEVC 37 38 /** Function and structure definitions to keep code similar for each codec */ 39 #define ivdec_api_function ihevcd_cxa_api_function 40 #define ivdext_create_ip_t ihevcd_cxa_create_ip_t 41 #define ivdext_create_op_t ihevcd_cxa_create_op_t 42 #define ivdext_delete_ip_t ihevcd_cxa_delete_ip_t 43 #define ivdext_delete_op_t ihevcd_cxa_delete_op_t 44 #define ivdext_ctl_set_num_cores_ip_t ihevcd_cxa_ctl_set_num_cores_ip_t 45 #define ivdext_ctl_set_num_cores_op_t ihevcd_cxa_ctl_set_num_cores_op_t 46 47 #define IVDEXT_CMD_CTL_SET_NUM_CORES \ 48 (IVD_CONTROL_API_COMMAND_TYPE_T)IHEVCD_CXA_CMD_CTL_SET_NUM_CORES 49 50 static const CodecProfileLevel kProfileLevels[] = { 51 { OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel1 }, 52 { OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel2 }, 53 { OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel21 }, 54 { OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel3 }, 55 { OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel31 }, 56 { OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel4 }, 57 { OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel41 }, 58 { OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel5 }, 59 { OMX_VIDEO_HEVCProfileMain, OMX_VIDEO_HEVCMainTierLevel51 }, 60 }; 61 62 SoftHEVC::SoftHEVC( 63 const char *name, 64 const OMX_CALLBACKTYPE *callbacks, 65 OMX_PTR appData, 66 OMX_COMPONENTTYPE **component) 67 : SoftVideoDecoderOMXComponent(name, componentName, codingType, 68 kProfileLevels, ARRAY_SIZE(kProfileLevels), 69 320 /* width */, 240 /* height */, callbacks, 70 appData, component), 71 mCodecCtx(NULL), 72 mFlushOutBuffer(NULL), 73 mOmxColorFormat(OMX_COLOR_FormatYUV420Planar), 74 mIvColorFormat(IV_YUV_420P), 75 mChangingResolution(false), 76 mSignalledError(false), 77 mStride(mWidth) { 78 const size_t kMinCompressionRatio = 4 /* compressionRatio (for Level 4+) */; 79 const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2; 80 // INPUT_BUF_SIZE is given by HEVC codec as minimum input size 81 initPorts( 82 kNumBuffers, max(kMaxOutputBufferSize / kMinCompressionRatio, (size_t)INPUT_BUF_SIZE), 83 kNumBuffers, CODEC_MIME_TYPE, kMinCompressionRatio); 84 } 85 86 status_t SoftHEVC::init() { 87 return initDecoder(); 88 } 89 90 SoftHEVC::~SoftHEVC() { 91 ALOGV("In SoftHEVC::~SoftHEVC"); 92 CHECK_EQ(deInitDecoder(), (status_t)OK); 93 } 94 95 static void *ivd_aligned_malloc(void *ctxt, WORD32 alignment, WORD32 size) { 96 UNUSED(ctxt); 97 return memalign(alignment, size); 98 } 99 100 static void ivd_aligned_free(void *ctxt, void *buf) { 101 UNUSED(ctxt); 102 free(buf); 103 return; 104 } 105 106 static size_t GetCPUCoreCount() { 107 long cpuCoreCount = 1; 108 #if defined(_SC_NPROCESSORS_ONLN) 109 cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN); 110 #else 111 // _SC_NPROC_ONLN must be defined... 112 cpuCoreCount = sysconf(_SC_NPROC_ONLN); 113 #endif 114 CHECK(cpuCoreCount >= 1); 115 ALOGV("Number of CPU cores: %ld", cpuCoreCount); 116 return (size_t)cpuCoreCount; 117 } 118 119 void SoftHEVC::logVersion() { 120 ivd_ctl_getversioninfo_ip_t s_ctl_ip; 121 ivd_ctl_getversioninfo_op_t s_ctl_op; 122 UWORD8 au1_buf[512]; 123 IV_API_CALL_STATUS_T status; 124 125 s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; 126 s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_GETVERSION; 127 s_ctl_ip.u4_size = sizeof(ivd_ctl_getversioninfo_ip_t); 128 s_ctl_op.u4_size = sizeof(ivd_ctl_getversioninfo_op_t); 129 s_ctl_ip.pv_version_buffer = au1_buf; 130 s_ctl_ip.u4_version_buffer_size = sizeof(au1_buf); 131 132 status = ivdec_api_function(mCodecCtx, (void *)&s_ctl_ip, 133 (void *)&s_ctl_op); 134 135 if (status != IV_SUCCESS) { 136 ALOGE("Error in getting version number: 0x%x", 137 s_ctl_op.u4_error_code); 138 } else { 139 ALOGV("Ittiam decoder version number: %s", 140 (char *)s_ctl_ip.pv_version_buffer); 141 } 142 return; 143 } 144 145 status_t SoftHEVC::setParams(size_t stride) { 146 ivd_ctl_set_config_ip_t s_ctl_ip; 147 ivd_ctl_set_config_op_t s_ctl_op; 148 IV_API_CALL_STATUS_T status; 149 s_ctl_ip.u4_disp_wd = (UWORD32)stride; 150 s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE; 151 152 s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; 153 s_ctl_ip.e_vid_dec_mode = IVD_DECODE_FRAME; 154 s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; 155 s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS; 156 s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t); 157 s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t); 158 159 ALOGV("Set the run-time (dynamic) parameters stride = %zu", stride); 160 status = ivdec_api_function(mCodecCtx, (void *)&s_ctl_ip, 161 (void *)&s_ctl_op); 162 163 if (status != IV_SUCCESS) { 164 ALOGE("Error in setting the run-time parameters: 0x%x", 165 s_ctl_op.u4_error_code); 166 167 return UNKNOWN_ERROR; 168 } 169 return OK; 170 } 171 172 status_t SoftHEVC::resetPlugin() { 173 mIsInFlush = false; 174 mReceivedEOS = false; 175 memset(mTimeStamps, 0, sizeof(mTimeStamps)); 176 memset(mTimeStampsValid, 0, sizeof(mTimeStampsValid)); 177 178 /* Initialize both start and end times */ 179 gettimeofday(&mTimeStart, NULL); 180 gettimeofday(&mTimeEnd, NULL); 181 182 return OK; 183 } 184 185 bool SoftHEVC::getVUIParams() { 186 IV_API_CALL_STATUS_T status; 187 ihevcd_cxa_ctl_get_vui_params_ip_t s_ctl_get_vui_params_ip; 188 ihevcd_cxa_ctl_get_vui_params_op_t s_ctl_get_vui_params_op; 189 190 s_ctl_get_vui_params_ip.e_cmd = IVD_CMD_VIDEO_CTL; 191 s_ctl_get_vui_params_ip.e_sub_cmd = 192 (IVD_CONTROL_API_COMMAND_TYPE_T)IHEVCD_CXA_CMD_CTL_GET_VUI_PARAMS; 193 194 s_ctl_get_vui_params_ip.u4_size = 195 sizeof(ihevcd_cxa_ctl_get_vui_params_ip_t); 196 197 s_ctl_get_vui_params_op.u4_size = sizeof(ihevcd_cxa_ctl_get_vui_params_op_t); 198 199 status = ivdec_api_function( 200 (iv_obj_t *)mCodecCtx, (void *)&s_ctl_get_vui_params_ip, 201 (void *)&s_ctl_get_vui_params_op); 202 203 if (status != IV_SUCCESS) { 204 ALOGW("Error in getting VUI params: 0x%x", 205 s_ctl_get_vui_params_op.u4_error_code); 206 return false; 207 } 208 209 int32_t primaries = s_ctl_get_vui_params_op.u1_colour_primaries; 210 int32_t transfer = s_ctl_get_vui_params_op.u1_transfer_characteristics; 211 int32_t coeffs = s_ctl_get_vui_params_op.u1_matrix_coefficients; 212 bool fullRange = s_ctl_get_vui_params_op.u1_video_full_range_flag; 213 214 ColorAspects colorAspects; 215 ColorUtils::convertIsoColorAspectsToCodecAspects( 216 primaries, transfer, coeffs, fullRange, colorAspects); 217 218 // Update color aspects if necessary. 219 if (colorAspectsDiffer(colorAspects, mBitstreamColorAspects)) { 220 mBitstreamColorAspects = colorAspects; 221 status_t err = handleColorAspectsChange(); 222 CHECK(err == OK); 223 } 224 return true; 225 } 226 227 status_t SoftHEVC::resetDecoder() { 228 ivd_ctl_reset_ip_t s_ctl_ip; 229 ivd_ctl_reset_op_t s_ctl_op; 230 IV_API_CALL_STATUS_T status; 231 232 s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; 233 s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_RESET; 234 s_ctl_ip.u4_size = sizeof(ivd_ctl_reset_ip_t); 235 s_ctl_op.u4_size = sizeof(ivd_ctl_reset_op_t); 236 237 status = ivdec_api_function(mCodecCtx, (void *)&s_ctl_ip, 238 (void *)&s_ctl_op); 239 if (IV_SUCCESS != status) { 240 ALOGE("Error in reset: 0x%x", s_ctl_op.u4_error_code); 241 return UNKNOWN_ERROR; 242 } 243 mSignalledError = false; 244 245 /* Set number of cores/threads to be used by the codec */ 246 setNumCores(); 247 248 mStride = 0; 249 return OK; 250 } 251 252 status_t SoftHEVC::setNumCores() { 253 ivdext_ctl_set_num_cores_ip_t s_set_cores_ip; 254 ivdext_ctl_set_num_cores_op_t s_set_cores_op; 255 IV_API_CALL_STATUS_T status; 256 s_set_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL; 257 s_set_cores_ip.e_sub_cmd = IVDEXT_CMD_CTL_SET_NUM_CORES; 258 s_set_cores_ip.u4_num_cores = MIN(mNumCores, CODEC_MAX_NUM_CORES); 259 s_set_cores_ip.u4_size = sizeof(ivdext_ctl_set_num_cores_ip_t); 260 s_set_cores_op.u4_size = sizeof(ivdext_ctl_set_num_cores_op_t); 261 ALOGV("Set number of cores to %u", s_set_cores_ip.u4_num_cores); 262 status = ivdec_api_function(mCodecCtx, (void *)&s_set_cores_ip, 263 (void *)&s_set_cores_op); 264 if (IV_SUCCESS != status) { 265 ALOGE("Error in setting number of cores: 0x%x", 266 s_set_cores_op.u4_error_code); 267 return UNKNOWN_ERROR; 268 } 269 return OK; 270 } 271 272 status_t SoftHEVC::setFlushMode() { 273 IV_API_CALL_STATUS_T status; 274 ivd_ctl_flush_ip_t s_video_flush_ip; 275 ivd_ctl_flush_op_t s_video_flush_op; 276 277 s_video_flush_ip.e_cmd = IVD_CMD_VIDEO_CTL; 278 s_video_flush_ip.e_sub_cmd = IVD_CMD_CTL_FLUSH; 279 s_video_flush_ip.u4_size = sizeof(ivd_ctl_flush_ip_t); 280 s_video_flush_op.u4_size = sizeof(ivd_ctl_flush_op_t); 281 ALOGV("Set the decoder in flush mode "); 282 283 /* Set the decoder in Flush mode, subsequent decode() calls will flush */ 284 status = ivdec_api_function(mCodecCtx, (void *)&s_video_flush_ip, 285 (void *)&s_video_flush_op); 286 287 if (status != IV_SUCCESS) { 288 ALOGE("Error in setting the decoder in flush mode: (%d) 0x%x", status, 289 s_video_flush_op.u4_error_code); 290 return UNKNOWN_ERROR; 291 } 292 293 mIsInFlush = true; 294 return OK; 295 } 296 297 status_t SoftHEVC::initDecoder() { 298 IV_API_CALL_STATUS_T status; 299 300 mNumCores = GetCPUCoreCount(); 301 mCodecCtx = NULL; 302 303 mStride = outputBufferWidth(); 304 305 /* Initialize the decoder */ 306 { 307 ivdext_create_ip_t s_create_ip; 308 ivdext_create_op_t s_create_op; 309 310 void *dec_fxns = (void *)ivdec_api_function; 311 312 s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ivdext_create_ip_t); 313 s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE; 314 s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 0; 315 s_create_op.s_ivd_create_op_t.u4_size = sizeof(ivdext_create_op_t); 316 s_create_ip.s_ivd_create_ip_t.e_output_format = mIvColorFormat; 317 s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ivd_aligned_malloc; 318 s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ivd_aligned_free; 319 s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = NULL; 320 321 status = ivdec_api_function(mCodecCtx, (void *)&s_create_ip, (void *)&s_create_op); 322 323 mCodecCtx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle; 324 mCodecCtx->pv_fxns = dec_fxns; 325 mCodecCtx->u4_size = sizeof(iv_obj_t); 326 327 if (status != IV_SUCCESS) { 328 ALOGE("Error in create: 0x%x", 329 s_create_op.s_ivd_create_op_t.u4_error_code); 330 deInitDecoder(); 331 mCodecCtx = NULL; 332 return UNKNOWN_ERROR; 333 } 334 } 335 336 /* Reset the plugin state */ 337 resetPlugin(); 338 339 /* Set the run time (dynamic) parameters */ 340 setParams(mStride); 341 342 /* Set number of cores/threads to be used by the codec */ 343 setNumCores(); 344 345 /* Get codec version */ 346 logVersion(); 347 348 mFlushNeeded = false; 349 return OK; 350 } 351 352 status_t SoftHEVC::deInitDecoder() { 353 size_t i; 354 IV_API_CALL_STATUS_T status; 355 356 if (mCodecCtx) { 357 ivdext_delete_ip_t s_delete_ip; 358 ivdext_delete_op_t s_delete_op; 359 360 s_delete_ip.s_ivd_delete_ip_t.u4_size = sizeof(ivdext_delete_ip_t); 361 s_delete_ip.s_ivd_delete_ip_t.e_cmd = IVD_CMD_DELETE; 362 363 s_delete_op.s_ivd_delete_op_t.u4_size = sizeof(ivdext_delete_op_t); 364 365 status = ivdec_api_function(mCodecCtx, (void *)&s_delete_ip, (void *)&s_delete_op); 366 if (status != IV_SUCCESS) { 367 ALOGE("Error in delete: 0x%x", 368 s_delete_op.s_ivd_delete_op_t.u4_error_code); 369 return UNKNOWN_ERROR; 370 } 371 } 372 373 374 mChangingResolution = false; 375 376 return OK; 377 } 378 379 void SoftHEVC::onReset() { 380 ALOGV("onReset called"); 381 SoftVideoDecoderOMXComponent::onReset(); 382 383 mSignalledError = false; 384 resetDecoder(); 385 resetPlugin(); 386 } 387 388 bool SoftHEVC::setDecodeArgs(ivd_video_decode_ip_t *ps_dec_ip, 389 ivd_video_decode_op_t *ps_dec_op, 390 OMX_BUFFERHEADERTYPE *inHeader, 391 OMX_BUFFERHEADERTYPE *outHeader, 392 size_t timeStampIx) { 393 size_t sizeY = outputBufferWidth() * outputBufferHeight(); 394 size_t sizeUV; 395 396 ps_dec_ip->u4_size = sizeof(ivd_video_decode_ip_t); 397 ps_dec_op->u4_size = sizeof(ivd_video_decode_op_t); 398 399 ps_dec_ip->e_cmd = IVD_CMD_VIDEO_DECODE; 400 401 /* When in flush and after EOS with zero byte input, 402 * inHeader is set to zero. Hence check for non-null */ 403 if (inHeader) { 404 ps_dec_ip->u4_ts = timeStampIx; 405 ps_dec_ip->pv_stream_buffer = inHeader->pBuffer 406 + inHeader->nOffset; 407 ps_dec_ip->u4_num_Bytes = inHeader->nFilledLen; 408 } else { 409 ps_dec_ip->u4_ts = 0; 410 ps_dec_ip->pv_stream_buffer = NULL; 411 ps_dec_ip->u4_num_Bytes = 0; 412 } 413 414 sizeUV = sizeY / 4; 415 ps_dec_ip->s_out_buffer.u4_min_out_buf_size[0] = sizeY; 416 ps_dec_ip->s_out_buffer.u4_min_out_buf_size[1] = sizeUV; 417 ps_dec_ip->s_out_buffer.u4_min_out_buf_size[2] = sizeUV; 418 419 uint8_t *pBuf; 420 if (outHeader) { 421 if (outHeader->nAllocLen < sizeY + (sizeUV * 2)) { 422 android_errorWriteLog(0x534e4554, "27833616"); 423 return false; 424 } 425 pBuf = outHeader->pBuffer; 426 } else { 427 // mFlushOutBuffer always has the right size. 428 pBuf = mFlushOutBuffer; 429 } 430 431 ps_dec_ip->s_out_buffer.pu1_bufs[0] = pBuf; 432 ps_dec_ip->s_out_buffer.pu1_bufs[1] = pBuf + sizeY; 433 ps_dec_ip->s_out_buffer.pu1_bufs[2] = pBuf + sizeY + sizeUV; 434 ps_dec_ip->s_out_buffer.u4_num_bufs = 3; 435 return true; 436 } 437 void SoftHEVC::onPortFlushCompleted(OMX_U32 portIndex) { 438 /* Once the output buffers are flushed, ignore any buffers that are held in decoder */ 439 if (kOutputPortIndex == portIndex) { 440 setFlushMode(); 441 442 /* Allocate a picture buffer to flushed data */ 443 uint32_t displayStride = outputBufferWidth(); 444 uint32_t displayHeight = outputBufferHeight(); 445 446 uint32_t bufferSize = displayStride * displayHeight * 3 / 2; 447 mFlushOutBuffer = (uint8_t *)memalign(128, bufferSize); 448 if (NULL == mFlushOutBuffer) { 449 ALOGE("Could not allocate flushOutputBuffer of size %u", bufferSize); 450 return; 451 } 452 453 while (true) { 454 ivd_video_decode_ip_t s_dec_ip; 455 ivd_video_decode_op_t s_dec_op; 456 IV_API_CALL_STATUS_T status; 457 size_t sizeY, sizeUV; 458 459 setDecodeArgs(&s_dec_ip, &s_dec_op, NULL, NULL, 0); 460 461 status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, 462 (void *)&s_dec_op); 463 if (0 == s_dec_op.u4_output_present) { 464 resetPlugin(); 465 break; 466 } 467 } 468 469 if (mFlushOutBuffer) { 470 free(mFlushOutBuffer); 471 mFlushOutBuffer = NULL; 472 } 473 474 } 475 } 476 477 void SoftHEVC::onQueueFilled(OMX_U32 portIndex) { 478 UNUSED(portIndex); 479 480 if (mSignalledError) { 481 return; 482 } 483 if (mOutputPortSettingsChange != NONE) { 484 return; 485 } 486 487 if (NULL == mCodecCtx) { 488 if (OK != initDecoder()) { 489 ALOGE("Failed to initialize decoder"); 490 notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL); 491 mSignalledError = true; 492 return; 493 } 494 } 495 if (outputBufferWidth() != mStride) { 496 /* Set the run-time (dynamic) parameters */ 497 mStride = outputBufferWidth(); 498 setParams(mStride); 499 } 500 501 List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex); 502 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex); 503 504 while (!outQueue.empty()) { 505 BufferInfo *inInfo; 506 OMX_BUFFERHEADERTYPE *inHeader; 507 508 BufferInfo *outInfo; 509 OMX_BUFFERHEADERTYPE *outHeader; 510 size_t timeStampIx; 511 512 inInfo = NULL; 513 inHeader = NULL; 514 515 if (!mIsInFlush) { 516 if (!inQueue.empty()) { 517 inInfo = *inQueue.begin(); 518 inHeader = inInfo->mHeader; 519 } else { 520 break; 521 } 522 } 523 524 outInfo = *outQueue.begin(); 525 outHeader = outInfo->mHeader; 526 outHeader->nFlags = 0; 527 outHeader->nTimeStamp = 0; 528 outHeader->nOffset = 0; 529 530 if (inHeader != NULL && (inHeader->nFlags & OMX_BUFFERFLAG_EOS)) { 531 mReceivedEOS = true; 532 if (inHeader->nFilledLen == 0) { 533 inQueue.erase(inQueue.begin()); 534 inInfo->mOwnedByUs = false; 535 notifyEmptyBufferDone(inHeader); 536 inHeader = NULL; 537 setFlushMode(); 538 } 539 } 540 541 /* Get a free slot in timestamp array to hold input timestamp */ 542 { 543 size_t i; 544 timeStampIx = 0; 545 for (i = 0; i < MAX_TIME_STAMPS; i++) { 546 if (!mTimeStampsValid[i]) { 547 timeStampIx = i; 548 break; 549 } 550 } 551 if (inHeader != NULL) { 552 mTimeStampsValid[timeStampIx] = true; 553 mTimeStamps[timeStampIx] = inHeader->nTimeStamp; 554 } 555 } 556 557 { 558 ivd_video_decode_ip_t s_dec_ip; 559 ivd_video_decode_op_t s_dec_op; 560 WORD32 timeDelay, timeTaken; 561 size_t sizeY, sizeUV; 562 563 if (!setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx)) { 564 ALOGE("Decoder arg setup failed"); 565 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 566 mSignalledError = true; 567 return; 568 } 569 570 GETTIME(&mTimeStart, NULL); 571 /* Compute time elapsed between end of previous decode() 572 * to start of current decode() */ 573 TIME_DIFF(mTimeEnd, mTimeStart, timeDelay); 574 575 IV_API_CALL_STATUS_T status; 576 status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op); 577 578 bool unsupportedResolution = 579 (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_dec_op.u4_error_code & 0xFF)); 580 581 /* Check for unsupported dimensions */ 582 if (unsupportedResolution) { 583 ALOGE("Unsupported resolution : %dx%d", mWidth, mHeight); 584 notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL); 585 mSignalledError = true; 586 return; 587 } 588 589 bool allocationFailed = (IVD_MEM_ALLOC_FAILED == (s_dec_op.u4_error_code & 0xFF)); 590 if (allocationFailed) { 591 ALOGE("Allocation failure in decoder"); 592 notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL); 593 mSignalledError = true; 594 return; 595 } 596 597 bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF)); 598 599 getVUIParams(); 600 601 GETTIME(&mTimeEnd, NULL); 602 /* Compute time taken for decode() */ 603 TIME_DIFF(mTimeStart, mTimeEnd, timeTaken); 604 605 ALOGV("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay, 606 s_dec_op.u4_num_bytes_consumed); 607 if (s_dec_op.u4_frame_decoded_flag && !mFlushNeeded) { 608 mFlushNeeded = true; 609 } 610 611 if ((inHeader != NULL) && (1 != s_dec_op.u4_frame_decoded_flag)) { 612 /* If the input did not contain picture data, then ignore 613 * the associated timestamp */ 614 mTimeStampsValid[timeStampIx] = false; 615 } 616 617 // If the decoder is in the changing resolution mode and there is no output present, 618 // that means the switching is done and it's ready to reset the decoder and the plugin. 619 if (mChangingResolution && !s_dec_op.u4_output_present) { 620 mChangingResolution = false; 621 resetDecoder(); 622 resetPlugin(); 623 mStride = outputBufferWidth(); 624 setParams(mStride); 625 continue; 626 } 627 628 if (resChanged) { 629 mChangingResolution = true; 630 if (mFlushNeeded) { 631 setFlushMode(); 632 } 633 continue; 634 } 635 636 // Combine the resolution change and coloraspects change in one PortSettingChange event 637 // if necessary. 638 if ((0 < s_dec_op.u4_pic_wd) && (0 < s_dec_op.u4_pic_ht)) { 639 uint32_t width = s_dec_op.u4_pic_wd; 640 uint32_t height = s_dec_op.u4_pic_ht; 641 bool portWillReset = false; 642 handlePortSettingsChange(&portWillReset, width, height); 643 644 if (portWillReset) { 645 resetDecoder(); 646 return; 647 } 648 } else if (mUpdateColorAspects) { 649 notify(OMX_EventPortSettingsChanged, kOutputPortIndex, 650 kDescribeColorAspectsIndex, NULL); 651 mUpdateColorAspects = false; 652 return; 653 } 654 655 if (s_dec_op.u4_output_present) { 656 outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2; 657 658 outHeader->nTimeStamp = mTimeStamps[s_dec_op.u4_ts]; 659 mTimeStampsValid[s_dec_op.u4_ts] = false; 660 661 outInfo->mOwnedByUs = false; 662 outQueue.erase(outQueue.begin()); 663 outInfo = NULL; 664 notifyFillBufferDone(outHeader); 665 outHeader = NULL; 666 } else if (mIsInFlush) { 667 /* If in flush mode and no output is returned by the codec, 668 * then come out of flush mode */ 669 mIsInFlush = false; 670 671 /* If EOS was recieved on input port and there is no output 672 * from the codec, then signal EOS on output port */ 673 if (mReceivedEOS) { 674 outHeader->nFilledLen = 0; 675 outHeader->nFlags |= OMX_BUFFERFLAG_EOS; 676 677 outInfo->mOwnedByUs = false; 678 outQueue.erase(outQueue.begin()); 679 outInfo = NULL; 680 notifyFillBufferDone(outHeader); 681 outHeader = NULL; 682 resetPlugin(); 683 } 684 } 685 } 686 687 /* If input EOS is seen and decoder is not in flush mode, 688 * set the decoder in flush mode. 689 * There can be a case where EOS is sent along with last picture data 690 * In that case, only after decoding that input data, decoder has to be 691 * put in flush. This case is handled here */ 692 693 if (mReceivedEOS && !mIsInFlush) { 694 setFlushMode(); 695 } 696 697 // TODO: Handle more than one picture data 698 if (inHeader != NULL) { 699 inInfo->mOwnedByUs = false; 700 inQueue.erase(inQueue.begin()); 701 inInfo = NULL; 702 notifyEmptyBufferDone(inHeader); 703 inHeader = NULL; 704 } 705 } 706 } 707 708 int SoftHEVC::getColorAspectPreference() { 709 return kPreferBitstream; 710 } 711 712 } // namespace android 713 714 android::SoftOMXComponent *createSoftOMXComponent(const char *name, 715 const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData, 716 OMX_COMPONENTTYPE **component) { 717 android::SoftHEVC *codec = new android::SoftHEVC(name, callbacks, appData, component); 718 if (codec->init() != android::OK) { 719 android::sp<android::SoftOMXComponent> release = codec; 720 return NULL; 721 } 722 return codec; 723 } 724