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