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