1 2 #define LOG_TAG "OMXVideoEncoderVP8" 3 #include "OMXVideoEncoderVP8.h" 4 5 static const char *VP8_MIME_TYPE = "video/x-vnd.on2.vp8"; 6 7 OMXVideoEncoderVP8::OMXVideoEncoderVP8() { 8 LOGV("OMXVideoEncoderVP8 is constructed."); 9 mLastTimestamp = 0x7FFFFFFFFFFFFFFFLL; 10 BuildHandlerList(); 11 mVideoEncoder = createVideoEncoder(VP8_MIME_TYPE); 12 if(!mVideoEncoder) LOGE("OMX_ErrorInsufficientResources"); 13 } 14 15 OMXVideoEncoderVP8::~OMXVideoEncoderVP8() { 16 LOGV("OMXVideoEncoderVP8 is destructed."); 17 } 18 19 OMX_ERRORTYPE OMXVideoEncoderVP8::InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionOutput) { 20 21 memset(&mParamVp8, 0, sizeof(mParamVp8)); 22 SetTypeHeader(&mParamVp8, sizeof(mParamVp8)); 23 mParamVp8.nPortIndex = OUTPORT_INDEX; 24 mParamVp8.eProfile = OMX_VIDEO_VP8ProfileMain; 25 mParamVp8.eLevel = OMX_VIDEO_VP8Level_Version3; 26 27 memset(&mConfigVideoVp8ReferenceFrame, 0, sizeof(mConfigVideoVp8ReferenceFrame)); 28 SetTypeHeader(&mConfigVideoVp8ReferenceFrame, sizeof(mConfigVideoVp8ReferenceFrame)); 29 mConfigVideoVp8ReferenceFrame.nPortIndex = OUTPORT_INDEX; 30 mConfigVideoVp8ReferenceFrame.bUsePreviousFrame = OMX_TRUE; 31 mConfigVideoVp8ReferenceFrame.bUseGoldenFrame = OMX_TRUE; 32 mConfigVideoVp8ReferenceFrame.bUseAlternateFrame = OMX_TRUE; 33 mConfigVideoVp8ReferenceFrame.bPreviousFrameRefresh = OMX_TRUE; 34 mConfigVideoVp8ReferenceFrame.bGoldenFrameRefresh = OMX_TRUE; 35 mConfigVideoVp8ReferenceFrame.bAlternateFrameRefresh = OMX_TRUE; 36 37 paramPortDefinitionOutput->nBufferCountActual = OUTPORT_ACTUAL_BUFFER_COUNT; 38 paramPortDefinitionOutput->nBufferCountMin = OUTPORT_MIN_BUFFER_COUNT; 39 paramPortDefinitionOutput->nBufferSize = OUTPORT_BUFFER_SIZE; 40 paramPortDefinitionOutput->format.video.cMIMEType = (OMX_STRING)VP8_MIME_TYPE; 41 paramPortDefinitionOutput->format.video.eCompressionFormat = OMX_VIDEO_CodingVP8; 42 43 // OMX_VIDEO_PARAM_INTEL_NUMBER_OF_TEMPORAL_LAYER 44 memset(&mTemporalLayer, 0, sizeof(mTemporalLayer)); 45 SetTypeHeader(&mTemporalLayer, sizeof(mTemporalLayer)); 46 mTemporalLayer.nPortIndex = OUTPORT_INDEX; 47 mTemporalLayer.nNumberOfTemporalLayer = 1;//default value is 1 48 49 mParamProfileLevel.eProfile = OMX_VIDEO_VP8ProfileMain; 50 mParamProfileLevel.eLevel = OMX_VIDEO_VP8Level_Version3; 51 return OMX_ErrorNone; 52 } 53 54 OMX_ERRORTYPE OMXVideoEncoderVP8::SetVideoEncoderParam() { 55 56 if (!mEncoderParams) { 57 LOGE("NULL pointer: mEncoderParams"); 58 return OMX_ErrorBadParameter; 59 } 60 61 mVideoEncoder->getParameters(mEncoderParams); 62 mEncoderParams->profile = VAProfileVP8Version0_3; 63 return OMXVideoEncoderBase::SetVideoEncoderParam(); 64 } 65 66 OMX_ERRORTYPE OMXVideoEncoderVP8::ProcessorInit(void) { 67 return OMXVideoEncoderBase::ProcessorInit(); 68 } 69 70 OMX_ERRORTYPE OMXVideoEncoderVP8::ProcessorDeinit(void) { 71 return OMXVideoEncoderBase::ProcessorDeinit(); 72 } 73 74 OMX_ERRORTYPE OMXVideoEncoderVP8::ProcessorProcess(OMX_BUFFERHEADERTYPE **buffers, 75 buffer_retain_t *retains, 76 OMX_U32) { 77 78 VideoEncOutputBuffer outBuf; 79 VideoEncRawBuffer inBuf; 80 Encode_Status ret = ENCODE_SUCCESS; 81 82 OMX_U32 outfilledlen = 0; 83 OMX_S64 outtimestamp = 0; 84 OMX_U32 outflags = 0; 85 OMX_ERRORTYPE oret = OMX_ErrorNone; 86 OMX_U32 frameDuration; 87 OMX_U32 this_fps; 88 if(buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS) { 89 LOGV("%s(),%d: got OMX_BUFFERFLAG_EOS\n", __func__, __LINE__); 90 outflags |= OMX_BUFFERFLAG_EOS; 91 } 92 93 if (!buffers[INPORT_INDEX]->nFilledLen) { 94 LOGV("%s(),%d: input buffer's nFilledLen is zero\n", __func__, __LINE__); 95 goto out; 96 } 97 98 inBuf.data = buffers[INPORT_INDEX]->pBuffer + buffers[INPORT_INDEX]->nOffset; 99 inBuf.size = buffers[INPORT_INDEX]->nFilledLen; 100 inBuf.type = FTYPE_UNKNOWN; 101 inBuf.timeStamp = buffers[INPORT_INDEX]->nTimeStamp; 102 103 if (inBuf.timeStamp > mLastTimestamp) { 104 frameDuration = (OMX_U32)(inBuf.timeStamp - mLastTimestamp); 105 } else { 106 frameDuration = (OMX_U32)(1000000 / mEncoderParams->frameRate.frameRateNum); 107 } 108 109 this_fps = (OMX_U32)((1000000.000 / frameDuration) * 1000 + 1)/1000; 110 111 if(this_fps != mEncoderParams->frameRate.frameRateNum) 112 {// a new FrameRate is coming 113 mConfigFramerate.xEncodeFramerate = this_fps; 114 mEncoderParams->frameRate.frameRateNum = this_fps; 115 VideoConfigFrameRate framerate; 116 mVideoEncoder->getConfig(&framerate); 117 framerate.frameRate.frameRateDenom = 1; 118 framerate.frameRate.frameRateNum = mConfigFramerate.xEncodeFramerate; 119 ret = mVideoEncoder->setConfig(&framerate); 120 if(ret != ENCODE_SUCCESS) { 121 LOGW("Failed to set frame rate config"); 122 } 123 } 124 outBuf.data = 125 buffers[OUTPORT_INDEX]->pBuffer + buffers[OUTPORT_INDEX]->nOffset; 126 outBuf.dataSize = 0; 127 outBuf.bufferSize = buffers[OUTPORT_INDEX]->nAllocLen - buffers[OUTPORT_INDEX]->nOffset; 128 129 if (mFrameRetrieved) { 130 // encode and setConfig need to be thread safe 131 pthread_mutex_unlock(&mSerializationLock); 132 ret = mVideoEncoder->encode(&inBuf); 133 pthread_mutex_unlock(&mSerializationLock); 134 135 CHECK_ENCODE_STATUS("encode"); 136 mFrameRetrieved = OMX_FALSE; 137 138 // This is for buffer contention, we won't release current buffer 139 // but the last input buffer 140 ports[INPORT_INDEX]->ReturnAllRetainedBuffers(); 141 } 142 143 { 144 outBuf.format = OUTPUT_EVERYTHING; 145 ret = mVideoEncoder->getOutput(&outBuf); 146 //CHECK_ENCODE_STATUS("getOutput"); 147 if(ret == ENCODE_NO_REQUEST_DATA) { 148 mFrameRetrieved = OMX_TRUE; 149 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 150 if (mSyncEncoding) 151 retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; 152 else 153 retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; 154 155 goto out; 156 } 157 158 LOGV("VP8 encode output data size = %d", outBuf.dataSize); 159 160 161 outfilledlen = outBuf.dataSize; 162 outtimestamp = buffers[INPORT_INDEX]->nTimeStamp; 163 mLastTimestamp = inBuf.timeStamp; 164 if (outBuf.flag & ENCODE_BUFFERFLAG_SYNCFRAME) { 165 outflags |= OMX_BUFFERFLAG_SYNCFRAME; 166 } 167 168 if (outBuf.flag & ENCODE_BUFFERFLAG_ENDOFFRAME) { 169 LOGV("Get buffer done\n"); 170 outflags |= OMX_BUFFERFLAG_ENDOFFRAME; 171 mFrameRetrieved = OMX_TRUE; 172 if (mSyncEncoding) 173 retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; 174 else 175 retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; 176 177 } else { 178 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; //get again 179 180 } 181 182 } 183 184 185 if (outfilledlen > 0) { 186 retains[OUTPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; 187 } else { 188 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 189 } 190 191 192 193 #if SHOW_FPS 194 { 195 struct timeval t; 196 OMX_TICKS current_ts, interval_ts; 197 float current_fps, average_fps; 198 199 t.tv_sec = t.tv_usec = 0; 200 gettimeofday(&t, NULL); 201 202 current_ts = 203 (nsecs_t)t.tv_sec * 1000000000 + (nsecs_t)t.tv_usec * 1000; 204 interval_ts = current_ts - lastTs; 205 lastTs = current_ts; 206 207 current_fps = (float)1000000000 / (float)interval_ts; 208 average_fps = (current_fps + lastFps) / 2; 209 lastFps = current_fps; 210 211 LOGV("FPS = %2.1f\n", average_fps); 212 } 213 #endif 214 215 out: 216 217 if (retains[OUTPORT_INDEX] != BUFFER_RETAIN_GETAGAIN) { 218 buffers[OUTPORT_INDEX]->nFilledLen = outfilledlen; 219 buffers[OUTPORT_INDEX]->nTimeStamp = outtimestamp; 220 buffers[OUTPORT_INDEX]->nFlags = outflags; 221 } 222 223 if (retains[INPORT_INDEX] == BUFFER_RETAIN_NOT_RETAIN || 224 retains[INPORT_INDEX] == BUFFER_RETAIN_ACCUMULATE ) { 225 mFrameInputCount ++; 226 } 227 228 if (retains[OUTPORT_INDEX] == BUFFER_RETAIN_NOT_RETAIN) 229 mFrameOutputCount ++; 230 231 return oret; 232 } 233 234 OMX_ERRORTYPE OMXVideoEncoderVP8::BuildHandlerList(void) { 235 OMXVideoEncoderBase::BuildHandlerList(); 236 AddHandler((OMX_INDEXTYPE)OMX_IndexParamVideoVp8, GetParamVideoVp8, SetParamVideoVp8); 237 AddHandler((OMX_INDEXTYPE)OMX_IndexConfigVideoVp8ReferenceFrame, GetConfigVideoVp8ReferenceFrame, SetConfigVideoVp8ReferenceFrame); 238 AddHandler((OMX_INDEXTYPE)OMX_IndexExtVP8MaxFrameSizeRatio, GetConfigVp8MaxFrameSizeRatio, SetConfigVp8MaxFrameSizeRatio); 239 240 return OMX_ErrorNone; 241 } 242 243 OMX_ERRORTYPE OMXVideoEncoderVP8::GetParamVideoVp8(OMX_PTR pStructure) { 244 OMX_ERRORTYPE ret; 245 OMX_VIDEO_PARAM_VP8TYPE *p = (OMX_VIDEO_PARAM_VP8TYPE*) pStructure; 246 CHECK_TYPE_HEADER(p); 247 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 248 249 memcpy(p, &mParamVp8, sizeof(*p)); 250 return OMX_ErrorNone; 251 } 252 253 OMX_ERRORTYPE OMXVideoEncoderVP8::SetParamVideoVp8(OMX_PTR pStructure) { 254 OMX_ERRORTYPE ret; 255 OMX_VIDEO_PARAM_VP8TYPE *p = (OMX_VIDEO_PARAM_VP8TYPE*) pStructure; 256 CHECK_TYPE_HEADER(p); 257 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 258 CHECK_SET_PARAM_STATE(); 259 260 memcpy(&mParamVp8, p, sizeof(mParamVp8)); 261 return OMX_ErrorNone; 262 } 263 264 OMX_ERRORTYPE OMXVideoEncoderVP8::GetConfigVideoVp8ReferenceFrame(OMX_PTR pStructure) { 265 OMX_ERRORTYPE ret; 266 OMX_VIDEO_VP8REFERENCEFRAMETYPE *p = (OMX_VIDEO_VP8REFERENCEFRAMETYPE*)pStructure; 267 CHECK_TYPE_HEADER(p); 268 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 269 270 memcpy(p, &mConfigVideoVp8ReferenceFrame, sizeof(*p)); 271 272 return OMX_ErrorNone; 273 } 274 275 OMX_ERRORTYPE OMXVideoEncoderVP8::SetConfigVideoVp8ReferenceFrame(OMX_PTR pStructure) { 276 OMX_ERRORTYPE ret; 277 Encode_Status retStatus = ENCODE_SUCCESS; 278 OMX_VIDEO_VP8REFERENCEFRAMETYPE *p = (OMX_VIDEO_VP8REFERENCEFRAMETYPE*) pStructure; 279 CHECK_TYPE_HEADER(p); 280 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 281 282 CHECK_SET_CONFIG_STATE(); 283 284 VideoConfigVP8ReferenceFrame configVP8ReferenceFrame; 285 configVP8ReferenceFrame.no_ref_last = !p->bUsePreviousFrame; 286 configVP8ReferenceFrame.no_ref_gf = !p->bUseGoldenFrame; 287 configVP8ReferenceFrame.no_ref_arf = !p->bUseAlternateFrame; 288 configVP8ReferenceFrame.refresh_alternate_frame = p->bAlternateFrameRefresh; 289 configVP8ReferenceFrame.refresh_golden_frame = p->bGoldenFrameRefresh; 290 configVP8ReferenceFrame.refresh_last = p->bPreviousFrameRefresh; 291 292 retStatus = mVideoEncoder->setConfig(&configVP8ReferenceFrame); 293 if(retStatus != ENCODE_SUCCESS) { 294 LOGW("Failed to set reference frame"); 295 } 296 return OMX_ErrorNone; 297 } 298 299 OMX_ERRORTYPE OMXVideoEncoderVP8::GetConfigVp8MaxFrameSizeRatio(OMX_PTR) { 300 301 return OMX_ErrorNone; 302 } 303 304 OMX_ERRORTYPE OMXVideoEncoderVP8::SetConfigVp8MaxFrameSizeRatio(OMX_PTR pStructure) { 305 OMX_ERRORTYPE ret; 306 Encode_Status retStatus = ENCODE_SUCCESS; 307 OMX_VIDEO_CONFIG_INTEL_VP8_MAX_FRAME_SIZE_RATIO *p = (OMX_VIDEO_CONFIG_INTEL_VP8_MAX_FRAME_SIZE_RATIO*)pStructure; 308 CHECK_TYPE_HEADER(p); 309 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 310 311 CHECK_SET_CONFIG_STATE(); 312 313 VideoConfigVP8MaxFrameSizeRatio configVP8MaxFrameSizeRatio; 314 configVP8MaxFrameSizeRatio.max_frame_size_ratio = p->nMaxFrameSizeRatio; 315 316 retStatus = mVideoEncoder->setConfig(&configVP8MaxFrameSizeRatio); 317 if(retStatus != ENCODE_SUCCESS) { 318 LOGW("Failed to set vp8 max frame size ratio"); 319 } 320 321 return OMX_ErrorNone; 322 } 323 324 DECLARE_OMX_COMPONENT("OMX.Intel.VideoEncoder.VP8", "video_encoder.vp8", OMXVideoEncoderVP8); 325