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#include "scaling.h"
22#include "mbtype_mode.h"
23#include "idct.h"
24
25#define OSCL_DISABLE_WARNING_CONDITIONAL_IS_CONSTANT
26/* ======================================================================== */
27/*  Function : DecodeFrameDataPartMode()                                    */
28/*  Purpose  : Decode a frame of MPEG4 bitstream in datapartitioning mode.  */
29/*  In/out   :                                                              */
30/*  Return   :                                                              */
31/*  Modified :                                                              */
32/*                                                                          */
33/*      04/25/2000 : Rewrite the data partitioning path completely  */
34/*                           according to the pseudo codes in MPEG-4        */
35/*                           standard.                                      */
36/*  Modified : 09/18/2000 add fast VlcDecode+Dequant                    */
37/*             04/17/2001 cleanup                                       */
38/* ======================================================================== */
39PV_STATUS DecodeFrameDataPartMode(VideoDecData *video)
40{
41    PV_STATUS status;
42    Vop *currVop = video->currVop;
43    BitstreamDecVideo *stream = video->bitstream;
44
45    int nMBPerRow = video->nMBPerRow;
46
47    int vopType = currVop->predictionType;
48    int mbnum;
49    int nTotalMB = video->nTotalMB;
50    int slice_counter;
51    int resync_marker_length;
52
53    /* copy and pad to prev_Vop for INTER coding */
54    switch (vopType)
55    {
56        case I_VOP :
57//      oscl_memset(Mode, MODE_INTRA, sizeof(uint8)*nTotalMB);
58            resync_marker_length = 17;
59            break;
60        case P_VOP :
61            oscl_memset(video->motX, 0, sizeof(MOT)*4*nTotalMB);
62            oscl_memset(video->motY, 0, sizeof(MOT)*4*nTotalMB);
63//      oscl_memset(Mode, MODE_INTER, sizeof(uint8)*nTotalMB);
64            resync_marker_length = 16 + currVop->fcodeForward;
65            break;
66        default :
67            mp4dec_log("DecodeFrameDataPartMode(): Vop type not supported.\n");
68            return PV_FAIL;
69    }
70
71    /** Initialize sliceNo ***/
72    mbnum = slice_counter = 0;
73//  oscl_memset(video->sliceNo, 0, sizeof(uint8)*nTotalMB);
74
75    do
76    {
77        /* This section is equivalent to motion_shape_texture() */
78        /* in the MPEG-4 standard.            04/13/2000      */
79        video->mbnum = mbnum;
80        video->mbnum_row = PV_GET_ROW(mbnum, nMBPerRow);   /*  This is needed if nbnum is read from the packet header */
81        video->mbnum_col = mbnum - video->mbnum_row * nMBPerRow;
82
83        switch (vopType)
84        {
85            case I_VOP :
86                status = DecodeDataPart_I_VideoPacket(video, slice_counter);
87                break;
88
89            case P_VOP :
90                status = DecodeDataPart_P_VideoPacket(video, slice_counter);
91                break;
92
93            default :
94                mp4dec_log("DecodeFrameDataPartMode(): Vop type not supported.\n");
95                return PV_FAIL;
96        }
97
98        while ((status = PV_ReadVideoPacketHeader(video, &mbnum)) == PV_FAIL)
99        {
100            if ((status = quickSearchVideoPacketHeader(stream, resync_marker_length)) != PV_SUCCESS)
101            {
102                break;
103            }
104        }
105
106        if (status == PV_END_OF_VOP)
107        {
108            mbnum = nTotalMB;
109        }
110
111        if (mbnum > video->mbnum + 1)
112        {
113            ConcealPacket(video, video->mbnum, mbnum, slice_counter);
114        }
115        slice_counter++;
116        if (mbnum >= nTotalMB)
117        {
118            break;
119        }
120
121
122    }
123    while (TRUE);
124
125    return PV_SUCCESS;
126}
127
128
129/* ======================================================================== */
130/*  Function : DecodeDataPart_I_VideoPacket()                               */
131/*  Date     : 04/25/2000                                                   */
132/*  Purpose  : Decode Data Partitioned Mode Video Packet in I-VOP           */
133/*  In/out   :                                                              */
134/*  Return   : PV_SUCCESS if successed, PV_FAIL if failed.                  */
135/*  Modified : 09/18/2000 add fast VlcDecode+Dequant                    */
136/*             04/01/2001 fixed MB_stuffing, removed unnecessary code   */
137/* ======================================================================== */
138PV_STATUS DecodeDataPart_I_VideoPacket(VideoDecData *video, int slice_counter)
139{
140    PV_STATUS status;
141    uint8 *Mode = video->headerInfo.Mode;
142    BitstreamDecVideo *stream = video->bitstream;
143    int  nTotalMB = video->nTotalMB;
144    int  mbnum, mb_start, mb_end;
145    int16 QP, *QPMB = video->QPMB;
146    int  MBtype, MCBPC, CBPY;
147    uint32 tmpvar;
148    uint code;
149    int nMBPerRow = video->nMBPerRow;
150    Bool valid_stuffing;
151    int32 startSecondPart, startFirstPart = getPointer(stream);
152
153    /* decode the first partition */
154    QP = video->currVop->quantizer;
155    mb_start = mbnum = video->mbnum;
156    video->usePrevQP = 0;         /*  04/27/01 */
157
158
159    BitstreamShowBits16(stream, 9, &code);
160    while (code == 1)
161    {
162        PV_BitstreamFlushBits(stream, 9);
163        BitstreamShowBits16(stream, 9, &code);
164    }
165
166    do
167    {
168        /* decode COD, MCBPC, ACpred_flag, CPBY and DQUANT */
169        MCBPC = PV_VlcDecMCBPC_com_intra(stream);
170
171        if (!VLC_ERROR_DETECTED(MCBPC))
172        {
173            Mode[mbnum] = (uint8)(MBtype = MBtype_mode[MCBPC & 7]);
174            video->headerInfo.CBP[mbnum] = (uint8)((MCBPC >> 4) & 3);
175            status = GetMBheaderDataPart_DQUANT_DC(video, &QP);
176            video->usePrevQP = 1;        /* set it after the first coded MB      04/27/01 */
177        }
178        else
179        {
180            /* Report the error to the application.   06/20/2000 */
181            VideoDecoderErrorDetected(video);
182            video->mbnum = mb_start;
183            movePointerTo(stream, startFirstPart);
184            return PV_FAIL;
185        }
186
187        video->sliceNo[mbnum] = (uint8) slice_counter;
188        QPMB[mbnum] = QP;
189        video->mbnum = ++mbnum;
190
191        BitstreamShowBits16(stream, 9, &code);
192        while (code == 1)
193        {
194            PV_BitstreamFlushBits(stream, 9);
195            BitstreamShowBits16(stream, 9, &code);
196        }
197        /* have we reached the end of the video packet or vop? */
198        status = BitstreamShowBits32(stream, DC_MARKER_LENGTH, &tmpvar);
199
200    }
201    while (tmpvar != DC_MARKER && video->mbnum < nTotalMB);
202
203    if (tmpvar == DC_MARKER)
204    {
205        PV_BitstreamFlushBits(stream, DC_MARKER_LENGTH);
206    }
207    else
208    {
209        status = quickSearchDCM(stream);
210        if (status == PV_SUCCESS)
211        {
212            /* only way you can end up being here is in the last packet,and there is stuffing at
213            the end of the first partition */
214            PV_BitstreamFlushBits(stream, DC_MARKER_LENGTH);
215        }
216        else
217        {
218            /* Report the error to the application.   06/20/2000 */
219            VideoDecoderErrorDetected(video);
220            movePointerTo(stream, startFirstPart);
221            video->mbnum = mb_start;
222            /* concealment will be taken care of in the upper layer */
223            return PV_FAIL;
224        }
225    }
226
227    /* decode the second partition */
228    startSecondPart = getPointer(stream);
229
230    mb_end = video->mbnum;
231
232    for (mbnum = mb_start; mbnum < mb_end; mbnum++)
233    {
234        MBtype = Mode[mbnum];
235        /* No skipped mode in I-packets  3/1/2001    */
236        video->mbnum = mbnum;
237
238        video->mbnum_row = PV_GET_ROW(mbnum, nMBPerRow);   /*  This is needed if nbnum is read from the packet header */
239        video->mbnum_col = mbnum - video->mbnum_row * nMBPerRow;
240        /* there is always acdcpred in DataPart mode  04/10/01 */
241        video->acPredFlag[mbnum] = (uint8) BitstreamRead1Bits(stream);
242
243        CBPY = PV_VlcDecCBPY(stream, MBtype & INTRA_MASK); /* MODE_INTRA || MODE_INTRA_Q */
244        if (CBPY < 0)
245        {
246            /* Report the error to the application.   06/20/2000 */
247            VideoDecoderErrorDetected(video);
248            movePointerTo(stream, startSecondPart); /*  */
249            /* Conceal packet,  05/15/2000 */
250            ConcealTexture_I(video, startFirstPart, mb_start, mb_end, slice_counter);
251            return PV_FAIL;
252        }
253
254        video->headerInfo.CBP[mbnum] |= (uint8)(CBPY << 2);
255    }
256
257    video->usePrevQP = 0;
258
259    for (mbnum = mb_start; mbnum < mb_end; mbnum++)
260    {
261        video->mbnum = mbnum;
262
263        video->mbnum_row = PV_GET_ROW(mbnum , nMBPerRow);  /*  This is needed if nbnum is read from the packet header */
264        video->mbnum_col = mbnum - video->mbnum_row * nMBPerRow;
265        /* No skipped mode in I-packets  3/1/2001    */
266        /* decode the DCT coeficients for the MB */
267        status = GetMBData_DataPart(video);
268        if (status != PV_SUCCESS)
269        {
270            /* Report the error to the application.   06/20/2000 */
271            VideoDecoderErrorDetected(video);
272            movePointerTo(stream, startSecondPart); /*  */
273            /* Conceal packet,  05/15/2000 */
274            ConcealTexture_I(video, startFirstPart, mb_start, mb_end, slice_counter);
275            return status;
276        }
277        video->usePrevQP = 1;           /*  04/27/01 should be set after decoding first MB */
278    }
279
280    valid_stuffing = validStuffing(stream);
281    if (!valid_stuffing)
282    {
283        VideoDecoderErrorDetected(video);
284        movePointerTo(stream, startSecondPart);
285        ConcealTexture_I(video, startFirstPart, mb_start, mb_end, slice_counter);
286        return PV_FAIL;
287    }
288    return PV_SUCCESS;
289}
290
291
292/* ======================================================================== */
293/*  Function : DecodeDataPart_P_VideoPacket()                               */
294/*  Date     : 04/25/2000                                                   */
295/*  Purpose  : Decode Data Partitioned Mode Video Packet in P-VOP           */
296/*  In/out   :                                                              */
297/*  Return   : PV_SUCCESS if successed, PV_FAIL if failed.                  */
298/*  Modified :   09/18/2000,  fast VlcDecode+Dequant                        */
299/*              04/13/2001,  fixed MB_stuffing, new ACDC pred structure,  */
300/*                              cleanup                                     */
301/*              08/07/2001,  remove MBzero                              */
302/* ======================================================================== */
303PV_STATUS DecodeDataPart_P_VideoPacket(VideoDecData *video, int slice_counter)
304{
305    PV_STATUS status;
306    uint8 *Mode = video->headerInfo.Mode;
307    BitstreamDecVideo *stream = video->bitstream;
308    int nTotalMB = video->nTotalMB;
309    int mbnum, mb_start, mb_end;
310    int16 QP, *QPMB = video->QPMB;
311    int MBtype, CBPY;
312    Bool valid_stuffing;
313    int intra_MB;
314    uint32 tmpvar;
315    uint code;
316    int32  startFirstPart, startSecondPart;
317    int nMBPerRow = video->nMBPerRow;
318    uint8 *pbyte;
319    /* decode the first partition */
320    startFirstPart = getPointer(stream);
321    mb_start = video->mbnum;
322    video->usePrevQP = 0;            /*  04/27/01 */
323
324    BitstreamShowBits16(stream, 10, &code);
325    while (code == 1)
326    {
327        PV_BitstreamFlushBits(stream, 10);
328        BitstreamShowBits16(stream, 10, &code);
329    }
330
331    do
332    {
333        /* decode COD, MCBPC, ACpred_flag, CPBY and DQUANT */
334        /* We have to discard stuffed MB header */
335
336        status = GetMBheaderDataPart_P(video);
337
338        if (status != PV_SUCCESS)
339        {
340            /* Report the error to the application.   06/20/2000 */
341            VideoDecoderErrorDetected(video);
342            movePointerTo(stream, startFirstPart);
343            video->mbnum = mb_start;
344            return PV_FAIL;
345        }
346
347        /* we must update slice_counter before motion vector decoding.   */
348        video->sliceNo[video->mbnum] = (uint8) slice_counter;
349
350        if (Mode[video->mbnum] & INTER_MASK) /* INTER || INTER_Q || INTER_4V */
351        {
352            /* decode the motion vector (if there are any) */
353            status = PV_GetMBvectors(video, Mode[video->mbnum]);
354            if (status != PV_SUCCESS)
355            {
356                /* Report the error to the application.   06/20/2000 */
357                VideoDecoderErrorDetected(video);
358                movePointerTo(stream, startFirstPart);
359                video->mbnum = mb_start;
360                return PV_FAIL;
361            }
362        }
363        video->mbnum++;
364
365        video->mbnum_row = PV_GET_ROW(video->mbnum, nMBPerRow);   /*  This is needed if mbnum is read from the packet header */
366        video->mbnum_col = video->mbnum - video->mbnum_row * nMBPerRow;
367
368        BitstreamShowBits16(stream, 10, &code);
369        while (code == 1)
370        {
371            PV_BitstreamFlushBits(stream, 10);
372            BitstreamShowBits16(stream, 10, &code);
373        }
374        /* have we reached the end of the video packet or vop? */
375        status = BitstreamShowBits32(stream, MOTION_MARKER_COMB_LENGTH, &tmpvar);
376        /*      if (status != PV_SUCCESS && status != PV_END_OF_BUFFER) return status;  */
377    }
378    while (tmpvar != MOTION_MARKER_COMB && video->mbnum < nTotalMB);
379
380    if (tmpvar == MOTION_MARKER_COMB)
381    {
382        PV_BitstreamFlushBits(stream, MOTION_MARKER_COMB_LENGTH);
383    }
384    else
385    {
386        status = quickSearchMotionMarker(stream);
387        if (status == PV_SUCCESS)
388        {
389            /* only way you can end up being here is in the last packet,and there is stuffing at
390            the end of the first partition */
391            PV_BitstreamFlushBits(stream, MOTION_MARKER_COMB_LENGTH);
392        }
393        else
394        {
395            /* Report the error to the application.   06/20/2000 */
396            VideoDecoderErrorDetected(video);
397            movePointerTo(stream, startFirstPart);
398            video->mbnum = mb_start;
399            /* concealment will be taken care of in the upper layer  */
400            return PV_FAIL;
401        }
402    }
403
404    /* decode the second partition */
405    startSecondPart = getPointer(stream);
406    QP = video->currVop->quantizer;
407
408    mb_end = video->mbnum;
409
410    for (mbnum = mb_start; mbnum < mb_end; mbnum++)
411    {
412        MBtype = Mode[mbnum];
413
414        if (MBtype == MODE_SKIPPED)
415        {
416            QPMB[mbnum] = QP; /*  03/01/01 */
417            continue;
418        }
419        intra_MB = (MBtype & INTRA_MASK); /* (MBtype == MODE_INTRA || MBtype == MODE_INTRA_Q) */
420        video->mbnum = mbnum;
421        video->mbnum_row = PV_GET_ROW(mbnum, nMBPerRow);   /*  This is needed if nbnum is read from the packet header */
422        video->mbnum_col = mbnum - video->mbnum_row * nMBPerRow;
423
424        /* there is always acdcprediction in DataPart mode    04/10/01 */
425        if (intra_MB)
426        {
427            video->acPredFlag[mbnum] = (uint8) BitstreamRead1Bits_INLINE(stream);
428        }
429
430        CBPY = PV_VlcDecCBPY(stream, intra_MB);
431        if (CBPY < 0)
432        {
433            /* Report the error to the application.   06/20/2000 */
434            VideoDecoderErrorDetected(video);
435            /* Conceal second partition,  5/15/2000 */
436            movePointerTo(stream, startSecondPart);
437            ConcealTexture_P(video, mb_start, mb_end, slice_counter);
438            return PV_FAIL;
439        }
440
441        video->headerInfo.CBP[mbnum] |= (uint8)(CBPY << 2);
442        if (intra_MB || MBtype == MODE_INTER_Q)                     /*  04/26/01 */
443        {
444            status = GetMBheaderDataPart_DQUANT_DC(video, &QP);
445            if (status != PV_SUCCESS) return status;
446        }
447        video->usePrevQP = 1;        /*  04/27/01 */
448        QPMB[mbnum] = QP;
449    }
450
451    video->usePrevQP = 0;  /*  04/27/01 */
452
453    for (mbnum = mb_start; mbnum < mb_end; mbnum++)
454    {
455        video->mbnum = mbnum;
456        video->mbnum_row = PV_GET_ROW(mbnum, nMBPerRow);  /*  This is needed if nbnum is read from the packet header */
457        video->mbnum_col = mbnum - video->mbnum_row * nMBPerRow;
458
459
460        if (Mode[mbnum] != MODE_SKIPPED)
461        {
462            /* decode the DCT coeficients for the MB */
463            status = GetMBData_DataPart(video);
464            if (status != PV_SUCCESS)
465            {
466                /* Report the error to the application.   06/20/2000 */
467                VideoDecoderErrorDetected(video);
468
469                /* Conceal second partition,  5/15/2000 */
470                movePointerTo(stream, startSecondPart);
471                ConcealTexture_P(video, mb_start, mb_end, slice_counter);
472                return status;
473            }
474            video->usePrevQP = 1;  /*  04/27/01 */
475        }
476        else
477        {   // SKIPPED
478
479            /* Motion compensation and put it to video->mblock->pred_block */
480            SkippedMBMotionComp(video);
481
482            //oscl_memset(video->predDCAC_row + video->mbnum_col, 0, sizeof(typeDCACStore)); /*  SKIPPED_ACDC */
483            //oscl_memset(video->predDCAC_col, 0, sizeof(typeDCACStore));
484            /*  08/08/2005 */
485            pbyte = (uint8*)(video->predDCAC_row + video->mbnum_col);
486            ZERO_OUT_64BYTES(pbyte);
487            pbyte = (uint8*)(video->predDCAC_col);
488            ZERO_OUT_64BYTES(pbyte);
489
490        }
491    }
492
493    valid_stuffing = validStuffing(stream);   /*  */
494    if (!valid_stuffing)
495    {
496        VideoDecoderErrorDetected(video);
497        movePointerTo(stream, startSecondPart); /*  */
498        ConcealTexture_P(video, mb_start, mb_end, slice_counter);
499
500        return PV_FAIL;
501    }
502    return PV_SUCCESS;
503}
504
505
506/* ======================================================================== */
507/*  Function : GetMBheaderDataPart_DQUANT_DC()                              */
508/*  Date     : 04/26/2000                                                   */
509/*  Purpose  : Decode DQUANT and DC in Data Partitioned Mode for both       */
510/*             I-VOP and P-VOP.                                             */
511/*  In/out   :                                                              */
512/*  Return   : PV_SUCCESS if successed, PV_FAIL if failed.                  */
513/*  Modified : 02/13/2001 new ACDC prediction structure,        */
514/*                                       cleanup                            */
515/* ======================================================================== */
516PV_STATUS GetMBheaderDataPart_DQUANT_DC(VideoDecData *video, int16 *QP)
517{
518    PV_STATUS status = PV_SUCCESS;
519    BitstreamDecVideo *stream = video->bitstream;
520    int mbnum = video->mbnum;
521    int intra_dc_vlc_thr = video->currVop->intraDCVlcThr;
522    uint8 *Mode = video->headerInfo.Mode;
523    int  MBtype = Mode[mbnum];
524    typeDCStore *DC = video->predDC + mbnum;
525    int  comp;
526    Bool switched;
527    uint  DQUANT;
528    int16 QP_tmp;
529
530    const static int  DQ_tab[4] = { -1, -2, 1, 2};
531
532    if (MBtype & Q_MASK)             /* INTRA_Q || INTER_Q */
533    {
534        DQUANT = BitstreamReadBits16(stream, 2);
535        *QP += DQ_tab[DQUANT];
536
537        if (*QP < 1) *QP = 1;
538        else if (*QP > 31) *QP = 31;
539    }
540    if (MBtype & INTRA_MASK)  /* INTRA || INTRA_Q */ /* no switch, code DC separately */
541    {
542        QP_tmp = *QP;                      /* running QP  04/26/01*/
543        switched = 0;
544        if (intra_dc_vlc_thr)                 /*  04/27/01 */
545        {
546            if (video->usePrevQP)
547                QP_tmp = video->QPMB[mbnum-1];
548            switched = (intra_dc_vlc_thr == 7 || QP_tmp >= intra_dc_vlc_thr * 2 + 11);
549        }
550        if (!switched)
551        {
552            for (comp = 0; comp < 6; comp++)
553            {
554                status = PV_DecodePredictedIntraDC(comp, stream, (*DC + comp));   /*  03/01/01 */
555                if (status != PV_SUCCESS) return PV_FAIL;
556            }
557        }
558        else
559        {
560            for (comp = 0; comp < 6; comp++)
561            {
562                (*DC)[comp] = 0;   /*  04/26/01 needed for switched case*/
563            }
564        }
565    }
566    return status;
567}
568
569
570/***********************************************************CommentBegin******
571*       04/25/2000 : Initial modification to the new PV Lib format.
572*       04/17/2001 : new ACDC pred structure
573***********************************************************CommentEnd********/
574PV_STATUS GetMBheaderDataPart_P(VideoDecData *video)
575{
576    BitstreamDecVideo *stream = video->bitstream;
577    int mbnum = video->mbnum;
578    uint8 *Mode = video->headerInfo.Mode;
579    typeDCStore *DC = video->predDC + mbnum;
580    uint no_dct_flag;
581    int comp;
582    int MCBPC;
583
584    no_dct_flag = BitstreamRead1Bits_INLINE(stream);
585
586    if (no_dct_flag)
587    {
588        /* skipped macroblock */
589        Mode[mbnum] = MODE_SKIPPED;
590
591        for (comp = 0; comp < 6; comp++)
592        {
593            (*DC)[comp] = mid_gray;
594            /*  ACDC REMOVE AC coefs are set in DecodeDataPart_P */
595        }
596    }
597    else
598    {
599        /* coded macroblock */
600        MCBPC = PV_VlcDecMCBPC_com_inter(stream);
601
602        if (VLC_ERROR_DETECTED(MCBPC))
603        {
604            return PV_FAIL;
605        }
606
607        Mode[mbnum] = (uint8)MBtype_mode[MCBPC & 7];
608        video->headerInfo.CBP[mbnum] = (uint8)((MCBPC >> 4) & 3);
609    }
610
611    return PV_SUCCESS;
612}
613
614
615/***********************************************************CommentBegin******
616*       04/17/01  new ACDC pred structure, reorganized code, cleanup
617***********************************************************CommentEnd********/
618PV_STATUS GetMBData_DataPart(VideoDecData *video)
619{
620    int mbnum = video->mbnum;
621    int16 *dataBlock;
622    MacroBlock *mblock = video->mblock;
623    int QP = video->QPMB[mbnum];
624    int32 offset;
625    PIXEL *c_comp;
626    int width = video->width;
627    int intra_dc_vlc_thr = video->currVop->intraDCVlcThr;
628    uint CBP = video->headerInfo.CBP[mbnum];
629    uint8 mode = video->headerInfo.Mode[mbnum];
630    int x_pos = video->mbnum_col;
631    typeDCStore *DC = video->predDC + mbnum;
632    int  ncoeffs[6], *no_coeff = mblock->no_coeff;
633    int  comp;
634    Bool  switched;
635    int QP_tmp = QP;
636
637    int y_pos = video->mbnum_row;
638#ifdef PV_POSTPROC_ON
639    uint8 *pp_mod[6];
640    int TotalMB = video->nTotalMB;
641    int MB_in_width = video->nMBPerRow;
642#endif
643
644
645
646    /*****
647    *     Decoding of the 6 blocks (depending on transparent pattern)
648    *****/
649#ifdef PV_POSTPROC_ON
650    if (video->postFilterType != PV_NO_POST_PROC)
651    {
652        /** post-processing ***/
653        pp_mod[0] = video->pstprcTypCur + (y_pos << 1) * (MB_in_width << 1) + (x_pos << 1);
654        pp_mod[1] = pp_mod[0] + 1;
655        pp_mod[2] = pp_mod[0] + (MB_in_width << 1);
656        pp_mod[3] = pp_mod[2] + 1;
657        pp_mod[4] = video->pstprcTypCur + (TotalMB << 2) + mbnum;
658        pp_mod[5] = pp_mod[4] + TotalMB;
659    }
660#endif
661
662    /*  oscl_memset(mblock->block, 0, sizeof(typeMBStore));    Aug 9,2005 */
663
664    if (mode & INTRA_MASK) /* MODE_INTRA || mode == MODE_INTRA_Q */
665    {
666        switched = 0;
667        if (intra_dc_vlc_thr)
668        {
669            if (video->usePrevQP)
670                QP_tmp = video->QPMB[mbnum-1];   /* running QP  04/26/01 */
671
672            switched = (intra_dc_vlc_thr == 7 || QP_tmp >= intra_dc_vlc_thr * 2 + 11);
673        }
674
675        mblock->DCScalarLum = cal_dc_scaler(QP, LUMINANCE_DC_TYPE);     /*   ACDC 03/01/01 */
676        mblock->DCScalarChr = cal_dc_scaler(QP, CHROMINANCE_DC_TYPE);
677
678        for (comp = 0; comp < 6; comp++)
679        {
680            dataBlock = mblock->block[comp];    /*, 10/20/2000 */
681
682            dataBlock[0] = (*DC)[comp];
683
684            ncoeffs[comp] = VlcDequantH263IntraBlock(video, comp,
685                            switched, mblock->bitmapcol[comp], &mblock->bitmaprow[comp]);
686
687            if (VLC_ERROR_DETECTED(ncoeffs[comp]))         /*  */
688            {
689                if (switched)
690                    return PV_FAIL;
691                else
692                {
693                    ncoeffs[comp] = 1;
694                    oscl_memset((dataBlock + 1), 0, sizeof(int16)*63);
695                }
696            }
697            no_coeff[comp] = ncoeffs[comp];
698            /*  modified to new semaphore for post-proc */
699            // Future work:: can be combined in the dequant function
700            // @todo Deblocking Semaphore for INTRA block
701#ifdef PV_POSTPROC_ON
702            if (video->postFilterType != PV_NO_POST_PROC)
703                *pp_mod[comp] = (uint8) PostProcSemaphore(dataBlock);
704#endif
705        }
706        MBlockIDCT(video);
707    }
708    else /* MODE INTER*/
709    {
710
711
712
713
714        MBMotionComp(video, CBP);
715        offset = (int32)(y_pos << 4) * width + (x_pos << 4);
716        c_comp  = video->currVop->yChan + offset;
717
718
719        for (comp = 0; comp < 4; comp++)
720        {
721            (*DC)[comp] = mid_gray;
722
723            if (CBP & (1 << (5 - comp)))
724            {
725                ncoeffs[comp] = VlcDequantH263InterBlock(video, comp,
726                                mblock->bitmapcol[comp], &mblock->bitmaprow[comp]);
727                if (VLC_ERROR_DETECTED(ncoeffs[comp]))
728                    return PV_FAIL;
729
730
731                BlockIDCT(c_comp + (comp&2)*(width << 2) + 8*(comp&1), mblock->pred_block + (comp&2)*64 + 8*(comp&1), mblock->block[comp], width, ncoeffs[comp],
732                          mblock->bitmapcol[comp], mblock->bitmaprow[comp]);
733
734            }
735            else
736            {
737                ncoeffs[comp] = 0;
738            }
739
740            /*  @todo Deblocking Semaphore for INTRA block, for inter just test for ringing  */
741#ifdef PV_POSTPROC_ON
742            if (video->postFilterType != PV_NO_POST_PROC)
743                *pp_mod[comp] = (uint8)((ncoeffs[comp] > 3) ? 4 : 0);
744#endif
745        }
746
747        (*DC)[4] = mid_gray;
748        if (CBP & 2)
749        {
750            ncoeffs[4] = VlcDequantH263InterBlock(video, 4,
751                                                  mblock->bitmapcol[4], &mblock->bitmaprow[4]);
752            if (VLC_ERROR_DETECTED(ncoeffs[4]))
753                return PV_FAIL;
754
755            BlockIDCT(video->currVop->uChan + (offset >> 2) + (x_pos << 2), mblock->pred_block + 256, mblock->block[4], width >> 1, ncoeffs[4],
756                      mblock->bitmapcol[4], mblock->bitmaprow[4]);
757
758        }
759        else
760        {
761            ncoeffs[4] = 0;
762        }
763#ifdef PV_POSTPROC_ON
764        if (video->postFilterType != PV_NO_POST_PROC)
765            *pp_mod[4] = (uint8)((ncoeffs[4] > 3) ? 4 : 0);
766#endif
767        (*DC)[5] = mid_gray;
768        if (CBP & 1)
769        {
770            ncoeffs[5] = VlcDequantH263InterBlock(video, 5,
771                                                  mblock->bitmapcol[5], &mblock->bitmaprow[5]);
772            if (VLC_ERROR_DETECTED(ncoeffs[5]))
773                return PV_FAIL;
774
775            BlockIDCT(video->currVop->vChan + (offset >> 2) + (x_pos << 2), mblock->pred_block + 264, mblock->block[5], width >> 1, ncoeffs[5],
776                      mblock->bitmapcol[5], mblock->bitmaprow[5]);
777
778        }
779        else
780        {
781            ncoeffs[5] = 0;
782        }
783#ifdef PV_POSTPROC_ON
784        if (video->postFilterType != PV_NO_POST_PROC)
785            *pp_mod[5] = (uint8)((ncoeffs[5] > 3) ? 4 : 0);
786#endif
787
788
789
790
791        /* Motion compensation and put it to video->mblock->pred_block */
792    }
793    return PV_SUCCESS;
794}
795