omxVCM4P2_EncodeMV.c revision 78e52bfac041d71ce53b5b13c2abf78af742b09d
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_EncodeMV.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 predicting MV of MB
29 *
30 */
31
32#include "omxtypes.h"
33#include "armOMX.h"
34#include "omxVC.h"
35
36#include "armCOMM.h"
37#include "armCOMM_Bitstream.h"
38#include "armVCM4P2_Huff_Tables_VLC.h"
39
40
41
42/**
43 * Function:  omxVCM4P2_EncodeMV   (6.2.4.5.4)
44 *
45 * Description:
46 * Predicts a motion vector for the current macroblock, encodes the
47 * difference, and writes the output to the stream buffer. The input MVs
48 * pMVCurMB, pSrcMVLeftMB, pSrcMVUpperMB, and pSrcMVUpperRightMB should lie
49 * within the ranges associated with the input parameter fcodeForward, as
50 * described in [ISO14496-2], subclause 7.6.3.  This function provides a
51 * superset of the functionality associated with the function
52 * omxVCM4P2_FindMVpred.
53 *
54 * Input Arguments:
55 *
56 *   ppBitStream - double pointer to the current byte in the bitstream buffer
57 *   pBitOffset - index of the first free (next available) bit in the stream
58 *            buffer referenced by *ppBitStream, valid in the range 0 to 7.
59 *   pMVCurMB - pointer to the current macroblock motion vector; a value of
60 *            NULL indicates unavailability.
61 *   pSrcMVLeftMB - pointer to the source left macroblock motion vector; a
62 *            value of  NULLindicates unavailability.
63 *   pSrcMVUpperMB - pointer to source upper macroblock motion vector; a
64 *            value of NULL indicates unavailability.
65 *   pSrcMVUpperRightMB - pointer to source upper right MB motion vector; a
66 *            value of NULL indicates unavailability.
67 *   fcodeForward - an integer with values from 1 to 7; used in encoding
68 *            motion vectors related to search range, as described in
69 *            [ISO14496-2], subclause 7.6.3.
70 *   MBType - macro block type, valid in the range 0 to 5
71 *
72 * Output Arguments:
73 *
74 *   ppBitStream - updated pointer to the current byte in the bit stream
75 *            buffer
76 *   pBitOffset - updated index of the next available bit position in stream
77 *            buffer referenced by *ppBitStream
78 *
79 * Return Value:
80 *
81 *    OMX_Sts_NoErr - no error
82 *    OMX_Sts_BadArgErr - bad arguments
83 *    -    At least one of the following pointers is NULL: ppBitStream,
84 *              *ppBitStream, pBitOffset, pMVCurMB
85 *    -    *pBitOffset < 0, or *pBitOffset >7.
86 *    -    fcodeForward <= 0, or fcodeForward > 7, or MBType < 0.
87 *
88 */
89
90OMXResult omxVCM4P2_EncodeMV(
91     OMX_U8 **ppBitStream,
92     OMX_INT *pBitOffset,
93     const OMXVCMotionVector * pMVCurMB,
94     const OMXVCMotionVector * pSrcMVLeftMB,
95     const OMXVCMotionVector * pSrcMVUpperMB,
96     const OMXVCMotionVector * pSrcMVUpperRightMB,
97     OMX_INT fcodeForward,
98     OMXVCM4P2MacroblockType MBType
99)
100{
101    OMXVCMotionVector dstMVPred, diffMV;
102    OMXVCMotionVector dstMVPredME[12];
103    /* Initialized to remove compilation warning */
104    OMX_INT iBlk, i, count = 1;
105    OMX_S32 mvHorResidual, mvVerResidual, mvHorData, mvVerData;
106    OMX_U8 scaleFactor, index;
107
108    /* Argument error checks */
109    armRetArgErrIf(ppBitStream == NULL, OMX_Sts_BadArgErr);
110    armRetArgErrIf(*ppBitStream == NULL, OMX_Sts_BadArgErr);
111    armRetArgErrIf(pBitOffset == NULL, OMX_Sts_BadArgErr);
112    armRetArgErrIf(pMVCurMB == NULL, OMX_Sts_BadArgErr);
113    armRetArgErrIf(((*pBitOffset < 0) || (*pBitOffset > 7)), OMX_Sts_BadArgErr);
114    armRetArgErrIf(((fcodeForward < 1) || (fcodeForward > 7)), \
115                    OMX_Sts_BadArgErr);
116
117    if ((MBType == OMX_VC_INTRA) ||
118        (MBType == OMX_VC_INTRA_Q)
119       )
120    {
121        /* No candidate vectors hence make them zero */
122        for (i = 0; i < 12; i++)
123        {
124            dstMVPredME[i].dx = 0;
125            dstMVPredME[i].dy = 0;
126        }
127
128        return OMX_Sts_NoErr;
129    }
130
131    if ((MBType == OMX_VC_INTER4V) || (MBType == OMX_VC_INTER4V_Q))
132    {
133        count = 4;
134    }
135    else if ((MBType == OMX_VC_INTER) || (MBType == OMX_VC_INTER_Q))
136    {
137        count = 1;
138    }
139
140    /* Calculating the scale factor */
141    scaleFactor = 1 << (fcodeForward -1);
142
143    for (iBlk = 0; iBlk < count; iBlk++)
144    {
145
146        /* Find the predicted vector */
147        omxVCM4P2_FindMVpred (
148            pMVCurMB,
149            pSrcMVLeftMB,
150            pSrcMVUpperMB,
151            pSrcMVUpperRightMB,
152            &dstMVPred,
153            dstMVPredME,
154            iBlk );
155
156        /* Calculating the differential motion vector (diffMV) */
157        diffMV.dx = pMVCurMB[iBlk].dx - dstMVPred.dx;
158        diffMV.dy = pMVCurMB[iBlk].dy - dstMVPred.dy;
159
160        /* Calculating the mv_data and mv_residual for Horizantal MV */
161        if (diffMV.dx == 0)
162        {
163            mvHorResidual = 0;
164            mvHorData = 0;
165        }
166        else
167        {
168            mvHorResidual = ( armAbs(diffMV.dx) - 1) % scaleFactor;
169            mvHorData = (armAbs(diffMV.dx) - mvHorResidual + (scaleFactor - 1))
170                     / scaleFactor;
171            if (diffMV.dx < 0)
172            {
173                mvHorData = -mvHorData;
174            }
175        }
176
177        /* Calculating the mv_data and mv_residual for Vertical MV */
178        if (diffMV.dy == 0)
179        {
180            mvVerResidual = 0;
181            mvVerData = 0;
182        }
183        else
184        {
185            mvVerResidual = ( armAbs(diffMV.dy) - 1) % scaleFactor;
186            mvVerData = (armAbs(diffMV.dy) - mvVerResidual + (scaleFactor - 1))
187                     / scaleFactor;
188            if (diffMV.dy < 0)
189            {
190                mvVerData = -mvVerData;
191            }
192        }
193
194        /* Huffman encoding */
195
196        /* The index is actually calculate as
197           index = ((float) (mvHorData/2) + 16) * 2,
198           meaning the MV data is halfed and then normalized
199           to begin with zero and then doubled to take care of indexing
200           the fractional part included */
201        index = mvHorData + 32;
202        armPackVLC32 (ppBitStream, pBitOffset, armVCM4P2_aVlcMVD[index]);
203        if ((fcodeForward > 1) && (diffMV.dx != 0))
204        {
205            armPackBits (ppBitStream, pBitOffset, mvHorResidual, (fcodeForward -1));
206        }
207
208        /* The index is actually calculate as
209           index = ((float) (mvVerData/2) + 16) * 2,
210           meaning the MV data is halfed and then normalized
211           to begin with zero and then doubled to take care of indexing
212           the fractional part included */
213        index = mvVerData + 32;
214        armPackVLC32 (ppBitStream, pBitOffset, armVCM4P2_aVlcMVD[index]);
215        if ((fcodeForward > 1) && (diffMV.dy != 0))
216        {
217            armPackBits (ppBitStream, pBitOffset, mvVerResidual, (fcodeForward -1));
218        }
219    }
220
221    return OMX_Sts_NoErr;
222}
223
224
225/* End of file */
226
227
228