1 /*
2 * Copyright (C) 2011 The Android Open Source Project
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 * @file M4DECODER_Null.c
19 * @brief Implementation of the Null decoder public interface
20 * @note This file implements a "null" video decoder, i.e. a decoder
21 * that does nothing
22 *************************************************************************
23 */
24 #include "NXPSW_CompilerSwitches.h"
25
26 #include "M4OSA_Types.h"
27 #include "M4OSA_Debug.h"
28 #include "M4TOOL_VersionInfo.h"
29 #include "M4DA_Types.h"
30 #include "M4DECODER_Common.h"
31 #include "M4DECODER_Null.h"
32
33 /**
34 ************************************************************************
35 * NULL Video Decoder version information
36 ************************************************************************
37 */
38 /* CHANGE_VERSION_HERE */
39 #define M4DECODER_NULL_MAJOR 1
40 #define M4DECODER_NULL_MINOR 0
41 #define M4DECODER_NULL_REVISION 0
42
43 /**
44 ************************************************************************
45 * structure M4_VideoHandler_Context
46 * @brief Defines the internal context of a video decoder instance
47 * @note The context is allocated and freed by the video decoder
48 ************************************************************************
49 */
50 typedef struct {
51 void* m_pLibrary; // Core library identifier
52 M4OSA_Int32 m_DecoderId; // Core decoder identifier
53 M4OSA_Int32 m_RendererId; // Core renderer identifier
54 M4_VideoStreamHandler* m_pVideoStreamhandler; // Video stream description
55 M4_AccessUnit* m_pNextAccessUnitToDecode; // Access unit used to
56 // read and decode one frame
57 void* m_pUserData; // Pointer to any user data
58 M4READER_DataInterface* m_pReader; // Reader data interface
59 M4OSA_Bool m_bDoRendering; // Decides if render required
60 M4OSA_Int32 m_structSize; // Size of the structure
61
62 M4DECODER_OutputFilter* m_pVideoFilter; // Color conversion filter
63 M4VIFI_ImagePlane *pDecYuvData; // Pointer to Yuv data plane
64 M4VIFI_ImagePlane *pDecYuvWithEffect; // Pointer to Yuv plane with color effect
65 M4OSA_Bool bYuvWithEffectSet; // Original Yuv data OR Yuv with color effect
66
67 } M4_VideoHandler_Context;
68
69 /***********************************************************************/
70 /************** M4DECODER_VideoInterface implementation ****************/
71 /***********************************************************************/
72
73 /**
74 ************************************************************************
75 * @brief Creates an instance of the decoder
76 * @note Allocates the context
77 *
78 * @param pContext: (OUT) Context of the decoder
79 * @param pStreamHandler: (IN) Pointer to a video stream description
80 * @param pSrcInterface: (IN) Pointer to the M4READER_DataInterface
81 * structure that must be used by the
82 * decoder to read data from the stream
83 * @param pAccessUnit (IN) Pointer to an access unit
84 * (allocated by the caller) where decoded data
85 * are stored
86 *
87 * @return M4NO_ERROR There is no error
88 * @return M4ERR_STATE State automaton is not applied
89 * @return M4ERR_ALLOC A memory allocation has failed
90 * @return M4ERR_PARAMETER At least one input parameter is not proper
91 ************************************************************************
92 */
M4DECODER_NULL_create(M4OSA_Context * pContext,M4_StreamHandler * pStreamHandler,M4READER_GlobalInterface * pReaderGlobalInterface,M4READER_DataInterface * pReaderDataInterface,M4_AccessUnit * pAccessUnit,M4OSA_Void * pUserData)93 M4OSA_ERR M4DECODER_NULL_create(M4OSA_Context *pContext,
94 M4_StreamHandler *pStreamHandler,
95 M4READER_GlobalInterface *pReaderGlobalInterface,
96 M4READER_DataInterface *pReaderDataInterface,
97 M4_AccessUnit* pAccessUnit,
98 M4OSA_Void* pUserData) {
99
100 M4_VideoHandler_Context* pStreamContext = M4OSA_NULL;
101
102 *pContext = M4OSA_NULL;
103 pStreamContext = (M4_VideoHandler_Context*)M4OSA_32bitAlignedMalloc (
104 sizeof(M4_VideoHandler_Context), M4DECODER_MPEG4,
105 (M4OSA_Char *)"M4_VideoHandler_Context");
106 if (pStreamContext == 0) {
107 return M4ERR_ALLOC;
108 }
109
110 pStreamContext->m_structSize = sizeof(M4_VideoHandler_Context);
111 pStreamContext->m_pNextAccessUnitToDecode = M4OSA_NULL;
112 pStreamContext->m_pLibrary = M4OSA_NULL;
113 pStreamContext->m_pVideoStreamhandler = M4OSA_NULL;
114 pStreamContext->m_DecoderId = -1;
115 pStreamContext->m_RendererId = -1;
116
117 pStreamContext->m_pUserData = M4OSA_NULL;
118 pStreamContext->m_bDoRendering = M4OSA_TRUE;
119 pStreamContext->m_pVideoFilter = M4OSA_NULL;
120 pStreamContext->bYuvWithEffectSet = M4OSA_FALSE;
121
122 *pContext=pStreamContext;
123 return M4NO_ERROR;
124 }
125
126 /**
127 ************************************************************************
128 * @brief Destroy the instance of the decoder
129 * @note After this call the context is invalid
130 *
131 * @param context: (IN) Context of the decoder
132 *
133 * @return M4NO_ERROR There is no error
134 * @return M4ERR_PARAMETER The context is invalid
135 ************************************************************************
136 */
M4DECODER_NULL_destroy(M4OSA_Context pContext)137 M4OSA_ERR M4DECODER_NULL_destroy(M4OSA_Context pContext) {
138
139 M4_VideoHandler_Context* pStreamContext = (M4_VideoHandler_Context*)pContext;
140
141 M4OSA_DEBUG_IF1((M4OSA_NULL == pStreamContext),
142 M4ERR_PARAMETER, "M4DECODER_NULL_destroy: invalid context pointer");
143
144 free(pStreamContext);
145
146 return M4NO_ERROR;
147 }
148
149 /**
150 ************************************************************************
151 * @brief Get an option value from the decoder
152 * @note This function allows the caller to retrieve a property value:
153 *
154 * @param context: (IN) Context of the decoder
155 * @param optionId: (IN) Indicates the option to get
156 * @param pValue: (IN/OUT) Pointer to structure or value where
157 * option is stored
158 *
159 * @return M4NO_ERROR There is no error
160 * @return M4ERR_PARAMETER The context is invalid (in DEBUG only)
161 * @return M4ERR_BAD_OPTION_ID When the option ID is not a valid one
162 * @return M4ERR_STATE State automaton is not applied
163 * @return M4ERR_NOT_IMPLEMENTED Function not implemented
164 ************************************************************************
165 */
M4DECODER_NULL_getOption(M4OSA_Context context,M4OSA_OptionID optionId,M4OSA_DataOption pValue)166 M4OSA_ERR M4DECODER_NULL_getOption(M4OSA_Context context,
167 M4OSA_OptionID optionId,
168 M4OSA_DataOption pValue) {
169
170 return M4ERR_NOT_IMPLEMENTED;
171 }
172
173 /**
174 ************************************************************************
175 * @brief Set an option value of the decoder
176 * @note Allows the caller to set a property value:
177 *
178 * @param context: (IN) Context of the decoder
179 * @param optionId: (IN) Identifier indicating the option to set
180 * @param pValue: (IN) Pointer to structure or value
181 * where option is stored
182 *
183 * @return M4NO_ERROR There is no error
184 * @return M4ERR_BAD_OPTION_ID The option ID is not a valid one
185 * @return M4ERR_STATE State automaton is not applied
186 * @return M4ERR_PARAMETER The option parameter is invalid
187 ************************************************************************
188 */
M4DECODER_NULL_setOption(M4OSA_Context context,M4OSA_OptionID optionId,M4OSA_DataOption pValue)189 M4OSA_ERR M4DECODER_NULL_setOption(M4OSA_Context context,
190 M4OSA_OptionID optionId,
191 M4OSA_DataOption pValue) {
192
193 M4DECODER_OutputFilter *pFilterOption;
194
195 M4_VideoHandler_Context *pStreamContext =
196 (M4_VideoHandler_Context*)context;
197
198 M4OSA_ERR err = M4NO_ERROR;
199 M4OSA_UInt32 height = 0;
200 M4OSA_UInt8 *p_src,*p_des;
201 M4VIFI_ImagePlane* pTempDecYuvData = M4OSA_NULL;
202
203 switch (optionId) {
204 case M4DECODER_kOptionID_DecYuvData:
205 pStreamContext->pDecYuvData = (M4VIFI_ImagePlane *)pValue;
206 break;
207
208 case M4DECODER_kOptionID_YuvWithEffectContiguous:
209 pStreamContext->pDecYuvWithEffect = (M4VIFI_ImagePlane *)pValue;
210 break;
211
212 case M4DECODER_kOptionID_EnableYuvWithEffect:
213 pStreamContext->bYuvWithEffectSet = (M4OSA_Bool)pValue;
214 break;
215
216 case M4DECODER_kOptionID_YuvWithEffectNonContiguous:
217 pTempDecYuvData = (M4VIFI_ImagePlane *)pValue;
218
219 p_des = pStreamContext->pDecYuvWithEffect[0].pac_data +
220 pStreamContext->pDecYuvWithEffect[0].u_topleft;
221 p_src = pTempDecYuvData[0].pac_data +
222 pTempDecYuvData[0].u_topleft;
223
224 for (height = 0; height<pStreamContext->pDecYuvWithEffect[0].u_height;
225 height++) {
226 memcpy((void *)p_des, (void *)p_src,
227 pStreamContext->pDecYuvWithEffect[0].u_width);
228
229 p_des += pStreamContext->pDecYuvWithEffect[0].u_stride;
230 p_src += pTempDecYuvData[0].u_stride;
231 }
232
233 p_des = pStreamContext->pDecYuvWithEffect[1].pac_data +
234 pStreamContext->pDecYuvWithEffect[1].u_topleft;
235 p_src = pTempDecYuvData[1].pac_data +
236 pTempDecYuvData[1].u_topleft;
237
238 for (height = 0; height<pStreamContext->pDecYuvWithEffect[1].u_height;
239 height++) {
240 memcpy((void *)p_des, (void *)p_src,
241 pStreamContext->pDecYuvWithEffect[1].u_width);
242
243 p_des += pStreamContext->pDecYuvWithEffect[1].u_stride;
244 p_src += pTempDecYuvData[1].u_stride;
245 }
246
247 p_des = pStreamContext->pDecYuvWithEffect[2].pac_data +
248 pStreamContext->pDecYuvWithEffect[2].u_topleft;
249 p_src = pTempDecYuvData[2].pac_data +
250 pTempDecYuvData[2].u_topleft;
251
252 for (height = 0; height<pStreamContext->pDecYuvWithEffect[2].u_height;
253 height++) {
254 memcpy((void *)p_des, (void *)p_src,
255 pStreamContext->pDecYuvWithEffect[2].u_width);
256
257 p_des += pStreamContext->pDecYuvWithEffect[2].u_stride;
258 p_src += pTempDecYuvData[2].u_stride;
259 }
260 break;
261
262 case M4DECODER_kOptionID_OutputFilter:
263 pFilterOption = (M4DECODER_OutputFilter*)pValue;
264 break;
265
266 case M4DECODER_kOptionID_DeblockingFilter:
267 err = M4ERR_BAD_OPTION_ID;
268 break;
269
270 default:
271 err = M4ERR_BAD_OPTION_ID;
272 break;
273 }
274 return err;
275 }
276
277 /**
278 ************************************************************************
279 * @brief Decode video Access Units up to a target time
280 * @note Parse and decode the video until it can output a decoded image
281 * for which the composition time is equal or greater to the
282 * passed targeted time.
283 * The data are read from the reader data interface passed to
284 * M4DECODER_MPEG4_create.
285 *
286 * @param context: (IN) Context of the decoder
287 * @param pTime: (IN/OUT) IN: Time to decode up to (in msec)
288 * OUT:Time of the last decoded frame (in msec)
289 * @param bJump: (IN) 0 if no jump occured just before this call
290 * 1 if a a jump has just been made
291 * @return M4NO_ERROR there is no error
292 * @return M4ERR_PARAMETER at least one parameter is not properly set
293 * @return M4WAR_NO_MORE_AU there is no more access unit to decode (EOS)
294 ************************************************************************
295 */
M4DECODER_NULL_decode(M4OSA_Context context,M4_MediaTime * pTime,M4OSA_Bool bJump,M4OSA_UInt32 tolerance)296 M4OSA_ERR M4DECODER_NULL_decode(M4OSA_Context context,
297 M4_MediaTime* pTime, M4OSA_Bool bJump,
298 M4OSA_UInt32 tolerance) {
299
300 // Do nothing; input time stamp itself returned
301 return M4NO_ERROR;
302 }
303
304 /**
305 ************************************************************************
306 * @brief Renders the video at the specified time.
307 * @note
308 * @param context: (IN) Context of the decoder
309 * @param pTime: (IN/OUT) IN: Time to render to (in msecs)
310 * OUT:Time of the rendered frame (in ms)
311 * @param pOutputPlane:(OUT) Output plane filled with decoded data
312 * @param bForceRender:(IN) 1 if the image must be rendered even it
313 * has been rendered already
314 * 0 if not
315 *
316 * @return M4NO_ERROR There is no error
317 * @return M4ERR_PARAMETER At least one parameter is not properly set
318 * @return M4ERR_STATE State automaton is not applied
319 * @return M4ERR_ALLOC There is no more available memory
320 * @return M4WAR_VIDEORENDERER_NO_NEW_FRAME If the frame has already been rendered
321 ************************************************************************
322 */
M4DECODER_NULL_render(M4OSA_Context context,M4_MediaTime * pTime,M4VIFI_ImagePlane * pOutputPlane,M4OSA_Bool bForceRender)323 M4OSA_ERR M4DECODER_NULL_render(M4OSA_Context context, M4_MediaTime* pTime,
324 M4VIFI_ImagePlane* pOutputPlane,
325 M4OSA_Bool bForceRender) {
326
327 M4OSA_ERR err = M4NO_ERROR;
328 M4OSA_UInt32 height;
329 M4OSA_UInt8 *p_src,*p_des;
330 M4_VideoHandler_Context* pStreamContext =
331 (M4_VideoHandler_Context*)context;
332
333 if (pStreamContext->bYuvWithEffectSet == M4OSA_TRUE) {
334
335 p_des = pOutputPlane[0].pac_data + pOutputPlane[0].u_topleft;
336 p_src = pStreamContext->pDecYuvWithEffect[0].pac_data +
337 pStreamContext->pDecYuvWithEffect[0].u_topleft;
338
339 for (height = 0; height<pOutputPlane[0].u_height; height++) {
340 memcpy((void *)p_des, (void *)p_src, pOutputPlane[0].u_width);
341 p_des += pOutputPlane[0].u_stride;
342 p_src += pStreamContext->pDecYuvWithEffect[0].u_stride;
343 }
344
345 p_des = pOutputPlane[1].pac_data + pOutputPlane[1].u_topleft;
346 p_src = pStreamContext->pDecYuvWithEffect[1].pac_data +
347 pStreamContext->pDecYuvWithEffect[1].u_topleft;
348
349 for (height = 0; height<pOutputPlane[1].u_height; height++) {
350 memcpy((void *)p_des, (void *)p_src, pOutputPlane[1].u_width);
351 p_des += pOutputPlane[1].u_stride;
352 p_src += pStreamContext->pDecYuvWithEffect[1].u_stride;
353 }
354
355 p_des = pOutputPlane[2].pac_data + pOutputPlane[2].u_topleft;
356 p_src = pStreamContext->pDecYuvWithEffect[2].pac_data +
357 pStreamContext->pDecYuvWithEffect[2].u_topleft;
358
359 for (height = 0; height<pOutputPlane[2].u_height; height++) {
360 memcpy((void *)p_des, (void *)p_src, pOutputPlane[2].u_width);
361 p_des += pOutputPlane[2].u_stride;
362 p_src += pStreamContext->pDecYuvWithEffect[2].u_stride;
363 }
364 } else {
365
366 p_des = pOutputPlane[0].pac_data + pOutputPlane[0].u_topleft;
367 p_src = pStreamContext->pDecYuvData[0].pac_data +
368 pStreamContext->pDecYuvData[0].u_topleft;
369
370 for (height = 0; height<pOutputPlane[0].u_height; height++) {
371 memcpy((void *)p_des, (void *)p_src, pOutputPlane[0].u_width);
372 p_des += pOutputPlane[0].u_stride;
373 p_src += pStreamContext->pDecYuvData[0].u_stride;
374 }
375
376 p_des = pOutputPlane[1].pac_data + pOutputPlane[1].u_topleft;
377 p_src = pStreamContext->pDecYuvData[1].pac_data +
378 pStreamContext->pDecYuvData[1].u_topleft;
379
380 for (height = 0; height<pOutputPlane[1].u_height; height++) {
381 memcpy((void *)p_des, (void *)p_src, pOutputPlane[1].u_width);
382 p_des += pOutputPlane[1].u_stride;
383 p_src += pStreamContext->pDecYuvData[1].u_stride;
384 }
385
386 p_des = pOutputPlane[2].pac_data + pOutputPlane[2].u_topleft;
387 p_src = pStreamContext->pDecYuvData[2].pac_data +
388 pStreamContext->pDecYuvData[2].u_topleft;
389
390 for (height = 0; height<pOutputPlane[2].u_height; height++) {
391 memcpy((void *)p_des,(void *)p_src,pOutputPlane[2].u_width);
392 p_des += pOutputPlane[2].u_stride;
393 p_src += pStreamContext->pDecYuvData[2].u_stride;
394 }
395 }
396 return err;
397 }
398
399 /**
400 ************************************************************************
401 * @brief Retrieves the interface implemented by the decoder
402 * @param pDecoderType : Pointer to a M4DECODER_VideoType
403 * (allocated by the caller)
404 * that will be filled with the decoder type
405 * @param pDecoderInterface : Address of a pointer that will be set to
406 * the interface implemented by this decoder.
407 * The interface is a structure allocated by
408 * this function and must be freed by the caller.
409 *
410 * @returns : M4NO_ERROR if OK
411 * M4ERR_ALLOC if allocation failed
412 ************************************************************************
413 */
M4DECODER_NULL_getInterface(M4DECODER_VideoType * pDecoderType,M4DECODER_VideoInterface ** pDecoderInterface)414 M4OSA_ERR M4DECODER_NULL_getInterface (M4DECODER_VideoType *pDecoderType,
415 M4DECODER_VideoInterface **pDecoderInterface) {
416
417 *pDecoderInterface =
418 (M4DECODER_VideoInterface*)M4OSA_32bitAlignedMalloc(
419 sizeof(M4DECODER_VideoInterface),
420 M4DECODER_MPEG4, (M4OSA_Char *)"M4DECODER_VideoInterface");
421
422 if (M4OSA_NULL == *pDecoderInterface) {
423 return M4ERR_ALLOC;
424 }
425
426 *pDecoderType = M4DECODER_kVideoTypeYUV420P;
427
428 (*pDecoderInterface)->m_pFctCreate = M4DECODER_NULL_create;
429 (*pDecoderInterface)->m_pFctDestroy = M4DECODER_NULL_destroy;
430 (*pDecoderInterface)->m_pFctGetOption = M4DECODER_NULL_getOption;
431 (*pDecoderInterface)->m_pFctSetOption = M4DECODER_NULL_setOption;
432 (*pDecoderInterface)->m_pFctDecode = M4DECODER_NULL_decode;
433 (*pDecoderInterface)->m_pFctRender = M4DECODER_NULL_render;
434
435 return M4NO_ERROR;
436 }
437