1 /* 2 * Copyright (c) 2009-2011 Intel Corporation. All rights reserved. 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 18 #define LOG_TAG "OMXVideoEncoderH263" 19 #include "OMXVideoEncoderH263.h" 20 21 static const char *H263_MIME_TYPE = "video/h263"; 22 23 OMXVideoEncoderH263::OMXVideoEncoderH263() { 24 LOGV("Constructer for OMXVideoEncoderH263."); 25 BuildHandlerList(); 26 mVideoEncoder = createVideoEncoder(H263_MIME_TYPE); 27 if (!mVideoEncoder) LOGE("OMX_ErrorInsufficientResources"); 28 #ifdef SYNC_MODE 29 mSyncEncoding = OMX_TRUE; 30 #endif 31 } 32 33 OMXVideoEncoderH263::~OMXVideoEncoderH263() { 34 LOGV("Destructer for OMXVideoEncoderH263."); 35 } 36 37 OMX_ERRORTYPE OMXVideoEncoderH263::InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionOutput) { 38 // OMX_VIDEO_PARAM_H263TYPE 39 memset(&mParamH263, 0, sizeof(mParamH263)); 40 SetTypeHeader(&mParamH263, sizeof(mParamH263)); 41 mParamH263.nPortIndex = OUTPORT_INDEX; 42 mParamH263.eProfile = OMX_VIDEO_H263ProfileBaseline; 43 // TODO: check eLevel, 10 44 mParamH263.eLevel = OMX_VIDEO_H263Level45; //OMX_VIDEO_H263Level10; 45 46 // override OMX_PARAM_PORTDEFINITIONTYPE 47 paramPortDefinitionOutput->nBufferCountActual = OUTPORT_ACTUAL_BUFFER_COUNT; 48 paramPortDefinitionOutput->nBufferCountMin = OUTPORT_MIN_BUFFER_COUNT; 49 paramPortDefinitionOutput->nBufferSize = OUTPORT_BUFFER_SIZE; 50 paramPortDefinitionOutput->format.video.cMIMEType = (OMX_STRING)H263_MIME_TYPE; 51 paramPortDefinitionOutput->format.video.eCompressionFormat = OMX_VIDEO_CodingH263; 52 53 // override OMX_VIDEO_PARAM_PROFILELEVELTYPE 54 // TODO: check if profile/level supported is correct 55 mParamProfileLevel.eProfile = mParamH263.eProfile; 56 mParamProfileLevel.eLevel = mParamH263.eLevel; //OMX_VIDEO_H263Level70 57 58 // override OMX_VIDEO_PARAM_BITRATETYPE 59 mParamBitrate.nTargetBitrate = 64000; 60 61 // override OMX_VIDEO_CONFIG_INTEL_BITRATETYPE 62 mConfigIntelBitrate.nInitialQP = 15; // Initial QP for I frames 63 return OMX_ErrorNone; 64 } 65 66 OMX_ERRORTYPE OMXVideoEncoderH263::SetVideoEncoderParam(void) { 67 68 if (!mEncoderParams) { 69 LOGE("NULL pointer: mEncoderParams"); 70 return OMX_ErrorBadParameter; 71 } 72 73 mVideoEncoder->getParameters(mEncoderParams); 74 mEncoderParams->profile = (VAProfile)PROFILE_H263BASELINE; 75 return OMXVideoEncoderBase::SetVideoEncoderParam(); 76 } 77 78 OMX_ERRORTYPE OMXVideoEncoderH263::ProcessorInit(void) { 79 LOGV("OMXVideoEncoderH263::ProcessorInit\n"); 80 return OMXVideoEncoderBase::ProcessorInit(); 81 } 82 83 OMX_ERRORTYPE OMXVideoEncoderH263::ProcessorDeinit(void) { 84 return OMXVideoEncoderBase::ProcessorDeinit(); 85 } 86 87 OMX_ERRORTYPE OMXVideoEncoderH263::ProcessorProcess( 88 OMX_BUFFERHEADERTYPE **buffers, 89 buffer_retain_t *retains, 90 OMX_U32) { 91 LOGV("OMXVideoEncoderH263::ProcessorProcess \n"); 92 93 VideoEncOutputBuffer outBuf; 94 VideoEncRawBuffer inBuf; 95 OMX_U32 outfilledlen = 0; 96 OMX_S64 outtimestamp = 0; 97 OMX_U32 outflags = 0; 98 99 OMX_ERRORTYPE oret = OMX_ErrorNone; 100 Encode_Status ret = ENCODE_SUCCESS; 101 102 LOGV("%s(): enter encode\n", __func__); 103 104 LOGV_IF(buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS, 105 "%s(),%d: got OMX_BUFFERFLAG_EOS\n", __func__, __LINE__); 106 107 if (!buffers[INPORT_INDEX]->nFilledLen) { 108 LOGE("%s(),%d: input buffer's nFilledLen is zero\n", __func__, __LINE__); 109 goto out; 110 } 111 112 inBuf.data = buffers[INPORT_INDEX]->pBuffer + buffers[INPORT_INDEX]->nOffset; 113 inBuf.size = buffers[INPORT_INDEX]->nFilledLen; 114 inBuf.type = FTYPE_UNKNOWN; 115 inBuf.flag = 0; 116 inBuf.timeStamp = buffers[INPORT_INDEX]->nTimeStamp; 117 118 LOGV("buffer_in.data=%x, data_size=%d", 119 (unsigned)inBuf.data, inBuf.size); 120 121 outBuf.data = buffers[OUTPORT_INDEX]->pBuffer + buffers[OUTPORT_INDEX]->nOffset; 122 outBuf.bufferSize = buffers[OUTPORT_INDEX]->nAllocLen - buffers[OUTPORT_INDEX]->nOffset; 123 outBuf.dataSize = 0; 124 125 if(mFrameRetrieved) { 126 // encode and setConfig need to be thread safe 127 pthread_mutex_unlock(&mSerializationLock); 128 ret = mVideoEncoder->encode(&inBuf); 129 pthread_mutex_unlock(&mSerializationLock); 130 131 CHECK_ENCODE_STATUS("encode"); 132 mFrameRetrieved = OMX_FALSE; 133 134 // This is for buffer contention, we won't release current buffer 135 // but the last input buffer 136 ports[INPORT_INDEX]->ReturnAllRetainedBuffers(); 137 } 138 139 if (mSyncEncoding == OMX_FALSE && mFrameInputCount == 0) { 140 retains[INPORT_INDEX] = BUFFER_RETAIN_ACCUMULATE; 141 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 142 mFrameRetrieved = OMX_TRUE; 143 goto out; 144 } 145 146 outBuf.format = OUTPUT_EVERYTHING; 147 ret = mVideoEncoder->getOutput(&outBuf); 148 // CHECK_ENCODE_STATUS("encode"); 149 if(ret == ENCODE_NO_REQUEST_DATA) { 150 mFrameRetrieved = OMX_TRUE; 151 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 152 if (mSyncEncoding) 153 retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; 154 else 155 retains[INPORT_INDEX] = BUFFER_RETAIN_ACCUMULATE; 156 157 goto out; 158 } 159 160 LOGV("output data size = %d", outBuf.dataSize); 161 outfilledlen = outBuf.dataSize; 162 outtimestamp = outBuf.timeStamp; 163 164 165 if (outBuf.flag & ENCODE_BUFFERFLAG_SYNCFRAME) { 166 outflags |= OMX_BUFFERFLAG_SYNCFRAME; 167 } 168 169 if(outBuf.flag & ENCODE_BUFFERFLAG_ENDOFFRAME) { 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_ACCUMULATE; 176 177 } else { 178 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; //get again 179 180 } 181 182 if (outfilledlen > 0) { 183 retains[OUTPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; 184 } else { 185 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 186 } 187 188 189 if(ret == ENCODE_SLICESIZE_OVERFLOW) { 190 LOGV("%s(), mix_video_encode returns MIX_RESULT_VIDEO_ENC_SLICESIZE_OVERFLOW" 191 , __func__); 192 oret = (OMX_ERRORTYPE)OMX_ErrorIntelExtSliceSizeOverflow; 193 } 194 #if SHOW_FPS 195 { 196 struct timeval t; 197 OMX_TICKS current_ts, interval_ts; 198 float current_fps, average_fps; 199 200 t.tv_sec = t.tv_usec = 0; 201 gettimeofday(&t, NULL); 202 203 current_ts =(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 LOGD("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 LOGV("********** output buffer: len=%d, ts=%lld, flags=%x", 223 outfilledlen, 224 outtimestamp, 225 outflags); 226 } 227 228 if (retains[INPORT_INDEX] == BUFFER_RETAIN_NOT_RETAIN || 229 retains[INPORT_INDEX] == BUFFER_RETAIN_ACCUMULATE ) { 230 mFrameInputCount ++; 231 } 232 233 if (retains[OUTPORT_INDEX] == BUFFER_RETAIN_NOT_RETAIN) 234 mFrameOutputCount ++; 235 236 LOGV_IF(oret == OMX_ErrorNone, "%s(),%d: exit, encode is done\n", __func__, __LINE__); 237 238 return oret; 239 240 } 241 242 OMX_ERRORTYPE OMXVideoEncoderH263::BuildHandlerList(void) { 243 OMXVideoEncoderBase::BuildHandlerList(); 244 AddHandler(OMX_IndexParamVideoH263, GetParamVideoH263, SetParamVideoH263); 245 AddHandler(OMX_IndexParamVideoProfileLevelQuerySupported, GetParamVideoProfileLevelQuerySupported, SetParamVideoProfileLevelQuerySupported); 246 return OMX_ErrorNone; 247 } 248 249 OMX_ERRORTYPE OMXVideoEncoderH263::GetParamVideoProfileLevelQuerySupported(OMX_PTR pStructure) { 250 OMX_ERRORTYPE ret; 251 OMX_VIDEO_PARAM_PROFILELEVELTYPE *p = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pStructure; 252 CHECK_TYPE_HEADER(p); 253 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 254 255 struct ProfileLevelTable { 256 OMX_U32 profile; 257 OMX_U32 level; 258 } plTable[] = { 259 {OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level45} 260 }; 261 262 OMX_U32 count = sizeof(plTable)/sizeof(ProfileLevelTable); 263 CHECK_ENUMERATION_RANGE(p->nProfileIndex,count); 264 265 p->eProfile = plTable[p->nProfileIndex].profile; 266 p->eLevel = plTable[p->nProfileIndex].level; 267 268 return OMX_ErrorNone; 269 } 270 271 OMX_ERRORTYPE OMXVideoEncoderH263::SetParamVideoProfileLevelQuerySupported(OMX_PTR) { 272 LOGW("SetParamVideoH263ProfileLevel is not supported."); 273 return OMX_ErrorUnsupportedSetting; 274 } 275 276 OMX_ERRORTYPE OMXVideoEncoderH263::GetParamVideoH263(OMX_PTR pStructure) { 277 OMX_ERRORTYPE ret; 278 OMX_VIDEO_PARAM_H263TYPE *p = (OMX_VIDEO_PARAM_H263TYPE *)pStructure; 279 CHECK_TYPE_HEADER(p); 280 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 281 282 memcpy(p, &mParamH263, sizeof(*p)); 283 return OMX_ErrorNone; 284 } 285 286 OMX_ERRORTYPE OMXVideoEncoderH263::SetParamVideoH263(OMX_PTR pStructure) { 287 OMX_ERRORTYPE ret; 288 OMX_VIDEO_PARAM_H263TYPE *p = (OMX_VIDEO_PARAM_H263TYPE *)pStructure; 289 CHECK_TYPE_HEADER(p); 290 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 291 CHECK_SET_PARAM_STATE(); 292 293 // TODO: do we need to check if port is enabled? 294 // TODO: see SetPortH263Param implementation - Can we make simple copy???? 295 memcpy(&mParamH263, p, sizeof(mParamH263)); 296 return OMX_ErrorNone; 297 } 298 299 300 DECLARE_OMX_COMPONENT("OMX.Intel.VideoEncoder.H263", "video_encoder.h263", OMXVideoEncoderH263); 301 302