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