SoftVP8Encoder.cpp revision 4f61e52d32f05db3cb04a0e29f9a2507ceffaf99
1/* 2 * Copyright (C) 2016 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 "SoftVP8Encoder" 19#include "SoftVP8Encoder.h" 20 21#include <utils/Log.h> 22#include <utils/misc.h> 23 24#include <media/hardware/HardwareAPI.h> 25#include <media/hardware/MetadataBufferType.h> 26#include <media/stagefright/foundation/ADebug.h> 27#include <media/stagefright/MediaDefs.h> 28 29#ifndef INT32_MAX 30#define INT32_MAX 2147483647 31#endif 32 33namespace android { 34 35static const CodecProfileLevel kVp8ProfileLevels[] = { 36 { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version0 }, 37 { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version1 }, 38 { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version2 }, 39 { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version3 }, 40}; 41 42SoftVP8Encoder::SoftVP8Encoder(const char *name, 43 const OMX_CALLBACKTYPE *callbacks, 44 OMX_PTR appData, 45 OMX_COMPONENTTYPE **component) 46 : SoftVPXEncoder( 47 name, callbacks, appData, component, "video_encoder.vp8", 48 OMX_VIDEO_CodingVP8, MEDIA_MIMETYPE_VIDEO_VP8, 2, 49 kVp8ProfileLevels, NELEM(kVp8ProfileLevels)), 50 mDCTPartitions(0), 51 mLevel(OMX_VIDEO_VP8Level_Version0) { 52} 53 54void SoftVP8Encoder::setCodecSpecificInterface() { 55 mCodecInterface = vpx_codec_vp8_cx(); 56} 57 58bool SoftVP8Encoder::setCodecSpecificConfiguration() { 59 switch (mLevel) { 60 case OMX_VIDEO_VP8Level_Version0: 61 mCodecConfiguration->g_profile = 0; 62 break; 63 64 case OMX_VIDEO_VP8Level_Version1: 65 mCodecConfiguration->g_profile = 1; 66 break; 67 68 case OMX_VIDEO_VP8Level_Version2: 69 mCodecConfiguration->g_profile = 2; 70 break; 71 72 case OMX_VIDEO_VP8Level_Version3: 73 mCodecConfiguration->g_profile = 3; 74 break; 75 76 default: 77 mCodecConfiguration->g_profile = 0; 78 } 79 return true; 80} 81 82vpx_codec_err_t SoftVP8Encoder::setCodecSpecificControls() { 83 vpx_codec_err_t codec_return = vpx_codec_control(mCodecContext, 84 VP8E_SET_TOKEN_PARTITIONS, 85 mDCTPartitions); 86 if (codec_return != VPX_CODEC_OK) { 87 ALOGE("Error setting dct partitions for vpx encoder."); 88 } 89 return codec_return; 90} 91 92OMX_ERRORTYPE SoftVP8Encoder::internalGetParameter(OMX_INDEXTYPE index, 93 OMX_PTR param) { 94 // can include extension index OMX_INDEXEXTTYPE 95 const int32_t indexFull = index; 96 97 switch (indexFull) { 98 case OMX_IndexParamVideoVp8: 99 return internalGetVp8Params( 100 (OMX_VIDEO_PARAM_VP8TYPE *)param); 101 102 case OMX_IndexParamVideoAndroidVp8Encoder: 103 return internalGetAndroidVp8Params( 104 (OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param); 105 106 default: 107 return SoftVPXEncoder::internalGetParameter(index, param); 108 } 109} 110 111OMX_ERRORTYPE SoftVP8Encoder::internalSetParameter(OMX_INDEXTYPE index, 112 const OMX_PTR param) { 113 // can include extension index OMX_INDEXEXTTYPE 114 const int32_t indexFull = index; 115 116 switch (indexFull) { 117 case OMX_IndexParamVideoVp8: 118 return internalSetVp8Params( 119 (const OMX_VIDEO_PARAM_VP8TYPE *)param); 120 121 case OMX_IndexParamVideoAndroidVp8Encoder: 122 return internalSetAndroidVp8Params( 123 (const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param); 124 125 default: 126 return SoftVPXEncoder::internalSetParameter(index, param); 127 } 128} 129 130OMX_ERRORTYPE SoftVP8Encoder::internalGetVp8Params( 131 OMX_VIDEO_PARAM_VP8TYPE* vp8Params) { 132 if (vp8Params->nPortIndex != kOutputPortIndex) { 133 return OMX_ErrorUnsupportedIndex; 134 } 135 136 vp8Params->eProfile = OMX_VIDEO_VP8ProfileMain; 137 vp8Params->eLevel = mLevel; 138 vp8Params->bErrorResilientMode = mErrorResilience; 139 vp8Params->nDCTPartitions = mDCTPartitions; 140 return OMX_ErrorNone; 141} 142 143OMX_ERRORTYPE SoftVP8Encoder::internalSetVp8Params( 144 const OMX_VIDEO_PARAM_VP8TYPE* vp8Params) { 145 if (vp8Params->nPortIndex != kOutputPortIndex) { 146 return OMX_ErrorUnsupportedIndex; 147 } 148 149 if (vp8Params->eProfile != OMX_VIDEO_VP8ProfileMain) { 150 return OMX_ErrorBadParameter; 151 } 152 153 if (vp8Params->eLevel == OMX_VIDEO_VP8Level_Version0 || 154 vp8Params->eLevel == OMX_VIDEO_VP8Level_Version1 || 155 vp8Params->eLevel == OMX_VIDEO_VP8Level_Version2 || 156 vp8Params->eLevel == OMX_VIDEO_VP8Level_Version3) { 157 mLevel = vp8Params->eLevel; 158 } else { 159 return OMX_ErrorBadParameter; 160 } 161 162 mErrorResilience = vp8Params->bErrorResilientMode; 163 if (vp8Params->nDCTPartitions <= kMaxDCTPartitions) { 164 mDCTPartitions = vp8Params->nDCTPartitions; 165 } else { 166 return OMX_ErrorBadParameter; 167 } 168 return OMX_ErrorNone; 169} 170 171OMX_ERRORTYPE SoftVP8Encoder::internalGetAndroidVp8Params( 172 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE* vp8AndroidParams) { 173 if (vp8AndroidParams->nPortIndex != kOutputPortIndex) { 174 return OMX_ErrorUnsupportedIndex; 175 } 176 177 vp8AndroidParams->nKeyFrameInterval = mKeyFrameInterval; 178 vp8AndroidParams->eTemporalPattern = mTemporalPatternType; 179 vp8AndroidParams->nTemporalLayerCount = mTemporalLayers; 180 vp8AndroidParams->nMinQuantizer = mMinQuantizer; 181 vp8AndroidParams->nMaxQuantizer = mMaxQuantizer; 182 memcpy(vp8AndroidParams->nTemporalLayerBitrateRatio, 183 mTemporalLayerBitrateRatio, sizeof(mTemporalLayerBitrateRatio)); 184 return OMX_ErrorNone; 185} 186 187OMX_ERRORTYPE SoftVP8Encoder::internalSetAndroidVp8Params( 188 const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE* vp8AndroidParams) { 189 if (vp8AndroidParams->nPortIndex != kOutputPortIndex) { 190 return OMX_ErrorUnsupportedIndex; 191 } 192 if (vp8AndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternNone && 193 vp8AndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternWebRTC) { 194 return OMX_ErrorBadParameter; 195 } 196 if (vp8AndroidParams->nTemporalLayerCount > OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS) { 197 return OMX_ErrorBadParameter; 198 } 199 if (vp8AndroidParams->nMinQuantizer > vp8AndroidParams->nMaxQuantizer) { 200 return OMX_ErrorBadParameter; 201 } 202 203 mTemporalPatternType = vp8AndroidParams->eTemporalPattern; 204 if (vp8AndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) { 205 mTemporalLayers = vp8AndroidParams->nTemporalLayerCount; 206 } else if (vp8AndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternNone) { 207 mTemporalLayers = 0; 208 } 209 // Check the bitrate distribution between layers is in increasing order 210 if (mTemporalLayers > 1) { 211 for (size_t i = 0; i < mTemporalLayers - 1; i++) { 212 if (vp8AndroidParams->nTemporalLayerBitrateRatio[i + 1] <= 213 vp8AndroidParams->nTemporalLayerBitrateRatio[i]) { 214 ALOGE("Wrong bitrate ratio - should be in increasing order."); 215 return OMX_ErrorBadParameter; 216 } 217 } 218 } 219 mKeyFrameInterval = vp8AndroidParams->nKeyFrameInterval; 220 mMinQuantizer = vp8AndroidParams->nMinQuantizer; 221 mMaxQuantizer = vp8AndroidParams->nMaxQuantizer; 222 memcpy(mTemporalLayerBitrateRatio, vp8AndroidParams->nTemporalLayerBitrateRatio, 223 sizeof(mTemporalLayerBitrateRatio)); 224 ALOGD("VPx: internalSetAndroidVp8Params. BRMode: %u. TS: %zu. KF: %u." 225 " QP: %u - %u BR0: %u. BR1: %u. BR2: %u", 226 (uint32_t)mBitrateControlMode, mTemporalLayers, mKeyFrameInterval, 227 mMinQuantizer, mMaxQuantizer, mTemporalLayerBitrateRatio[0], 228 mTemporalLayerBitrateRatio[1], mTemporalLayerBitrateRatio[2]); 229 return OMX_ErrorNone; 230} 231 232} // namespace android 233