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