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