H264SwDecApi.c revision 84333e0475bc911adc16417f4ca327c975cf6c36
1/*
2 * Copyright (C) 2009 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
19    Table of contents
20
21     1. Include headers
22     2. External compiler flags
23     3. Module defines
24     4. Local function prototypes
25     5. Functions
26          H264SwDecInit
27          H264SwDecGetInfo
28          H264SwDecRelease
29          H264SwDecDecode
30          H264SwDecGetAPIVersion
31          H264SwDecNextPicture
32
33------------------------------------------------------------------------------*/
34
35/*------------------------------------------------------------------------------
36    1. Include headers
37------------------------------------------------------------------------------*/
38#include <stdlib.h>
39#include "basetype.h"
40#include "h264bsd_container.h"
41#include "H264SwDecApi.h"
42#include "h264bsd_decoder.h"
43#include "h264bsd_util.h"
44
45#define UNUSED(x) (void)(x)
46
47/*------------------------------------------------------------------------------
48       Version Information
49------------------------------------------------------------------------------*/
50
51#define H264SWDEC_MAJOR_VERSION 2
52#define H264SWDEC_MINOR_VERSION 3
53
54/*------------------------------------------------------------------------------
55    2. External compiler flags
56--------------------------------------------------------------------------------
57
58H264DEC_TRACE           Trace H264 Decoder API function calls.
59H264DEC_EVALUATION      Compile evaluation version, restricts number of frames
60                        that can be decoded
61
62--------------------------------------------------------------------------------
63    3. Module defines
64------------------------------------------------------------------------------*/
65
66#ifdef H264DEC_TRACE
67#include <stdio.h>
68#define DEC_API_TRC(str)    H264SwDecTrace(str)
69#else
70#define DEC_API_TRC(str)
71#endif
72
73#ifdef H264DEC_EVALUATION
74#define H264DEC_EVALUATION_LIMIT   500
75#endif
76
77void H264SwDecTrace(char *string) {
78    UNUSED(string);
79}
80
81void* H264SwDecMalloc(u32 size) {
82    return malloc(size);
83}
84
85void H264SwDecFree(void *ptr) {
86    free(ptr);
87}
88
89void H264SwDecMemcpy(void *dest, void *src, u32 count) {
90    memcpy(dest, src, count);
91}
92
93void H264SwDecMemset(void *ptr, i32 value, u32 count) {
94    memset(ptr, value, count);
95}
96
97
98/*------------------------------------------------------------------------------
99
100    Function: H264SwDecInit()
101
102        Functional description:
103            Initialize decoder software. Function reserves memory for the
104            decoder instance and calls h264bsdInit to initialize the
105            instance data.
106
107        Inputs:
108            noOutputReordering  flag to indicate decoder that it doesn't have
109                                to try to provide output pictures in display
110                                order, saves memory
111
112        Outputs:
113            decInst             pointer to initialized instance is stored here
114
115        Returns:
116            H264SWDEC_OK        successfully initialized the instance
117            H264SWDEC_INITFAIL  initialization failed
118            H264SWDEC_PARAM_ERR invalid parameters
119            H264SWDEC_MEM_FAIL  memory allocation failed
120
121------------------------------------------------------------------------------*/
122
123H264SwDecRet H264SwDecInit(H264SwDecInst *decInst, u32 noOutputReordering)
124{
125    u32 rv = 0;
126
127    decContainer_t *pDecCont;
128
129    DEC_API_TRC("H264SwDecInit#");
130
131    /* check that right shift on negative numbers is performed signed */
132    /*lint -save -e* following check causes multiple lint messages */
133    if ( ((-1)>>1) != (-1) )
134    {
135        DEC_API_TRC("H264SwDecInit# ERROR: Right shift is not signed");
136        return(H264SWDEC_INITFAIL);
137    }
138    /*lint -restore */
139
140    if (decInst == NULL)
141    {
142        DEC_API_TRC("H264SwDecInit# ERROR: decInst == NULL");
143        return(H264SWDEC_PARAM_ERR);
144    }
145
146    pDecCont = (decContainer_t *)H264SwDecMalloc(sizeof(decContainer_t));
147
148    if (pDecCont == NULL)
149    {
150        DEC_API_TRC("H264SwDecInit# ERROR: Memory allocation failed");
151        return(H264SWDEC_MEMFAIL);
152    }
153
154#ifdef H264DEC_TRACE
155    sprintf(pDecCont->str, "H264SwDecInit# decInst %p noOutputReordering %d",
156            (void*)decInst, noOutputReordering);
157    DEC_API_TRC(pDecCont->str);
158#endif
159
160    rv = h264bsdInit(&pDecCont->storage, noOutputReordering);
161    if (rv != HANTRO_OK)
162    {
163        H264SwDecRelease(pDecCont);
164        return(H264SWDEC_MEMFAIL);
165    }
166
167    pDecCont->decStat  = INITIALIZED;
168    pDecCont->picNumber = 0;
169
170#ifdef H264DEC_TRACE
171    sprintf(pDecCont->str, "H264SwDecInit# OK: return %p", (void*)pDecCont);
172    DEC_API_TRC(pDecCont->str);
173#endif
174
175    *decInst = (decContainer_t *)pDecCont;
176
177    return(H264SWDEC_OK);
178
179}
180
181/*------------------------------------------------------------------------------
182
183    Function: H264SwDecGetInfo()
184
185        Functional description:
186            This function provides read access to decoder information. This
187            function should not be called before H264SwDecDecode function has
188            indicated that headers are ready.
189
190        Inputs:
191            decInst     decoder instance
192
193        Outputs:
194            pDecInfo    pointer to info struct where data is written
195
196        Returns:
197            H264SWDEC_OK            success
198            H264SWDEC_PARAM_ERR     invalid parameters
199            H264SWDEC_HDRS_NOT_RDY  information not available yet
200
201------------------------------------------------------------------------------*/
202
203H264SwDecRet H264SwDecGetInfo(H264SwDecInst decInst, H264SwDecInfo *pDecInfo)
204{
205
206    storage_t *pStorage;
207
208    DEC_API_TRC("H264SwDecGetInfo#");
209
210    if (decInst == NULL || pDecInfo == NULL)
211    {
212        DEC_API_TRC("H264SwDecGetInfo# ERROR: decInst or pDecInfo is NULL");
213        return(H264SWDEC_PARAM_ERR);
214    }
215
216    pStorage = &(((decContainer_t *)decInst)->storage);
217
218    if (pStorage->activeSps == NULL || pStorage->activePps == NULL)
219    {
220        DEC_API_TRC("H264SwDecGetInfo# ERROR: Headers not decoded yet");
221        return(H264SWDEC_HDRS_NOT_RDY);
222    }
223
224#ifdef H264DEC_TRACE
225    sprintf(((decContainer_t*)decInst)->str,
226        "H264SwDecGetInfo# decInst %p  pDecInfo %p", decInst, (void*)pDecInfo);
227    DEC_API_TRC(((decContainer_t*)decInst)->str);
228#endif
229
230    /* h264bsdPicWidth and -Height return dimensions in macroblock units,
231     * picWidth and -Height in pixels */
232    pDecInfo->picWidth        = h264bsdPicWidth(pStorage) << 4;
233    pDecInfo->picHeight       = h264bsdPicHeight(pStorage) << 4;
234    pDecInfo->videoRange      = h264bsdVideoRange(pStorage);
235    pDecInfo->matrixCoefficients = h264bsdMatrixCoefficients(pStorage);
236
237    h264bsdCroppingParams(pStorage,
238        &pDecInfo->croppingFlag,
239        &pDecInfo->cropParams.cropLeftOffset,
240        &pDecInfo->cropParams.cropOutWidth,
241        &pDecInfo->cropParams.cropTopOffset,
242        &pDecInfo->cropParams.cropOutHeight);
243
244    /* sample aspect ratio */
245    h264bsdSampleAspectRatio(pStorage,
246                             &pDecInfo->parWidth,
247                             &pDecInfo->parHeight);
248
249    /* profile */
250    pDecInfo->profile = h264bsdProfile(pStorage);
251
252    DEC_API_TRC("H264SwDecGetInfo# OK");
253
254    return(H264SWDEC_OK);
255
256}
257
258/*------------------------------------------------------------------------------
259
260    Function: H264SwDecRelease()
261
262        Functional description:
263            Release the decoder instance. Function calls h264bsdShutDown to
264            release instance data and frees the memory allocated for the
265            instance.
266
267        Inputs:
268            decInst     Decoder instance
269
270        Outputs:
271            none
272
273        Returns:
274            none
275
276------------------------------------------------------------------------------*/
277
278void H264SwDecRelease(H264SwDecInst decInst)
279{
280
281    decContainer_t *pDecCont;
282
283    DEC_API_TRC("H264SwDecRelease#");
284
285    if (decInst == NULL)
286    {
287        DEC_API_TRC("H264SwDecRelease# ERROR: decInst == NULL");
288        return;
289    }
290
291    pDecCont = (decContainer_t*)decInst;
292
293#ifdef H264DEC_TRACE
294    sprintf(pDecCont->str, "H264SwDecRelease# decInst %p",decInst);
295    DEC_API_TRC(pDecCont->str);
296#endif
297
298    h264bsdShutdown(&pDecCont->storage);
299
300    H264SwDecFree(pDecCont);
301
302}
303
304/*------------------------------------------------------------------------------
305
306    Function: H264SwDecDecode
307
308        Functional description:
309            Decode stream data. Calls h264bsdDecode to do the actual decoding.
310
311        Input:
312            decInst     decoder instance
313            pInput      pointer to input struct
314
315        Outputs:
316            pOutput     pointer to output struct
317
318        Returns:
319            H264SWDEC_NOT_INITIALIZED   decoder instance not initialized yet
320            H264SWDEC_PARAM_ERR         invalid parameters
321
322            H264SWDEC_STRM_PROCESSED    stream buffer decoded
323            H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY   headers decoded,
324                                                stream buffer not finished
325            H264SWDEC_PIC_RDY                   decoding of a picture finished
326            H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY    decoding of a picture finished,
327                                                stream buffer not finished
328            H264SWDEC_STRM_ERR                  serious error in decoding, no
329                                                valid parameter sets available
330                                                to decode picture data
331            H264SWDEC_EVALUATION_LIMIT_EXCEEDED this can only occur when
332                                                evaluation version is used,
333                                                max number of frames reached
334
335------------------------------------------------------------------------------*/
336
337H264SwDecRet H264SwDecDecode(H264SwDecInst decInst, H264SwDecInput *pInput,
338                  H264SwDecOutput *pOutput)
339{
340
341    decContainer_t *pDecCont;
342    u32 strmLen;
343    u32 numReadBytes;
344    u8 *tmpStream;
345    u32 decResult = 0;
346    H264SwDecRet returnValue = H264SWDEC_STRM_PROCESSED;
347
348    DEC_API_TRC("H264SwDecDecode#");
349
350    /* Check that function input parameters are valid */
351    if (pInput == NULL || pOutput == NULL)
352    {
353        DEC_API_TRC("H264SwDecDecode# ERROR: pInput or pOutput is NULL");
354        return(H264SWDEC_PARAM_ERR);
355    }
356
357    if ((pInput->pStream == NULL) || (pInput->dataLen == 0))
358    {
359        DEC_API_TRC("H264SwDecDecode# ERROR: Invalid input parameters");
360        return(H264SWDEC_PARAM_ERR);
361    }
362
363    pDecCont = (decContainer_t *)decInst;
364
365    /* Check if decoder is in an incorrect mode */
366    if (decInst == NULL || pDecCont->decStat == UNINITIALIZED)
367    {
368        DEC_API_TRC("H264SwDecDecode# ERROR: Decoder not initialized");
369        return(H264SWDEC_NOT_INITIALIZED);
370    }
371
372#ifdef H264DEC_EVALUATION
373    if (pDecCont->picNumber >= H264DEC_EVALUATION_LIMIT)
374        return(H264SWDEC_EVALUATION_LIMIT_EXCEEDED);
375#endif
376
377#ifdef H264DEC_TRACE
378    sprintf(pDecCont->str, "H264SwDecDecode# decInst %p  pInput %p  pOutput %p",
379            decInst, (void*)pInput, (void*)pOutput);
380    DEC_API_TRC(pDecCont->str);
381#endif
382
383    pOutput->pStrmCurrPos   = NULL;
384
385    numReadBytes = 0;
386    strmLen = pInput->dataLen;
387    tmpStream = pInput->pStream;
388    pDecCont->storage.intraConcealmentFlag = pInput->intraConcealmentMethod;
389
390    do
391    {
392        /* Return HDRS_RDY after DPB flush caused by new SPS */
393        if (pDecCont->decStat == NEW_HEADERS)
394        {
395            decResult = H264BSD_HDRS_RDY;
396            pDecCont->decStat = INITIALIZED;
397        }
398        else /* Continue decoding normally */
399        {
400            decResult = h264bsdDecode(&pDecCont->storage, tmpStream, strmLen,
401                pInput->picId, &numReadBytes);
402        }
403        tmpStream += numReadBytes;
404        /* check if too many bytes are read from stream */
405        if ( (i32)(strmLen - numReadBytes) >= 0 )
406            strmLen -= numReadBytes;
407        else
408            strmLen = 0;
409
410        pOutput->pStrmCurrPos = tmpStream;
411
412        switch (decResult)
413        {
414            case H264BSD_HDRS_RDY:
415
416                if(pDecCont->storage.dpb->flushed &&
417                   pDecCont->storage.dpb->numOut !=
418                   pDecCont->storage.dpb->outIndex)
419                {
420                    /* output first all DPB stored pictures
421                     * DPB flush caused by new SPS */
422                    pDecCont->storage.dpb->flushed = 0;
423                    pDecCont->decStat = NEW_HEADERS;
424                    returnValue = H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY;
425                    strmLen = 0;
426                }
427                else
428                {
429                    returnValue = H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY;
430                    strmLen = 0;
431                }
432                break;
433
434            case H264BSD_PIC_RDY:
435                pDecCont->picNumber++;
436
437                if (strmLen == 0)
438                    returnValue = H264SWDEC_PIC_RDY;
439                else
440                    returnValue = H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY;
441
442                strmLen = 0;
443                break;
444
445            case H264BSD_PARAM_SET_ERROR:
446                if ( !h264bsdCheckValidParamSets(&pDecCont->storage) &&
447                     strmLen == 0 )
448                {
449                    returnValue = H264SWDEC_STRM_ERR;
450                }
451                break;
452            case H264BSD_MEMALLOC_ERROR:
453                {
454                    returnValue = H264SWDEC_MEMFAIL;
455                    strmLen = 0;
456                }
457                break;
458            default:
459                break;
460        }
461
462    } while (strmLen);
463
464#ifdef H264DEC_TRACE
465    sprintf(pDecCont->str, "H264SwDecDecode# OK: DecResult %d",
466            returnValue);
467    DEC_API_TRC(pDecCont->str);
468#endif
469
470    return(returnValue);
471
472}
473
474/*------------------------------------------------------------------------------
475
476    Function: H264SwDecGetAPIVersion
477
478        Functional description:
479            Return version information of the API
480
481        Inputs:
482            none
483
484        Outputs:
485            none
486
487        Returns:
488            API version
489
490------------------------------------------------------------------------------*/
491
492H264SwDecApiVersion H264SwDecGetAPIVersion()
493{
494    H264SwDecApiVersion ver;
495
496    ver.major = H264SWDEC_MAJOR_VERSION;
497    ver.minor = H264SWDEC_MINOR_VERSION;
498
499    return(ver);
500}
501
502/*------------------------------------------------------------------------------
503
504    Function: H264SwDecNextPicture
505
506        Functional description:
507            Get next picture in display order if any available.
508
509        Input:
510            decInst     decoder instance.
511            flushBuffer force output of all buffered pictures
512
513        Output:
514            pOutput     pointer to output structure
515
516        Returns:
517            H264SWDEC_OK            no pictures available for display
518            H264SWDEC_PIC_RDY       picture available for display
519            H264SWDEC_PARAM_ERR     invalid parameters
520
521------------------------------------------------------------------------------*/
522
523H264SwDecRet H264SwDecNextPicture(H264SwDecInst decInst,
524    H264SwDecPicture *pOutput, u32 flushBuffer)
525{
526
527    decContainer_t *pDecCont;
528    u32 numErrMbs, isIdrPic, picId;
529    u32 *pOutPic;
530
531    DEC_API_TRC("H264SwDecNextPicture#");
532
533    if (decInst == NULL || pOutput == NULL)
534    {
535        DEC_API_TRC("H264SwDecNextPicture# ERROR: decInst or pOutput is NULL");
536        return(H264SWDEC_PARAM_ERR);
537    }
538
539    pDecCont = (decContainer_t*)decInst;
540
541#ifdef H264DEC_TRACE
542    sprintf(pDecCont->str, "H264SwDecNextPicture# decInst %p pOutput %p %s %d",
543            decInst, (void*)pOutput, "flushBuffer", flushBuffer);
544    DEC_API_TRC(pDecCont->str);
545#endif
546
547    if (flushBuffer)
548        h264bsdFlushBuffer(&pDecCont->storage);
549
550    pOutPic = (u32*)h264bsdNextOutputPicture(&pDecCont->storage, &picId,
551                                             &isIdrPic, &numErrMbs);
552
553    if (pOutPic == NULL)
554    {
555        DEC_API_TRC("H264SwDecNextPicture# OK: return H264SWDEC_OK");
556        return(H264SWDEC_OK);
557    }
558    else
559    {
560        pOutput->pOutputPicture = pOutPic;
561        pOutput->picId          = picId;
562        pOutput->isIdrPicture   = isIdrPic;
563        pOutput->nbrOfErrMBs    = numErrMbs;
564        DEC_API_TRC("H264SwDecNextPicture# OK: return H264SWDEC_PIC_RDY");
565        return(H264SWDEC_PIC_RDY);
566    }
567
568}
569
570
571