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