1/* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
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
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18#include "mp4dec_lib.h"
19#include "vlc_decode.h"
20#include "bitstream.h"
21
22#define OSCL_DISABLE_WARNING_CONDITIONAL_IS_CONSTANT
23
24#ifdef DEC_INTERNAL_MEMORY_OPT
25#define QCIF_MBS 99
26#define QCIF_BS (4*QCIF_MBS)
27#define QCIF_MB_ROWS 11
28extern uint8                IMEM_sliceNo[QCIF_MBS];
29extern uint8                IMEM_acPredFlag[QCIF_MBS];
30extern uint8                IMEM_headerInfo_Mode[QCIF_MBS];
31extern uint8                IMEM_headerInfo_CBP[QCIF_MBS];
32extern int                  IMEM_headerInfo_QPMB[QCIF_MBS];
33extern MacroBlock           IMEM_mblock;
34extern MOT                  IMEM_motX[QCIF_BS];
35extern MOT                  IMEM_motY[QCIF_BS];
36extern BitstreamDecVideo    IMEM_BitstreamDecVideo[4];
37extern typeDCStore          IMEM_predDC[QCIF_MBS];
38extern typeDCACStore        IMEM_predDCAC_col[QCIF_MB_ROWS+1];
39
40extern VideoDecData         IMEM_VideoDecData[1];
41extern Vop                  IMEM_currVop[1];
42extern Vop                  IMEM_prevVop[1];
43extern PIXEL                IMEM_currVop_yChan[QCIF_MBS*128*3];
44extern PIXEL                IMEM_prevVop_yChan[QCIF_MBS*128*3];
45extern uint8                IMEM_pstprcTypCur[6*QCIF_MBS];
46extern uint8                IMEM_pstprcTypPrv[6*QCIF_MBS];
47
48
49extern Vop                  IMEM_vopHEADER[2];
50extern Vol                  IMEM_VOL[2];
51extern Vop                  IMEM_vopHeader[2][1];
52extern Vol                  IMEM_vol[2][1];
53
54#endif
55
56/* ======================================================================== */
57/*  Function : PVInitVideoDecoder()                                         */
58/*  Date     : 04/11/2000, 08/29/2000                                       */
59/*  Purpose  : Initialization of the MPEG-4 video decoder library.          */
60/*             The return type is Bool instead of PV_STATUS because         */
61/*             we don't want to expose PV_STATUS to (outside) programmers   */
62/*             that use our decoder library SDK.                            */
63/*  In/out   :                                                              */
64/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
65/*  Modified :                                                              */
66/* ======================================================================== */
67OSCL_EXPORT_REF Bool PVInitVideoDecoder(VideoDecControls *decCtrl, uint8 *volbuf[],
68                                        int32 *volbuf_size, int nLayers, int width, int height, MP4DecodingMode mode)
69{
70    VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
71    Bool status = PV_TRUE;
72    int idx;
73    BitstreamDecVideo *stream;
74
75
76    oscl_memset(decCtrl, 0, sizeof(VideoDecControls)); /* fix a size bug.   03/28/2001 */
77    decCtrl->nLayers = nLayers;
78    for (idx = 0; idx < nLayers; idx++)
79    {
80        decCtrl->volbuf[idx] = volbuf[idx];
81        decCtrl->volbuf_size[idx] = volbuf_size[idx];
82    }
83
84    /* memory allocation & initialization */
85#ifdef DEC_INTERNAL_MEMORY_OPT
86    video = IMEM_VideoDecData;
87#else
88    video = (VideoDecData *) oscl_malloc(sizeof(VideoDecData));
89#endif
90    if (video != NULL)
91    {
92        oscl_memset(video, 0, sizeof(VideoDecData));
93        video->memoryUsage = sizeof(VideoDecData);
94        video->numberOfLayers = nLayers;
95#ifdef DEC_INTERNAL_MEMORY_OPT
96        video->vol = (Vol **) IMEM_VOL;
97#else
98        video->vol = (Vol **) oscl_malloc(nLayers * sizeof(Vol *));
99#endif
100        if (video->vol == NULL) status = PV_FALSE;
101        video->memoryUsage += nLayers * sizeof(Vol *);
102
103
104        /* we need to setup this pointer for the application to */
105        /*    pass it around.                                   */
106        decCtrl->videoDecoderData = (void *) video;
107        video->videoDecControls = decCtrl;  /* yes. we have a cyclic */
108        /* references here :)    */
109
110        /* Allocating Vop space, this has to change when we add */
111        /*    spatial scalability to the decoder                */
112#ifdef DEC_INTERNAL_MEMORY_OPT
113        video->currVop = IMEM_currVop;
114        if (video->currVop == NULL) status = PV_FALSE;
115        else oscl_memset(video->currVop, 0, sizeof(Vop));
116        video->prevVop = IMEM_prevVop;
117        if (video->prevVop == NULL) status = PV_FALSE;
118        else oscl_memset(video->prevVop, 0, sizeof(Vop));
119        video->memoryUsage += (sizeof(Vop) * 2);
120        video->vopHeader = (Vop **) IMEM_vopHEADER;
121#else
122
123        video->currVop = (Vop *) oscl_malloc(sizeof(Vop));
124        if (video->currVop == NULL) status = PV_FALSE;
125        else oscl_memset(video->currVop, 0, sizeof(Vop));
126        video->prevVop = (Vop *) oscl_malloc(sizeof(Vop));
127        if (video->prevVop == NULL) status = PV_FALSE;
128        else oscl_memset(video->prevVop, 0, sizeof(Vop));
129        video->memoryUsage += (sizeof(Vop) * 2);
130
131        video->vopHeader = (Vop **) oscl_malloc(sizeof(Vop *) * nLayers);
132#endif
133        if (video->vopHeader == NULL) status = PV_FALSE;
134        else oscl_memset(video->vopHeader, 0, sizeof(Vop *)*nLayers);
135        video->memoryUsage += (sizeof(Vop *) * nLayers);
136
137        video->initialized = PV_FALSE;
138        /* Decode the header to get all information to allocate data */
139        if (status == PV_TRUE)
140        {
141            /* initialize decoded frame counter.   04/24/2001 */
142            video->frame_idx = -1;
143
144
145            for (idx = 0; idx < nLayers; idx++)
146            {
147
148#ifdef DEC_INTERNAL_MEMORY_OPT
149                video->vopHeader[idx] = IMEM_vopHeader[idx];
150#else
151                video->vopHeader[idx] = (Vop *) oscl_malloc(sizeof(Vop));
152#endif
153                if (video->vopHeader[idx] == NULL)
154                {
155                    status = PV_FALSE;
156                    break;
157                }
158                else
159                {
160                    oscl_memset(video->vopHeader[idx], 0, sizeof(Vop));
161                    video->vopHeader[idx]->timeStamp = 0;
162                    video->memoryUsage += (sizeof(Vop));
163                }
164#ifdef DEC_INTERNAL_MEMORY_OPT
165                video->vol[idx] = IMEM_vol[idx];
166                video->memoryUsage += sizeof(Vol);
167                oscl_memset(video->vol[idx], 0, sizeof(Vol));
168                if (video->vol[idx] == NULL) status = PV_FALSE;
169                stream = IMEM_BitstreamDecVideo;
170#else
171                video->vol[idx] = (Vol *) oscl_malloc(sizeof(Vol));
172                if (video->vol[idx] == NULL)
173                {
174                    status = PV_FALSE;
175                    break;
176                }
177                else
178                {
179                    video->memoryUsage += sizeof(Vol);
180                    oscl_memset(video->vol[idx], 0, sizeof(Vol));
181                }
182
183                stream = (BitstreamDecVideo *) oscl_malloc(sizeof(BitstreamDecVideo));
184#endif
185                video->memoryUsage += sizeof(BitstreamDecVideo);
186                if (stream == NULL)
187                {
188                    status = PV_FALSE;
189                    break;
190                }
191                else
192                {
193                    int32 buffer_size;
194                    if ((buffer_size = BitstreamOpen(stream, idx)) < 0)
195                    {
196                        mp4dec_log("InitVideoDecoder(): Can't allocate bitstream buffer.\n");
197                        status = PV_FALSE;
198                        break;
199                    }
200                    video->memoryUsage += buffer_size;
201                    video->vol[idx]->bitstream = stream;
202                    video->vol[idx]->volID = idx;
203                    video->vol[idx]->timeInc_offset = 0;  /*  11/12/01 */
204                    video->vlcDecCoeffIntra = &VlcDecTCOEFShortHeader;
205                    video->vlcDecCoeffInter = &VlcDecTCOEFShortHeader;
206                    if (mode == MPEG4_MODE)
207                    {
208                        /* Set up VOL header bitstream for frame-based decoding.  08/30/2000 */
209                        BitstreamReset(stream, decCtrl->volbuf[idx], decCtrl->volbuf_size[idx]);
210
211                        switch (DecodeVOLHeader(video, idx))
212                        {
213                            case PV_SUCCESS :
214                                if (status == PV_TRUE)
215                                    status = PV_TRUE;   /*  we want to make sure that if first layer is bad, second layer is good return PV_FAIL */
216                                else
217                                    status = PV_FALSE;
218                                break;
219#ifdef PV_TOLERATE_VOL_ERRORS
220                            case PV_BAD_VOLHEADER:
221                                status = PV_TRUE;
222                                break;
223#endif
224                            default :
225                                status = PV_FALSE;
226                                break;
227                        }
228
229                    }
230                    else
231                    {
232                        video->shortVideoHeader = PV_TRUE;
233                    }
234
235                    if (video->shortVideoHeader == PV_TRUE)
236                    {
237                        mode = H263_MODE;
238                        /* Set max width and height.  In H.263 mode, we use    */
239                        /*  volbuf_size[0] to pass in width and volbuf_size[1] */
240                        /*  to pass in height.                    04/23/2001 */
241                        video->prevVop->temporalRef = 0; /*  11/12/01 */
242                        /* Compute some convenience variables:   04/23/2001 */
243                        video->vol[idx]->quantType = 0;
244                        video->vol[idx]->quantPrecision = 5;
245                        video->vol[idx]->errorResDisable = 1;
246                        video->vol[idx]->dataPartitioning = 0;
247                        video->vol[idx]->useReverseVLC = 0;
248                        video->intra_acdcPredDisable = 1;
249                        video->vol[idx]->scalability = 0;
250                        video->size = (int32)width * height;
251
252                        video->displayWidth = video->width = width;
253                        video->displayHeight = video->height = height;
254#ifdef PV_ANNEX_IJKT_SUPPORT
255                        video->modified_quant = 0;
256                        video->advanced_INTRA = 0;
257                        video->deblocking = 0;
258                        video->slice_structure = 0;
259#endif
260                    }
261
262                }
263            }
264
265        }
266        if (status != PV_FALSE)
267        {
268            status = PVAllocVideoData(decCtrl, width, height, nLayers);
269            video->initialized = PV_TRUE;
270        }
271    }
272    else
273    {
274        status = PV_FALSE;
275    }
276
277    if (status == PV_FALSE) PVCleanUpVideoDecoder(decCtrl);
278
279    return status;
280}
281
282Bool PVAllocVideoData(VideoDecControls *decCtrl, int width, int height, int nLayers)
283{
284    VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
285    Bool status = PV_TRUE;
286    int nTotalMB;
287    int nMBPerRow;
288    int32 size;
289
290    if (video->shortVideoHeader == PV_TRUE)
291    {
292        video->displayWidth = video->width = width;
293        video->displayHeight = video->height = height;
294
295        video->nMBPerRow =
296            video->nMBinGOB  = video->width / MB_SIZE;
297        video->nMBPerCol =
298            video->nGOBinVop = video->height / MB_SIZE;
299        video->nTotalMB =
300            video->nMBPerRow * video->nMBPerCol;
301    }
302
303    size = (int32)sizeof(PIXEL) * video->width * video->height;
304#ifdef PV_MEMORY_POOL
305    decCtrl->size = size;
306#else
307#ifdef DEC_INTERNAL_MEMORY_OPT
308    video->currVop->yChan = IMEM_currVop_yChan; /* Allocate memory for all VOP OKA 3/2/1*/
309    if (video->currVop->yChan == NULL) status = PV_FALSE;
310    video->currVop->uChan = video->currVop->yChan + size;
311    video->currVop->vChan = video->currVop->uChan + (size >> 2);
312
313    video->prevVop->yChan = IMEM_prevVop_yChan; /* Allocate memory for all VOP OKA 3/2/1*/
314    if (video->prevVop->yChan == NULL) status = PV_FALSE;
315    video->prevVop->uChan = video->prevVop->yChan + size;
316    video->prevVop->vChan = video->prevVop->uChan + (size >> 2);
317#else
318    video->currVop->yChan = (PIXEL *) oscl_malloc(size * 3 / 2); /* Allocate memory for all VOP OKA 3/2/1*/
319    if (video->currVop->yChan == NULL) status = PV_FALSE;
320
321    video->currVop->uChan = video->currVop->yChan + size;
322    video->currVop->vChan = video->currVop->uChan + (size >> 2);
323    video->prevVop->yChan = (PIXEL *) oscl_malloc(size * 3 / 2); /* Allocate memory for all VOP OKA 3/2/1*/
324    if (video->prevVop->yChan == NULL) status = PV_FALSE;
325
326    video->prevVop->uChan = video->prevVop->yChan + size;
327    video->prevVop->vChan = video->prevVop->uChan + (size >> 2);
328#endif
329    video->memoryUsage += (size * 3);
330#endif   // MEMORY_POOL
331    /* Note that baseVop, enhcVop is only used to hold enhancement */
332    /*    layer header information.                  05/04/2000  */
333    if (nLayers > 1)
334    {
335        video->prevEnhcVop = (Vop *) oscl_malloc(sizeof(Vop));
336        video->memoryUsage += (sizeof(Vop));
337        if (video->prevEnhcVop == NULL)
338        {
339            status = PV_FALSE;
340        }
341        else
342        {
343            oscl_memset(video->prevEnhcVop, 0, sizeof(Vop));
344#ifndef PV_MEMORY_POOL
345            video->prevEnhcVop->yChan = (PIXEL *) oscl_malloc(size * 3 / 2); /* Allocate memory for all VOP OKA 3/2/1*/
346            if (video->prevEnhcVop->yChan == NULL) status = PV_FALSE;
347            video->prevEnhcVop->uChan = video->prevEnhcVop->yChan + size;
348            video->prevEnhcVop->vChan = video->prevEnhcVop->uChan + (size >> 2);
349            video->memoryUsage += (3 * size / 2);
350#endif
351        }
352    }
353
354    /* Allocating space for slices, AC prediction flag, and */
355    /*    AC/DC prediction storage */
356    nTotalMB = video->nTotalMB;
357    nMBPerRow = video->nMBPerRow;
358
359#ifdef DEC_INTERNAL_MEMORY_OPT
360    video->sliceNo = (uint8 *)(IMEM_sliceNo);
361    if (video->sliceNo == NULL) status = PV_FALSE;
362    video->memoryUsage += nTotalMB;
363    video->acPredFlag = (uint8 *)(IMEM_acPredFlag);
364    if (video->acPredFlag == NULL) status = PV_FALSE;
365    video->memoryUsage += (nTotalMB);
366    video->predDC = (typeDCStore *)(IMEM_predDC);
367    if (video->predDC == NULL) status = PV_FALSE;
368    video->memoryUsage += (nTotalMB * sizeof(typeDCStore));
369    video->predDCAC_col = (typeDCACStore *)(IMEM_predDCAC_col);
370    if (video->predDCAC_col == NULL) status = PV_FALSE;
371    video->memoryUsage += ((nMBPerRow + 1) * sizeof(typeDCACStore));
372    video->predDCAC_row = video->predDCAC_col + 1;
373    video->headerInfo.Mode = (uint8 *)(IMEM_headerInfo_Mode);
374    if (video->headerInfo.Mode == NULL) status = PV_FALSE;
375    video->memoryUsage += nTotalMB;
376    video->headerInfo.CBP = (uint8 *)(IMEM_headerInfo_CBP);
377    if (video->headerInfo.CBP == NULL) status = PV_FALSE;
378    video->memoryUsage += nTotalMB;
379    video->QPMB = (int *)(IMEM_headerInfo_QPMB);
380    if (video->QPMB == NULL) status = PV_FALSE;
381    video->memoryUsage += (nTotalMB * sizeof(int));
382    video->mblock = &IMEM_mblock;
383    if (video->mblock == NULL) status = PV_FALSE;
384    oscl_memset(video->mblock->block, 0, sizeof(int16)*6*NCOEFF_BLOCK); //  Aug 23,2005
385
386    video->memoryUsage += sizeof(MacroBlock);
387    video->motX = (MOT *)(IMEM_motX);
388    if (video->motX == NULL) status = PV_FALSE;
389    video->motY = (MOT *)(IMEM_motY);
390    if (video->motY == NULL) status = PV_FALSE;
391    video->memoryUsage += (sizeof(MOT) * 8 * nTotalMB);
392#else
393    video->sliceNo = (uint8 *) oscl_malloc(nTotalMB);
394    if (video->sliceNo == NULL) status = PV_FALSE;
395    video->memoryUsage += nTotalMB;
396
397    video->acPredFlag = (uint8 *) oscl_malloc(nTotalMB * sizeof(uint8));
398    if (video->acPredFlag == NULL) status = PV_FALSE;
399    video->memoryUsage += (nTotalMB);
400
401    video->predDC = (typeDCStore *) oscl_malloc(nTotalMB * sizeof(typeDCStore));
402    if (video->predDC == NULL) status = PV_FALSE;
403    video->memoryUsage += (nTotalMB * sizeof(typeDCStore));
404
405    video->predDCAC_col = (typeDCACStore *) oscl_malloc((nMBPerRow + 1) * sizeof(typeDCACStore));
406    if (video->predDCAC_col == NULL) status = PV_FALSE;
407    video->memoryUsage += ((nMBPerRow + 1) * sizeof(typeDCACStore));
408
409    /* element zero will be used for storing vertical (col) AC coefficients */
410    /*  the rest will be used for storing horizontal (row) AC coefficients  */
411    video->predDCAC_row = video->predDCAC_col + 1;        /*  ACDC */
412
413    /* Allocating HeaderInfo structure & Quantizer array */
414    video->headerInfo.Mode = (uint8 *) oscl_malloc(nTotalMB);
415    if (video->headerInfo.Mode == NULL) status = PV_FALSE;
416    video->memoryUsage += nTotalMB;
417    video->headerInfo.CBP = (uint8 *) oscl_malloc(nTotalMB);
418    if (video->headerInfo.CBP == NULL) status = PV_FALSE;
419    video->memoryUsage += nTotalMB;
420    video->QPMB = (int16 *) oscl_malloc(nTotalMB * sizeof(int16));
421    if (video->QPMB == NULL) status = PV_FALSE;
422    video->memoryUsage += (nTotalMB * sizeof(int));
423
424    /* Allocating macroblock space */
425    video->mblock = (MacroBlock *) oscl_malloc(sizeof(MacroBlock));
426    if (video->mblock == NULL)
427    {
428        status = PV_FALSE;
429    }
430    else
431    {
432        oscl_memset(video->mblock->block, 0, sizeof(int16)*6*NCOEFF_BLOCK); //  Aug 23,2005
433
434        video->memoryUsage += sizeof(MacroBlock);
435    }
436    /* Allocating motion vector space */
437    video->motX = (MOT *) oscl_malloc(sizeof(MOT) * 4 * nTotalMB);
438    if (video->motX == NULL) status = PV_FALSE;
439    video->motY = (MOT *) oscl_malloc(sizeof(MOT) * 4 * nTotalMB);
440    if (video->motY == NULL) status = PV_FALSE;
441    video->memoryUsage += (sizeof(MOT) * 8 * nTotalMB);
442#endif
443
444#ifdef PV_POSTPROC_ON
445    /* Allocating space for post-processing Mode */
446#ifdef DEC_INTERNAL_MEMORY_OPT
447    video->pstprcTypCur = IMEM_pstprcTypCur;
448    video->memoryUsage += (nTotalMB * 6);
449    if (video->pstprcTypCur == NULL)
450    {
451        status = PV_FALSE;
452    }
453    else
454    {
455        oscl_memset(video->pstprcTypCur, 0, 4*nTotalMB + 2*nTotalMB);
456    }
457
458    video->pstprcTypPrv = IMEM_pstprcTypPrv;
459    video->memoryUsage += (nTotalMB * 6);
460    if (video->pstprcTypPrv == NULL)
461    {
462        status = PV_FALSE;
463    }
464    else
465    {
466        oscl_memset(video->pstprcTypPrv, 0, nTotalMB*6);
467    }
468
469#else
470    video->pstprcTypCur = (uint8 *) oscl_malloc(nTotalMB * 6);
471    video->memoryUsage += (nTotalMB * 6);
472    if (video->pstprcTypCur == NULL)
473    {
474        status = PV_FALSE;
475    }
476    else
477    {
478        oscl_memset(video->pstprcTypCur, 0, 4*nTotalMB + 2*nTotalMB);
479    }
480
481    video->pstprcTypPrv = (uint8 *) oscl_malloc(nTotalMB * 6);
482    video->memoryUsage += (nTotalMB * 6);
483    if (video->pstprcTypPrv == NULL)
484    {
485        status = PV_FALSE;
486    }
487    else
488    {
489        oscl_memset(video->pstprcTypPrv, 0, nTotalMB*6);
490    }
491
492#endif
493
494#endif
495
496    /* initialize the decoder library */
497    video->prevVop->predictionType = I_VOP;
498    video->prevVop->timeStamp = 0;
499#ifndef PV_MEMORY_POOL
500    oscl_memset(video->prevVop->yChan, 16, sizeof(uint8)*size);     /*  10/31/01 */
501    oscl_memset(video->prevVop->uChan, 128, sizeof(uint8)*size / 2);
502
503    oscl_memset(video->currVop->yChan, 0, sizeof(uint8)*size*3 / 2);
504    if (nLayers > 1)
505    {
506        oscl_memset(video->prevEnhcVop->yChan, 0, sizeof(uint8)*size*3 / 2);
507        video->prevEnhcVop->timeStamp = 0;
508    }
509    video->concealFrame = video->prevVop->yChan;               /*  07/07/2001 */
510    decCtrl->outputFrame = video->prevVop->yChan;              /*  06/19/2002 */
511#endif
512
513    /* always start from base layer */
514    video->currLayer = 0;
515    return status;
516}
517
518/* ======================================================================== */
519/*  Function : PVResetVideoDecoder()                                        */
520/*  Date     : 01/14/2002                                                   */
521/*  Purpose  : Reset video timestamps                                       */
522/*  In/out   :                                                              */
523/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
524/*  Modified :                                                              */
525/* ======================================================================== */
526Bool PVResetVideoDecoder(VideoDecControls *decCtrl)
527{
528    VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
529    int idx;
530
531    for (idx = 0; idx < decCtrl->nLayers; idx++)
532    {
533        video->vopHeader[idx]->timeStamp = 0;
534    }
535    video->prevVop->timeStamp = 0;
536    if (decCtrl->nLayers > 1)
537        video->prevEnhcVop->timeStamp = 0;
538
539    oscl_memset(video->mblock->block, 0, sizeof(int16)*6*NCOEFF_BLOCK); //  Aug 23,2005
540
541    return PV_TRUE;
542}
543
544
545/* ======================================================================== */
546/*  Function : PVCleanUpVideoDecoder()                                      */
547/*  Date     : 04/11/2000, 08/29/2000                                       */
548/*  Purpose  : Cleanup of the MPEG-4 video decoder library.                 */
549/*  In/out   :                                                              */
550/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
551/*  Modified :                                                              */
552/* ======================================================================== */
553OSCL_EXPORT_REF Bool PVCleanUpVideoDecoder(VideoDecControls *decCtrl)
554{
555    int idx;
556    VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
557#ifdef DEC_INTERNAL_MEMORY_OPT
558    if (video)
559    {
560#ifdef PV_POSTPROC_ON
561        video->pstprcTypCur = NULL;
562        video->pstprcTypPrv = NULL;
563#endif
564
565        video->acPredFlag       = NULL;
566        video->sliceNo          = NULL;
567        video->motX             = NULL;
568        video->motY             = NULL;
569        video->mblock           = NULL;
570        video->QPMB             = NULL;
571        video->predDC           = NULL;
572        video->predDCAC_row     = NULL;
573        video->predDCAC_col     = NULL;
574        video->headerInfo.Mode  = NULL;
575        video->headerInfo.CBP   = NULL;
576        if (video->numberOfLayers > 1)
577        {
578            if (video->prevEnhcVop)
579            {
580                video->prevEnhcVop->uChan = NULL;
581                video->prevEnhcVop->vChan = NULL;
582                if (video->prevEnhcVop->yChan) oscl_free(video->prevEnhcVop->yChan);
583                oscl_free(video->prevEnhcVop);
584            }
585        }
586        if (video->currVop)
587        {
588            video->currVop->uChan = NULL;
589            video->currVop->vChan = NULL;
590            if (video->currVop->yChan)
591                video->currVop->yChan = NULL;
592            video->currVop = NULL;
593        }
594        if (video->prevVop)
595        {
596            video->prevVop->uChan = NULL;
597            video->prevVop->vChan = NULL;
598            if (video->prevVop->yChan)
599                video->prevVop->yChan = NULL;
600            video->prevVop = NULL;
601        }
602
603        if (video->vol)
604        {
605            for (idx = 0; idx < video->numberOfLayers; idx++)
606            {
607                if (video->vol[idx])
608                {
609                    BitstreamClose(video->vol[idx]->bitstream);
610                    video->vol[idx]->bitstream = NULL;
611                    video->vol[idx] = NULL;
612                }
613                video->vopHeader[idx] = NULL;
614
615            }
616            video->vol = NULL;
617            video->vopHeader = NULL;
618        }
619
620        video = NULL;
621        decCtrl->videoDecoderData = NULL;
622    }
623
624#else
625
626    if (video)
627    {
628#ifdef PV_POSTPROC_ON
629        if (video->pstprcTypCur) oscl_free(video->pstprcTypCur);
630        if (video->pstprcTypPrv) oscl_free(video->pstprcTypPrv);
631#endif
632        if (video->predDC) oscl_free(video->predDC);
633        video->predDCAC_row = NULL;
634        if (video->predDCAC_col) oscl_free(video->predDCAC_col);
635        if (video->motX) oscl_free(video->motX);
636        if (video->motY) oscl_free(video->motY);
637        if (video->mblock) oscl_free(video->mblock);
638        if (video->QPMB) oscl_free(video->QPMB);
639        if (video->headerInfo.Mode) oscl_free(video->headerInfo.Mode);
640        if (video->headerInfo.CBP) oscl_free(video->headerInfo.CBP);
641        if (video->sliceNo) oscl_free(video->sliceNo);
642        if (video->acPredFlag) oscl_free(video->acPredFlag);
643
644        if (video->numberOfLayers > 1)
645        {
646            if (video->prevEnhcVop)
647            {
648                video->prevEnhcVop->uChan = NULL;
649                video->prevEnhcVop->vChan = NULL;
650                if (video->prevEnhcVop->yChan) oscl_free(video->prevEnhcVop->yChan);
651                oscl_free(video->prevEnhcVop);
652            }
653        }
654        if (video->currVop)
655        {
656
657#ifndef PV_MEMORY_POOL
658            video->currVop->uChan = NULL;
659            video->currVop->vChan = NULL;
660            if (video->currVop->yChan)
661                oscl_free(video->currVop->yChan);
662#endif
663            oscl_free(video->currVop);
664        }
665        if (video->prevVop)
666        {
667#ifndef PV_MEMORY_POOL
668            video->prevVop->uChan = NULL;
669            video->prevVop->vChan = NULL;
670            if (video->prevVop->yChan)
671                oscl_free(video->prevVop->yChan);
672#endif
673            oscl_free(video->prevVop);
674        }
675
676        if (video->vol)
677        {
678            for (idx = 0; idx < video->numberOfLayers; idx++)
679            {
680                if (video->vol[idx])
681                {
682                    if (video->vol[idx]->bitstream)
683                    {
684                        BitstreamClose(video->vol[idx]->bitstream);
685                        oscl_free(video->vol[idx]->bitstream);
686                    }
687                    oscl_free(video->vol[idx]);
688                }
689
690            }
691            oscl_free(video->vol);
692        }
693
694        for (idx = 0; idx < video->numberOfLayers; idx++)
695        {
696            if (video->vopHeader[idx]) oscl_free(video->vopHeader[idx]);
697        }
698
699        if (video->vopHeader) oscl_free(video->vopHeader);
700
701        oscl_free(video);
702        decCtrl->videoDecoderData = NULL;
703    }
704#endif
705    return PV_TRUE;
706}
707/* ======================================================================== */
708/*  Function : PVGetVideoDimensions()                                       */
709/*  Date     : 040505                                                       */
710/*  Purpose  :                                                              */
711/*  In/out   :                                                              */
712/*  Return   : the display_width and display_height of                      */
713/*          the frame in the current layer.                                 */
714/*  Note     : This is not a macro or inline function because we do         */
715/*              not want to expose our internal data structure.             */
716/*  Modified :                                                              */
717/* ======================================================================== */
718OSCL_EXPORT_REF void PVGetVideoDimensions(VideoDecControls *decCtrl, int32 *display_width, int32 *display_height)
719{
720    VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
721    *display_width = video->displayWidth;
722    *display_height = video->displayHeight;
723}
724
725OSCL_EXPORT_REF void PVGetBufferDimensions(VideoDecControls *decCtrl, int32 *width, int32 *height) {
726    VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
727    *width = video->width;
728    *height = video->height;
729}
730
731/* ======================================================================== */
732/*  Function : PVGetVideoTimeStamp()                                        */
733/*  Date     : 04/27/2000, 08/29/2000                                       */
734/*  Purpose  :                                                              */
735/*  In/out   :                                                              */
736/*  Return   : current time stamp in millisecond.                           */
737/*  Note     :                                                              */
738/*  Modified :                                                              */
739/* ======================================================================== */
740uint32 PVGetVideoTimeStamp(VideoDecControls *decCtrl)
741{
742    VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
743    return video->currTimestamp;
744}
745
746
747/* ======================================================================== */
748/*  Function : PVSetPostProcType()                                          */
749/*  Date     : 07/07/2000                                                   */
750/*  Purpose  :                                                              */
751/*  In/out   :                                                              */
752/*  Return   : Set post-processing filter type.                             */
753/*  Note     :                                                              */
754/*  Modified : . 08/29/2000 changes the name for consistency.               */
755/* ======================================================================== */
756OSCL_EXPORT_REF void PVSetPostProcType(VideoDecControls *decCtrl, int mode)
757{
758    VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
759    video->postFilterType = mode;
760}
761
762
763/* ======================================================================== */
764/*  Function : PVGetDecBitrate()                                            */
765/*  Date     : 08/23/2000                                                   */
766/*  Purpose  :                                                              */
767/*  In/out   :                                                              */
768/*  Return   : This function returns the average bits per second.           */
769/*  Note     :                                                              */
770/*  Modified :                                                              */
771/* ======================================================================== */
772int PVGetDecBitrate(VideoDecControls *decCtrl)
773{
774    VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
775    int     idx;
776    int32   sum = 0;
777
778    for (idx = 0; idx < BITRATE_AVERAGE_WINDOW; idx++)
779    {
780        sum += video->nBitsPerVop[idx];
781    }
782    sum = (sum * video->frameRate) / (10 * BITRATE_AVERAGE_WINDOW);
783    return (int) sum;
784}
785
786
787/* ======================================================================== */
788/*  Function : PVGetDecFramerate()                                          */
789/*  Date     : 08/23/2000                                                   */
790/*  Purpose  :                                                              */
791/*  In/out   :                                                              */
792/*  Return   : This function returns the average frame per 10 second.       */
793/*  Note     : The fps can be calculated by PVGetDecFramerate()/10          */
794/*  Modified :                                                              */
795/* ======================================================================== */
796int PVGetDecFramerate(VideoDecControls *decCtrl)
797{
798    VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
799
800    return video->frameRate;
801}
802
803/* ======================================================================== */
804/*  Function : PVGetOutputFrame()                                           */
805/*  Date     : 05/07/2001                                                   */
806/*  Purpose  :                                                              */
807/*  In/out   :                                                              */
808/*  Return   : This function returns the pointer to the output frame        */
809/*  Note     :                                                              */
810/*  Modified :                                                              */
811/* ======================================================================== */
812uint8 *PVGetDecOutputFrame(VideoDecControls *decCtrl)
813{
814    return decCtrl->outputFrame;
815}
816
817/* ======================================================================== */
818/*  Function : PVGetLayerID()                                               */
819/*  Date     : 07/09/2001                                                   */
820/*  Purpose  :                                                              */
821/*  In/out   :                                                              */
822/*  Return   : This function returns decoded frame layer id (BASE/ENHANCE)  */
823/*  Note     :                                                              */
824/*  Modified :                                                              */
825/* ======================================================================== */
826int PVGetLayerID(VideoDecControls *decCtrl)
827{
828    VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
829    return video->currLayer;
830}
831/* ======================================================================== */
832/*  Function : PVGetDecMemoryUsage()                                        */
833/*  Date     : 08/23/2000                                                   */
834/*  Purpose  :                                                              */
835/*  In/out   :                                                              */
836/*  Return   : This function returns the amount of memory used.             */
837/*  Note     :                                                              */
838/*  Modified :                                                              */
839/* ======================================================================== */
840int32 PVGetDecMemoryUsage(VideoDecControls *decCtrl)
841{
842    VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
843    return video->memoryUsage;
844}
845
846
847/* ======================================================================== */
848/*  Function : PVGetDecBitstreamMode()                                      */
849/*  Date     : 08/23/2000                                                   */
850/*  Purpose  :                                                              */
851/*  In/out   :                                                              */
852/*  Return   : This function returns the decoding mode of the baselayer     */
853/*              bitstream.                                                  */
854/*  Note     :                                                              */
855/*  Modified :                                                              */
856/* ======================================================================== */
857OSCL_EXPORT_REF MP4DecodingMode PVGetDecBitstreamMode(VideoDecControls *decCtrl)
858{
859    VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
860    if (video->shortVideoHeader)
861    {
862        return H263_MODE;
863    }
864    else
865    {
866        return MPEG4_MODE;
867    }
868}
869
870
871/* ======================================================================== */
872/*  Function : PVExtractVolHeader()                                         */
873/*  Date     : 08/29/2000                                                   */
874/*  Purpose  :                                                              */
875/*  In/out   :                                                              */
876/*  Return   : Extract vol header of the bitstream from buffer[].           */
877/*  Note     :                                                              */
878/*  Modified :                                                              */
879/* ======================================================================== */
880Bool PVExtractVolHeader(uint8 *video_buffer, uint8 *vol_header, int32 *vol_header_size)
881{
882    int idx = -1;
883    uint8 start_code_prefix[] = { 0x00, 0x00, 0x01 };
884    uint8 h263_prefix[] = { 0x00, 0x00, 0x80 };
885
886    if (oscl_memcmp(h263_prefix, video_buffer, 3) == 0) /* we have short header stream */
887    {
888        oscl_memcpy(vol_header, video_buffer, 32);
889        *vol_header_size = 32;
890        return TRUE;
891    }
892    else
893    {
894        if (oscl_memcmp(start_code_prefix, video_buffer, 3) ||
895                (video_buffer[3] != 0xb0 && video_buffer[3] >= 0x20)) return FALSE;
896
897        do
898        {
899            idx++;
900            while (oscl_memcmp(start_code_prefix, video_buffer + idx, 3))
901            {
902                idx++;
903                if (idx + 3 >= *vol_header_size) goto quit;
904            }
905        }
906        while (video_buffer[idx+3] != 0xb3 && video_buffer[idx+3] != 0xb6);
907
908        oscl_memcpy(vol_header, video_buffer, idx);
909        *vol_header_size = idx;
910        return TRUE;
911    }
912
913quit:
914    oscl_memcpy(vol_header, video_buffer, *vol_header_size);
915    return FALSE;
916}
917
918
919/* ======================================================================== */
920/*  Function : PVLocateFrameHeader()                                        */
921/*  Date     : 04/8/2005                                                    */
922/*  Purpose  :                                                              */
923/*  In/out   :                                                              */
924/*  Return   : Return the offset to the first SC in the buffer              */
925/*  Note     :                                                              */
926/*  Modified :                                                              */
927/* ======================================================================== */
928int32 PVLocateFrameHeader(uint8 *ptr, int32 size)
929{
930    int count = 0;
931    int32 i = size;
932
933    if (size < 1)
934    {
935        return 0;
936    }
937    while (i--)
938    {
939        if ((count > 1) && (*ptr == 0x01))
940        {
941            i += 2;
942            break;
943        }
944
945        if (*ptr++)
946            count = 0;
947        else
948            count++;
949    }
950    return (size - (i + 1));
951}
952
953
954/* ======================================================================== */
955/*  Function : PVLocateH263FrameHeader()                                    */
956/*  Date     : 04/8/2005                                                    */
957/*  Purpose  :                                                              */
958/*  In/out   :                                                              */
959/*  Return   : Return the offset to the first SC in the buffer              */
960/*  Note     :                                                              */
961/*  Modified :                                                              */
962/* ======================================================================== */
963int32 PVLocateH263FrameHeader(uint8 *ptr, int32 size)
964{
965    int count = 0;
966    int32 i = size;
967
968    if (size < 1)
969    {
970        return 0;
971    }
972
973    while (i--)
974    {
975        if ((count > 1) && ((*ptr & 0xFC) == 0x80))
976        {
977            i += 2;
978            break;
979        }
980
981        if (*ptr++)
982            count = 0;
983        else
984            count++;
985    }
986    return (size - (i + 1));
987}
988
989
990/* ======================================================================== */
991/*  Function : PVDecodeVideoFrame()                                         */
992/*  Date     : 08/29/2000                                                   */
993/*  Purpose  : Decode one video frame and return a YUV-12 image.            */
994/*  In/out   :                                                              */
995/*  Return   :                                                              */
996/*  Note     :                                                              */
997/*  Modified : 04/17/2001 removed PV_EOS, PV_END_OF_BUFFER              */
998/*           : 08/22/2002 break up into 2 functions PVDecodeVopHeader and */
999/*                          PVDecodeVopBody                                 */
1000/* ======================================================================== */
1001OSCL_EXPORT_REF Bool PVDecodeVideoFrame(VideoDecControls *decCtrl, uint8 *buffer[],
1002                                        uint32 timestamp[], int32 buffer_size[], uint use_ext_timestamp[], uint8 *currYUV)
1003{
1004    PV_STATUS status = PV_FAIL;
1005    VopHeaderInfo header_info;
1006
1007    status = (PV_STATUS)PVDecodeVopHeader(decCtrl, buffer, timestamp, buffer_size, &header_info, use_ext_timestamp, currYUV);
1008    if (status != PV_TRUE)
1009        return PV_FALSE;
1010
1011    if (PVDecodeVopBody(decCtrl, buffer_size) != PV_TRUE)
1012    {
1013        return PV_FALSE;
1014    }
1015
1016    return PV_TRUE;
1017}
1018
1019/* ======================================================================== */
1020/*  Function : PVDecodeVopHeader()                                          */
1021/*  Date     : 08/22/2002                                                   */
1022/*  Purpose  : Determine target layer and decode vop header, modified from  */
1023/*              original PVDecodeVideoFrame.                                */
1024/*  In/out   :                                                              */
1025/*  Return   :                                                              */
1026/*  Note     :                                                              */
1027/*  Modified :                                                              */
1028/* ======================================================================== */
1029Bool PVDecodeVopHeader(VideoDecControls *decCtrl, uint8 *buffer[],
1030                       uint32 timestamp[], int32 buffer_size[], VopHeaderInfo *header_info, uint use_ext_timestamp [], uint8 *currYUV)
1031{
1032    VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
1033    Vol *currVol;
1034    Vop *currVop = video->currVop;
1035    Vop **vopHeader = video->vopHeader;
1036    BitstreamDecVideo *stream;
1037
1038    int target_layer;
1039
1040#ifdef PV_SUPPORT_TEMPORAL_SCALABILITY
1041    PV_STATUS status = PV_FAIL;
1042    int idx;
1043    int32 display_time;
1044
1045    /* decide which frame to decode next */
1046    if (decCtrl->nLayers > 1)
1047    {
1048        display_time = target_layer = -1;
1049        for (idx = 0; idx < decCtrl->nLayers; idx++)
1050        {
1051            /* do we have data for this layer? */
1052            if (buffer_size[idx] <= 0)
1053            {
1054                timestamp[idx] = -1;
1055                continue;
1056            }
1057
1058            /* did the application provide a timestamp for this vop? */
1059            if (timestamp[idx] < 0)
1060            {
1061                if (vopHeader[idx]->timeStamp < 0)
1062                {
1063                    /* decode the timestamp in the bitstream */
1064                    video->currLayer = idx;
1065                    stream = video->vol[idx]->bitstream;
1066                    BitstreamReset(stream, buffer[idx], buffer_size[idx]);
1067
1068                    while ((status = DecodeVOPHeader(video, vopHeader[idx], FALSE)) != PV_SUCCESS)
1069                    {
1070                        /* Try to find a VOP header in the buffer.   08/30/2000. */
1071                        if (PVSearchNextM4VFrame(stream) != PV_SUCCESS)
1072                        {
1073                            /* if we don't have data for enhancement layer, */
1074                            /*    don't just stop.   09/07/2000.          */
1075                            buffer_size[idx] = 0;
1076                            break;
1077                        }
1078                    }
1079                    if (status == PV_SUCCESS)
1080                    {
1081                        vopHeader[idx]->timeStamp =
1082                            timestamp[idx] = CalcVopDisplayTime(video->vol[idx], vopHeader[idx], video->shortVideoHeader);
1083                        if (idx == 0) vopHeader[idx]->refSelectCode = 1;
1084                    }
1085                }
1086                else
1087                {
1088                    /* We've decoded this vop header in the previous run already. */
1089                    timestamp[idx] = vopHeader[idx]->timeStamp;
1090                }
1091            }
1092
1093            /* Use timestamps to select the next VOP to be decoded */
1094            if (timestamp[idx] >= 0 && (display_time < 0 || display_time > timestamp[idx]))
1095            {
1096                display_time = timestamp[idx];
1097                target_layer = idx;
1098            }
1099            else if (display_time == timestamp[idx])
1100            {
1101                /* we have to handle either SNR or spatial scalability here. */
1102            }
1103        }
1104        if (target_layer < 0) return PV_FALSE;
1105
1106        /* set up for decoding the target layer */
1107        video->currLayer = target_layer;
1108        currVol = video->vol[target_layer];
1109        video->bitstream = stream = currVol->bitstream;
1110
1111        /* We need to decode the vop header if external timestamp   */
1112        /*    is provided.    10/04/2000                            */
1113        if (vopHeader[target_layer]->timeStamp < 0)
1114        {
1115            stream = video->vol[target_layer]->bitstream;
1116            BitstreamReset(stream, buffer[target_layer], buffer_size[target_layer]);
1117
1118            while (DecodeVOPHeader(video, vopHeader[target_layer], TRUE) != PV_SUCCESS)
1119            {
1120                /* Try to find a VOP header in the buffer.   08/30/2000. */
1121                if (PVSearchNextM4VFrame(stream) != PV_SUCCESS)
1122                {
1123                    /* if we don't have data for enhancement layer, */
1124                    /*    don't just stop.   09/07/2000.          */
1125                    buffer_size[target_layer] = 0;
1126                    break;
1127                }
1128            }
1129            video->vol[target_layer]->timeInc_offset = vopHeader[target_layer]->timeInc;
1130            video->vol[target_layer]->moduloTimeBase = timestamp[target_layer];
1131            vopHeader[target_layer]->timeStamp = timestamp[target_layer];
1132            if (target_layer == 0) vopHeader[target_layer]->refSelectCode = 1;
1133        }
1134    }
1135    else /* base layer only decoding */
1136    {
1137#endif
1138        video->currLayer = target_layer = 0;
1139        currVol = video->vol[0];
1140        video->bitstream = stream = currVol->bitstream;
1141        if (buffer_size[0] <= 0) return PV_FALSE;
1142        BitstreamReset(stream, buffer[0], buffer_size[0]);
1143
1144        if (video->shortVideoHeader)
1145        {
1146            while (DecodeShortHeader(video, vopHeader[0]) != PV_SUCCESS)
1147            {
1148                if (PVSearchNextH263Frame(stream) != PV_SUCCESS)
1149                {
1150                    /* There is no vop header in the buffer,    */
1151                    /*   clean bitstream buffer.     2/5/2001   */
1152                    buffer_size[0] = 0;
1153                    if (video->initialized == PV_FALSE)
1154                    {
1155                        video->displayWidth = video->width = 0;
1156                        video->displayHeight = video->height = 0;
1157                    }
1158                    return PV_FALSE;
1159                }
1160            }
1161
1162            if (use_ext_timestamp[0])
1163            {
1164                /* MTB for H263 is absolute TR */
1165                /* following line is equivalent to  round((timestamp[0]*30)/1001);   11/13/2001 */
1166                video->vol[0]->moduloTimeBase = 30 * ((timestamp[0] + 17) / 1001) + (30 * ((timestamp[0] + 17) % 1001) / 1001);
1167                vopHeader[0]->timeStamp = timestamp[0];
1168            }
1169            else
1170                vopHeader[0]->timeStamp = CalcVopDisplayTime(currVol, vopHeader[0], video->shortVideoHeader);
1171        }
1172        else
1173        {
1174            while (DecodeVOPHeader(video, vopHeader[0], FALSE) != PV_SUCCESS)
1175            {
1176                /* Try to find a VOP header in the buffer.   08/30/2000. */
1177                if (PVSearchNextM4VFrame(stream) != PV_SUCCESS)
1178                {
1179                    /* There is no vop header in the buffer,    */
1180                    /*   clean bitstream buffer.     2/5/2001   */
1181                    buffer_size[0] = 0;
1182                    return PV_FALSE;
1183                }
1184            }
1185
1186            if (use_ext_timestamp[0])
1187            {
1188                video->vol[0]->timeInc_offset = vopHeader[0]->timeInc;
1189                video->vol[0]->moduloTimeBase = timestamp[0];  /*  11/12/2001 */
1190                vopHeader[0]->timeStamp = timestamp[0];
1191            }
1192            else
1193            {
1194                vopHeader[0]->timeStamp = CalcVopDisplayTime(currVol, vopHeader[0], video->shortVideoHeader);
1195            }
1196        }
1197
1198        /* set up some base-layer only parameters */
1199        vopHeader[0]->refSelectCode = 1;
1200#ifdef PV_SUPPORT_TEMPORAL_SCALABILITY
1201    }
1202#endif
1203    timestamp[target_layer] = video->currTimestamp = vopHeader[target_layer]->timeStamp;
1204#ifdef PV_MEMORY_POOL
1205    vopHeader[target_layer]->yChan = (PIXEL *)currYUV;
1206    vopHeader[target_layer]->uChan = (PIXEL *)currYUV + decCtrl->size;
1207    vopHeader[target_layer]->vChan = (PIXEL *)(vopHeader[target_layer]->uChan) + (decCtrl->size >> 2);
1208#else
1209    vopHeader[target_layer]->yChan = currVop->yChan;
1210    vopHeader[target_layer]->uChan = currVop->uChan;
1211    vopHeader[target_layer]->vChan = currVop->vChan;
1212#endif
1213    oscl_memcpy(currVop, vopHeader[target_layer], sizeof(Vop));
1214
1215#ifdef PV_SUPPORT_TEMPORAL_SCALABILITY
1216    vopHeader[target_layer]->timeStamp = -1;
1217#endif
1218    /* put header info into the structure */
1219    header_info->currLayer = target_layer;
1220    header_info->timestamp = video->currTimestamp;
1221    header_info->frameType = (MP4FrameType)currVop->predictionType;
1222    header_info->refSelCode = vopHeader[target_layer]->refSelectCode;
1223    header_info->quantizer = currVop->quantizer;
1224    /***************************************/
1225
1226    return PV_TRUE;
1227}
1228
1229
1230/* ======================================================================== */
1231/*  Function : PVDecodeVopBody()                                            */
1232/*  Date     : 08/22/2002                                                   */
1233/*  Purpose  : Decode vop body after the header is decoded, modified from   */
1234/*              original PVDecodeVideoFrame.                                */
1235/*  In/out   :                                                              */
1236/*  Return   :                                                              */
1237/*  Note     :                                                              */
1238/*  Modified :                                                              */
1239/* ======================================================================== */
1240Bool PVDecodeVopBody(VideoDecControls *decCtrl, int32 buffer_size[])
1241{
1242    PV_STATUS status = PV_FAIL;
1243    VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
1244    int target_layer = video->currLayer;
1245    Vol *currVol = video->vol[target_layer];
1246    Vop *currVop = video->currVop;
1247    Vop *prevVop = video->prevVop;
1248    Vop *tempVopPtr;
1249    int bytes_consumed = 0; /* Record how many bits we used in the buffer.   04/24/2001 */
1250
1251    int idx;
1252
1253    if (currVop->vopCoded == 0)                  /*  07/03/2001 */
1254    {
1255        PV_BitstreamByteAlign(currVol->bitstream);
1256        /* We should always clear up bitstream buffer.   10/10/2000 */
1257        bytes_consumed = (getPointer(currVol->bitstream) + 7) >> 3;
1258
1259        if (bytes_consumed > currVol->bitstream->data_end_pos)
1260        {
1261            bytes_consumed = currVol->bitstream->data_end_pos;
1262        }
1263
1264        if (bytes_consumed < buffer_size[target_layer])
1265        {
1266            /* If we only consume part of the bits in the buffer, take those */
1267            /*  out.     04/24/2001 */
1268            /*          oscl_memcpy(buffer[target_layer], buffer[target_layer]+bytes_consumed,
1269                            (buffer_size[target_layer]-=bytes_consumed)); */
1270            buffer_size[target_layer] -= bytes_consumed;
1271        }
1272        else
1273        {
1274            buffer_size[target_layer] = 0;
1275        }
1276#ifdef PV_MEMORY_POOL
1277
1278        if (target_layer)
1279        {
1280            if (video->prevEnhcVop->timeStamp > video->prevVop->timeStamp)
1281            {
1282                video->prevVop = video->prevEnhcVop;
1283            }
1284        }
1285
1286        oscl_memcpy(currVop->yChan, video->prevVop->yChan, (decCtrl->size*3) / 2);
1287
1288        video->prevVop = prevVop;
1289
1290        video->concealFrame = currVop->yChan;       /*  07/07/2001 */
1291
1292        video->vop_coding_type = currVop->predictionType; /*  07/09/01 */
1293
1294        decCtrl->outputFrame = currVop->yChan;
1295
1296        /* Swap VOP pointers.  No enhc. frame oscl_memcpy() anymore!   04/24/2001 */
1297        if (target_layer)
1298        {
1299            tempVopPtr = video->prevEnhcVop;
1300            video->prevEnhcVop = video->currVop;
1301            video->currVop = tempVopPtr;
1302        }
1303        else
1304        {
1305            tempVopPtr = video->prevVop;
1306            video->prevVop = video->currVop;
1307            video->currVop = tempVopPtr;
1308        }
1309#else
1310        if (target_layer)       /* this is necessary to avoid flashback problems   06/21/2002*/
1311        {
1312            video->prevEnhcVop->timeStamp = currVop->timeStamp;
1313        }
1314        else
1315        {
1316            video->prevVop->timeStamp = currVop->timeStamp;
1317        }
1318#endif
1319        video->vop_coding_type = currVop->predictionType; /*  07/09/01 */
1320        /* the following is necessary to avoid displaying an notCoded I-VOP at the beginning of a session
1321        or after random positioning  07/03/02*/
1322        if (currVop->predictionType == I_VOP)
1323        {
1324            video->vop_coding_type = P_VOP;
1325        }
1326
1327
1328        return PV_TRUE;
1329    }
1330    /* ======================================================= */
1331    /*  Decode vop body (if there is no error in the header!)  */
1332    /* ======================================================= */
1333
1334    /* first, we need to select a reference frame */
1335    if (decCtrl->nLayers > 1)
1336    {
1337        if (currVop->predictionType == I_VOP)
1338        {
1339            /* do nothing here */
1340        }
1341        else if (currVop->predictionType == P_VOP)
1342        {
1343            switch (currVop->refSelectCode)
1344            {
1345                case 0 : /* most recently decoded enhancement vop */
1346                    /* Setup video->prevVop before we call PV_DecodeVop().   04/24/2001 */
1347                    if (video->prevEnhcVop->timeStamp >= video->prevVop->timeStamp)
1348                        video->prevVop = video->prevEnhcVop;
1349                    break;
1350
1351                case 1 : /* most recently displayed base-layer vop */
1352                    if (target_layer)
1353                    {
1354                        if (video->prevEnhcVop->timeStamp > video->prevVop->timeStamp)
1355                            video->prevVop = video->prevEnhcVop;
1356                    }
1357                    break;
1358
1359                case 2 : /* next base-layer vop in display order */
1360                    break;
1361
1362                case 3 : /* temporally coincident base-layer vop (no MV's) */
1363                    break;
1364            }
1365        }
1366        else /* we have a B-Vop */
1367        {
1368            mp4dec_log("DecodeVideoFrame(): B-VOP not supported.\n");
1369        }
1370    }
1371
1372    /* This is for the calculation of the frame rate and bitrate. */
1373    idx = ++video->frame_idx % BITRATE_AVERAGE_WINDOW;
1374
1375    /* Calculate bitrate for this layer.   08/23/2000 */
1376    status = PV_DecodeVop(video);
1377    video->nBitsPerVop[idx] = getPointer(currVol->bitstream);
1378    video->prevTimestamp[idx] = currVop->timeStamp;
1379
1380    /* restore video->prevVop after PV_DecodeVop().   04/24/2001 */
1381//  if (currVop->refSelectCode == 0) video->prevVop = prevVop;
1382    video->prevVop = prevVop;
1383
1384    /* Estimate the frame rate.   08/23/2000 */
1385    video->duration = video->prevTimestamp[idx];
1386    video->duration -= video->prevTimestamp[(++idx)%BITRATE_AVERAGE_WINDOW];
1387    if (video->duration > 0)
1388    { /* Only update framerate when the timestamp is right */
1389        video->frameRate = (int)(FRAMERATE_SCALE) / video->duration;
1390    }
1391
1392    /* We should always clear up bitstream buffer.   10/10/2000 */
1393    bytes_consumed = (getPointer(currVol->bitstream) + 7) >> 3; /*  11/4/03 */
1394
1395    if (bytes_consumed > currVol->bitstream->data_end_pos)
1396    {
1397        bytes_consumed = currVol->bitstream->data_end_pos;
1398    }
1399
1400    if (bytes_consumed < buffer_size[target_layer])
1401    {
1402        /* If we only consume part of the bits in the buffer, take those */
1403        /*  out.     04/24/2001 */
1404        /*      oscl_memcpy(buffer[target_layer], buffer[target_layer]+bytes_consumed,
1405                    (buffer_size[target_layer]-=bytes_consumed)); */
1406        buffer_size[target_layer] -= bytes_consumed;
1407    }
1408    else
1409    {
1410        buffer_size[target_layer] = 0;
1411    }
1412    switch (status)
1413    {
1414        case PV_FAIL :
1415            return PV_FALSE;        /* this will take care of concealment if we lose whole frame  */
1416
1417        case PV_END_OF_VOP :
1418            /* we may want to differenciate PV_END_OF_VOP and PV_SUCCESS */
1419            /*    in the future.     05/10/2000                      */
1420
1421        case PV_SUCCESS :
1422            /* Nohting is wrong :). */
1423
1424
1425            video->concealFrame = video->currVop->yChan;       /*  07/07/2001 */
1426
1427            video->vop_coding_type = video->currVop->predictionType; /*  07/09/01 */
1428
1429            decCtrl->outputFrame = video->currVop->yChan;
1430
1431            /* Swap VOP pointers.  No enhc. frame oscl_memcpy() anymore!   04/24/2001 */
1432            if (target_layer)
1433            {
1434                tempVopPtr = video->prevEnhcVop;
1435                video->prevEnhcVop = video->currVop;
1436                video->currVop = tempVopPtr;
1437            }
1438            else
1439            {
1440                tempVopPtr = video->prevVop;
1441                video->prevVop = video->currVop;
1442                video->currVop = tempVopPtr;
1443            }
1444            break;
1445
1446        default :
1447            /* This will never happen */
1448            break;
1449    }
1450
1451    return PV_TRUE;
1452}
1453
1454#ifdef PV_MEMORY_POOL
1455OSCL_EXPORT_REF void PVSetReferenceYUV(VideoDecControls *decCtrl, uint8 *YUV)
1456{
1457    VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
1458    video->prevVop->yChan = (PIXEL *)YUV;
1459    video->prevVop->uChan = (PIXEL *)YUV + video->size;
1460    video->prevVop->vChan = (PIXEL *)video->prevVop->uChan + (decCtrl->size >> 2);
1461    oscl_memset(video->prevVop->yChan, 16, sizeof(uint8)*decCtrl->size);     /*  10/31/01 */
1462    oscl_memset(video->prevVop->uChan, 128, sizeof(uint8)*decCtrl->size / 2);
1463    video->concealFrame = video->prevVop->yChan;               /*  07/07/2001 */
1464    decCtrl->outputFrame = video->prevVop->yChan;              /*  06/19/2002 */
1465}
1466#endif
1467
1468
1469/* ======================================================================== */
1470/*  Function : VideoDecoderErrorDetected()                                  */
1471/*  Date     : 06/20/2000                                                   */
1472/*  Purpose  :                                                              */
1473/*  In/out   :                                                              */
1474/*  Return   : This function will be called everytime an error int the      */
1475/*              bitstream is detected.                                      */
1476/*  Note     :                                                              */
1477/*  Modified :                                                              */
1478/* ======================================================================== */
1479uint VideoDecoderErrorDetected(VideoDecData *)
1480{
1481    /* This is only used for trapping bitstream error for debuging */
1482    return 0;
1483}
1484
1485#ifdef ENABLE_LOG
1486#include <stdio.h>
1487#include <stdarg.h>
1488/* ======================================================================== */
1489/*  Function : m4vdec_dprintf()                                             */
1490/*  Date     : 08/15/2000                                                   */
1491/*  Purpose  : This is a function that logs messages in the mpeg4 video     */
1492/*             decoder.  We can call the standard PacketVideo PVMessage     */
1493/*             from inside this function if necessary.                      */
1494/*  In/out   :                                                              */
1495/*  Return   :                                                              */
1496/*  Note     : To turn on the logging, LOG_MP4DEC_MESSAGE must be defined   */
1497/*              when compiling this file (only this file).                  */
1498/*  Modified :                                                              */
1499/* ======================================================================== */
1500void m4vdec_dprintf(char *format, ...)
1501{
1502    FILE *log_fp;
1503    va_list args;
1504    va_start(args, format);
1505
1506    /* open the log file */
1507    log_fp = fopen("\\mp4dec_log.txt", "a+");
1508    if (log_fp == NULL) return;
1509    /* output the message */
1510    vfprintf(log_fp, format, args);
1511    fclose(log_fp);
1512
1513    va_end(args);
1514}
1515#endif
1516
1517
1518/* ======================================================================== */
1519/*  Function : IsIntraFrame()                                               */
1520/*  Date     : 05/29/2000                                                   */
1521/*  Purpose  :                                                              */
1522/*  In/out   :                                                              */
1523/*  Return   : The most recently decoded frame is an Intra frame.           */
1524/*  Note     :                                                              */
1525/*  Modified :                                                              */
1526/* ======================================================================== */
1527Bool IsIntraFrame(VideoDecControls *decCtrl)
1528{
1529    VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
1530    return (video->vop_coding_type == I_VOP);
1531}
1532
1533/* ======================================================================== */
1534/*  Function : PVDecPostProcess()                                           */
1535/*  Date     : 01/09/2002                                                   */
1536/*  Purpose  : PostProcess one video frame and return a YUV-12 image.       */
1537/*  In/out   :                                                              */
1538/*  Return   :                                                              */
1539/*  Note     :                                                              */
1540/*  Modified :                                                              */
1541/* ======================================================================== */
1542void PVDecPostProcess(VideoDecControls *decCtrl, uint8 *outputYUV)
1543{
1544    uint8 *outputBuffer;
1545#ifdef PV_POSTPROC_ON
1546    VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
1547    int32 tmpvar;
1548    if (outputYUV)
1549    {
1550        outputBuffer = outputYUV;
1551    }
1552    else
1553    {
1554        if (video->postFilterType)
1555        {
1556            outputBuffer = video->currVop->yChan;
1557        }
1558        else
1559        {
1560            outputBuffer = decCtrl->outputFrame;
1561        }
1562    }
1563
1564    if (video->postFilterType)
1565    {
1566        /* Post-processing,  */
1567        PostFilter(video, video->postFilterType, outputBuffer);
1568    }
1569    else
1570    {
1571        if (outputYUV)
1572        {
1573            /* Copy decoded frame to the output buffer. */
1574            tmpvar = (int32)video->width * video->height;
1575            oscl_memcpy(outputBuffer, decCtrl->outputFrame, tmpvar*3 / 2);           /*  3/3/01 */
1576        }
1577    }
1578#else
1579    outputBuffer = decCtrl->outputFrame;
1580    outputYUV;
1581#endif
1582    decCtrl->outputFrame = outputBuffer;
1583    return;
1584}
1585
1586
1587/* ======================================================================== */
1588/*  Function : PVDecSetReference(VideoDecControls *decCtrl, uint8 *refYUV,  */
1589/*                              int32 timestamp)                            */
1590/*  Date     : 07/22/2003                                                   */
1591/*  Purpose  : Get YUV reference frame from external source.                */
1592/*  In/out   : YUV 4-2-0 frame containing new reference frame in the same   */
1593/*   : dimension as original, i.e., doesn't have to be multiple of 16 !!!.  */
1594/*  Return   :                                                              */
1595/*  Note     :                                                              */
1596/*  Modified :                                                              */
1597/* ======================================================================== */
1598Bool PVDecSetReference(VideoDecControls *decCtrl, uint8 *refYUV, uint32 timestamp)
1599{
1600    VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
1601    Vop *prevVop = video->prevVop;
1602    int width = video->width;
1603    uint8 *dstPtr, *orgPtr, *dstPtr2, *orgPtr2;
1604    int32 size = (int32)width * video->height;
1605
1606
1607    /* set new parameters */
1608    prevVop->timeStamp = timestamp;
1609    prevVop->predictionType = I_VOP;
1610
1611    dstPtr = prevVop->yChan;
1612    orgPtr = refYUV;
1613    oscl_memcpy(dstPtr, orgPtr, size);
1614    dstPtr = prevVop->uChan;
1615    dstPtr2 = prevVop->vChan;
1616    orgPtr = refYUV + size;
1617    orgPtr2 = orgPtr + (size >> 2);
1618    oscl_memcpy(dstPtr, orgPtr, (size >> 2));
1619    oscl_memcpy(dstPtr2, orgPtr2, (size >> 2));
1620
1621    video->concealFrame = video->prevVop->yChan;
1622    video->vop_coding_type = I_VOP;
1623    decCtrl->outputFrame = video->prevVop->yChan;
1624
1625    return PV_TRUE;
1626}
1627
1628/* ======================================================================== */
1629/*  Function : PVDecSetEnhReference(VideoDecControls *decCtrl, uint8 *refYUV,   */
1630/*                              int32 timestamp)                            */
1631/*  Date     : 07/23/2003                                                   */
1632/*  Purpose  : Get YUV enhance reference frame from external source.        */
1633/*  In/out   : YUV 4-2-0 frame containing new reference frame in the same   */
1634/*   : dimension as original, i.e., doesn't have to be multiple of 16 !!!.  */
1635/*  Return   :                                                              */
1636/*  Note     :                                                              */
1637/*  Modified :                                                              */
1638/* ======================================================================== */
1639Bool PVDecSetEnhReference(VideoDecControls *decCtrl, uint8 *refYUV, uint32 timestamp)
1640{
1641    VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
1642    Vop *prevEnhcVop = video->prevEnhcVop;
1643    uint8 *dstPtr, *orgPtr, *dstPtr2, *orgPtr2;
1644    int32 size = (int32) video->width * video->height;
1645
1646    if (video->numberOfLayers <= 1)
1647        return PV_FALSE;
1648
1649
1650    /* set new parameters */
1651    prevEnhcVop->timeStamp = timestamp;
1652    prevEnhcVop->predictionType = I_VOP;
1653
1654    dstPtr = prevEnhcVop->yChan;
1655    orgPtr = refYUV;
1656    oscl_memcpy(dstPtr, orgPtr, size);
1657    dstPtr = prevEnhcVop->uChan;
1658    dstPtr2 = prevEnhcVop->vChan;
1659    orgPtr = refYUV + size;
1660    orgPtr2 = orgPtr + (size >> 2);
1661    oscl_memcpy(dstPtr, orgPtr, (size >> 2));
1662    oscl_memcpy(dstPtr2, orgPtr2, (size >> 2));
1663    video->concealFrame = video->prevEnhcVop->yChan;
1664    video->vop_coding_type = I_VOP;
1665    decCtrl->outputFrame = video->prevEnhcVop->yChan;
1666
1667    return PV_TRUE;
1668}
1669
1670
1671/* ======================================================================== */
1672/*  Function : PVGetVolInfo()                                               */
1673/*  Date     : 08/06/2003                                                   */
1674/*  Purpose  : Get the vol info(only base-layer).                           */
1675/*  In/out   :                                                              */
1676/*  Return   :                                                              */
1677/*  Note     :                                                              */
1678/*  Modified : 06/24/2004                                                   */
1679/* ======================================================================== */
1680Bool PVGetVolInfo(VideoDecControls *decCtrl, VolInfo *pVolInfo)
1681{
1682    Vol *currVol;
1683
1684    if (pVolInfo == NULL || decCtrl == NULL || decCtrl->videoDecoderData == NULL ||
1685            ((VideoDecData *)decCtrl->videoDecoderData)->vol[0] == NULL) return PV_FALSE;
1686
1687    currVol = ((VideoDecData *)(decCtrl->videoDecoderData))->vol[0];
1688
1689    // get the VOL info
1690    pVolInfo->shortVideoHeader = (int32)((VideoDecData *)(decCtrl->videoDecoderData))->shortVideoHeader;
1691    pVolInfo->dataPartitioning = (int32)currVol->dataPartitioning;
1692    pVolInfo->errorResDisable  = (int32)currVol->errorResDisable;
1693    pVolInfo->useReverseVLC    = (int32)currVol->useReverseVLC;
1694    pVolInfo->scalability      = (int32)currVol->scalability;
1695    pVolInfo->nbitsTimeIncRes  = (int32)currVol->nbitsTimeIncRes;
1696    pVolInfo->profile_level_id = (int32)currVol->profile_level_id;
1697
1698    return PV_TRUE;
1699}
1700
1701
1702
1703