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