Home | History | Annotate | Download | only in enc
      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 
     36 namespace android {
     37 
     38 template<class T>
     39 static 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 
     48 static 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 
     60 SoftVPXEncoder::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 
    100 SoftVPXEncoder::~SoftVPXEncoder() {
    101     releaseEncoder();
    102 }
    103 
    104 status_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 
    310 CLEAN_UP:
    311     releaseEncoder();
    312     return result;
    313 }
    314 
    315 status_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 
    338 OMX_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 
    377 OMX_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 
    403 OMX_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 
    448 OMX_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 
    466 OMX_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 
    485 OMX_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 
    501 OMX_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 
    546 vpx_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 
    617 void 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         const uint8_t *source =
    657             inputBufferHeader->pBuffer + inputBufferHeader->nOffset;
    658 
    659         size_t frameSize = mWidth * mHeight * 3 / 2;
    660         if (mInputDataIsMeta) {
    661             source = extractGraphicBuffer(
    662                     mConversionBuffer, frameSize,
    663                     source, inputBufferHeader->nFilledLen,
    664                     mWidth, mHeight);
    665             if (source == NULL) {
    666                 ALOGE("Unable to extract gralloc buffer in metadata mode");
    667                 notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
    668                 return;
    669             }
    670         } else {
    671             if (inputBufferHeader->nFilledLen < frameSize) {
    672                 android_errorWriteLog(0x534e4554, "27569635");
    673                 notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
    674                 return;
    675             } else if (inputBufferHeader->nFilledLen > frameSize) {
    676                 ALOGW("Input buffer contains too many pixels");
    677             }
    678 
    679             if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
    680                 ConvertYUV420SemiPlanarToYUV420Planar(
    681                         source, mConversionBuffer, mWidth, mHeight);
    682 
    683                 source = mConversionBuffer;
    684             }
    685         }
    686         vpx_image_t raw_frame;
    687         vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, mWidth, mHeight,
    688                      kInputBufferAlignment, (uint8_t *)source);
    689 
    690         vpx_enc_frame_flags_t flags = getEncodeFlags();
    691         if (mKeyFrameRequested) {
    692             flags |= VPX_EFLAG_FORCE_KF;
    693             mKeyFrameRequested = false;
    694         }
    695 
    696         if (mBitrateUpdated) {
    697             mCodecConfiguration->rc_target_bitrate = mBitrate/1000;
    698             vpx_codec_err_t res = vpx_codec_enc_config_set(mCodecContext,
    699                                                            mCodecConfiguration);
    700             if (res != VPX_CODEC_OK) {
    701                 ALOGE("vpx encoder failed to update bitrate: %s",
    702                       vpx_codec_err_to_string(res));
    703                 notify(OMX_EventError,
    704                        OMX_ErrorUndefined,
    705                        0, // Extra notification data
    706                        NULL); // Notification data pointer
    707             }
    708             mBitrateUpdated = false;
    709         }
    710 
    711         uint32_t frameDuration;
    712         if (inputBufferHeader->nTimeStamp > mLastTimestamp) {
    713             frameDuration = (uint32_t)(inputBufferHeader->nTimeStamp - mLastTimestamp);
    714         } else {
    715             // Use default of 30 fps in case of 0 frame rate.
    716             uint32_t framerate = mFramerate ?: (30 << 16);
    717             frameDuration = (uint32_t)(((uint64_t)1000000 << 16) / framerate);
    718         }
    719         mLastTimestamp = inputBufferHeader->nTimeStamp;
    720         codec_return = vpx_codec_encode(
    721                 mCodecContext,
    722                 &raw_frame,
    723                 inputBufferHeader->nTimeStamp,  // in timebase units
    724                 frameDuration,  // frame duration in timebase units
    725                 flags,  // frame flags
    726                 VPX_DL_REALTIME);  // encoding deadline
    727         if (codec_return != VPX_CODEC_OK) {
    728             ALOGE("vpx encoder failed to encode frame");
    729             notify(OMX_EventError,
    730                    OMX_ErrorUndefined,
    731                    0,  // Extra notification data
    732                    NULL);  // Notification data pointer
    733             return;
    734         }
    735 
    736         vpx_codec_iter_t encoded_packet_iterator = NULL;
    737         const vpx_codec_cx_pkt_t* encoded_packet;
    738 
    739         while ((encoded_packet = vpx_codec_get_cx_data(
    740                         mCodecContext, &encoded_packet_iterator))) {
    741             if (encoded_packet->kind == VPX_CODEC_CX_FRAME_PKT) {
    742                 outputBufferHeader->nTimeStamp = encoded_packet->data.frame.pts;
    743                 outputBufferHeader->nFlags = 0;
    744                 if (encoded_packet->data.frame.flags & VPX_FRAME_IS_KEY)
    745                     outputBufferHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
    746                 outputBufferHeader->nOffset = 0;
    747                 outputBufferHeader->nFilledLen = encoded_packet->data.frame.sz;
    748                 if (outputBufferHeader->nFilledLen > outputBufferHeader->nAllocLen) {
    749                     android_errorWriteLog(0x534e4554, "27569635");
    750                     notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
    751                     return;
    752                 }
    753                 memcpy(outputBufferHeader->pBuffer,
    754                        encoded_packet->data.frame.buf,
    755                        encoded_packet->data.frame.sz);
    756                 outputBufferInfo->mOwnedByUs = false;
    757                 outputBufferInfoQueue.erase(outputBufferInfoQueue.begin());
    758                 if (inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) {
    759                     outputBufferHeader->nFlags |= OMX_BUFFERFLAG_EOS;
    760                 }
    761                 notifyFillBufferDone(outputBufferHeader);
    762             }
    763         }
    764 
    765         inputBufferInfo->mOwnedByUs = false;
    766         inputBufferInfoQueue.erase(inputBufferInfoQueue.begin());
    767         notifyEmptyBufferDone(inputBufferHeader);
    768     }
    769 }
    770 
    771 void SoftVPXEncoder::onReset() {
    772     releaseEncoder();
    773     mLastTimestamp = 0x7FFFFFFFFFFFFFFFLL;
    774 }
    775 
    776 }  // namespace android
    777 
    778 android::SoftOMXComponent *createSoftOMXComponent(
    779         const char *name, const OMX_CALLBACKTYPE *callbacks,
    780         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
    781   if (!strcmp(name, "OMX.google.vp8.encoder")) {
    782       return new android::SoftVP8Encoder(name, callbacks, appData, component);
    783   } else if (!strcmp(name, "OMX.google.vp9.encoder")) {
    784       return new android::SoftVP9Encoder(name, callbacks, appData, component);
    785   } else {
    786       CHECK(!"Unknown component");
    787   }
    788   return NULL;
    789 }
    790