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