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