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 "SoftMPEG2" 19 #include <utils/Log.h> 20 21 #include "iv_datatypedef.h" 22 #include "iv.h" 23 #include "ivd.h" 24 #include "impeg2d.h" 25 #include "SoftMPEG2.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 componentName "video_decoder.mpeg2" 34 #define codingType OMX_VIDEO_CodingMPEG2 35 #define CODEC_MIME_TYPE MEDIA_MIMETYPE_VIDEO_MPEG2 36 37 /** Function and structure definitions to keep code similar for each codec */ 38 #define ivdec_api_function impeg2d_api_function 39 #define ivdext_init_ip_t impeg2d_init_ip_t 40 #define ivdext_init_op_t impeg2d_init_op_t 41 #define ivdext_fill_mem_rec_ip_t impeg2d_fill_mem_rec_ip_t 42 #define ivdext_fill_mem_rec_op_t impeg2d_fill_mem_rec_op_t 43 #define ivdext_ctl_set_num_cores_ip_t impeg2d_ctl_set_num_cores_ip_t 44 #define ivdext_ctl_set_num_cores_op_t impeg2d_ctl_set_num_cores_op_t 45 46 #define IVDEXT_CMD_CTL_SET_NUM_CORES \ 47 (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_SET_NUM_CORES 48 49 static const CodecProfileLevel kProfileLevels[] = { 50 { OMX_VIDEO_MPEG2ProfileSimple, OMX_VIDEO_MPEG2LevelHL }, 51 52 { OMX_VIDEO_MPEG2ProfileMain , OMX_VIDEO_MPEG2LevelHL }, 53 }; 54 55 SoftMPEG2::SoftMPEG2( 56 const char *name, 57 const OMX_CALLBACKTYPE *callbacks, 58 OMX_PTR appData, 59 OMX_COMPONENTTYPE **component) 60 : SoftVideoDecoderOMXComponent( 61 name, componentName, codingType, 62 kProfileLevels, ARRAY_SIZE(kProfileLevels), 63 320 /* width */, 240 /* height */, callbacks, 64 appData, component), 65 mCodecCtx(NULL), 66 mMemRecords(NULL), 67 mFlushOutBuffer(NULL), 68 mOmxColorFormat(OMX_COLOR_FormatYUV420Planar), 69 mIvColorFormat(IV_YUV_420P), 70 mNewWidth(mWidth), 71 mNewHeight(mHeight), 72 mChangingResolution(false), 73 mSignalledError(false), 74 mStride(mWidth) { 75 initPorts(kNumBuffers, INPUT_BUF_SIZE, kNumBuffers, CODEC_MIME_TYPE); 76 77 // If input dump is enabled, then open create an empty file 78 GENERATE_FILE_NAMES(); 79 CREATE_DUMP_FILE(mInFile); 80 } 81 82 SoftMPEG2::~SoftMPEG2() { 83 if (OK != deInitDecoder()) { 84 ALOGE("Failed to deinit decoder"); 85 notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL); 86 mSignalledError = true; 87 return; 88 } 89 } 90 91 92 static ssize_t getMinTimestampIdx(OMX_S64 *pNTimeStamp, bool *pIsTimeStampValid) { 93 OMX_S64 minTimeStamp = LLONG_MAX; 94 ssize_t idx = -1; 95 for (ssize_t i = 0; i < MAX_TIME_STAMPS; i++) { 96 if (pIsTimeStampValid[i]) { 97 if (pNTimeStamp[i] < minTimeStamp) { 98 minTimeStamp = pNTimeStamp[i]; 99 idx = i; 100 } 101 } 102 } 103 return idx; 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 SoftMPEG2::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, (void *)&s_ctl_op); 133 134 if (status != IV_SUCCESS) { 135 ALOGE("Error in getting version number: 0x%x", 136 s_ctl_op.u4_error_code); 137 } else { 138 ALOGV("Ittiam decoder version number: %s", 139 (char *)s_ctl_ip.pv_version_buffer); 140 } 141 return; 142 } 143 144 status_t SoftMPEG2::setParams(size_t stride) { 145 ivd_ctl_set_config_ip_t s_ctl_ip; 146 ivd_ctl_set_config_op_t s_ctl_op; 147 IV_API_CALL_STATUS_T status; 148 s_ctl_ip.u4_disp_wd = (UWORD32)stride; 149 s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE; 150 151 s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; 152 s_ctl_ip.e_vid_dec_mode = IVD_DECODE_FRAME; 153 s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; 154 s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS; 155 s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t); 156 s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t); 157 158 ALOGV("Set the run-time (dynamic) parameters stride = %zu", stride); 159 status = ivdec_api_function(mCodecCtx, (void *)&s_ctl_ip, (void *)&s_ctl_op); 160 161 if (status != IV_SUCCESS) { 162 ALOGE("Error in setting the run-time parameters: 0x%x", 163 s_ctl_op.u4_error_code); 164 165 return UNKNOWN_ERROR; 166 } 167 return OK; 168 } 169 170 status_t SoftMPEG2::resetPlugin() { 171 mIsInFlush = false; 172 mReceivedEOS = false; 173 memset(mTimeStamps, 0, sizeof(mTimeStamps)); 174 memset(mTimeStampsValid, 0, sizeof(mTimeStampsValid)); 175 176 /* Initialize both start and end times */ 177 gettimeofday(&mTimeStart, NULL); 178 gettimeofday(&mTimeEnd, NULL); 179 180 return OK; 181 } 182 183 status_t SoftMPEG2::resetDecoder() { 184 ivd_ctl_reset_ip_t s_ctl_ip; 185 ivd_ctl_reset_op_t s_ctl_op; 186 IV_API_CALL_STATUS_T status; 187 188 s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; 189 s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_RESET; 190 s_ctl_ip.u4_size = sizeof(ivd_ctl_reset_ip_t); 191 s_ctl_op.u4_size = sizeof(ivd_ctl_reset_op_t); 192 193 status = ivdec_api_function(mCodecCtx, (void *)&s_ctl_ip, (void *)&s_ctl_op); 194 if (IV_SUCCESS != status) { 195 ALOGE("Error in reset: 0x%x", s_ctl_op.u4_error_code); 196 return UNKNOWN_ERROR; 197 } 198 199 /* Set the run-time (dynamic) parameters */ 200 setParams(outputBufferWidth()); 201 202 /* Set number of cores/threads to be used by the codec */ 203 setNumCores(); 204 205 mStride = 0; 206 mSignalledError = false; 207 208 return OK; 209 } 210 211 status_t SoftMPEG2::setNumCores() { 212 ivdext_ctl_set_num_cores_ip_t s_set_cores_ip; 213 ivdext_ctl_set_num_cores_op_t s_set_cores_op; 214 IV_API_CALL_STATUS_T status; 215 s_set_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL; 216 s_set_cores_ip.e_sub_cmd = IVDEXT_CMD_CTL_SET_NUM_CORES; 217 s_set_cores_ip.u4_num_cores = MIN(mNumCores, CODEC_MAX_NUM_CORES); 218 s_set_cores_ip.u4_size = sizeof(ivdext_ctl_set_num_cores_ip_t); 219 s_set_cores_op.u4_size = sizeof(ivdext_ctl_set_num_cores_op_t); 220 221 status = ivdec_api_function(mCodecCtx, (void *)&s_set_cores_ip, (void *)&s_set_cores_op); 222 if (IV_SUCCESS != status) { 223 ALOGE("Error in setting number of cores: 0x%x", 224 s_set_cores_op.u4_error_code); 225 return UNKNOWN_ERROR; 226 } 227 return OK; 228 } 229 230 status_t SoftMPEG2::setFlushMode() { 231 IV_API_CALL_STATUS_T status; 232 ivd_ctl_flush_ip_t s_video_flush_ip; 233 ivd_ctl_flush_op_t s_video_flush_op; 234 235 s_video_flush_ip.e_cmd = IVD_CMD_VIDEO_CTL; 236 s_video_flush_ip.e_sub_cmd = IVD_CMD_CTL_FLUSH; 237 s_video_flush_ip.u4_size = sizeof(ivd_ctl_flush_ip_t); 238 s_video_flush_op.u4_size = sizeof(ivd_ctl_flush_op_t); 239 240 /* Set the decoder in Flush mode, subsequent decode() calls will flush */ 241 status = ivdec_api_function( 242 mCodecCtx, (void *)&s_video_flush_ip, (void *)&s_video_flush_op); 243 244 if (status != IV_SUCCESS) { 245 ALOGE("Error in setting the decoder in flush mode: (%d) 0x%x", status, 246 s_video_flush_op.u4_error_code); 247 return UNKNOWN_ERROR; 248 } 249 250 mWaitForI = true; 251 mIsInFlush = true; 252 return OK; 253 } 254 255 status_t SoftMPEG2::initDecoder() { 256 IV_API_CALL_STATUS_T status; 257 258 UWORD32 u4_num_reorder_frames; 259 UWORD32 u4_num_ref_frames; 260 UWORD32 u4_share_disp_buf; 261 262 mNumCores = GetCPUCoreCount(); 263 mWaitForI = true; 264 265 /* Initialize number of ref and reorder modes (for MPEG2) */ 266 u4_num_reorder_frames = 16; 267 u4_num_ref_frames = 16; 268 u4_share_disp_buf = 0; 269 270 uint32_t displayStride = outputBufferWidth(); 271 uint32_t displayHeight = outputBufferHeight(); 272 uint32_t displaySizeY = displayStride * displayHeight; 273 274 { 275 iv_num_mem_rec_ip_t s_num_mem_rec_ip; 276 iv_num_mem_rec_op_t s_num_mem_rec_op; 277 278 s_num_mem_rec_ip.u4_size = sizeof(s_num_mem_rec_ip); 279 s_num_mem_rec_op.u4_size = sizeof(s_num_mem_rec_op); 280 s_num_mem_rec_ip.e_cmd = IV_CMD_GET_NUM_MEM_REC; 281 282 status = ivdec_api_function( 283 mCodecCtx, (void *)&s_num_mem_rec_ip, (void *)&s_num_mem_rec_op); 284 if (IV_SUCCESS != status) { 285 ALOGE("Error in getting mem records: 0x%x", 286 s_num_mem_rec_op.u4_error_code); 287 return UNKNOWN_ERROR; 288 } 289 290 mNumMemRecords = s_num_mem_rec_op.u4_num_mem_rec; 291 } 292 293 mMemRecords = (iv_mem_rec_t *)ivd_aligned_malloc( 294 128, mNumMemRecords * sizeof(iv_mem_rec_t)); 295 if (mMemRecords == NULL) { 296 ALOGE("Allocation failure"); 297 return NO_MEMORY; 298 } 299 300 memset(mMemRecords, 0, mNumMemRecords * sizeof(iv_mem_rec_t)); 301 302 { 303 size_t i; 304 ivdext_fill_mem_rec_ip_t s_fill_mem_ip; 305 ivdext_fill_mem_rec_op_t s_fill_mem_op; 306 iv_mem_rec_t *ps_mem_rec; 307 308 s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_size = 309 sizeof(ivdext_fill_mem_rec_ip_t); 310 311 s_fill_mem_ip.u4_share_disp_buf = u4_share_disp_buf; 312 s_fill_mem_ip.e_output_format = mIvColorFormat; 313 s_fill_mem_ip.u4_deinterlace = 1; 314 s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.e_cmd = IV_CMD_FILL_NUM_MEM_REC; 315 s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.pv_mem_rec_location = mMemRecords; 316 s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_wd = displayStride; 317 s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_ht = displayHeight; 318 s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_size = 319 sizeof(ivdext_fill_mem_rec_op_t); 320 321 ps_mem_rec = mMemRecords; 322 for (i = 0; i < mNumMemRecords; i++) { 323 ps_mem_rec[i].u4_size = sizeof(iv_mem_rec_t); 324 } 325 326 status = ivdec_api_function( 327 mCodecCtx, (void *)&s_fill_mem_ip, (void *)&s_fill_mem_op); 328 329 if (IV_SUCCESS != status) { 330 ALOGE("Error in filling mem records: 0x%x", 331 s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_error_code); 332 return UNKNOWN_ERROR; 333 } 334 mNumMemRecords = 335 s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_num_mem_rec_filled; 336 337 ps_mem_rec = mMemRecords; 338 339 for (i = 0; i < mNumMemRecords; i++) { 340 ps_mem_rec->pv_base = ivd_aligned_malloc( 341 ps_mem_rec->u4_mem_alignment, ps_mem_rec->u4_mem_size); 342 if (ps_mem_rec->pv_base == NULL) { 343 ALOGE("Allocation failure for memory record #%zu of size %u", 344 i, ps_mem_rec->u4_mem_size); 345 status = IV_FAIL; 346 return NO_MEMORY; 347 } 348 349 ps_mem_rec++; 350 } 351 } 352 353 /* Initialize the decoder */ 354 { 355 ivdext_init_ip_t s_init_ip; 356 ivdext_init_op_t s_init_op; 357 358 void *dec_fxns = (void *)ivdec_api_function; 359 360 s_init_ip.s_ivd_init_ip_t.u4_size = sizeof(ivdext_init_ip_t); 361 s_init_ip.s_ivd_init_ip_t.e_cmd = (IVD_API_COMMAND_TYPE_T)IV_CMD_INIT; 362 s_init_ip.s_ivd_init_ip_t.pv_mem_rec_location = mMemRecords; 363 s_init_ip.s_ivd_init_ip_t.u4_frm_max_wd = displayStride; 364 s_init_ip.s_ivd_init_ip_t.u4_frm_max_ht = displayHeight; 365 366 s_init_ip.u4_share_disp_buf = u4_share_disp_buf; 367 s_init_ip.u4_deinterlace = 1; 368 369 s_init_op.s_ivd_init_op_t.u4_size = sizeof(s_init_op); 370 371 s_init_ip.s_ivd_init_ip_t.u4_num_mem_rec = mNumMemRecords; 372 s_init_ip.s_ivd_init_ip_t.e_output_format = mIvColorFormat; 373 374 mCodecCtx = (iv_obj_t *)mMemRecords[0].pv_base; 375 mCodecCtx->pv_fxns = dec_fxns; 376 mCodecCtx->u4_size = sizeof(iv_obj_t); 377 378 status = ivdec_api_function(mCodecCtx, (void *)&s_init_ip, (void *)&s_init_op); 379 if (status != IV_SUCCESS) { 380 ALOGE("Error in init: 0x%x", 381 s_init_op.s_ivd_init_op_t.u4_error_code); 382 return UNKNOWN_ERROR; 383 } 384 } 385 386 /* Reset the plugin state */ 387 resetPlugin(); 388 389 /* Set the run time (dynamic) parameters */ 390 mStride = outputBufferWidth(); 391 setParams(mStride); 392 393 /* Set number of cores/threads to be used by the codec */ 394 setNumCores(); 395 396 /* Get codec version */ 397 logVersion(); 398 399 /* Allocate internal picture buffer */ 400 uint32_t bufferSize = displaySizeY * 3 / 2; 401 mFlushOutBuffer = (uint8_t *)ivd_aligned_malloc(128, bufferSize); 402 if (NULL == mFlushOutBuffer) { 403 ALOGE("Could not allocate flushOutputBuffer of size %u", bufferSize); 404 return NO_MEMORY; 405 } 406 407 mInitNeeded = false; 408 mFlushNeeded = false; 409 return OK; 410 } 411 412 status_t SoftMPEG2::deInitDecoder() { 413 size_t i; 414 415 if (mMemRecords) { 416 iv_mem_rec_t *ps_mem_rec; 417 418 ps_mem_rec = mMemRecords; 419 for (i = 0; i < mNumMemRecords; i++) { 420 if (ps_mem_rec->pv_base) { 421 ivd_aligned_free(ps_mem_rec->pv_base); 422 } 423 ps_mem_rec++; 424 } 425 ivd_aligned_free(mMemRecords); 426 mMemRecords = NULL; 427 } 428 429 if (mFlushOutBuffer) { 430 ivd_aligned_free(mFlushOutBuffer); 431 mFlushOutBuffer = NULL; 432 } 433 434 mInitNeeded = true; 435 mChangingResolution = false; 436 mCodecCtx = NULL; 437 438 return OK; 439 } 440 441 status_t SoftMPEG2::reInitDecoder() { 442 status_t ret; 443 444 deInitDecoder(); 445 446 ret = initDecoder(); 447 if (OK != ret) { 448 ALOGE("Failed to initialize decoder"); 449 deInitDecoder(); 450 return ret; 451 } 452 mSignalledError = false; 453 return OK; 454 } 455 456 void SoftMPEG2::onReset() { 457 SoftVideoDecoderOMXComponent::onReset(); 458 459 mWaitForI = true; 460 461 resetDecoder(); 462 resetPlugin(); 463 } 464 465 bool SoftMPEG2::getSeqInfo() { 466 IV_API_CALL_STATUS_T status; 467 impeg2d_ctl_get_seq_info_ip_t s_ctl_get_seq_info_ip; 468 impeg2d_ctl_get_seq_info_op_t s_ctl_get_seq_info_op; 469 470 s_ctl_get_seq_info_ip.e_cmd = IVD_CMD_VIDEO_CTL; 471 s_ctl_get_seq_info_ip.e_sub_cmd = 472 (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_GET_SEQ_INFO; 473 474 s_ctl_get_seq_info_ip.u4_size = sizeof(impeg2d_ctl_get_seq_info_ip_t); 475 s_ctl_get_seq_info_op.u4_size = sizeof(impeg2d_ctl_get_seq_info_op_t); 476 477 status = ivdec_api_function( 478 (iv_obj_t *)mCodecCtx, (void *)&s_ctl_get_seq_info_ip, 479 (void *)&s_ctl_get_seq_info_op); 480 481 if (status != IV_SUCCESS) { 482 ALOGW("Error in getting Sequence info: 0x%x", 483 s_ctl_get_seq_info_op.u4_error_code); 484 return false; 485 } 486 487 488 int32_t primaries = s_ctl_get_seq_info_op.u1_colour_primaries; 489 int32_t transfer = s_ctl_get_seq_info_op.u1_transfer_characteristics; 490 int32_t coeffs = s_ctl_get_seq_info_op.u1_matrix_coefficients; 491 bool fullRange = false; // mpeg2 video has limited range. 492 493 ColorAspects colorAspects; 494 ColorUtils::convertIsoColorAspectsToCodecAspects( 495 primaries, transfer, coeffs, fullRange, colorAspects); 496 497 // Update color aspects if necessary. 498 if (colorAspectsDiffer(colorAspects, mBitstreamColorAspects)) { 499 mBitstreamColorAspects = colorAspects; 500 status_t err = handleColorAspectsChange(); 501 CHECK(err == OK); 502 } 503 return true; 504 } 505 506 OMX_ERRORTYPE SoftMPEG2::internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR params) { 507 const uint32_t oldWidth = mWidth; 508 const uint32_t oldHeight = mHeight; 509 OMX_ERRORTYPE ret = SoftVideoDecoderOMXComponent::internalSetParameter(index, params); 510 if (mWidth != oldWidth || mHeight != oldHeight) { 511 reInitDecoder(); 512 } 513 return ret; 514 } 515 516 bool SoftMPEG2::setDecodeArgs( 517 ivd_video_decode_ip_t *ps_dec_ip, 518 ivd_video_decode_op_t *ps_dec_op, 519 OMX_BUFFERHEADERTYPE *inHeader, 520 OMX_BUFFERHEADERTYPE *outHeader, 521 size_t timeStampIx) { 522 size_t sizeY = outputBufferWidth() * outputBufferHeight(); 523 size_t sizeUV; 524 525 ps_dec_ip->u4_size = sizeof(ivd_video_decode_ip_t); 526 ps_dec_op->u4_size = sizeof(ivd_video_decode_op_t); 527 528 ps_dec_ip->e_cmd = IVD_CMD_VIDEO_DECODE; 529 530 /* When in flush and after EOS with zero byte input, 531 * inHeader is set to zero. Hence check for non-null */ 532 if (inHeader) { 533 ps_dec_ip->u4_ts = timeStampIx; 534 ps_dec_ip->pv_stream_buffer = inHeader->pBuffer 535 + inHeader->nOffset; 536 ps_dec_ip->u4_num_Bytes = inHeader->nFilledLen; 537 } else { 538 ps_dec_ip->u4_ts = 0; 539 ps_dec_ip->pv_stream_buffer = NULL; 540 ps_dec_ip->u4_num_Bytes = 0; 541 } 542 543 sizeUV = sizeY / 4; 544 ps_dec_ip->s_out_buffer.u4_min_out_buf_size[0] = sizeY; 545 ps_dec_ip->s_out_buffer.u4_min_out_buf_size[1] = sizeUV; 546 ps_dec_ip->s_out_buffer.u4_min_out_buf_size[2] = sizeUV; 547 548 uint8_t *pBuf; 549 if (outHeader) { 550 if (outHeader->nAllocLen < sizeY + (sizeUV * 2)) { 551 android_errorWriteLog(0x534e4554, "27833616"); 552 return false; 553 } 554 pBuf = outHeader->pBuffer; 555 } else { 556 // mFlushOutBuffer always has the right size. 557 pBuf = mFlushOutBuffer; 558 } 559 560 ps_dec_ip->s_out_buffer.pu1_bufs[0] = pBuf; 561 ps_dec_ip->s_out_buffer.pu1_bufs[1] = pBuf + sizeY; 562 ps_dec_ip->s_out_buffer.pu1_bufs[2] = pBuf + sizeY + sizeUV; 563 ps_dec_ip->s_out_buffer.u4_num_bufs = 3; 564 return true; 565 } 566 void SoftMPEG2::onPortFlushCompleted(OMX_U32 portIndex) { 567 /* Once the output buffers are flushed, ignore any buffers that are held in decoder */ 568 if (kOutputPortIndex == portIndex) { 569 setFlushMode(); 570 571 while (true) { 572 ivd_video_decode_ip_t s_dec_ip; 573 ivd_video_decode_op_t s_dec_op; 574 IV_API_CALL_STATUS_T status; 575 size_t sizeY, sizeUV; 576 577 setDecodeArgs(&s_dec_ip, &s_dec_op, NULL, NULL, 0); 578 579 status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op); 580 if (0 == s_dec_op.u4_output_present) { 581 resetPlugin(); 582 break; 583 } 584 } 585 } 586 } 587 588 void SoftMPEG2::onQueueFilled(OMX_U32 portIndex) { 589 UNUSED(portIndex); 590 591 if (mSignalledError) { 592 return; 593 } 594 if (mOutputPortSettingsChange != NONE) { 595 return; 596 } 597 598 if (NULL == mCodecCtx) { 599 if (OK != initDecoder()) { 600 ALOGE("Failed to initialize decoder"); 601 notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL); 602 mSignalledError = true; 603 return; 604 } 605 } 606 607 List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex); 608 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex); 609 610 if (outputBufferWidth() != mStride) { 611 /* Set the run-time (dynamic) parameters */ 612 mStride = outputBufferWidth(); 613 setParams(mStride); 614 } 615 616 while (!outQueue.empty()) { 617 BufferInfo *inInfo; 618 OMX_BUFFERHEADERTYPE *inHeader; 619 620 BufferInfo *outInfo; 621 OMX_BUFFERHEADERTYPE *outHeader; 622 size_t timeStampIx; 623 624 inInfo = NULL; 625 inHeader = NULL; 626 627 if (!mIsInFlush) { 628 if (!inQueue.empty()) { 629 inInfo = *inQueue.begin(); 630 inHeader = inInfo->mHeader; 631 } else { 632 break; 633 } 634 } 635 636 outInfo = *outQueue.begin(); 637 outHeader = outInfo->mHeader; 638 outHeader->nFlags = 0; 639 outHeader->nTimeStamp = 0; 640 outHeader->nOffset = 0; 641 642 if (inHeader != NULL && (inHeader->nFlags & OMX_BUFFERFLAG_EOS)) { 643 mReceivedEOS = true; 644 if (inHeader->nFilledLen == 0) { 645 inQueue.erase(inQueue.begin()); 646 inInfo->mOwnedByUs = false; 647 notifyEmptyBufferDone(inHeader); 648 inHeader = NULL; 649 setFlushMode(); 650 } 651 } 652 653 // When there is an init required and the decoder is not in flush mode, 654 // update output port's definition and reinitialize decoder. 655 if (mInitNeeded && !mIsInFlush) { 656 bool portWillReset = false; 657 handlePortSettingsChange(&portWillReset, mNewWidth, mNewHeight); 658 659 if (OK != reInitDecoder()) { 660 ALOGE("Failed to reinitialize decoder"); 661 } 662 return; 663 } 664 665 /* Get a free slot in timestamp array to hold input timestamp */ 666 { 667 size_t i; 668 timeStampIx = 0; 669 for (i = 0; i < MAX_TIME_STAMPS; i++) { 670 if (!mTimeStampsValid[i]) { 671 timeStampIx = i; 672 break; 673 } 674 } 675 if (inHeader != NULL) { 676 mTimeStampsValid[timeStampIx] = true; 677 mTimeStamps[timeStampIx] = inHeader->nTimeStamp; 678 } 679 } 680 681 { 682 ivd_video_decode_ip_t s_dec_ip; 683 ivd_video_decode_op_t s_dec_op; 684 WORD32 timeDelay, timeTaken; 685 size_t sizeY, sizeUV; 686 687 if (!setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx)) { 688 ALOGE("Decoder arg setup failed"); 689 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 690 return; 691 } 692 // If input dump is enabled, then write to file 693 DUMP_TO_FILE(mInFile, s_dec_ip.pv_stream_buffer, s_dec_ip.u4_num_Bytes); 694 695 if (s_dec_ip.u4_num_Bytes > 0) { 696 char *ptr = (char *)s_dec_ip.pv_stream_buffer; 697 } 698 699 GETTIME(&mTimeStart, NULL); 700 /* Compute time elapsed between end of previous decode() 701 * to start of current decode() */ 702 TIME_DIFF(mTimeEnd, mTimeStart, timeDelay); 703 704 IV_API_CALL_STATUS_T status; 705 status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op); 706 707 bool unsupportedDimensions = (IMPEG2D_UNSUPPORTED_DIMENSIONS == s_dec_op.u4_error_code); 708 bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF)); 709 710 getSeqInfo(); 711 712 GETTIME(&mTimeEnd, NULL); 713 /* Compute time taken for decode() */ 714 TIME_DIFF(mTimeStart, mTimeEnd, timeTaken); 715 716 ALOGV("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay, 717 s_dec_op.u4_num_bytes_consumed); 718 if (s_dec_op.u4_frame_decoded_flag && !mFlushNeeded) { 719 mFlushNeeded = true; 720 } 721 722 if ((inHeader != NULL) && (1 != s_dec_op.u4_frame_decoded_flag)) { 723 /* If the input did not contain picture data, then ignore 724 * the associated timestamp */ 725 mTimeStampsValid[timeStampIx] = false; 726 } 727 728 // This is needed to handle CTS DecoderTest testCodecResetsMPEG2WithoutSurface, 729 // which is not sending SPS/PPS after port reconfiguration and flush to the codec. 730 if (unsupportedDimensions && !mFlushNeeded) { 731 bool portWillReset = false; 732 handlePortSettingsChange(&portWillReset, s_dec_op.u4_pic_wd, s_dec_op.u4_pic_ht); 733 734 if (OK != reInitDecoder()) { 735 ALOGE("Failed to reinitialize decoder"); 736 return; 737 } 738 739 if (setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx)) { 740 ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op); 741 } 742 return; 743 } 744 745 // If the decoder is in the changing resolution mode and there is no output present, 746 // that means the switching is done and it's ready to reset the decoder and the plugin. 747 if (mChangingResolution && !s_dec_op.u4_output_present) { 748 mChangingResolution = false; 749 resetDecoder(); 750 resetPlugin(); 751 mStride = outputBufferWidth(); 752 setParams(mStride); 753 continue; 754 } 755 756 if (unsupportedDimensions || resChanged) { 757 mChangingResolution = true; 758 if (mFlushNeeded) { 759 setFlushMode(); 760 } 761 762 if (unsupportedDimensions) { 763 mNewWidth = s_dec_op.u4_pic_wd; 764 mNewHeight = s_dec_op.u4_pic_ht; 765 mInitNeeded = true; 766 } 767 continue; 768 } 769 770 // Combine the resolution change and coloraspects change in one PortSettingChange event 771 // if necessary. 772 if ((0 < s_dec_op.u4_pic_wd) && (0 < s_dec_op.u4_pic_ht)) { 773 uint32_t width = s_dec_op.u4_pic_wd; 774 uint32_t height = s_dec_op.u4_pic_ht; 775 bool portWillReset = false; 776 handlePortSettingsChange(&portWillReset, width, height); 777 778 if (portWillReset) { 779 resetDecoder(); 780 resetPlugin(); 781 return; 782 } 783 } else if (mUpdateColorAspects) { 784 notify(OMX_EventPortSettingsChanged, kOutputPortIndex, 785 kDescribeColorAspectsIndex, NULL); 786 mUpdateColorAspects = false; 787 return; 788 } 789 790 if (s_dec_op.u4_output_present) { 791 ssize_t timeStampIdx; 792 outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2; 793 794 timeStampIdx = getMinTimestampIdx(mTimeStamps, mTimeStampsValid); 795 if (timeStampIdx < 0) { 796 ALOGE("b/62872863, Invalid timestamp index!"); 797 android_errorWriteLog(0x534e4554, "62872863"); 798 return; 799 } 800 outHeader->nTimeStamp = mTimeStamps[timeStampIdx]; 801 mTimeStampsValid[timeStampIdx] = false; 802 803 /* mWaitForI waits for the first I picture. Once made FALSE, it 804 has to remain false till explicitly set to TRUE. */ 805 mWaitForI = mWaitForI && !(IV_I_FRAME == s_dec_op.e_pic_type); 806 807 if (mWaitForI) { 808 s_dec_op.u4_output_present = false; 809 } else { 810 ALOGV("Output timestamp: %lld, res: %ux%u", 811 (long long)outHeader->nTimeStamp, mWidth, mHeight); 812 DUMP_TO_FILE(mOutFile, outHeader->pBuffer, outHeader->nFilledLen); 813 outInfo->mOwnedByUs = false; 814 outQueue.erase(outQueue.begin()); 815 outInfo = NULL; 816 notifyFillBufferDone(outHeader); 817 outHeader = NULL; 818 } 819 } else if (mIsInFlush) { 820 /* If in flush mode and no output is returned by the codec, 821 * then come out of flush mode */ 822 mIsInFlush = false; 823 824 /* If EOS was recieved on input port and there is no output 825 * from the codec, then signal EOS on output port */ 826 if (mReceivedEOS) { 827 outHeader->nFilledLen = 0; 828 outHeader->nFlags |= OMX_BUFFERFLAG_EOS; 829 830 outInfo->mOwnedByUs = false; 831 outQueue.erase(outQueue.begin()); 832 outInfo = NULL; 833 notifyFillBufferDone(outHeader); 834 outHeader = NULL; 835 resetPlugin(); 836 } 837 } 838 } 839 840 /* If input EOS is seen and decoder is not in flush mode, 841 * set the decoder in flush mode. 842 * There can be a case where EOS is sent along with last picture data 843 * In that case, only after decoding that input data, decoder has to be 844 * put in flush. This case is handled here */ 845 846 if (mReceivedEOS && !mIsInFlush) { 847 setFlushMode(); 848 } 849 850 // TODO: Handle more than one picture data 851 if (inHeader != NULL) { 852 inInfo->mOwnedByUs = false; 853 inQueue.erase(inQueue.begin()); 854 inInfo = NULL; 855 notifyEmptyBufferDone(inHeader); 856 inHeader = NULL; 857 } 858 } 859 } 860 861 int SoftMPEG2::getColorAspectPreference() { 862 return kPreferBitstream; 863 } 864 865 } // namespace android 866 867 android::SoftOMXComponent *createSoftOMXComponent( 868 const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData, 869 OMX_COMPONENTTYPE **component) { 870 return new android::SoftMPEG2(name, callbacks, appData, component); 871 } 872