• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_NDEBUG 0
19 #define LOG_TAG "OMXVideoDecoder"
20 #include <wrs_omxil_core/log.h>
21 #include "OMXVideoDecoderAVC.h"
22 
23 
24 // Be sure to have an equal string in VideoDecoderHost.cpp (libmix)
25 static const char* AVC_MIME_TYPE = "video/h264";
26 #define INVALID_PTS (OMX_S64)-1
27 
28 
OMXVideoDecoderAVC()29 OMXVideoDecoderAVC::OMXVideoDecoderAVC()
30     : mAccumulateBuffer(NULL),
31       mBufferSize(0),
32       mFilledLen(0),
33       mTimeStamp(INVALID_PTS) {
34     LOGV("OMXVideoDecoderAVC is constructed.");
35     mVideoDecoder = createVideoDecoder(AVC_MIME_TYPE);
36     if (!mVideoDecoder) {
37         LOGE("createVideoDecoder failed for \"%s\"", AVC_MIME_TYPE);
38     }
39     // Override default native buffer count defined in the base class
40     mNativeBufferCount = OUTPORT_NATIVE_BUFFER_COUNT;
41     BuildHandlerList();
42 }
43 
~OMXVideoDecoderAVC()44 OMXVideoDecoderAVC::~OMXVideoDecoderAVC() {
45     LOGV("OMXVideoDecoderAVC is destructed.");
46 }
47 
InitInputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE * paramPortDefinitionInput)48 OMX_ERRORTYPE OMXVideoDecoderAVC::InitInputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput) {
49     //OMX_VIDEO_PARAM_INTEL_AVC_DECODE_SETTINGS
50     memset(&mDecodeSettings, 0, sizeof(mDecodeSettings));
51     SetTypeHeader(&mDecodeSettings, sizeof(mDecodeSettings));
52     mDecodeSettings.nMaxNumberOfReferenceFrame = NUM_REFERENCE_FRAME;
53 
54     // OMX_PARAM_PORTDEFINITIONTYPE
55     paramPortDefinitionInput->nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT;
56     paramPortDefinitionInput->nBufferCountMin = INPORT_MIN_BUFFER_COUNT;
57     paramPortDefinitionInput->nBufferSize = INPORT_BUFFER_SIZE;
58     paramPortDefinitionInput->format.video.cMIMEType = (OMX_STRING)AVC_MIME_TYPE;
59     paramPortDefinitionInput->format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
60 
61     // OMX_VIDEO_PARAM_AVCTYPE
62     memset(&mParamAvc, 0, sizeof(mParamAvc));
63     SetTypeHeader(&mParamAvc, sizeof(mParamAvc));
64     mParamAvc.nPortIndex = INPORT_INDEX;
65     // TODO: check eProfile/eLevel
66     mParamAvc.eProfile = OMX_VIDEO_AVCProfileHigh; //OMX_VIDEO_AVCProfileBaseline;
67     mParamAvc.eLevel = OMX_VIDEO_AVCLevel41; //OMX_VIDEO_AVCLevel1;
68 
69     return OMX_ErrorNone;
70 }
71 
ProcessorInit(void)72 OMX_ERRORTYPE OMXVideoDecoderAVC::ProcessorInit(void) {
73     return OMXVideoDecoderBase::ProcessorInit();
74 }
75 
ProcessorDeinit(void)76 OMX_ERRORTYPE OMXVideoDecoderAVC::ProcessorDeinit(void) {
77     if (mAccumulateBuffer) {
78         delete mAccumulateBuffer;
79     }
80     mAccumulateBuffer = NULL;
81     mBufferSize = 0;
82     mFilledLen = 0;
83     mTimeStamp = INVALID_PTS;
84 
85     return OMXVideoDecoderBase::ProcessorDeinit();
86 }
87 
ProcessorFlush(OMX_U32 portIndex)88 OMX_ERRORTYPE OMXVideoDecoderAVC::ProcessorFlush(OMX_U32 portIndex) {
89     mFilledLen = 0;
90     mTimeStamp = INVALID_PTS;
91     return OMXVideoDecoderBase::ProcessorFlush(portIndex);
92 }
93 
ProcessorProcess(OMX_BUFFERHEADERTYPE *** pBuffers,buffer_retain_t * retains,OMX_U32 numberBuffers)94 OMX_ERRORTYPE OMXVideoDecoderAVC::ProcessorProcess(
95         OMX_BUFFERHEADERTYPE ***pBuffers,
96         buffer_retain_t *retains,
97         OMX_U32 numberBuffers) {
98 
99     return OMXVideoDecoderBase::ProcessorProcess(pBuffers, retains, numberBuffers);
100 }
101 
PrepareConfigBuffer(VideoConfigBuffer * p)102 OMX_ERRORTYPE OMXVideoDecoderAVC::PrepareConfigBuffer(VideoConfigBuffer *p) {
103     OMX_ERRORTYPE ret;
104 
105     ret = OMXVideoDecoderBase::PrepareConfigBuffer(p);
106     CHECK_RETURN_VALUE("OMXVideoDecoderBase::PrepareConfigBuffer");
107 
108     if (mParamAvc.eProfile == OMX_VIDEO_AVCProfileBaseline) {
109         p->flag |= WANT_LOW_DELAY;
110     }
111 
112     if (mDecodeSettings.nMaxWidth == 0 ||
113         mDecodeSettings.nMaxHeight == 0) {
114         return OMX_ErrorNone;
115     }
116 
117     LOGW("AVC Video decoder used in Video Conferencing Mode.");
118 
119     // For video conferencing application
120     p->width = mDecodeSettings.nMaxWidth;
121     p->height = mDecodeSettings.nMaxHeight;
122     p->profile = VAProfileH264ConstrainedBaseline;
123     if(!(p->flag & USE_NATIVE_GRAPHIC_BUFFER)) {
124         p->surfaceNumber = mDecodeSettings.nMaxNumberOfReferenceFrame + EXTRA_REFERENCE_FRAME;
125         p->flag = WANT_ERROR_CONCEALMENT | WANT_LOW_DELAY | HAS_SURFACE_NUMBER | HAS_VA_PROFILE;
126     } else {
127         p->flag |= WANT_ERROR_CONCEALMENT | WANT_LOW_DELAY | HAS_SURFACE_NUMBER | HAS_VA_PROFILE;
128     }
129 
130     return OMX_ErrorNone;
131 }
132 
PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE * buffer,buffer_retain_t * retain,VideoDecodeBuffer * p)133 OMX_ERRORTYPE OMXVideoDecoderAVC::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) {
134     OMX_ERRORTYPE ret;
135     ret = OMXVideoDecoderBase::PrepareDecodeBuffer(buffer, retain, p);
136     CHECK_RETURN_VALUE("OMXVideoDecoderBase::PrepareDecodeBuffer");
137 
138     // OMX_BUFFERFLAG_CODECCONFIG is an optional flag
139     // if flag is set, buffer will only contain codec data.
140     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
141         LOGV("Received AVC codec data.");
142         return ret;
143     }
144 
145     // OMX_BUFFERFLAG_ENDOFFRAME is an optional flag
146     if (buffer->nFlags & (OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS)) {
147         // TODO: if OMX_BUFFERFLAG_ENDOFFRAME indicates end of a NAL unit and in OMXVideoDecodeBase
148         // we set buffer flag to HAS_COMPLETE_FRAME,  corruption will happen
149         mTimeStamp = buffer->nTimeStamp;
150         if (mFilledLen == 0) {
151             // buffer is not accumulated and it contains a complete frame
152             return ret;
153         }
154         // buffer contains  the last part of fragmented frame
155         ret = AccumulateBuffer(buffer);
156         CHECK_RETURN_VALUE("AccumulateBuffer");
157         ret = FillDecodeBuffer(p);
158         CHECK_RETURN_VALUE("FillDecodeBuffer");
159         return ret;
160     }
161 
162     LOGW("Received fragmented buffer.");
163     // use time stamp to determine frame boundary
164     if (mTimeStamp == INVALID_PTS) {
165         // first ever buffer
166         mTimeStamp = buffer->nTimeStamp;
167     }
168 
169     if (mTimeStamp != buffer->nTimeStamp && mFilledLen != 0) {
170         // buffer accumulated contains a complete frame
171         ret = FillDecodeBuffer(p);
172         CHECK_RETURN_VALUE("FillDecodeBuffer");
173         // retain the current buffer
174         *retain = BUFFER_RETAIN_GETAGAIN;
175     } else {
176         // buffer accumulation for beginning of fragmented buffer (mFilledLen == 0) or
177         // middle/end of fragmented buffer (mFilledLen != 0)
178         ret = AccumulateBuffer(buffer);
179         CHECK_RETURN_VALUE("AccumulateBuffer");
180         ret = OMX_ErrorNotReady;
181     }
182 
183     if (buffer->nFilledLen != 0) {
184         mTimeStamp = buffer->nTimeStamp;
185     }
186     return ret;
187 }
188 
AccumulateBuffer(OMX_BUFFERHEADERTYPE * buffer)189 OMX_ERRORTYPE OMXVideoDecoderAVC::AccumulateBuffer(OMX_BUFFERHEADERTYPE *buffer) {
190     // check if allocated buffer is big enough
191     if (mFilledLen + buffer->nFilledLen > mBufferSize) {
192         mBufferSize = mFilledLen + buffer->nFilledLen;
193         if (mBufferSize < INPORT_BUFFER_SIZE) {
194             mBufferSize = INPORT_BUFFER_SIZE;
195         }
196         if (mBufferSize == 0) {
197             return OMX_ErrorBadParameter;
198         }
199         OMX_U8 *temp = new OMX_U8 [mBufferSize];
200         if (temp == NULL) {
201             mBufferSize = 0;
202             return OMX_ErrorInsufficientResources;
203         }
204         if (mFilledLen != 0) {
205             memcpy(temp, mAccumulateBuffer, mFilledLen);
206         }
207         if (mAccumulateBuffer) {
208             delete [] mAccumulateBuffer;
209         }
210         mAccumulateBuffer = temp;
211     }
212     if (buffer->nFilledLen != 0) {
213         memcpy(mAccumulateBuffer + mFilledLen, buffer->pBuffer + buffer->nOffset, buffer->nFilledLen);
214     }
215     mFilledLen += buffer->nFilledLen;
216     return OMX_ErrorNone;
217 }
218 
FillDecodeBuffer(VideoDecodeBuffer * p)219 OMX_ERRORTYPE OMXVideoDecoderAVC::FillDecodeBuffer(VideoDecodeBuffer *p) {
220     p->data = mAccumulateBuffer;
221     p->size = mFilledLen;
222     p->timeStamp = mTimeStamp;
223     p->flag = HAS_COMPLETE_FRAME;
224 
225     mFilledLen = 0;
226     return OMX_ErrorNone;
227 }
228 
BuildHandlerList(void)229 OMX_ERRORTYPE OMXVideoDecoderAVC::BuildHandlerList(void) {
230     OMXVideoDecoderBase::BuildHandlerList();
231     AddHandler(OMX_IndexParamVideoAvc, GetParamVideoAvc, SetParamVideoAvc);
232     AddHandler((OMX_INDEXTYPE)OMX_IndexParamIntelAVCDecodeSettings, GetParamIntelAVCDecodeSettings, SetParamIntelAVCDecodeSettings);
233     AddHandler(OMX_IndexParamVideoProfileLevelQuerySupported, GetParamVideoAVCProfileLevel, SetParamVideoAVCProfileLevel);
234     return OMX_ErrorNone;
235 }
236 
GetParamVideoAvc(OMX_PTR pStructure)237 OMX_ERRORTYPE OMXVideoDecoderAVC::GetParamVideoAvc(OMX_PTR pStructure) {
238     OMX_ERRORTYPE ret;
239     OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure;
240     CHECK_TYPE_HEADER(p);
241     CHECK_PORT_INDEX(p, INPORT_INDEX);
242 
243     memcpy(p, &mParamAvc, sizeof(*p));
244     return OMX_ErrorNone;
245 }
246 
SetParamVideoAvc(OMX_PTR pStructure)247 OMX_ERRORTYPE OMXVideoDecoderAVC::SetParamVideoAvc(OMX_PTR pStructure) {
248     OMX_ERRORTYPE ret;
249     OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure;
250     CHECK_TYPE_HEADER(p);
251     CHECK_PORT_INDEX(p, INPORT_INDEX);
252     CHECK_SET_PARAM_STATE();
253 
254     // TODO: do we need to check if port is enabled?
255     // TODO: see SetPortAvcParam implementation - Can we make simple copy????
256     memcpy(&mParamAvc, p, sizeof(mParamAvc));
257 
258     return OMX_ErrorNone;
259 }
260 
GetParamIntelAVCDecodeSettings(OMX_PTR)261 OMX_ERRORTYPE OMXVideoDecoderAVC::GetParamIntelAVCDecodeSettings(OMX_PTR) {
262     return OMX_ErrorNotImplemented;
263 }
264 
SetParamIntelAVCDecodeSettings(OMX_PTR pStructure)265 OMX_ERRORTYPE OMXVideoDecoderAVC::SetParamIntelAVCDecodeSettings(OMX_PTR pStructure) {
266     LOGW("SetParamIntelAVCDecodeSettings");
267 
268     OMX_ERRORTYPE ret;
269     OMX_VIDEO_PARAM_INTEL_AVC_DECODE_SETTINGS *p = (OMX_VIDEO_PARAM_INTEL_AVC_DECODE_SETTINGS *)pStructure;
270 
271     CHECK_TYPE_HEADER(p);
272     CHECK_PORT_INDEX(p, INPORT_INDEX);
273     CHECK_SET_PARAM_STATE();
274 
275     if(p->nMaxNumberOfReferenceFrame == 0) {
276         // TODO: check if we just return in this case.
277         p->nMaxNumberOfReferenceFrame = NUM_REFERENCE_FRAME;
278     }
279     LOGI("Maximum width = %u, height = %u, dpb = %u", p->nMaxWidth, p->nMaxHeight, p->nMaxNumberOfReferenceFrame);
280     mDecodeSettings = *p;
281 
282     return OMX_ErrorNone;
283 }
284 
GetParamVideoAVCProfileLevel(OMX_PTR pStructure)285 OMX_ERRORTYPE OMXVideoDecoderAVC::GetParamVideoAVCProfileLevel(OMX_PTR pStructure) {
286     OMX_ERRORTYPE ret;
287     OMX_VIDEO_PARAM_PROFILELEVELTYPE *p = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pStructure;
288     CHECK_TYPE_HEADER(p);
289     CHECK_PORT_INDEX(p, INPORT_INDEX);
290 
291     struct ProfileLevelTable {
292         OMX_U32 profile;
293         OMX_U32 level;
294     } plTable[] = {
295         {OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel42},
296         {OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel42},
297         {OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel42}
298     };
299 
300     OMX_U32 count = sizeof(plTable)/sizeof(ProfileLevelTable);
301     CHECK_ENUMERATION_RANGE(p->nProfileIndex,count);
302 
303     p->eProfile = plTable[p->nProfileIndex].profile;
304     p->eLevel = plTable[p->nProfileIndex].level;
305 
306     return OMX_ErrorNone;
307 }
308 
SetParamVideoAVCProfileLevel(OMX_PTR)309 OMX_ERRORTYPE OMXVideoDecoderAVC::SetParamVideoAVCProfileLevel(OMX_PTR) {
310     LOGW("SetParamVideoAVCProfileLevel is not supported.");
311     return OMX_ErrorUnsupportedSetting;
312 }
313 
GetOutputColorFormat(int width)314 OMX_COLOR_FORMATTYPE OMXVideoDecoderAVC::GetOutputColorFormat(int width)
315 {
316 #ifdef USE_GEN_HW
317     return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled;
318 #else
319     return OMXVideoDecoderBase::GetOutputColorFormat(width);
320 #endif
321 }
322 
SetMaxOutputBufferCount(OMX_PARAM_PORTDEFINITIONTYPE * p)323 OMX_ERRORTYPE OMXVideoDecoderAVC::SetMaxOutputBufferCount(OMX_PARAM_PORTDEFINITIONTYPE *p) {
324     OMX_ERRORTYPE ret;
325     CHECK_TYPE_HEADER(p);
326     CHECK_PORT_INDEX(p, OUTPORT_INDEX);
327 
328     p->nBufferCountActual = MAX_OUTPORT_BUFFER_COUNT;
329     return OMXVideoDecoderBase::SetMaxOutputBufferCount(p);
330 }
331 
332 DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.AVC", "video_decoder.avc", OMXVideoDecoderAVC);
333