SoftVPXEncoder.cpp revision d8274ce8759faa21b10e9c027745774fefc9d993
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 23#include <utils/Log.h> 24#include <utils/misc.h> 25 26#include <media/hardware/HardwareAPI.h> 27#include <media/hardware/MetadataBufferType.h> 28#include <media/stagefright/foundation/ADebug.h> 29#include <media/stagefright/MediaDefs.h> 30 31#ifndef INT32_MAX 32#define INT32_MAX 2147483647 33#endif 34 35namespace android { 36 37template<class T> 38static void InitOMXParams(T *params) { 39 params->nSize = sizeof(T); 40 // OMX IL 1.1.2 41 params->nVersion.s.nVersionMajor = 1; 42 params->nVersion.s.nVersionMinor = 1; 43 params->nVersion.s.nRevision = 2; 44 params->nVersion.s.nStep = 0; 45} 46 47static int GetCPUCoreCount() { 48 int cpuCoreCount = 1; 49#if defined(_SC_NPROCESSORS_ONLN) 50 cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN); 51#else 52 // _SC_NPROC_ONLN must be defined... 53 cpuCoreCount = sysconf(_SC_NPROC_ONLN); 54#endif 55 CHECK_GE(cpuCoreCount, 1); 56 return cpuCoreCount; 57} 58 59SoftVPXEncoder::SoftVPXEncoder(const char *name, 60 const OMX_CALLBACKTYPE *callbacks, 61 OMX_PTR appData, 62 OMX_COMPONENTTYPE **component, 63 const char* role, 64 OMX_VIDEO_CODINGTYPE codingType, 65 const char* mimeType, 66 int32_t minCompressionRatio, 67 const CodecProfileLevel *profileLevels, 68 size_t numProfileLevels) 69 : SoftVideoEncoderOMXComponent( 70 name, role, codingType, profileLevels, numProfileLevels, 71 176 /* width */, 144 /* height */, 72 callbacks, appData, component), 73 mCodecContext(NULL), 74 mCodecConfiguration(NULL), 75 mCodecInterface(NULL), 76 mBitrateUpdated(false), 77 mBitrateControlMode(VPX_VBR), 78 mErrorResilience(OMX_FALSE), 79 mLevel(OMX_VIDEO_VP8Level_Version0), 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 switch (mLevel) { 132 case OMX_VIDEO_VP8Level_Version0: 133 mCodecConfiguration->g_profile = 0; 134 break; 135 136 case OMX_VIDEO_VP8Level_Version1: 137 mCodecConfiguration->g_profile = 1; 138 break; 139 140 case OMX_VIDEO_VP8Level_Version2: 141 mCodecConfiguration->g_profile = 2; 142 break; 143 144 case OMX_VIDEO_VP8Level_Version3: 145 mCodecConfiguration->g_profile = 3; 146 break; 147 148 default: 149 mCodecConfiguration->g_profile = 0; 150 } 151 152 // OMX timebase unit is microsecond 153 // g_timebase is in seconds (i.e. 1/1000000 seconds) 154 mCodecConfiguration->g_timebase.num = 1; 155 mCodecConfiguration->g_timebase.den = 1000000; 156 // rc_target_bitrate is in kbps, mBitrate in bps 157 mCodecConfiguration->rc_target_bitrate = (mBitrate + 500) / 1000; 158 mCodecConfiguration->rc_end_usage = mBitrateControlMode; 159 // Disable frame drop - not allowed in MediaCodec now. 160 mCodecConfiguration->rc_dropframe_thresh = 0; 161 if (mBitrateControlMode == VPX_CBR) { 162 // Disable spatial resizing. 163 mCodecConfiguration->rc_resize_allowed = 0; 164 // Single-pass mode. 165 mCodecConfiguration->g_pass = VPX_RC_ONE_PASS; 166 // Maximum amount of bits that can be subtracted from the target 167 // bitrate - expressed as percentage of the target bitrate. 168 mCodecConfiguration->rc_undershoot_pct = 100; 169 // Maximum amount of bits that can be added to the target 170 // bitrate - expressed as percentage of the target bitrate. 171 mCodecConfiguration->rc_overshoot_pct = 15; 172 // Initial value of the buffer level in ms. 173 mCodecConfiguration->rc_buf_initial_sz = 500; 174 // Amount of data that the encoder should try to maintain in ms. 175 mCodecConfiguration->rc_buf_optimal_sz = 600; 176 // The amount of data that may be buffered by the decoding 177 // application in ms. 178 mCodecConfiguration->rc_buf_sz = 1000; 179 // Enable error resilience - needed for packet loss. 180 mCodecConfiguration->g_error_resilient = 1; 181 // Disable lagged encoding. 182 mCodecConfiguration->g_lag_in_frames = 0; 183 // Maximum key frame interval - for CBR boost to 3000 184 mCodecConfiguration->kf_max_dist = 3000; 185 // Encoder determines optimal key frame placement automatically. 186 mCodecConfiguration->kf_mode = VPX_KF_AUTO; 187 } 188 189 // Frames temporal pattern - for now WebRTC like pattern is only supported. 190 switch (mTemporalLayers) { 191 case 0: 192 { 193 mTemporalPatternLength = 0; 194 break; 195 } 196 case 1: 197 { 198 mCodecConfiguration->ts_number_layers = 1; 199 mCodecConfiguration->ts_rate_decimator[0] = 1; 200 mCodecConfiguration->ts_periodicity = 1; 201 mCodecConfiguration->ts_layer_id[0] = 0; 202 mTemporalPattern[0] = kTemporalUpdateLastRefAll; 203 mTemporalPatternLength = 1; 204 break; 205 } 206 case 2: 207 { 208 mCodecConfiguration->ts_number_layers = 2; 209 mCodecConfiguration->ts_rate_decimator[0] = 2; 210 mCodecConfiguration->ts_rate_decimator[1] = 1; 211 mCodecConfiguration->ts_periodicity = 2; 212 mCodecConfiguration->ts_layer_id[0] = 0; 213 mCodecConfiguration->ts_layer_id[1] = 1; 214 mTemporalPattern[0] = kTemporalUpdateLastAndGoldenRefAltRef; 215 mTemporalPattern[1] = kTemporalUpdateGoldenWithoutDependencyRefAltRef; 216 mTemporalPattern[2] = kTemporalUpdateLastRefAltRef; 217 mTemporalPattern[3] = kTemporalUpdateGoldenRefAltRef; 218 mTemporalPattern[4] = kTemporalUpdateLastRefAltRef; 219 mTemporalPattern[5] = kTemporalUpdateGoldenRefAltRef; 220 mTemporalPattern[6] = kTemporalUpdateLastRefAltRef; 221 mTemporalPattern[7] = kTemporalUpdateNone; 222 mTemporalPatternLength = 8; 223 break; 224 } 225 case 3: 226 { 227 mCodecConfiguration->ts_number_layers = 3; 228 mCodecConfiguration->ts_rate_decimator[0] = 4; 229 mCodecConfiguration->ts_rate_decimator[1] = 2; 230 mCodecConfiguration->ts_rate_decimator[2] = 1; 231 mCodecConfiguration->ts_periodicity = 4; 232 mCodecConfiguration->ts_layer_id[0] = 0; 233 mCodecConfiguration->ts_layer_id[1] = 2; 234 mCodecConfiguration->ts_layer_id[2] = 1; 235 mCodecConfiguration->ts_layer_id[3] = 2; 236 mTemporalPattern[0] = kTemporalUpdateLastAndGoldenRefAltRef; 237 mTemporalPattern[1] = kTemporalUpdateNoneNoRefGoldenRefAltRef; 238 mTemporalPattern[2] = kTemporalUpdateGoldenWithoutDependencyRefAltRef; 239 mTemporalPattern[3] = kTemporalUpdateNone; 240 mTemporalPattern[4] = kTemporalUpdateLastRefAltRef; 241 mTemporalPattern[5] = kTemporalUpdateNone; 242 mTemporalPattern[6] = kTemporalUpdateGoldenRefAltRef; 243 mTemporalPattern[7] = kTemporalUpdateNone; 244 mTemporalPatternLength = 8; 245 break; 246 } 247 default: 248 { 249 ALOGE("Wrong number of temporal layers %zu", mTemporalLayers); 250 goto CLEAN_UP; 251 } 252 } 253 254 // Set bitrate values for each layer 255 for (size_t i = 0; i < mCodecConfiguration->ts_number_layers; i++) { 256 mCodecConfiguration->ts_target_bitrate[i] = 257 mCodecConfiguration->rc_target_bitrate * 258 mTemporalLayerBitrateRatio[i] / 100; 259 } 260 if (mKeyFrameInterval > 0) { 261 mCodecConfiguration->kf_max_dist = mKeyFrameInterval; 262 mCodecConfiguration->kf_min_dist = mKeyFrameInterval; 263 mCodecConfiguration->kf_mode = VPX_KF_AUTO; 264 } 265 if (mMinQuantizer > 0) { 266 mCodecConfiguration->rc_min_quantizer = mMinQuantizer; 267 } 268 if (mMaxQuantizer > 0) { 269 mCodecConfiguration->rc_max_quantizer = mMaxQuantizer; 270 } 271 272 mCodecContext = new vpx_codec_ctx_t; 273 codec_return = vpx_codec_enc_init(mCodecContext, 274 mCodecInterface, 275 mCodecConfiguration, 276 0); // flags 277 278 if (codec_return != VPX_CODEC_OK) { 279 ALOGE("Error initializing vpx encoder"); 280 goto CLEAN_UP; 281 } 282 283 // Extra CBR settings 284 if (mBitrateControlMode == VPX_CBR) { 285 codec_return = vpx_codec_control(mCodecContext, 286 VP8E_SET_STATIC_THRESHOLD, 287 1); 288 if (codec_return == VPX_CODEC_OK) { 289 uint32_t rc_max_intra_target = 290 mCodecConfiguration->rc_buf_optimal_sz * (mFramerate >> 17) / 10; 291 // Don't go below 3 times per frame bandwidth. 292 if (rc_max_intra_target < 300) { 293 rc_max_intra_target = 300; 294 } 295 codec_return = vpx_codec_control(mCodecContext, 296 VP8E_SET_MAX_INTRA_BITRATE_PCT, 297 rc_max_intra_target); 298 } 299 if (codec_return == VPX_CODEC_OK) { 300 codec_return = vpx_codec_control(mCodecContext, 301 VP8E_SET_CPUUSED, 302 -8); 303 } 304 if (codec_return != VPX_CODEC_OK) { 305 ALOGE("Error setting cbr parameters for vpx encoder."); 306 goto CLEAN_UP; 307 } 308 } 309 310 codec_return = setCodecSpecificControls(); 311 312 if (codec_return != VPX_CODEC_OK) { 313 // The codec specific method would have logged the error. 314 goto CLEAN_UP; 315 } 316 317 if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) { 318 free(mConversionBuffer); 319 mConversionBuffer = NULL; 320 if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) { 321 ALOGE("b/25812794, Buffer size is too big, width=%d, height=%d.", mWidth, mHeight); 322 goto CLEAN_UP; 323 } 324 mConversionBuffer = (uint8_t *)malloc(mWidth * mHeight * 3 / 2); 325 if (mConversionBuffer == NULL) { 326 ALOGE("Allocating conversion buffer failed."); 327 goto CLEAN_UP; 328 } 329 } 330 return OK; 331 332CLEAN_UP: 333 releaseEncoder(); 334 return result; 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 360OMX_ERRORTYPE SoftVPXEncoder::internalGetParameter(OMX_INDEXTYPE index, 361 OMX_PTR param) { 362 // can include extension index OMX_INDEXEXTTYPE 363 const int32_t indexFull = index; 364 365 switch (indexFull) { 366 case OMX_IndexParamVideoBitrate: 367 return internalGetBitrateParams( 368 (OMX_VIDEO_PARAM_BITRATETYPE *)param); 369 370 default: 371 return SoftVideoEncoderOMXComponent::internalGetParameter(index, param); 372 } 373} 374 375OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index, 376 const OMX_PTR param) { 377 // can include extension index OMX_INDEXEXTTYPE 378 const int32_t indexFull = index; 379 380 switch (indexFull) { 381 case OMX_IndexParamVideoBitrate: 382 return internalSetBitrateParams( 383 (const OMX_VIDEO_PARAM_BITRATETYPE *)param); 384 385 default: 386 return SoftVideoEncoderOMXComponent::internalSetParameter(index, param); 387 } 388} 389 390OMX_ERRORTYPE SoftVPXEncoder::setConfig( 391 OMX_INDEXTYPE index, const OMX_PTR _params) { 392 switch (index) { 393 case OMX_IndexConfigVideoIntraVOPRefresh: 394 { 395 OMX_CONFIG_INTRAREFRESHVOPTYPE *params = 396 (OMX_CONFIG_INTRAREFRESHVOPTYPE *)_params; 397 398 if (params->nPortIndex != kOutputPortIndex) { 399 return OMX_ErrorBadPortIndex; 400 } 401 402 mKeyFrameRequested = params->IntraRefreshVOP; 403 return OMX_ErrorNone; 404 } 405 406 case OMX_IndexConfigVideoBitrate: 407 { 408 OMX_VIDEO_CONFIG_BITRATETYPE *params = 409 (OMX_VIDEO_CONFIG_BITRATETYPE *)_params; 410 411 if (params->nPortIndex != kOutputPortIndex) { 412 return OMX_ErrorBadPortIndex; 413 } 414 415 if (mBitrate != params->nEncodeBitrate) { 416 mBitrate = params->nEncodeBitrate; 417 mBitrateUpdated = true; 418 } 419 return OMX_ErrorNone; 420 } 421 422 default: 423 return SimpleSoftOMXComponent::setConfig(index, _params); 424 } 425} 426 427OMX_ERRORTYPE SoftVPXEncoder::internalGetBitrateParams( 428 OMX_VIDEO_PARAM_BITRATETYPE* bitrate) { 429 if (bitrate->nPortIndex != kOutputPortIndex) { 430 return OMX_ErrorUnsupportedIndex; 431 } 432 433 bitrate->nTargetBitrate = mBitrate; 434 435 if (mBitrateControlMode == VPX_VBR) { 436 bitrate->eControlRate = OMX_Video_ControlRateVariable; 437 } else if (mBitrateControlMode == VPX_CBR) { 438 bitrate->eControlRate = OMX_Video_ControlRateConstant; 439 } else { 440 return OMX_ErrorUnsupportedSetting; 441 } 442 return OMX_ErrorNone; 443} 444 445OMX_ERRORTYPE SoftVPXEncoder::internalSetBitrateParams( 446 const OMX_VIDEO_PARAM_BITRATETYPE* bitrate) { 447 if (bitrate->nPortIndex != kOutputPortIndex) { 448 return OMX_ErrorUnsupportedIndex; 449 } 450 451 mBitrate = bitrate->nTargetBitrate; 452 453 if (bitrate->eControlRate == OMX_Video_ControlRateVariable) { 454 mBitrateControlMode = VPX_VBR; 455 } else if (bitrate->eControlRate == OMX_Video_ControlRateConstant) { 456 mBitrateControlMode = VPX_CBR; 457 } else { 458 return OMX_ErrorUnsupportedSetting; 459 } 460 461 return OMX_ErrorNone; 462} 463 464vpx_enc_frame_flags_t SoftVPXEncoder::getEncodeFlags() { 465 vpx_enc_frame_flags_t flags = 0; 466 int patternIdx = mTemporalPatternIdx % mTemporalPatternLength; 467 mTemporalPatternIdx++; 468 switch (mTemporalPattern[patternIdx]) { 469 case kTemporalUpdateLast: 470 flags |= VP8_EFLAG_NO_UPD_GF; 471 flags |= VP8_EFLAG_NO_UPD_ARF; 472 flags |= VP8_EFLAG_NO_REF_GF; 473 flags |= VP8_EFLAG_NO_REF_ARF; 474 break; 475 case kTemporalUpdateGoldenWithoutDependency: 476 flags |= VP8_EFLAG_NO_REF_GF; 477 // Deliberately no break here. 478 case kTemporalUpdateGolden: 479 flags |= VP8_EFLAG_NO_REF_ARF; 480 flags |= VP8_EFLAG_NO_UPD_ARF; 481 flags |= VP8_EFLAG_NO_UPD_LAST; 482 break; 483 case kTemporalUpdateAltrefWithoutDependency: 484 flags |= VP8_EFLAG_NO_REF_ARF; 485 flags |= VP8_EFLAG_NO_REF_GF; 486 // Deliberately no break here. 487 case kTemporalUpdateAltref: 488 flags |= VP8_EFLAG_NO_UPD_GF; 489 flags |= VP8_EFLAG_NO_UPD_LAST; 490 break; 491 case kTemporalUpdateNoneNoRefAltref: 492 flags |= VP8_EFLAG_NO_REF_ARF; 493 // Deliberately no break here. 494 case kTemporalUpdateNone: 495 flags |= VP8_EFLAG_NO_UPD_GF; 496 flags |= VP8_EFLAG_NO_UPD_ARF; 497 flags |= VP8_EFLAG_NO_UPD_LAST; 498 flags |= VP8_EFLAG_NO_UPD_ENTROPY; 499 break; 500 case kTemporalUpdateNoneNoRefGoldenRefAltRef: 501 flags |= VP8_EFLAG_NO_REF_GF; 502 flags |= VP8_EFLAG_NO_UPD_GF; 503 flags |= VP8_EFLAG_NO_UPD_ARF; 504 flags |= VP8_EFLAG_NO_UPD_LAST; 505 flags |= VP8_EFLAG_NO_UPD_ENTROPY; 506 break; 507 case kTemporalUpdateGoldenWithoutDependencyRefAltRef: 508 flags |= VP8_EFLAG_NO_REF_GF; 509 flags |= VP8_EFLAG_NO_UPD_ARF; 510 flags |= VP8_EFLAG_NO_UPD_LAST; 511 break; 512 case kTemporalUpdateLastRefAltRef: 513 flags |= VP8_EFLAG_NO_UPD_GF; 514 flags |= VP8_EFLAG_NO_UPD_ARF; 515 flags |= VP8_EFLAG_NO_REF_GF; 516 break; 517 case kTemporalUpdateGoldenRefAltRef: 518 flags |= VP8_EFLAG_NO_UPD_ARF; 519 flags |= VP8_EFLAG_NO_UPD_LAST; 520 break; 521 case kTemporalUpdateLastAndGoldenRefAltRef: 522 flags |= VP8_EFLAG_NO_UPD_ARF; 523 flags |= VP8_EFLAG_NO_REF_GF; 524 break; 525 case kTemporalUpdateLastRefAll: 526 flags |= VP8_EFLAG_NO_UPD_ARF; 527 flags |= VP8_EFLAG_NO_UPD_GF; 528 break; 529 } 530 return flags; 531} 532 533void SoftVPXEncoder::onQueueFilled(OMX_U32 /* portIndex */) { 534 // Initialize encoder if not already 535 if (mCodecContext == NULL) { 536 if (OK != initEncoder()) { 537 ALOGE("Failed to initialize encoder"); 538 notify(OMX_EventError, 539 OMX_ErrorUndefined, 540 0, // Extra notification data 541 NULL); // Notification data pointer 542 return; 543 } 544 } 545 546 vpx_codec_err_t codec_return; 547 List<BufferInfo *> &inputBufferInfoQueue = getPortQueue(kInputPortIndex); 548 List<BufferInfo *> &outputBufferInfoQueue = getPortQueue(kOutputPortIndex); 549 550 while (!inputBufferInfoQueue.empty() && !outputBufferInfoQueue.empty()) { 551 BufferInfo *inputBufferInfo = *inputBufferInfoQueue.begin(); 552 OMX_BUFFERHEADERTYPE *inputBufferHeader = inputBufferInfo->mHeader; 553 554 BufferInfo *outputBufferInfo = *outputBufferInfoQueue.begin(); 555 OMX_BUFFERHEADERTYPE *outputBufferHeader = outputBufferInfo->mHeader; 556 557 if ((inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) && 558 inputBufferHeader->nFilledLen == 0) { 559 inputBufferInfoQueue.erase(inputBufferInfoQueue.begin()); 560 inputBufferInfo->mOwnedByUs = false; 561 notifyEmptyBufferDone(inputBufferHeader); 562 563 outputBufferHeader->nFilledLen = 0; 564 outputBufferHeader->nFlags = OMX_BUFFERFLAG_EOS; 565 566 outputBufferInfoQueue.erase(outputBufferInfoQueue.begin()); 567 outputBufferInfo->mOwnedByUs = false; 568 notifyFillBufferDone(outputBufferHeader); 569 return; 570 } 571 572 const uint8_t *source = 573 inputBufferHeader->pBuffer + inputBufferHeader->nOffset; 574 575 if (mInputDataIsMeta) { 576 source = extractGraphicBuffer( 577 mConversionBuffer, mWidth * mHeight * 3 / 2, 578 source, inputBufferHeader->nFilledLen, 579 mWidth, mHeight); 580 if (source == NULL) { 581 ALOGE("Unable to extract gralloc buffer in metadata mode"); 582 notify(OMX_EventError, OMX_ErrorUndefined, 0, 0); 583 return; 584 } 585 } else if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) { 586 ConvertYUV420SemiPlanarToYUV420Planar( 587 source, mConversionBuffer, mWidth, mHeight); 588 589 source = mConversionBuffer; 590 } 591 vpx_image_t raw_frame; 592 vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, mWidth, mHeight, 593 kInputBufferAlignment, (uint8_t *)source); 594 595 vpx_enc_frame_flags_t flags = 0; 596 if (mTemporalPatternLength > 0) { 597 flags = getEncodeFlags(); 598 } 599 if (mKeyFrameRequested) { 600 flags |= VPX_EFLAG_FORCE_KF; 601 mKeyFrameRequested = false; 602 } 603 604 if (mBitrateUpdated) { 605 mCodecConfiguration->rc_target_bitrate = mBitrate/1000; 606 vpx_codec_err_t res = vpx_codec_enc_config_set(mCodecContext, 607 mCodecConfiguration); 608 if (res != VPX_CODEC_OK) { 609 ALOGE("vpx encoder failed to update bitrate: %s", 610 vpx_codec_err_to_string(res)); 611 notify(OMX_EventError, 612 OMX_ErrorUndefined, 613 0, // Extra notification data 614 NULL); // Notification data pointer 615 } 616 mBitrateUpdated = false; 617 } 618 619 uint32_t frameDuration; 620 if (inputBufferHeader->nTimeStamp > mLastTimestamp) { 621 frameDuration = (uint32_t)(inputBufferHeader->nTimeStamp - mLastTimestamp); 622 } else { 623 frameDuration = (uint32_t)(((uint64_t)1000000 << 16) / mFramerate); 624 } 625 mLastTimestamp = inputBufferHeader->nTimeStamp; 626 codec_return = vpx_codec_encode( 627 mCodecContext, 628 &raw_frame, 629 inputBufferHeader->nTimeStamp, // in timebase units 630 frameDuration, // frame duration in timebase units 631 flags, // frame flags 632 VPX_DL_REALTIME); // encoding deadline 633 if (codec_return != VPX_CODEC_OK) { 634 ALOGE("vpx encoder failed to encode frame"); 635 notify(OMX_EventError, 636 OMX_ErrorUndefined, 637 0, // Extra notification data 638 NULL); // Notification data pointer 639 return; 640 } 641 642 vpx_codec_iter_t encoded_packet_iterator = NULL; 643 const vpx_codec_cx_pkt_t* encoded_packet; 644 645 while ((encoded_packet = vpx_codec_get_cx_data( 646 mCodecContext, &encoded_packet_iterator))) { 647 if (encoded_packet->kind == VPX_CODEC_CX_FRAME_PKT) { 648 outputBufferHeader->nTimeStamp = encoded_packet->data.frame.pts; 649 outputBufferHeader->nFlags = 0; 650 if (encoded_packet->data.frame.flags & VPX_FRAME_IS_KEY) 651 outputBufferHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; 652 outputBufferHeader->nOffset = 0; 653 outputBufferHeader->nFilledLen = encoded_packet->data.frame.sz; 654 memcpy(outputBufferHeader->pBuffer, 655 encoded_packet->data.frame.buf, 656 encoded_packet->data.frame.sz); 657 outputBufferInfo->mOwnedByUs = false; 658 outputBufferInfoQueue.erase(outputBufferInfoQueue.begin()); 659 if (inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) { 660 outputBufferHeader->nFlags |= OMX_BUFFERFLAG_EOS; 661 } 662 notifyFillBufferDone(outputBufferHeader); 663 } 664 } 665 666 inputBufferInfo->mOwnedByUs = false; 667 inputBufferInfoQueue.erase(inputBufferInfoQueue.begin()); 668 notifyEmptyBufferDone(inputBufferHeader); 669 } 670} 671 672} // namespace android 673 674android::SoftOMXComponent *createSoftOMXComponent( 675 const char *name, const OMX_CALLBACKTYPE *callbacks, 676 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 677 if (!strcmp(name, "OMX.google.vp8.encoder")) { 678 return new android::SoftVP8Encoder(name, callbacks, appData, component); 679 } else { 680 CHECK(!"Unknown component"); 681 } 682 return NULL; 683} 684