1
2 #define LOG_TAG "OMXVideoEncoderVP8"
3 #include "OMXVideoEncoderVP8.h"
4
5 static const char *VP8_MIME_TYPE = "video/x-vnd.on2.vp8";
6
OMXVideoEncoderVP8()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
~OMXVideoEncoderVP8()15 OMXVideoEncoderVP8::~OMXVideoEncoderVP8() {
16 LOGV("OMXVideoEncoderVP8 is destructed.");
17 }
18
InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE * paramPortDefinitionOutput)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
SetVideoEncoderParam()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
ProcessorInit(void)66 OMX_ERRORTYPE OMXVideoEncoderVP8::ProcessorInit(void) {
67 return OMXVideoEncoderBase::ProcessorInit();
68 }
69
ProcessorDeinit(void)70 OMX_ERRORTYPE OMXVideoEncoderVP8::ProcessorDeinit(void) {
71 return OMXVideoEncoderBase::ProcessorDeinit();
72 }
73
ProcessorProcess(OMX_BUFFERHEADERTYPE ** buffers,buffer_retain_t * retains,OMX_U32)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
BuildHandlerList(void)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
GetParamVideoVp8(OMX_PTR pStructure)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
SetParamVideoVp8(OMX_PTR pStructure)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
GetConfigVideoVp8ReferenceFrame(OMX_PTR pStructure)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
SetConfigVideoVp8ReferenceFrame(OMX_PTR pStructure)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
GetConfigVp8MaxFrameSizeRatio(OMX_PTR)299 OMX_ERRORTYPE OMXVideoEncoderVP8::GetConfigVp8MaxFrameSizeRatio(OMX_PTR) {
300
301 return OMX_ErrorNone;
302 }
303
SetConfigVp8MaxFrameSizeRatio(OMX_PTR pStructure)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