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