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