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*/
50typedef 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*/
93M4OSA_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*/
137M4OSA_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*/
166M4OSA_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*/
189M4OSA_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*/
296M4OSA_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*/
323M4OSA_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*/
414M4OSA_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