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