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