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