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