• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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