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
OMXVideoEncoderH263()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
~OMXVideoEncoderH263()33 OMXVideoEncoderH263::~OMXVideoEncoderH263() {
34 LOGV("Destructer for OMXVideoEncoderH263.");
35 }
36
InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE * paramPortDefinitionOutput)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
SetVideoEncoderParam(void)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
ProcessorInit(void)78 OMX_ERRORTYPE OMXVideoEncoderH263::ProcessorInit(void) {
79 LOGV("OMXVideoEncoderH263::ProcessorInit\n");
80 return OMXVideoEncoderBase::ProcessorInit();
81 }
82
ProcessorDeinit(void)83 OMX_ERRORTYPE OMXVideoEncoderH263::ProcessorDeinit(void) {
84 return OMXVideoEncoderBase::ProcessorDeinit();
85 }
86
ProcessorProcess(OMX_BUFFERHEADERTYPE ** buffers,buffer_retain_t * retains,OMX_U32)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
BuildHandlerList(void)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
GetParamVideoProfileLevelQuerySupported(OMX_PTR pStructure)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
SetParamVideoProfileLevelQuerySupported(OMX_PTR)271 OMX_ERRORTYPE OMXVideoEncoderH263::SetParamVideoProfileLevelQuerySupported(OMX_PTR) {
272 LOGW("SetParamVideoH263ProfileLevel is not supported.");
273 return OMX_ErrorUnsupportedSetting;
274 }
275
GetParamVideoH263(OMX_PTR pStructure)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
SetParamVideoH263(OMX_PTR pStructure)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