SoftVPXEncoder.cpp revision f1a2668f4f09e38722424a6a74f0ea26f49e4110
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 33namespace android { 34 35template<class T> 36static 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 46static 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 58static 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 65SoftVPXEncoder::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 103SoftVPXEncoder::~SoftVPXEncoder() { 104 releaseEncoder(); 105} 106 107status_t SoftVPXEncoder::initEncoder() { 108 vpx_codec_err_t codec_return; 109 110 mCodecContext = new vpx_codec_ctx_t; 111 mCodecConfiguration = new vpx_codec_enc_cfg_t; 112 mCodecInterface = vpx_codec_vp8_cx(); 113 114 if (mCodecInterface == NULL) { 115 return UNKNOWN_ERROR; 116 } 117 ALOGD("VP8: initEncoder. BRMode: %u. TSLayers: %zu. KF: %u. QP: %u - %u", 118 (uint32_t)mBitrateControlMode, mTemporalLayers, mKeyFrameInterval, 119 mMinQuantizer, mMaxQuantizer); 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 return UNKNOWN_ERROR; 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 return UNKNOWN_ERROR; 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 codec_return = vpx_codec_enc_init(mCodecContext, 276 mCodecInterface, 277 mCodecConfiguration, 278 0); // flags 279 280 if (codec_return != VPX_CODEC_OK) { 281 ALOGE("Error initializing vpx encoder"); 282 return UNKNOWN_ERROR; 283 } 284 285 codec_return = vpx_codec_control(mCodecContext, 286 VP8E_SET_TOKEN_PARTITIONS, 287 mDCTPartitions); 288 if (codec_return != VPX_CODEC_OK) { 289 ALOGE("Error setting dct partitions for vpx encoder."); 290 return UNKNOWN_ERROR; 291 } 292 293 // Extra CBR settings 294 if (mBitrateControlMode == VPX_CBR) { 295 codec_return = vpx_codec_control(mCodecContext, 296 VP8E_SET_STATIC_THRESHOLD, 297 1); 298 if (codec_return == VPX_CODEC_OK) { 299 uint32_t rc_max_intra_target = 300 mCodecConfiguration->rc_buf_optimal_sz * (mFramerate >> 17) / 10; 301 // Don't go below 3 times per frame bandwidth. 302 if (rc_max_intra_target < 300) { 303 rc_max_intra_target = 300; 304 } 305 codec_return = vpx_codec_control(mCodecContext, 306 VP8E_SET_MAX_INTRA_BITRATE_PCT, 307 rc_max_intra_target); 308 } 309 if (codec_return == VPX_CODEC_OK) { 310 codec_return = vpx_codec_control(mCodecContext, 311 VP8E_SET_CPUUSED, 312 -8); 313 } 314 if (codec_return != VPX_CODEC_OK) { 315 ALOGE("Error setting cbr parameters for vpx encoder."); 316 return UNKNOWN_ERROR; 317 } 318 } 319 320 if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) { 321 free(mConversionBuffer); 322 mConversionBuffer = NULL; 323 if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) { 324 ALOGE("b/25812794, Buffer size is too big."); 325 return UNKNOWN_ERROR; 326 } 327 mConversionBuffer = (uint8_t *)malloc(mWidth * mHeight * 3 / 2); 328 if (mConversionBuffer == NULL) { 329 ALOGE("Allocating conversion buffer failed."); 330 return UNKNOWN_ERROR; 331 } 332 } 333 return OK; 334} 335 336 337status_t SoftVPXEncoder::releaseEncoder() { 338 if (mCodecContext != NULL) { 339 vpx_codec_destroy(mCodecContext); 340 delete mCodecContext; 341 mCodecContext = NULL; 342 } 343 344 if (mCodecConfiguration != NULL) { 345 delete mCodecConfiguration; 346 mCodecConfiguration = NULL; 347 } 348 349 if (mConversionBuffer != NULL) { 350 free(mConversionBuffer); 351 mConversionBuffer = NULL; 352 } 353 354 // this one is not allocated by us 355 mCodecInterface = NULL; 356 357 return OK; 358} 359 360 361OMX_ERRORTYPE SoftVPXEncoder::internalGetParameter(OMX_INDEXTYPE index, 362 OMX_PTR param) { 363 // can include extension index OMX_INDEXEXTTYPE 364 const int32_t indexFull = index; 365 366 switch (indexFull) { 367 case OMX_IndexParamVideoBitrate: { 368 OMX_VIDEO_PARAM_BITRATETYPE *bitrate = 369 (OMX_VIDEO_PARAM_BITRATETYPE *)param; 370 371 if (!isValidOMXParam(bitrate)) { 372 return OMX_ErrorBadParameter; 373 } 374 375 if (bitrate->nPortIndex != kOutputPortIndex) { 376 return OMX_ErrorUnsupportedIndex; 377 } 378 379 bitrate->nTargetBitrate = mBitrate; 380 381 if (mBitrateControlMode == VPX_VBR) { 382 bitrate->eControlRate = OMX_Video_ControlRateVariable; 383 } else if (mBitrateControlMode == VPX_CBR) { 384 bitrate->eControlRate = OMX_Video_ControlRateConstant; 385 } else { 386 return OMX_ErrorUnsupportedSetting; 387 } 388 return OMX_ErrorNone; 389 } 390 391 // VP8 specific parameters that use extension headers 392 case OMX_IndexParamVideoVp8: { 393 OMX_VIDEO_PARAM_VP8TYPE *vp8Params = 394 (OMX_VIDEO_PARAM_VP8TYPE *)param; 395 396 if (!isValidOMXParam(vp8Params)) { 397 return OMX_ErrorBadParameter; 398 } 399 400 if (vp8Params->nPortIndex != kOutputPortIndex) { 401 return OMX_ErrorUnsupportedIndex; 402 } 403 404 vp8Params->eProfile = OMX_VIDEO_VP8ProfileMain; 405 vp8Params->eLevel = mLevel; 406 vp8Params->nDCTPartitions = mDCTPartitions; 407 vp8Params->bErrorResilientMode = mErrorResilience; 408 return OMX_ErrorNone; 409 } 410 411 case OMX_IndexParamVideoAndroidVp8Encoder: { 412 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vp8AndroidParams = 413 (OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param; 414 415 if (!isValidOMXParam(vp8AndroidParams)) { 416 return OMX_ErrorBadParameter; 417 } 418 419 if (vp8AndroidParams->nPortIndex != kOutputPortIndex) { 420 return OMX_ErrorUnsupportedIndex; 421 } 422 423 vp8AndroidParams->nKeyFrameInterval = mKeyFrameInterval; 424 vp8AndroidParams->eTemporalPattern = mTemporalPatternType; 425 vp8AndroidParams->nTemporalLayerCount = mTemporalLayers; 426 vp8AndroidParams->nMinQuantizer = mMinQuantizer; 427 vp8AndroidParams->nMaxQuantizer = mMaxQuantizer; 428 memcpy(vp8AndroidParams->nTemporalLayerBitrateRatio, 429 mTemporalLayerBitrateRatio, sizeof(mTemporalLayerBitrateRatio)); 430 return OMX_ErrorNone; 431 } 432 433 default: 434 return SoftVideoEncoderOMXComponent::internalGetParameter(index, param); 435 } 436} 437 438 439OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index, 440 const OMX_PTR param) { 441 // can include extension index OMX_INDEXEXTTYPE 442 const int32_t indexFull = index; 443 444 switch (indexFull) { 445 case OMX_IndexParamVideoBitrate: { 446 const OMX_VIDEO_PARAM_BITRATETYPE *bitRate = 447 (const OMX_VIDEO_PARAM_BITRATETYPE*) param; 448 449 if (!isValidOMXParam(bitRate)) { 450 return OMX_ErrorBadParameter; 451 } 452 453 return internalSetBitrateParams(bitRate); 454 } 455 456 case OMX_IndexParamVideoVp8: { 457 const OMX_VIDEO_PARAM_VP8TYPE *vp8Params = 458 (const OMX_VIDEO_PARAM_VP8TYPE*) param; 459 460 if (!isValidOMXParam(vp8Params)) { 461 return OMX_ErrorBadParameter; 462 } 463 464 return internalSetVp8Params(vp8Params); 465 } 466 467 case OMX_IndexParamVideoAndroidVp8Encoder: { 468 const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vp8AndroidParams = 469 (const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE*) param; 470 471 if (!isValidOMXParam(vp8AndroidParams)) { 472 return OMX_ErrorBadParameter; 473 } 474 475 return internalSetAndroidVp8Params(vp8AndroidParams); 476 } 477 478 default: 479 return SoftVideoEncoderOMXComponent::internalSetParameter(index, param); 480 } 481} 482 483OMX_ERRORTYPE SoftVPXEncoder::setConfig( 484 OMX_INDEXTYPE index, const OMX_PTR _params) { 485 switch (index) { 486 case OMX_IndexConfigVideoIntraVOPRefresh: 487 { 488 OMX_CONFIG_INTRAREFRESHVOPTYPE *params = 489 (OMX_CONFIG_INTRAREFRESHVOPTYPE *)_params; 490 491 if (!isValidOMXParam(params)) { 492 return OMX_ErrorBadParameter; 493 } 494 495 if (params->nPortIndex != kOutputPortIndex) { 496 return OMX_ErrorBadPortIndex; 497 } 498 499 mKeyFrameRequested = params->IntraRefreshVOP; 500 return OMX_ErrorNone; 501 } 502 503 case OMX_IndexConfigVideoBitrate: 504 { 505 OMX_VIDEO_CONFIG_BITRATETYPE *params = 506 (OMX_VIDEO_CONFIG_BITRATETYPE *)_params; 507 508 if (!isValidOMXParam(params)) { 509 return OMX_ErrorBadParameter; 510 } 511 512 if (params->nPortIndex != kOutputPortIndex) { 513 return OMX_ErrorBadPortIndex; 514 } 515 516 if (mBitrate != params->nEncodeBitrate) { 517 mBitrate = params->nEncodeBitrate; 518 mBitrateUpdated = true; 519 } 520 return OMX_ErrorNone; 521 } 522 523 default: 524 return SimpleSoftOMXComponent::setConfig(index, _params); 525 } 526} 527 528OMX_ERRORTYPE SoftVPXEncoder::internalSetVp8Params( 529 const OMX_VIDEO_PARAM_VP8TYPE* vp8Params) { 530 if (vp8Params->nPortIndex != kOutputPortIndex) { 531 return OMX_ErrorUnsupportedIndex; 532 } 533 534 if (vp8Params->eProfile != OMX_VIDEO_VP8ProfileMain) { 535 return OMX_ErrorBadParameter; 536 } 537 538 if (vp8Params->eLevel == OMX_VIDEO_VP8Level_Version0 || 539 vp8Params->eLevel == OMX_VIDEO_VP8Level_Version1 || 540 vp8Params->eLevel == OMX_VIDEO_VP8Level_Version2 || 541 vp8Params->eLevel == OMX_VIDEO_VP8Level_Version3) { 542 mLevel = vp8Params->eLevel; 543 } else { 544 return OMX_ErrorBadParameter; 545 } 546 547 if (vp8Params->nDCTPartitions <= kMaxDCTPartitions) { 548 mDCTPartitions = vp8Params->nDCTPartitions; 549 } else { 550 return OMX_ErrorBadParameter; 551 } 552 553 mErrorResilience = vp8Params->bErrorResilientMode; 554 return OMX_ErrorNone; 555} 556 557OMX_ERRORTYPE SoftVPXEncoder::internalSetAndroidVp8Params( 558 const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE* vp8AndroidParams) { 559 if (vp8AndroidParams->nPortIndex != kOutputPortIndex) { 560 return OMX_ErrorUnsupportedIndex; 561 } 562 if (vp8AndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternNone && 563 vp8AndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternWebRTC) { 564 return OMX_ErrorBadParameter; 565 } 566 if (vp8AndroidParams->nTemporalLayerCount > OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS) { 567 return OMX_ErrorBadParameter; 568 } 569 if (vp8AndroidParams->nMinQuantizer > vp8AndroidParams->nMaxQuantizer) { 570 return OMX_ErrorBadParameter; 571 } 572 573 mTemporalPatternType = vp8AndroidParams->eTemporalPattern; 574 if (vp8AndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) { 575 mTemporalLayers = vp8AndroidParams->nTemporalLayerCount; 576 } else if (vp8AndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternNone) { 577 mTemporalLayers = 0; 578 } 579 // Check the bitrate distribution between layers is in increasing order 580 if (mTemporalLayers > 1) { 581 for (size_t i = 0; i < mTemporalLayers - 1; i++) { 582 if (vp8AndroidParams->nTemporalLayerBitrateRatio[i + 1] <= 583 vp8AndroidParams->nTemporalLayerBitrateRatio[i]) { 584 ALOGE("Wrong bitrate ratio - should be in increasing order."); 585 return OMX_ErrorBadParameter; 586 } 587 } 588 } 589 mKeyFrameInterval = vp8AndroidParams->nKeyFrameInterval; 590 mMinQuantizer = vp8AndroidParams->nMinQuantizer; 591 mMaxQuantizer = vp8AndroidParams->nMaxQuantizer; 592 memcpy(mTemporalLayerBitrateRatio, vp8AndroidParams->nTemporalLayerBitrateRatio, 593 sizeof(mTemporalLayerBitrateRatio)); 594 ALOGD("VP8: internalSetAndroidVp8Params. BRMode: %u. TS: %zu. KF: %u." 595 " QP: %u - %u BR0: %u. BR1: %u. BR2: %u", 596 (uint32_t)mBitrateControlMode, mTemporalLayers, mKeyFrameInterval, 597 mMinQuantizer, mMaxQuantizer, mTemporalLayerBitrateRatio[0], 598 mTemporalLayerBitrateRatio[1], mTemporalLayerBitrateRatio[2]); 599 return OMX_ErrorNone; 600} 601 602OMX_ERRORTYPE SoftVPXEncoder::internalSetBitrateParams( 603 const OMX_VIDEO_PARAM_BITRATETYPE* bitrate) { 604 if (bitrate->nPortIndex != kOutputPortIndex) { 605 return OMX_ErrorUnsupportedIndex; 606 } 607 608 mBitrate = bitrate->nTargetBitrate; 609 610 if (bitrate->eControlRate == OMX_Video_ControlRateVariable) { 611 mBitrateControlMode = VPX_VBR; 612 } else if (bitrate->eControlRate == OMX_Video_ControlRateConstant) { 613 mBitrateControlMode = VPX_CBR; 614 } else { 615 return OMX_ErrorUnsupportedSetting; 616 } 617 618 return OMX_ErrorNone; 619} 620 621vpx_enc_frame_flags_t SoftVPXEncoder::getEncodeFlags() { 622 vpx_enc_frame_flags_t flags = 0; 623 int patternIdx = mTemporalPatternIdx % mTemporalPatternLength; 624 mTemporalPatternIdx++; 625 switch (mTemporalPattern[patternIdx]) { 626 case kTemporalUpdateLast: 627 flags |= VP8_EFLAG_NO_UPD_GF; 628 flags |= VP8_EFLAG_NO_UPD_ARF; 629 flags |= VP8_EFLAG_NO_REF_GF; 630 flags |= VP8_EFLAG_NO_REF_ARF; 631 break; 632 case kTemporalUpdateGoldenWithoutDependency: 633 flags |= VP8_EFLAG_NO_REF_GF; 634 // Deliberately no break here. 635 case kTemporalUpdateGolden: 636 flags |= VP8_EFLAG_NO_REF_ARF; 637 flags |= VP8_EFLAG_NO_UPD_ARF; 638 flags |= VP8_EFLAG_NO_UPD_LAST; 639 break; 640 case kTemporalUpdateAltrefWithoutDependency: 641 flags |= VP8_EFLAG_NO_REF_ARF; 642 flags |= VP8_EFLAG_NO_REF_GF; 643 // Deliberately no break here. 644 case kTemporalUpdateAltref: 645 flags |= VP8_EFLAG_NO_UPD_GF; 646 flags |= VP8_EFLAG_NO_UPD_LAST; 647 break; 648 case kTemporalUpdateNoneNoRefAltref: 649 flags |= VP8_EFLAG_NO_REF_ARF; 650 // Deliberately no break here. 651 case kTemporalUpdateNone: 652 flags |= VP8_EFLAG_NO_UPD_GF; 653 flags |= VP8_EFLAG_NO_UPD_ARF; 654 flags |= VP8_EFLAG_NO_UPD_LAST; 655 flags |= VP8_EFLAG_NO_UPD_ENTROPY; 656 break; 657 case kTemporalUpdateNoneNoRefGoldenRefAltRef: 658 flags |= VP8_EFLAG_NO_REF_GF; 659 flags |= VP8_EFLAG_NO_UPD_GF; 660 flags |= VP8_EFLAG_NO_UPD_ARF; 661 flags |= VP8_EFLAG_NO_UPD_LAST; 662 flags |= VP8_EFLAG_NO_UPD_ENTROPY; 663 break; 664 case kTemporalUpdateGoldenWithoutDependencyRefAltRef: 665 flags |= VP8_EFLAG_NO_REF_GF; 666 flags |= VP8_EFLAG_NO_UPD_ARF; 667 flags |= VP8_EFLAG_NO_UPD_LAST; 668 break; 669 case kTemporalUpdateLastRefAltRef: 670 flags |= VP8_EFLAG_NO_UPD_GF; 671 flags |= VP8_EFLAG_NO_UPD_ARF; 672 flags |= VP8_EFLAG_NO_REF_GF; 673 break; 674 case kTemporalUpdateGoldenRefAltRef: 675 flags |= VP8_EFLAG_NO_UPD_ARF; 676 flags |= VP8_EFLAG_NO_UPD_LAST; 677 break; 678 case kTemporalUpdateLastAndGoldenRefAltRef: 679 flags |= VP8_EFLAG_NO_UPD_ARF; 680 flags |= VP8_EFLAG_NO_REF_GF; 681 break; 682 case kTemporalUpdateLastRefAll: 683 flags |= VP8_EFLAG_NO_UPD_ARF; 684 flags |= VP8_EFLAG_NO_UPD_GF; 685 break; 686 } 687 return flags; 688} 689 690void SoftVPXEncoder::onQueueFilled(OMX_U32 /* portIndex */) { 691 // Initialize encoder if not already 692 if (mCodecContext == NULL) { 693 if (OK != initEncoder()) { 694 ALOGE("Failed to initialize encoder"); 695 notify(OMX_EventError, 696 OMX_ErrorUndefined, 697 0, // Extra notification data 698 NULL); // Notification data pointer 699 return; 700 } 701 } 702 703 vpx_codec_err_t codec_return; 704 List<BufferInfo *> &inputBufferInfoQueue = getPortQueue(kInputPortIndex); 705 List<BufferInfo *> &outputBufferInfoQueue = getPortQueue(kOutputPortIndex); 706 707 while (!inputBufferInfoQueue.empty() && !outputBufferInfoQueue.empty()) { 708 BufferInfo *inputBufferInfo = *inputBufferInfoQueue.begin(); 709 OMX_BUFFERHEADERTYPE *inputBufferHeader = inputBufferInfo->mHeader; 710 711 BufferInfo *outputBufferInfo = *outputBufferInfoQueue.begin(); 712 OMX_BUFFERHEADERTYPE *outputBufferHeader = outputBufferInfo->mHeader; 713 714 if ((inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) && 715 inputBufferHeader->nFilledLen == 0) { 716 inputBufferInfoQueue.erase(inputBufferInfoQueue.begin()); 717 inputBufferInfo->mOwnedByUs = false; 718 notifyEmptyBufferDone(inputBufferHeader); 719 720 outputBufferHeader->nFilledLen = 0; 721 outputBufferHeader->nFlags = OMX_BUFFERFLAG_EOS; 722 723 outputBufferInfoQueue.erase(outputBufferInfoQueue.begin()); 724 outputBufferInfo->mOwnedByUs = false; 725 notifyFillBufferDone(outputBufferHeader); 726 return; 727 } 728 729 const uint8_t *source = 730 inputBufferHeader->pBuffer + inputBufferHeader->nOffset; 731 732 if (mInputDataIsMeta) { 733 source = extractGraphicBuffer( 734 mConversionBuffer, mWidth * mHeight * 3 / 2, 735 source, inputBufferHeader->nFilledLen, 736 mWidth, mHeight); 737 if (source == NULL) { 738 ALOGE("Unable to extract gralloc buffer in metadata mode"); 739 notify(OMX_EventError, OMX_ErrorUndefined, 0, 0); 740 return; 741 } 742 } else if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) { 743 ConvertYUV420SemiPlanarToYUV420Planar( 744 source, mConversionBuffer, mWidth, mHeight); 745 746 source = mConversionBuffer; 747 } 748 vpx_image_t raw_frame; 749 vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, mWidth, mHeight, 750 kInputBufferAlignment, (uint8_t *)source); 751 752 vpx_enc_frame_flags_t flags = 0; 753 if (mTemporalPatternLength > 0) { 754 flags = getEncodeFlags(); 755 } 756 if (mKeyFrameRequested) { 757 flags |= VPX_EFLAG_FORCE_KF; 758 mKeyFrameRequested = false; 759 } 760 761 if (mBitrateUpdated) { 762 mCodecConfiguration->rc_target_bitrate = mBitrate/1000; 763 vpx_codec_err_t res = vpx_codec_enc_config_set(mCodecContext, 764 mCodecConfiguration); 765 if (res != VPX_CODEC_OK) { 766 ALOGE("vp8 encoder failed to update bitrate: %s", 767 vpx_codec_err_to_string(res)); 768 notify(OMX_EventError, 769 OMX_ErrorUndefined, 770 0, // Extra notification data 771 NULL); // Notification data pointer 772 } 773 mBitrateUpdated = false; 774 } 775 776 uint32_t frameDuration; 777 if (inputBufferHeader->nTimeStamp > mLastTimestamp) { 778 frameDuration = (uint32_t)(inputBufferHeader->nTimeStamp - mLastTimestamp); 779 } else { 780 frameDuration = (uint32_t)(((uint64_t)1000000 << 16) / mFramerate); 781 } 782 mLastTimestamp = inputBufferHeader->nTimeStamp; 783 codec_return = vpx_codec_encode( 784 mCodecContext, 785 &raw_frame, 786 inputBufferHeader->nTimeStamp, // in timebase units 787 frameDuration, // frame duration in timebase units 788 flags, // frame flags 789 VPX_DL_REALTIME); // encoding deadline 790 if (codec_return != VPX_CODEC_OK) { 791 ALOGE("vpx encoder failed to encode frame"); 792 notify(OMX_EventError, 793 OMX_ErrorUndefined, 794 0, // Extra notification data 795 NULL); // Notification data pointer 796 return; 797 } 798 799 vpx_codec_iter_t encoded_packet_iterator = NULL; 800 const vpx_codec_cx_pkt_t* encoded_packet; 801 802 while ((encoded_packet = vpx_codec_get_cx_data( 803 mCodecContext, &encoded_packet_iterator))) { 804 if (encoded_packet->kind == VPX_CODEC_CX_FRAME_PKT) { 805 outputBufferHeader->nTimeStamp = encoded_packet->data.frame.pts; 806 outputBufferHeader->nFlags = 0; 807 if (encoded_packet->data.frame.flags & VPX_FRAME_IS_KEY) 808 outputBufferHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; 809 outputBufferHeader->nOffset = 0; 810 outputBufferHeader->nFilledLen = encoded_packet->data.frame.sz; 811 memcpy(outputBufferHeader->pBuffer, 812 encoded_packet->data.frame.buf, 813 encoded_packet->data.frame.sz); 814 outputBufferInfo->mOwnedByUs = false; 815 outputBufferInfoQueue.erase(outputBufferInfoQueue.begin()); 816 if (inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) { 817 outputBufferHeader->nFlags |= OMX_BUFFERFLAG_EOS; 818 } 819 notifyFillBufferDone(outputBufferHeader); 820 } 821 } 822 823 inputBufferInfo->mOwnedByUs = false; 824 inputBufferInfoQueue.erase(inputBufferInfoQueue.begin()); 825 notifyEmptyBufferDone(inputBufferHeader); 826 } 827} 828 829} // namespace android 830 831 832android::SoftOMXComponent *createSoftOMXComponent( 833 const char *name, const OMX_CALLBACKTYPE *callbacks, 834 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 835 return new android::SoftVPXEncoder(name, callbacks, appData, component); 836} 837