1/**
2 *
3 * File Name:  omxVCM4P2_DecodePadMV_PVOP.c
4 * OpenMAX DL: v1.0.2
5 * Revision:   9641
6 * Date:       Thursday, February 7, 2008
7 *
8 * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
9 *
10 *
11 *
12 * Description:
13 * Contains module for decoding MV and padding the same
14 *
15 */
16
17#include "omxtypes.h"
18#include "armOMX.h"
19#include "omxVC.h"
20
21#include "armCOMM_Bitstream.h"
22#include "armCOMM.h"
23#include "armVCM4P2_Huff_Tables_VLC.h"
24
25
26
27/**
28 * Function:  omxVCM4P2_DecodePadMV_PVOP   (6.2.5.1.1)
29 *
30 * Description:
31 * Decodes and pads the four motion vectors associated with a non-intra P-VOP
32 * macroblock.  For macroblocks of type OMX_VC_INTER4V, the output MV is
33 * padded as specified in [ISO14496-2], subclause 7.6.1.6. Otherwise, for
34 * macroblocks of types other than OMX_VC_INTER4V, the decoded MV is copied to
35 * all four output MV buffer entries.
36 *
37 * Input Arguments:
38 *
39 *   ppBitStream - pointer to the pointer to the current byte in the bit
40 *            stream buffer
41 *   pBitOffset - pointer to the bit position in the byte pointed to by
42 *            *ppBitStream. *pBitOffset is valid within [0-7].
43 *   pSrcMVLeftMB, pSrcMVUpperMB, and pSrcMVUpperRightMB - pointers to the
44 *            motion vector buffers of the macroblocks specially at the left,
45 *            upper, and upper-right side of the current macroblock,
46 *            respectively; a value of NULL indicates unavailability.  Note:
47 *            Any neighborhood macroblock outside the current VOP or video
48 *            packet or outside the current GOB (when short_video_header is
49 *             1 ) for which gob_header_empty is  0  is treated as
50 *            transparent, according to [ISO14496-2], subclause 7.6.5.
51 *   fcodeForward - a code equal to vop_fcode_forward in MPEG-4 bit stream
52 *            syntax
53 *   MBType - the type of the current macroblock. If MBType is not equal to
54 *            OMX_VC_INTER4V, the destination motion vector buffer is still
55 *            filled with the same decoded vector.
56 *
57 * Output Arguments:
58 *
59 *   ppBitStream - *ppBitStream is updated after the block is decoded, so
60 *            that it points to the current byte in the bit stream buffer
61 *   pBitOffset - *pBitOffset is updated so that it points to the current bit
62 *            position in the byte pointed by *ppBitStream
63 *   pDstMVCurMB - pointer to the motion vector buffer for the current
64 *            macroblock; contains four decoded motion vectors
65 *
66 * Return Value:
67 *
68 *    OMX_Sts_NoErr - no error
69 *    OMX_Sts_BadArgErr - bad arguments:
70 *    -    At least one of the following pointers is NULL:
71 *         ppBitStream, *ppBitStream, pBitOffset, pDstMVCurMB
72 *    -    *pBitOffset exceeds [0,7]
73 *    -    fcodeForward exceeds (0,7]
74 *    -    MBType less than zero
75 *    -    motion vector buffer is not 4-byte aligned.
76 *    OMX_Sts_Err - status error
77 *
78 */
79
80OMXResult omxVCM4P2_DecodePadMV_PVOP(
81     const OMX_U8 ** ppBitStream,
82     OMX_INT * pBitOffset,
83     OMXVCMotionVector * pSrcMVLeftMB,
84     OMXVCMotionVector *pSrcMVUpperMB,
85     OMXVCMotionVector * pSrcMVUpperRightMB,
86     OMXVCMotionVector * pDstMVCurMB,
87     OMX_INT fcodeForward,
88     OMXVCM4P2MacroblockType MBType
89 )
90{
91    OMXVCMotionVector diffMV;
92    OMXVCMotionVector dstMVPredME[12];
93    OMX_INT iBlk, i, count = 1;
94    OMX_S32 mvHorResidual = 1, mvVerResidual = 1, mvHorData, mvVerData;
95    OMX_S8 scaleFactor, index;
96    OMX_S16 high, low, range;
97
98
99    /* Argument error checks */
100    armRetArgErrIf(ppBitStream == NULL, OMX_Sts_BadArgErr);
101    armRetArgErrIf(*ppBitStream == NULL, OMX_Sts_BadArgErr);
102    armRetArgErrIf(pBitOffset == NULL, OMX_Sts_BadArgErr);
103    armRetArgErrIf(pDstMVCurMB == NULL, OMX_Sts_BadArgErr);
104    armRetArgErrIf(((*pBitOffset < 0) || (*pBitOffset > 7)), OMX_Sts_BadArgErr);
105    armRetArgErrIf(((fcodeForward < 1) || (fcodeForward > 7)), \
106                    OMX_Sts_BadArgErr);
107    armRetArgErrIf(!armIs4ByteAligned(pDstMVCurMB), OMX_Sts_BadArgErr);
108
109    if ((MBType == OMX_VC_INTRA) ||
110        (MBType == OMX_VC_INTRA_Q)
111       )
112    {
113        /* All MV's are zero */
114        for (i = 0; i < 4; i++)
115        {
116            pDstMVCurMB[i].dx = 0;
117            pDstMVCurMB[i].dy = 0;
118        }
119
120        return OMX_Sts_NoErr;
121    }
122
123    if ((MBType == OMX_VC_INTER4V) || (MBType == OMX_VC_INTER4V_Q))
124    {
125        count = 4;
126    }
127    else if ((MBType == OMX_VC_INTER) || (MBType == OMX_VC_INTER_Q))
128    {
129        count = 1;
130    }
131
132    /* Calculating the scale factor */
133    scaleFactor = 1 << (fcodeForward -1);
134    high =  ( 32 * scaleFactor) - 1;
135    low =   ( (-32) * scaleFactor);
136    range = ( 64 * scaleFactor);
137
138    /* Huffman decoding and MV reconstruction */
139    for (iBlk = 0; iBlk < count; iBlk++)
140    {
141
142        /* Huffman decoding to get Horizontal data and residual */
143        index = armUnPackVLC32(ppBitStream, pBitOffset,
144                                            armVCM4P2_aVlcMVD);
145        armRetDataErrIf(index == -1, OMX_Sts_Err);
146
147        mvHorData = index - 32;
148
149        if ((fcodeForward > 1) && (mvHorData != 0))
150        {
151            mvHorResidual = (OMX_S32) armGetBits(ppBitStream,
152                                            pBitOffset, (fcodeForward -1));
153        }
154
155        /* Huffman decoding to get Vertical data and residual */
156        index = armUnPackVLC32(ppBitStream, pBitOffset, armVCM4P2_aVlcMVD);
157        armRetDataErrIf(index == -1, OMX_Sts_Err);
158
159        mvVerData = index - 32;
160
161        if ((fcodeForward > 1) && (mvVerData != 0))
162        {
163            mvVerResidual = (OMX_S32) armGetBits(ppBitStream,
164                                            pBitOffset, (fcodeForward -1));
165        }
166
167        /* Calculating the differtial MV */
168        if ( (scaleFactor == 1) || (mvHorData == 0) )
169        {
170            diffMV.dx = mvHorData;
171        }
172        else
173        {
174            diffMV.dx = ((armAbs(mvHorData) - 1) * fcodeForward)
175                         + mvHorResidual + 1;
176            if (mvHorData < 0)
177            {
178                diffMV.dx = -diffMV.dx;
179            }
180        }
181
182        if ( (scaleFactor == 1) || (mvVerData == 0) )
183        {
184            diffMV.dy = mvVerData;
185        }
186        else
187        {
188            diffMV.dy = ((armAbs(mvVerData) - 1) * fcodeForward)
189                         + mvVerResidual + 1;
190            if (mvVerData < 0)
191            {
192                diffMV.dy = -diffMV.dy;
193            }
194        }
195
196        /* Find the predicted vector */
197        omxVCM4P2_FindMVpred (
198            pDstMVCurMB,
199            pSrcMVLeftMB,
200            pSrcMVUpperMB,
201            pSrcMVUpperRightMB,
202            &pDstMVCurMB[iBlk],
203            dstMVPredME,
204            iBlk);
205
206        /* Adding the difference to the predicted MV to reconstruct MV */
207        pDstMVCurMB[iBlk].dx += diffMV.dx;
208        pDstMVCurMB[iBlk].dy += diffMV.dy;
209
210        /* Checking the range and keeping it within the limits */
211        if ( pDstMVCurMB[iBlk].dx < low )
212        {
213            pDstMVCurMB[iBlk].dx += range;
214        }
215        if (pDstMVCurMB[iBlk].dx > high)
216        {
217            pDstMVCurMB[iBlk].dx -= range;
218        }
219
220        if ( pDstMVCurMB[iBlk].dy < low )
221        {
222            pDstMVCurMB[iBlk].dy += range;
223        }
224        if (pDstMVCurMB[iBlk].dy > high)
225        {
226            pDstMVCurMB[iBlk].dy -= range;
227        }
228    }
229
230    if ((MBType == OMX_VC_INTER) || (MBType == OMX_VC_INTER_Q))
231    {
232        pDstMVCurMB[1] = pDstMVCurMB[0];
233        pDstMVCurMB[2] = pDstMVCurMB[0];
234        pDstMVCurMB[3] = pDstMVCurMB[0];
235    }
236
237    return OMX_Sts_NoErr;
238}
239
240
241/* End of file */
242
243
244