1 /* 2 * Copyright (C) 2013 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 "SoftVPXEncoder" 19 #include "SoftVPXEncoder.h" 20 21 #include <utils/Log.h> 22 #include <utils/misc.h> 23 24 #include <media/hardware/HardwareAPI.h> 25 #include <media/hardware/MetadataBufferType.h> 26 #include <media/stagefright/foundation/ADebug.h> 27 #include <media/stagefright/MediaDefs.h> 28 29 #ifndef INT32_MAX 30 #define INT32_MAX 2147483647 31 #endif 32 33 namespace android { 34 35 template<class T> 36 static void InitOMXParams(T *params) { 37 params->nSize = sizeof(T); 38 // OMX IL 1.1.2 39 params->nVersion.s.nVersionMajor = 1; 40 params->nVersion.s.nVersionMinor = 1; 41 params->nVersion.s.nRevision = 2; 42 params->nVersion.s.nStep = 0; 43 } 44 45 46 static int GetCPUCoreCount() { 47 int cpuCoreCount = 1; 48 #if defined(_SC_NPROCESSORS_ONLN) 49 cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN); 50 #else 51 // _SC_NPROC_ONLN must be defined... 52 cpuCoreCount = sysconf(_SC_NPROC_ONLN); 53 #endif 54 CHECK_GE(cpuCoreCount, 1); 55 return cpuCoreCount; 56 } 57 58 static const CodecProfileLevel kProfileLevels[] = { 59 { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version0 }, 60 { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version1 }, 61 { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version2 }, 62 { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version3 }, 63 }; 64 65 SoftVPXEncoder::SoftVPXEncoder(const char *name, 66 const OMX_CALLBACKTYPE *callbacks, 67 OMX_PTR appData, 68 OMX_COMPONENTTYPE **component) 69 : SoftVideoEncoderOMXComponent( 70 name, "video_encoder.vp8", OMX_VIDEO_CodingVP8, 71 kProfileLevels, NELEM(kProfileLevels), 72 176 /* width */, 144 /* height */, 73 callbacks, appData, component), 74 mCodecContext(NULL), 75 mCodecConfiguration(NULL), 76 mCodecInterface(NULL), 77 mBitrateUpdated(false), 78 mBitrateControlMode(VPX_VBR), // variable bitrate 79 mDCTPartitions(0), 80 mErrorResilience(OMX_FALSE), 81 mLevel(OMX_VIDEO_VP8Level_Version0), 82 mKeyFrameInterval(0), 83 mMinQuantizer(0), 84 mMaxQuantizer(0), 85 mTemporalLayers(0), 86 mTemporalPatternType(OMX_VIDEO_VPXTemporalLayerPatternNone), 87 mTemporalPatternLength(0), 88 mTemporalPatternIdx(0), 89 mLastTimestamp(0x7FFFFFFFFFFFFFFFLL), 90 mConversionBuffer(NULL), 91 mKeyFrameRequested(false) { 92 memset(mTemporalLayerBitrateRatio, 0, sizeof(mTemporalLayerBitrateRatio)); 93 mTemporalLayerBitrateRatio[0] = 100; 94 95 const size_t kMinOutputBufferSize = 1024 * 1024; // arbitrary 96 97 initPorts( 98 kNumBuffers, kNumBuffers, kMinOutputBufferSize, 99 MEDIA_MIMETYPE_VIDEO_VP8, 2 /* minCompressionRatio */); 100 } 101 102 103 SoftVPXEncoder::~SoftVPXEncoder() { 104 releaseEncoder(); 105 } 106 107 status_t SoftVPXEncoder::initEncoder() { 108 vpx_codec_err_t codec_return; 109 status_t result = UNKNOWN_ERROR; 110 111 mCodecInterface = vpx_codec_vp8_cx(); 112 if (mCodecInterface == NULL) { 113 goto CLEAN_UP; 114 } 115 ALOGD("VP8: initEncoder. BRMode: %u. TSLayers: %zu. KF: %u. QP: %u - %u", 116 (uint32_t)mBitrateControlMode, mTemporalLayers, mKeyFrameInterval, 117 mMinQuantizer, mMaxQuantizer); 118 119 mCodecConfiguration = new vpx_codec_enc_cfg_t; 120 codec_return = vpx_codec_enc_config_default(mCodecInterface, 121 mCodecConfiguration, 122 0); // Codec specific flags 123 124 if (codec_return != VPX_CODEC_OK) { 125 ALOGE("Error populating default configuration for vpx encoder."); 126 goto CLEAN_UP; 127 } 128 129 mCodecConfiguration->g_w = mWidth; 130 mCodecConfiguration->g_h = mHeight; 131 mCodecConfiguration->g_threads = GetCPUCoreCount(); 132 mCodecConfiguration->g_error_resilient = mErrorResilience; 133 134 switch (mLevel) { 135 case OMX_VIDEO_VP8Level_Version0: 136 mCodecConfiguration->g_profile = 0; 137 break; 138 139 case OMX_VIDEO_VP8Level_Version1: 140 mCodecConfiguration->g_profile = 1; 141 break; 142 143 case OMX_VIDEO_VP8Level_Version2: 144 mCodecConfiguration->g_profile = 2; 145 break; 146 147 case OMX_VIDEO_VP8Level_Version3: 148 mCodecConfiguration->g_profile = 3; 149 break; 150 151 default: 152 mCodecConfiguration->g_profile = 0; 153 } 154 155 // OMX timebase unit is microsecond 156 // g_timebase is in seconds (i.e. 1/1000000 seconds) 157 mCodecConfiguration->g_timebase.num = 1; 158 mCodecConfiguration->g_timebase.den = 1000000; 159 // rc_target_bitrate is in kbps, mBitrate in bps 160 mCodecConfiguration->rc_target_bitrate = (mBitrate + 500) / 1000; 161 mCodecConfiguration->rc_end_usage = mBitrateControlMode; 162 // Disable frame drop - not allowed in MediaCodec now. 163 mCodecConfiguration->rc_dropframe_thresh = 0; 164 if (mBitrateControlMode == VPX_CBR) { 165 // Disable spatial resizing. 166 mCodecConfiguration->rc_resize_allowed = 0; 167 // Single-pass mode. 168 mCodecConfiguration->g_pass = VPX_RC_ONE_PASS; 169 // Maximum amount of bits that can be subtracted from the target 170 // bitrate - expressed as percentage of the target bitrate. 171 mCodecConfiguration->rc_undershoot_pct = 100; 172 // Maximum amount of bits that can be added to the target 173 // bitrate - expressed as percentage of the target bitrate. 174 mCodecConfiguration->rc_overshoot_pct = 15; 175 // Initial value of the buffer level in ms. 176 mCodecConfiguration->rc_buf_initial_sz = 500; 177 // Amount of data that the encoder should try to maintain in ms. 178 mCodecConfiguration->rc_buf_optimal_sz = 600; 179 // The amount of data that may be buffered by the decoding 180 // application in ms. 181 mCodecConfiguration->rc_buf_sz = 1000; 182 // Enable error resilience - needed for packet loss. 183 mCodecConfiguration->g_error_resilient = 1; 184 // Disable lagged encoding. 185 mCodecConfiguration->g_lag_in_frames = 0; 186 // Maximum key frame interval - for CBR boost to 3000 187 mCodecConfiguration->kf_max_dist = 3000; 188 // Encoder determines optimal key frame placement automatically. 189 mCodecConfiguration->kf_mode = VPX_KF_AUTO; 190 } 191 192 // Frames temporal pattern - for now WebRTC like pattern is only supported. 193 switch (mTemporalLayers) { 194 case 0: 195 { 196 mTemporalPatternLength = 0; 197 break; 198 } 199 case 1: 200 { 201 mCodecConfiguration->ts_number_layers = 1; 202 mCodecConfiguration->ts_rate_decimator[0] = 1; 203 mCodecConfiguration->ts_periodicity = 1; 204 mCodecConfiguration->ts_layer_id[0] = 0; 205 mTemporalPattern[0] = kTemporalUpdateLastRefAll; 206 mTemporalPatternLength = 1; 207 break; 208 } 209 case 2: 210 { 211 mCodecConfiguration->ts_number_layers = 2; 212 mCodecConfiguration->ts_rate_decimator[0] = 2; 213 mCodecConfiguration->ts_rate_decimator[1] = 1; 214 mCodecConfiguration->ts_periodicity = 2; 215 mCodecConfiguration->ts_layer_id[0] = 0; 216 mCodecConfiguration->ts_layer_id[1] = 1; 217 mTemporalPattern[0] = kTemporalUpdateLastAndGoldenRefAltRef; 218 mTemporalPattern[1] = kTemporalUpdateGoldenWithoutDependencyRefAltRef; 219 mTemporalPattern[2] = kTemporalUpdateLastRefAltRef; 220 mTemporalPattern[3] = kTemporalUpdateGoldenRefAltRef; 221 mTemporalPattern[4] = kTemporalUpdateLastRefAltRef; 222 mTemporalPattern[5] = kTemporalUpdateGoldenRefAltRef; 223 mTemporalPattern[6] = kTemporalUpdateLastRefAltRef; 224 mTemporalPattern[7] = kTemporalUpdateNone; 225 mTemporalPatternLength = 8; 226 break; 227 } 228 case 3: 229 { 230 mCodecConfiguration->ts_number_layers = 3; 231 mCodecConfiguration->ts_rate_decimator[0] = 4; 232 mCodecConfiguration->ts_rate_decimator[1] = 2; 233 mCodecConfiguration->ts_rate_decimator[2] = 1; 234 mCodecConfiguration->ts_periodicity = 4; 235 mCodecConfiguration->ts_layer_id[0] = 0; 236 mCodecConfiguration->ts_layer_id[1] = 2; 237 mCodecConfiguration->ts_layer_id[2] = 1; 238 mCodecConfiguration->ts_layer_id[3] = 2; 239 mTemporalPattern[0] = kTemporalUpdateLastAndGoldenRefAltRef; 240 mTemporalPattern[1] = kTemporalUpdateNoneNoRefGoldenRefAltRef; 241 mTemporalPattern[2] = kTemporalUpdateGoldenWithoutDependencyRefAltRef; 242 mTemporalPattern[3] = kTemporalUpdateNone; 243 mTemporalPattern[4] = kTemporalUpdateLastRefAltRef; 244 mTemporalPattern[5] = kTemporalUpdateNone; 245 mTemporalPattern[6] = kTemporalUpdateGoldenRefAltRef; 246 mTemporalPattern[7] = kTemporalUpdateNone; 247 mTemporalPatternLength = 8; 248 break; 249 } 250 default: 251 { 252 ALOGE("Wrong number of temporal layers %zu", mTemporalLayers); 253 goto CLEAN_UP; 254 } 255 } 256 257 // Set bitrate values for each layer 258 for (size_t i = 0; i < mCodecConfiguration->ts_number_layers; i++) { 259 mCodecConfiguration->ts_target_bitrate[i] = 260 mCodecConfiguration->rc_target_bitrate * 261 mTemporalLayerBitrateRatio[i] / 100; 262 } 263 if (mKeyFrameInterval > 0) { 264 mCodecConfiguration->kf_max_dist = mKeyFrameInterval; 265 mCodecConfiguration->kf_min_dist = mKeyFrameInterval; 266 mCodecConfiguration->kf_mode = VPX_KF_AUTO; 267 } 268 if (mMinQuantizer > 0) { 269 mCodecConfiguration->rc_min_quantizer = mMinQuantizer; 270 } 271 if (mMaxQuantizer > 0) { 272 mCodecConfiguration->rc_max_quantizer = mMaxQuantizer; 273 } 274 275 mCodecContext = new vpx_codec_ctx_t; 276 codec_return = vpx_codec_enc_init(mCodecContext, 277 mCodecInterface, 278 mCodecConfiguration, 279 0); // flags 280 281 if (codec_return != VPX_CODEC_OK) { 282 ALOGE("Error initializing vpx encoder"); 283 goto CLEAN_UP; 284 } 285 286 codec_return = vpx_codec_control(mCodecContext, 287 VP8E_SET_TOKEN_PARTITIONS, 288 mDCTPartitions); 289 if (codec_return != VPX_CODEC_OK) { 290 ALOGE("Error setting dct partitions for vpx encoder."); 291 goto CLEAN_UP; 292 } 293 294 // Extra CBR settings 295 if (mBitrateControlMode == VPX_CBR) { 296 codec_return = vpx_codec_control(mCodecContext, 297 VP8E_SET_STATIC_THRESHOLD, 298 1); 299 if (codec_return == VPX_CODEC_OK) { 300 uint32_t rc_max_intra_target = 301 mCodecConfiguration->rc_buf_optimal_sz * (mFramerate >> 17) / 10; 302 // Don't go below 3 times per frame bandwidth. 303 if (rc_max_intra_target < 300) { 304 rc_max_intra_target = 300; 305 } 306 codec_return = vpx_codec_control(mCodecContext, 307 VP8E_SET_MAX_INTRA_BITRATE_PCT, 308 rc_max_intra_target); 309 } 310 if (codec_return == VPX_CODEC_OK) { 311 codec_return = vpx_codec_control(mCodecContext, 312 VP8E_SET_CPUUSED, 313 -8); 314 } 315 if (codec_return != VPX_CODEC_OK) { 316 ALOGE("Error setting cbr parameters for vpx encoder."); 317 goto CLEAN_UP; 318 } 319 } 320 321 if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) { 322 free(mConversionBuffer); 323 mConversionBuffer = NULL; 324 if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) { 325 ALOGE("b/25812794, Buffer size is too big, width=%d, height=%d.", mWidth, mHeight); 326 goto CLEAN_UP; 327 } 328 mConversionBuffer = (uint8_t *)malloc(mWidth * mHeight * 3 / 2); 329 if (mConversionBuffer == NULL) { 330 ALOGE("Allocating conversion buffer failed."); 331 goto CLEAN_UP; 332 } 333 } 334 return OK; 335 336 CLEAN_UP: 337 releaseEncoder(); 338 return result; 339 } 340 341 342 status_t SoftVPXEncoder::releaseEncoder() { 343 if (mCodecContext != NULL) { 344 vpx_codec_destroy(mCodecContext); 345 delete mCodecContext; 346 mCodecContext = NULL; 347 } 348 349 if (mCodecConfiguration != NULL) { 350 delete mCodecConfiguration; 351 mCodecConfiguration = NULL; 352 } 353 354 if (mConversionBuffer != NULL) { 355 free(mConversionBuffer); 356 mConversionBuffer = NULL; 357 } 358 359 // this one is not allocated by us 360 mCodecInterface = NULL; 361 362 return OK; 363 } 364 365 366 OMX_ERRORTYPE SoftVPXEncoder::internalGetParameter(OMX_INDEXTYPE index, 367 OMX_PTR param) { 368 // can include extension index OMX_INDEXEXTTYPE 369 const int32_t indexFull = index; 370 371 switch (indexFull) { 372 case OMX_IndexParamVideoBitrate: { 373 OMX_VIDEO_PARAM_BITRATETYPE *bitrate = 374 (OMX_VIDEO_PARAM_BITRATETYPE *)param; 375 376 if (!isValidOMXParam(bitrate)) { 377 return OMX_ErrorBadParameter; 378 } 379 380 if (bitrate->nPortIndex != kOutputPortIndex) { 381 return OMX_ErrorUnsupportedIndex; 382 } 383 384 bitrate->nTargetBitrate = mBitrate; 385 386 if (mBitrateControlMode == VPX_VBR) { 387 bitrate->eControlRate = OMX_Video_ControlRateVariable; 388 } else if (mBitrateControlMode == VPX_CBR) { 389 bitrate->eControlRate = OMX_Video_ControlRateConstant; 390 } else { 391 return OMX_ErrorUnsupportedSetting; 392 } 393 return OMX_ErrorNone; 394 } 395 396 // VP8 specific parameters that use extension headers 397 case OMX_IndexParamVideoVp8: { 398 OMX_VIDEO_PARAM_VP8TYPE *vp8Params = 399 (OMX_VIDEO_PARAM_VP8TYPE *)param; 400 401 if (!isValidOMXParam(vp8Params)) { 402 return OMX_ErrorBadParameter; 403 } 404 405 if (vp8Params->nPortIndex != kOutputPortIndex) { 406 return OMX_ErrorUnsupportedIndex; 407 } 408 409 vp8Params->eProfile = OMX_VIDEO_VP8ProfileMain; 410 vp8Params->eLevel = mLevel; 411 vp8Params->nDCTPartitions = mDCTPartitions; 412 vp8Params->bErrorResilientMode = mErrorResilience; 413 return OMX_ErrorNone; 414 } 415 416 case OMX_IndexParamVideoAndroidVp8Encoder: { 417 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vp8AndroidParams = 418 (OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param; 419 420 if (!isValidOMXParam(vp8AndroidParams)) { 421 return OMX_ErrorBadParameter; 422 } 423 424 if (vp8AndroidParams->nPortIndex != kOutputPortIndex) { 425 return OMX_ErrorUnsupportedIndex; 426 } 427 428 vp8AndroidParams->nKeyFrameInterval = mKeyFrameInterval; 429 vp8AndroidParams->eTemporalPattern = mTemporalPatternType; 430 vp8AndroidParams->nTemporalLayerCount = mTemporalLayers; 431 vp8AndroidParams->nMinQuantizer = mMinQuantizer; 432 vp8AndroidParams->nMaxQuantizer = mMaxQuantizer; 433 memcpy(vp8AndroidParams->nTemporalLayerBitrateRatio, 434 mTemporalLayerBitrateRatio, sizeof(mTemporalLayerBitrateRatio)); 435 return OMX_ErrorNone; 436 } 437 438 default: 439 return SoftVideoEncoderOMXComponent::internalGetParameter(index, param); 440 } 441 } 442 443 444 OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index, 445 const OMX_PTR param) { 446 // can include extension index OMX_INDEXEXTTYPE 447 const int32_t indexFull = index; 448 449 switch (indexFull) { 450 case OMX_IndexParamVideoBitrate: { 451 const OMX_VIDEO_PARAM_BITRATETYPE *bitRate = 452 (const OMX_VIDEO_PARAM_BITRATETYPE*) param; 453 454 if (!isValidOMXParam(bitRate)) { 455 return OMX_ErrorBadParameter; 456 } 457 458 return internalSetBitrateParams(bitRate); 459 } 460 461 case OMX_IndexParamVideoVp8: { 462 const OMX_VIDEO_PARAM_VP8TYPE *vp8Params = 463 (const OMX_VIDEO_PARAM_VP8TYPE*) param; 464 465 if (!isValidOMXParam(vp8Params)) { 466 return OMX_ErrorBadParameter; 467 } 468 469 return internalSetVp8Params(vp8Params); 470 } 471 472 case OMX_IndexParamVideoAndroidVp8Encoder: { 473 const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vp8AndroidParams = 474 (const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE*) param; 475 476 if (!isValidOMXParam(vp8AndroidParams)) { 477 return OMX_ErrorBadParameter; 478 } 479 480 return internalSetAndroidVp8Params(vp8AndroidParams); 481 } 482 483 default: 484 return SoftVideoEncoderOMXComponent::internalSetParameter(index, param); 485 } 486 } 487 488 OMX_ERRORTYPE SoftVPXEncoder::setConfig( 489 OMX_INDEXTYPE index, const OMX_PTR _params) { 490 switch (index) { 491 case OMX_IndexConfigVideoIntraVOPRefresh: 492 { 493 OMX_CONFIG_INTRAREFRESHVOPTYPE *params = 494 (OMX_CONFIG_INTRAREFRESHVOPTYPE *)_params; 495 496 if (!isValidOMXParam(params)) { 497 return OMX_ErrorBadParameter; 498 } 499 500 if (params->nPortIndex != kOutputPortIndex) { 501 return OMX_ErrorBadPortIndex; 502 } 503 504 mKeyFrameRequested = params->IntraRefreshVOP; 505 return OMX_ErrorNone; 506 } 507 508 case OMX_IndexConfigVideoBitrate: 509 { 510 OMX_VIDEO_CONFIG_BITRATETYPE *params = 511 (OMX_VIDEO_CONFIG_BITRATETYPE *)_params; 512 513 if (!isValidOMXParam(params)) { 514 return OMX_ErrorBadParameter; 515 } 516 517 if (params->nPortIndex != kOutputPortIndex) { 518 return OMX_ErrorBadPortIndex; 519 } 520 521 if (mBitrate != params->nEncodeBitrate) { 522 mBitrate = params->nEncodeBitrate; 523 mBitrateUpdated = true; 524 } 525 return OMX_ErrorNone; 526 } 527 528 default: 529 return SimpleSoftOMXComponent::setConfig(index, _params); 530 } 531 } 532 533 OMX_ERRORTYPE SoftVPXEncoder::internalSetVp8Params( 534 const OMX_VIDEO_PARAM_VP8TYPE* vp8Params) { 535 if (vp8Params->nPortIndex != kOutputPortIndex) { 536 return OMX_ErrorUnsupportedIndex; 537 } 538 539 if (vp8Params->eProfile != OMX_VIDEO_VP8ProfileMain) { 540 return OMX_ErrorBadParameter; 541 } 542 543 if (vp8Params->eLevel == OMX_VIDEO_VP8Level_Version0 || 544 vp8Params->eLevel == OMX_VIDEO_VP8Level_Version1 || 545 vp8Params->eLevel == OMX_VIDEO_VP8Level_Version2 || 546 vp8Params->eLevel == OMX_VIDEO_VP8Level_Version3) { 547 mLevel = vp8Params->eLevel; 548 } else { 549 return OMX_ErrorBadParameter; 550 } 551 552 if (vp8Params->nDCTPartitions <= kMaxDCTPartitions) { 553 mDCTPartitions = vp8Params->nDCTPartitions; 554 } else { 555 return OMX_ErrorBadParameter; 556 } 557 558 mErrorResilience = vp8Params->bErrorResilientMode; 559 return OMX_ErrorNone; 560 } 561 562 OMX_ERRORTYPE SoftVPXEncoder::internalSetAndroidVp8Params( 563 const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE* vp8AndroidParams) { 564 if (vp8AndroidParams->nPortIndex != kOutputPortIndex) { 565 return OMX_ErrorUnsupportedIndex; 566 } 567 if (vp8AndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternNone && 568 vp8AndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternWebRTC) { 569 return OMX_ErrorBadParameter; 570 } 571 if (vp8AndroidParams->nTemporalLayerCount > OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS) { 572 return OMX_ErrorBadParameter; 573 } 574 if (vp8AndroidParams->nMinQuantizer > vp8AndroidParams->nMaxQuantizer) { 575 return OMX_ErrorBadParameter; 576 } 577 578 mTemporalPatternType = vp8AndroidParams->eTemporalPattern; 579 if (vp8AndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) { 580 mTemporalLayers = vp8AndroidParams->nTemporalLayerCount; 581 } else if (vp8AndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternNone) { 582 mTemporalLayers = 0; 583 } 584 // Check the bitrate distribution between layers is in increasing order 585 if (mTemporalLayers > 1) { 586 for (size_t i = 0; i < mTemporalLayers - 1; i++) { 587 if (vp8AndroidParams->nTemporalLayerBitrateRatio[i + 1] <= 588 vp8AndroidParams->nTemporalLayerBitrateRatio[i]) { 589 ALOGE("Wrong bitrate ratio - should be in increasing order."); 590 return OMX_ErrorBadParameter; 591 } 592 } 593 } 594 mKeyFrameInterval = vp8AndroidParams->nKeyFrameInterval; 595 mMinQuantizer = vp8AndroidParams->nMinQuantizer; 596 mMaxQuantizer = vp8AndroidParams->nMaxQuantizer; 597 memcpy(mTemporalLayerBitrateRatio, vp8AndroidParams->nTemporalLayerBitrateRatio, 598 sizeof(mTemporalLayerBitrateRatio)); 599 ALOGD("VP8: internalSetAndroidVp8Params. BRMode: %u. TS: %zu. KF: %u." 600 " QP: %u - %u BR0: %u. BR1: %u. BR2: %u", 601 (uint32_t)mBitrateControlMode, mTemporalLayers, mKeyFrameInterval, 602 mMinQuantizer, mMaxQuantizer, mTemporalLayerBitrateRatio[0], 603 mTemporalLayerBitrateRatio[1], mTemporalLayerBitrateRatio[2]); 604 return OMX_ErrorNone; 605 } 606 607 OMX_ERRORTYPE SoftVPXEncoder::internalSetBitrateParams( 608 const OMX_VIDEO_PARAM_BITRATETYPE* bitrate) { 609 if (bitrate->nPortIndex != kOutputPortIndex) { 610 return OMX_ErrorUnsupportedIndex; 611 } 612 613 mBitrate = bitrate->nTargetBitrate; 614 615 if (bitrate->eControlRate == OMX_Video_ControlRateVariable) { 616 mBitrateControlMode = VPX_VBR; 617 } else if (bitrate->eControlRate == OMX_Video_ControlRateConstant) { 618 mBitrateControlMode = VPX_CBR; 619 } else { 620 return OMX_ErrorUnsupportedSetting; 621 } 622 623 return OMX_ErrorNone; 624 } 625 626 vpx_enc_frame_flags_t SoftVPXEncoder::getEncodeFlags() { 627 vpx_enc_frame_flags_t flags = 0; 628 int patternIdx = mTemporalPatternIdx % mTemporalPatternLength; 629 mTemporalPatternIdx++; 630 switch (mTemporalPattern[patternIdx]) { 631 case kTemporalUpdateLast: 632 flags |= VP8_EFLAG_NO_UPD_GF; 633 flags |= VP8_EFLAG_NO_UPD_ARF; 634 flags |= VP8_EFLAG_NO_REF_GF; 635 flags |= VP8_EFLAG_NO_REF_ARF; 636 break; 637 case kTemporalUpdateGoldenWithoutDependency: 638 flags |= VP8_EFLAG_NO_REF_GF; 639 // Deliberately no break here. 640 case kTemporalUpdateGolden: 641 flags |= VP8_EFLAG_NO_REF_ARF; 642 flags |= VP8_EFLAG_NO_UPD_ARF; 643 flags |= VP8_EFLAG_NO_UPD_LAST; 644 break; 645 case kTemporalUpdateAltrefWithoutDependency: 646 flags |= VP8_EFLAG_NO_REF_ARF; 647 flags |= VP8_EFLAG_NO_REF_GF; 648 // Deliberately no break here. 649 case kTemporalUpdateAltref: 650 flags |= VP8_EFLAG_NO_UPD_GF; 651 flags |= VP8_EFLAG_NO_UPD_LAST; 652 break; 653 case kTemporalUpdateNoneNoRefAltref: 654 flags |= VP8_EFLAG_NO_REF_ARF; 655 // Deliberately no break here. 656 case kTemporalUpdateNone: 657 flags |= VP8_EFLAG_NO_UPD_GF; 658 flags |= VP8_EFLAG_NO_UPD_ARF; 659 flags |= VP8_EFLAG_NO_UPD_LAST; 660 flags |= VP8_EFLAG_NO_UPD_ENTROPY; 661 break; 662 case kTemporalUpdateNoneNoRefGoldenRefAltRef: 663 flags |= VP8_EFLAG_NO_REF_GF; 664 flags |= VP8_EFLAG_NO_UPD_GF; 665 flags |= VP8_EFLAG_NO_UPD_ARF; 666 flags |= VP8_EFLAG_NO_UPD_LAST; 667 flags |= VP8_EFLAG_NO_UPD_ENTROPY; 668 break; 669 case kTemporalUpdateGoldenWithoutDependencyRefAltRef: 670 flags |= VP8_EFLAG_NO_REF_GF; 671 flags |= VP8_EFLAG_NO_UPD_ARF; 672 flags |= VP8_EFLAG_NO_UPD_LAST; 673 break; 674 case kTemporalUpdateLastRefAltRef: 675 flags |= VP8_EFLAG_NO_UPD_GF; 676 flags |= VP8_EFLAG_NO_UPD_ARF; 677 flags |= VP8_EFLAG_NO_REF_GF; 678 break; 679 case kTemporalUpdateGoldenRefAltRef: 680 flags |= VP8_EFLAG_NO_UPD_ARF; 681 flags |= VP8_EFLAG_NO_UPD_LAST; 682 break; 683 case kTemporalUpdateLastAndGoldenRefAltRef: 684 flags |= VP8_EFLAG_NO_UPD_ARF; 685 flags |= VP8_EFLAG_NO_REF_GF; 686 break; 687 case kTemporalUpdateLastRefAll: 688 flags |= VP8_EFLAG_NO_UPD_ARF; 689 flags |= VP8_EFLAG_NO_UPD_GF; 690 break; 691 } 692 return flags; 693 } 694 695 void SoftVPXEncoder::onQueueFilled(OMX_U32 /* portIndex */) { 696 // Initialize encoder if not already 697 if (mCodecContext == NULL) { 698 if (OK != initEncoder()) { 699 ALOGE("Failed to initialize encoder"); 700 notify(OMX_EventError, 701 OMX_ErrorUndefined, 702 0, // Extra notification data 703 NULL); // Notification data pointer 704 return; 705 } 706 } 707 708 vpx_codec_err_t codec_return; 709 List<BufferInfo *> &inputBufferInfoQueue = getPortQueue(kInputPortIndex); 710 List<BufferInfo *> &outputBufferInfoQueue = getPortQueue(kOutputPortIndex); 711 712 while (!inputBufferInfoQueue.empty() && !outputBufferInfoQueue.empty()) { 713 BufferInfo *inputBufferInfo = *inputBufferInfoQueue.begin(); 714 OMX_BUFFERHEADERTYPE *inputBufferHeader = inputBufferInfo->mHeader; 715 716 BufferInfo *outputBufferInfo = *outputBufferInfoQueue.begin(); 717 OMX_BUFFERHEADERTYPE *outputBufferHeader = outputBufferInfo->mHeader; 718 719 if ((inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) && 720 inputBufferHeader->nFilledLen == 0) { 721 inputBufferInfoQueue.erase(inputBufferInfoQueue.begin()); 722 inputBufferInfo->mOwnedByUs = false; 723 notifyEmptyBufferDone(inputBufferHeader); 724 725 outputBufferHeader->nFilledLen = 0; 726 outputBufferHeader->nFlags = OMX_BUFFERFLAG_EOS; 727 728 outputBufferInfoQueue.erase(outputBufferInfoQueue.begin()); 729 outputBufferInfo->mOwnedByUs = false; 730 notifyFillBufferDone(outputBufferHeader); 731 return; 732 } 733 734 const uint8_t *source = 735 inputBufferHeader->pBuffer + inputBufferHeader->nOffset; 736 737 size_t frameSize = mWidth * mHeight * 3 / 2; 738 if (mInputDataIsMeta) { 739 source = extractGraphicBuffer( 740 mConversionBuffer, frameSize, 741 source, inputBufferHeader->nFilledLen, 742 mWidth, mHeight); 743 if (source == NULL) { 744 ALOGE("Unable to extract gralloc buffer in metadata mode"); 745 notify(OMX_EventError, OMX_ErrorUndefined, 0, 0); 746 return; 747 } 748 } else { 749 if (inputBufferHeader->nFilledLen < frameSize) { 750 android_errorWriteLog(0x534e4554, "27569635"); 751 notify(OMX_EventError, OMX_ErrorUndefined, 0, 0); 752 return; 753 } else if (inputBufferHeader->nFilledLen > frameSize) { 754 ALOGW("Input buffer contains too many pixels"); 755 } 756 757 if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) { 758 ConvertYUV420SemiPlanarToYUV420Planar( 759 source, mConversionBuffer, mWidth, mHeight); 760 761 source = mConversionBuffer; 762 } 763 } 764 vpx_image_t raw_frame; 765 vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, mWidth, mHeight, 766 kInputBufferAlignment, (uint8_t *)source); 767 768 vpx_enc_frame_flags_t flags = 0; 769 if (mTemporalPatternLength > 0) { 770 flags = getEncodeFlags(); 771 } 772 if (mKeyFrameRequested) { 773 flags |= VPX_EFLAG_FORCE_KF; 774 mKeyFrameRequested = false; 775 } 776 777 if (mBitrateUpdated) { 778 mCodecConfiguration->rc_target_bitrate = mBitrate/1000; 779 vpx_codec_err_t res = vpx_codec_enc_config_set(mCodecContext, 780 mCodecConfiguration); 781 if (res != VPX_CODEC_OK) { 782 ALOGE("vp8 encoder failed to update bitrate: %s", 783 vpx_codec_err_to_string(res)); 784 notify(OMX_EventError, 785 OMX_ErrorUndefined, 786 0, // Extra notification data 787 NULL); // Notification data pointer 788 } 789 mBitrateUpdated = false; 790 } 791 792 uint32_t frameDuration; 793 if (inputBufferHeader->nTimeStamp > mLastTimestamp) { 794 frameDuration = (uint32_t)(inputBufferHeader->nTimeStamp - mLastTimestamp); 795 } else { 796 frameDuration = (uint32_t)(((uint64_t)1000000 << 16) / mFramerate); 797 } 798 mLastTimestamp = inputBufferHeader->nTimeStamp; 799 codec_return = vpx_codec_encode( 800 mCodecContext, 801 &raw_frame, 802 inputBufferHeader->nTimeStamp, // in timebase units 803 frameDuration, // frame duration in timebase units 804 flags, // frame flags 805 VPX_DL_REALTIME); // encoding deadline 806 if (codec_return != VPX_CODEC_OK) { 807 ALOGE("vpx encoder failed to encode frame"); 808 notify(OMX_EventError, 809 OMX_ErrorUndefined, 810 0, // Extra notification data 811 NULL); // Notification data pointer 812 return; 813 } 814 815 vpx_codec_iter_t encoded_packet_iterator = NULL; 816 const vpx_codec_cx_pkt_t* encoded_packet; 817 818 while ((encoded_packet = vpx_codec_get_cx_data( 819 mCodecContext, &encoded_packet_iterator))) { 820 if (encoded_packet->kind == VPX_CODEC_CX_FRAME_PKT) { 821 outputBufferHeader->nTimeStamp = encoded_packet->data.frame.pts; 822 outputBufferHeader->nFlags = 0; 823 if (encoded_packet->data.frame.flags & VPX_FRAME_IS_KEY) 824 outputBufferHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; 825 outputBufferHeader->nOffset = 0; 826 outputBufferHeader->nFilledLen = encoded_packet->data.frame.sz; 827 if (outputBufferHeader->nFilledLen > outputBufferHeader->nAllocLen) { 828 android_errorWriteLog(0x534e4554, "27569635"); 829 notify(OMX_EventError, OMX_ErrorUndefined, 0, 0); 830 return; 831 } 832 memcpy(outputBufferHeader->pBuffer, 833 encoded_packet->data.frame.buf, 834 encoded_packet->data.frame.sz); 835 outputBufferInfo->mOwnedByUs = false; 836 outputBufferInfoQueue.erase(outputBufferInfoQueue.begin()); 837 if (inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) { 838 outputBufferHeader->nFlags |= OMX_BUFFERFLAG_EOS; 839 } 840 notifyFillBufferDone(outputBufferHeader); 841 } 842 } 843 844 inputBufferInfo->mOwnedByUs = false; 845 inputBufferInfoQueue.erase(inputBufferInfoQueue.begin()); 846 notifyEmptyBufferDone(inputBufferHeader); 847 } 848 } 849 850 } // namespace android 851 852 853 android::SoftOMXComponent *createSoftOMXComponent( 854 const char *name, const OMX_CALLBACKTYPE *callbacks, 855 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 856 return new android::SoftVPXEncoder(name, callbacks, appData, component); 857 } 858