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