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