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