1/*
2 * Copyright (C) 2009 The Android Open Source Project
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    Table of contents
20
21     1. Include headers
22     2. External compiler flags
23     3. Module defines
24     4. Local function prototypes
25     5. Functions
26          h264bsdInterPrediction
27          MvPrediction16x16
28          MvPrediction16x8
29          MvPrediction8x16
30          MvPrediction8x8
31          MvPrediction
32          MedianFilter
33          GetInterNeighbour
34          GetPredictionMv
35
36------------------------------------------------------------------------------*/
37
38/*------------------------------------------------------------------------------
39    1. Include headers
40------------------------------------------------------------------------------*/
41
42#include "h264bsd_inter_prediction.h"
43#include "h264bsd_neighbour.h"
44#include "h264bsd_util.h"
45#include "h264bsd_reconstruct.h"
46#include "h264bsd_dpb.h"
47
48/*------------------------------------------------------------------------------
49    2. External compiler flags
50--------------------------------------------------------------------------------
51
52--------------------------------------------------------------------------------
53    3. Module defines
54------------------------------------------------------------------------------*/
55
56typedef struct
57{
58    u32 available;
59    u32 refIndex;
60    mv_t mv;
61} interNeighbour_t;
62
63/*------------------------------------------------------------------------------
64    4. Local function prototypes
65------------------------------------------------------------------------------*/
66
67static u32 MvPrediction16x16(mbStorage_t *pMb, mbPred_t *mbPred,
68    dpbStorage_t *dpb);
69static u32 MvPrediction16x8(mbStorage_t *pMb, mbPred_t *mbPred,
70    dpbStorage_t *dpb);
71static u32 MvPrediction8x16(mbStorage_t *pMb, mbPred_t *mbPred,
72    dpbStorage_t *dpb);
73static u32 MvPrediction8x8(mbStorage_t *pMb, subMbPred_t *subMbPred,
74    dpbStorage_t *dpb);
75static u32 MvPrediction(mbStorage_t *pMb, subMbPred_t *subMbPred,
76    u32 mbPartIdx, u32 subMbPartIdx);
77static i32 MedianFilter(i32 a, i32 b, i32 c);
78
79static void GetInterNeighbour(u32 sliceId, mbStorage_t *nMb,
80    interNeighbour_t *n, u32 index);
81static void GetPredictionMv(mv_t *mv, interNeighbour_t *a, u32 refIndex);
82
83static const neighbour_t N_A_SUB_PART[4][4][4] = {
84    { { {MB_A,5}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
85      { {MB_A,5}, {MB_A,7}, {MB_NA,0}, {MB_NA,0} },
86      { {MB_A,5}, {MB_CURR,0}, {MB_NA,0}, {MB_NA,0} },
87      { {MB_A,5}, {MB_CURR,0}, {MB_A,7}, {MB_CURR,2} } },
88
89    { { {MB_CURR,1}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
90      { {MB_CURR,1}, {MB_CURR,3}, {MB_NA,0}, {MB_NA,0} },
91      { {MB_CURR,1}, {MB_CURR,4}, {MB_NA,0}, {MB_NA,0} },
92      { {MB_CURR,1}, {MB_CURR,4}, {MB_CURR,3}, {MB_CURR,6} } },
93
94    { { {MB_A,13}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
95      { {MB_A,13}, {MB_A,15}, {MB_NA,0}, {MB_NA,0} },
96      { {MB_A,13}, {MB_CURR,8}, {MB_NA,0}, {MB_NA,0} },
97      { {MB_A,13}, {MB_CURR,8}, {MB_A,15}, {MB_CURR,10} } },
98
99    { { {MB_CURR,9}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
100      { {MB_CURR,9}, {MB_CURR,11}, {MB_NA,0}, {MB_NA,0} },
101      { {MB_CURR,9}, {MB_CURR,12}, {MB_NA,0}, {MB_NA,0} },
102      { {MB_CURR,9}, {MB_CURR,12}, {MB_CURR,11}, {MB_CURR,14} } } };
103
104static const neighbour_t N_B_SUB_PART[4][4][4] = {
105    { { {MB_B,10}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
106      { {MB_B,10}, {MB_CURR,0}, {MB_NA,0}, {MB_NA,0} },
107      { {MB_B,10}, {MB_B,11}, {MB_NA,0}, {MB_NA,0} },
108      { {MB_B,10}, {MB_B,11}, {MB_CURR,0}, {MB_CURR,1} } },
109
110    { { {MB_B,14}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
111      { {MB_B,14}, {MB_CURR,4}, {MB_NA,0}, {MB_NA,0} },
112      { {MB_B,14}, {MB_B,15}, {MB_NA,0}, {MB_NA,0} },
113      { {MB_B,14}, {MB_B,15}, {MB_CURR,4}, {MB_CURR,5} } },
114
115    { { {MB_CURR,2}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
116      { {MB_CURR,2}, {MB_CURR,8}, {MB_NA,0}, {MB_NA,0} },
117      { {MB_CURR,2}, {MB_CURR,3}, {MB_NA,0}, {MB_NA,0} },
118      { {MB_CURR,2}, {MB_CURR,3}, {MB_CURR,8}, {MB_CURR,9} } },
119
120    { { {MB_CURR,6}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
121      { {MB_CURR,6}, {MB_CURR,12}, {MB_NA,0}, {MB_NA,0} },
122      { {MB_CURR,6}, {MB_CURR,7}, {MB_NA,0}, {MB_NA,0} },
123      { {MB_CURR,6}, {MB_CURR,7}, {MB_CURR,12}, {MB_CURR,13} } } };
124
125static const neighbour_t N_C_SUB_PART[4][4][4] = {
126    { { {MB_B,14}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
127      { {MB_B,14}, {MB_NA,4}, {MB_NA,0}, {MB_NA,0} },
128      { {MB_B,11}, {MB_B,14}, {MB_NA,0}, {MB_NA,0} },
129      { {MB_B,11}, {MB_B,14}, {MB_CURR,1}, {MB_NA,4} } },
130
131    { { {MB_C,10}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
132      { {MB_C,10}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
133      { {MB_B,15}, {MB_C,10}, {MB_NA,0}, {MB_NA,0} },
134      { {MB_B,15}, {MB_C,10}, {MB_CURR,5}, {MB_NA,0} } },
135
136    { { {MB_CURR,6}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
137      { {MB_CURR,6}, {MB_NA,12}, {MB_NA,0}, {MB_NA,0} },
138      { {MB_CURR,3}, {MB_CURR,6}, {MB_NA,0}, {MB_NA,0} },
139      { {MB_CURR,3}, {MB_CURR,6}, {MB_CURR,9}, {MB_NA,12} } },
140
141    { { {MB_NA,2}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
142      { {MB_NA,2}, {MB_NA,8}, {MB_NA,0}, {MB_NA,0} },
143      { {MB_CURR,7}, {MB_NA,2}, {MB_NA,0}, {MB_NA,0} },
144      { {MB_CURR,7}, {MB_NA,2}, {MB_CURR,13}, {MB_NA,8} } } };
145
146static const neighbour_t N_D_SUB_PART[4][4][4] = {
147    { { {MB_D,15}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
148      { {MB_D,15}, {MB_A,5}, {MB_NA,0}, {MB_NA,0} },
149      { {MB_D,15}, {MB_B,10}, {MB_NA,0}, {MB_NA,0} },
150      { {MB_D,15}, {MB_B,10}, {MB_A,5}, {MB_CURR,0} } },
151
152    { { {MB_B,11}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
153      { {MB_B,11}, {MB_CURR,1}, {MB_NA,0}, {MB_NA,0} },
154      { {MB_B,11}, {MB_B,14}, {MB_NA,0}, {MB_NA,0} },
155      { {MB_B,11}, {MB_B,14}, {MB_CURR,1}, {MB_CURR,4} } },
156
157    { { {MB_A,7}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
158      { {MB_A,7}, {MB_A,13}, {MB_NA,0}, {MB_NA,0} },
159      { {MB_A,7}, {MB_CURR,2}, {MB_NA,0}, {MB_NA,0} },
160      { {MB_A,7}, {MB_CURR,2}, {MB_A,13}, {MB_CURR,8} } },
161
162    { { {MB_CURR,3}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
163      { {MB_CURR,3}, {MB_CURR,9}, {MB_NA,0}, {MB_NA,0} },
164      { {MB_CURR,3}, {MB_CURR,6}, {MB_NA,0}, {MB_NA,0} },
165      { {MB_CURR,3}, {MB_CURR,6}, {MB_CURR,9}, {MB_CURR,12} } } };
166
167
168#ifdef H264DEC_OMXDL
169
170/*------------------------------------------------------------------------------
171
172    Function: h264bsdInterPrediction
173
174        Functional description:
175          Processes one inter macroblock. Performs motion vector prediction
176          and reconstructs prediction macroblock. Writes the final macroblock
177          (prediction + residual) into the output image (currImage)
178
179        Inputs:
180          pMb           pointer to macroblock specific information
181          pMbLayer      pointer to current macroblock data from stream
182          dpb           pointer to decoded picture buffer
183          mbNum         current macroblock number
184          currImage     pointer to output image
185          data          pointer where predicted macroblock will be stored
186
187        Outputs:
188          pMb           structure is updated with current macroblock
189          currImage     current macroblock is written into image
190          data          prediction is stored here
191
192        Returns:
193          HANTRO_OK     success
194          HANTRO_NOK    error in motion vector prediction
195
196------------------------------------------------------------------------------*/
197u32 h264bsdInterPrediction(mbStorage_t *pMb, macroblockLayer_t *pMbLayer,
198    dpbStorage_t *dpb, u32 mbNum, image_t *currImage, u8 *data)
199{
200
201/* Variables */
202
203    u32 i;
204    u32 x, y;
205    u32 colAndRow;
206    subMbPartMode_e subPartMode;
207    image_t refImage;
208    u8 fillBuff[32*21 + 15 + 32];
209    u8 *pFill;
210    u32 tmp;
211/* Code */
212
213    ASSERT(pMb);
214    ASSERT(h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTER);
215    ASSERT(pMbLayer);
216
217    /* 16-byte alignment */
218    pFill = ALIGN(fillBuff, 16);
219
220    /* set row bits 15:0 */
221    colAndRow = mbNum / currImage->width;
222    /*set col to bits 31:16 */
223    colAndRow += (mbNum - colAndRow * currImage->width) << 16;
224    colAndRow <<= 4;
225
226    refImage.width = currImage->width;
227    refImage.height = currImage->height;
228
229    switch (pMb->mbType)
230    {
231        case P_Skip:
232        case P_L0_16x16:
233            if (MvPrediction16x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
234                return(HANTRO_NOK);
235            refImage.data = pMb->refAddr[0];
236            tmp = (0<<24) + (0<<16) + (16<<8) + 16;
237            h264bsdPredictSamples(data, pMb->mv, &refImage,
238                                    colAndRow, tmp, pFill);
239            break;
240
241        case P_L0_L0_16x8:
242            if ( MvPrediction16x8(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
243                return(HANTRO_NOK);
244            refImage.data = pMb->refAddr[0];
245            tmp = (0<<24) + (0<<16) + (16<<8) + 8;
246            h264bsdPredictSamples(data, pMb->mv, &refImage,
247                                    colAndRow, tmp, pFill);
248
249            refImage.data = pMb->refAddr[2];
250            tmp = (0<<24) + (8<<16) + (16<<8) + 8;
251            h264bsdPredictSamples(data, pMb->mv+8, &refImage,
252                                    colAndRow, tmp, pFill);
253            break;
254
255        case P_L0_L0_8x16:
256            if ( MvPrediction8x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
257                return(HANTRO_NOK);
258            refImage.data = pMb->refAddr[0];
259            tmp = (0<<24) + (0<<16) + (8<<8) + 16;
260            h264bsdPredictSamples(data, pMb->mv, &refImage,
261                                    colAndRow, tmp, pFill);
262            refImage.data = pMb->refAddr[1];
263            tmp = (8<<24) + (0<<16) + (8<<8) + 16;
264            h264bsdPredictSamples(data, pMb->mv+4, &refImage,
265                                    colAndRow, tmp, pFill);
266            break;
267
268        default: /* P_8x8 and P_8x8ref0 */
269            if ( MvPrediction8x8(pMb, &pMbLayer->subMbPred, dpb) != HANTRO_OK)
270                return(HANTRO_NOK);
271            for (i = 0; i < 4; i++)
272            {
273                refImage.data = pMb->refAddr[i];
274                subPartMode =
275                    h264bsdSubMbPartMode(pMbLayer->subMbPred.subMbType[i]);
276                x = i & 0x1 ? 8 : 0;
277                y = i < 2 ? 0 : 8;
278                switch (subPartMode)
279                {
280                    case MB_SP_8x8:
281                        tmp = (x<<24) + (y<<16) + (8<<8) + 8;
282                        h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
283                                                    colAndRow, tmp, pFill);
284                        break;
285
286                    case MB_SP_8x4:
287                        tmp = (x<<24) + (y<<16) + (8<<8) + 4;
288                        h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
289                                                    colAndRow, tmp, pFill);
290                        tmp = (x<<24) + ((y+4)<<16) + (8<<8) + 4;
291                        h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
292                                                    colAndRow, tmp, pFill);
293                        break;
294
295                    case MB_SP_4x8:
296                        tmp = (x<<24) + (y<<16) + (4<<8) + 8;
297                        h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
298                                                    colAndRow, tmp, pFill);
299                        tmp = ((x+4)<<24) + (y<<16) + (4<<8) + 8;
300                        h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
301                                                    colAndRow, tmp, pFill);
302                        break;
303
304                    default:
305                        tmp = (x<<24) + (y<<16) + (4<<8) + 4;
306                        h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
307                                                    colAndRow, tmp, pFill);
308                        tmp = ((x+4)<<24) + (y<<16) + (4<<8) + 4;
309                        h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
310                                                    colAndRow, tmp, pFill);
311                        tmp = (x<<24) + ((y+4)<<16) + (4<<8) + 4;
312                        h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
313                                                    colAndRow, tmp, pFill);
314                        tmp = ((x+4)<<24) + ((y+4)<<16) + (4<<8) + 4;
315                        h264bsdPredictSamples(data, pMb->mv+4*i+3, &refImage,
316                                                    colAndRow, tmp, pFill);
317                        break;
318                }
319            }
320            break;
321    }
322
323    /* if decoded flag > 1 -> mb has already been successfully decoded and
324     * written to output -> do not write again */
325    if (pMb->decoded > 1)
326        return HANTRO_OK;
327
328    return(HANTRO_OK);
329}
330
331#else /* H264DEC_OMXDL */
332
333/*------------------------------------------------------------------------------
334
335    Function: h264bsdInterPrediction
336
337        Functional description:
338          Processes one inter macroblock. Performs motion vector prediction
339          and reconstructs prediction macroblock. Writes the final macroblock
340          (prediction + residual) into the output image (currImage)
341
342        Inputs:
343          pMb           pointer to macroblock specific information
344          pMbLayer      pointer to current macroblock data from stream
345          dpb           pointer to decoded picture buffer
346          mbNum         current macroblock number
347          currImage     pointer to output image
348          data          pointer where predicted macroblock will be stored
349
350        Outputs:
351          pMb           structure is updated with current macroblock
352          currImage     current macroblock is written into image
353          data          prediction is stored here
354
355        Returns:
356          HANTRO_OK     success
357          HANTRO_NOK    error in motion vector prediction
358
359------------------------------------------------------------------------------*/
360u32 h264bsdInterPrediction(mbStorage_t *pMb, macroblockLayer_t *pMbLayer,
361    dpbStorage_t *dpb, u32 mbNum, image_t *currImage, u8 *data)
362{
363
364/* Variables */
365
366    u32 i;
367    u32 x, y;
368    u32 row, col;
369    subMbPartMode_e subPartMode;
370    image_t refImage;
371
372/* Code */
373
374    ASSERT(pMb);
375    ASSERT(h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTER);
376    ASSERT(pMbLayer);
377
378    row = mbNum / currImage->width;
379    col = mbNum - row * currImage->width;
380    row *= 16;
381    col *= 16;
382
383    refImage.width = currImage->width;
384    refImage.height = currImage->height;
385
386    switch (pMb->mbType)
387    {
388        case P_Skip:
389        case P_L0_16x16:
390            if (MvPrediction16x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
391                return(HANTRO_NOK);
392            refImage.data = pMb->refAddr[0];
393            h264bsdPredictSamples(data, pMb->mv, &refImage, col, row, 0, 0,
394                16, 16);
395            break;
396
397        case P_L0_L0_16x8:
398            if ( MvPrediction16x8(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
399                return(HANTRO_NOK);
400            refImage.data = pMb->refAddr[0];
401            h264bsdPredictSamples(data, pMb->mv, &refImage, col, row, 0, 0,
402                16, 8);
403            refImage.data = pMb->refAddr[2];
404            h264bsdPredictSamples(data, pMb->mv+8, &refImage, col, row, 0, 8,
405                16, 8);
406            break;
407
408        case P_L0_L0_8x16:
409            if ( MvPrediction8x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
410                return(HANTRO_NOK);
411            refImage.data = pMb->refAddr[0];
412            h264bsdPredictSamples(data, pMb->mv, &refImage, col, row, 0, 0,
413                8, 16);
414            refImage.data = pMb->refAddr[1];
415            h264bsdPredictSamples(data, pMb->mv+4, &refImage, col, row, 8, 0,
416                8, 16);
417            break;
418
419        default: /* P_8x8 and P_8x8ref0 */
420            if ( MvPrediction8x8(pMb, &pMbLayer->subMbPred, dpb) != HANTRO_OK)
421                return(HANTRO_NOK);
422            for (i = 0; i < 4; i++)
423            {
424                refImage.data = pMb->refAddr[i];
425                subPartMode =
426                    h264bsdSubMbPartMode(pMbLayer->subMbPred.subMbType[i]);
427                x = i & 0x1 ? 8 : 0;
428                y = i < 2 ? 0 : 8;
429                switch (subPartMode)
430                {
431                    case MB_SP_8x8:
432                        h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
433                            col, row, x, y, 8, 8);
434                        break;
435
436                    case MB_SP_8x4:
437                        h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
438                            col, row, x, y, 8, 4);
439                        h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
440                            col, row, x, y+4, 8, 4);
441                        break;
442
443                    case MB_SP_4x8:
444                        h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
445                            col, row, x, y, 4, 8);
446                        h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
447                            col, row, x+4, y, 4, 8);
448                        break;
449
450                    default:
451                        h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
452                            col, row, x, y, 4, 4);
453                        h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
454                            col, row, x+4, y, 4, 4);
455                        h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
456                            col, row, x, y+4, 4, 4);
457                        h264bsdPredictSamples(data, pMb->mv+4*i+3, &refImage,
458                            col, row, x+4, y+4, 4, 4);
459                        break;
460                }
461            }
462            break;
463    }
464
465    /* if decoded flag > 1 -> mb has already been successfully decoded and
466     * written to output -> do not write again */
467    if (pMb->decoded > 1)
468        return HANTRO_OK;
469
470    if (pMb->mbType != P_Skip)
471    {
472        h264bsdWriteOutputBlocks(currImage, mbNum, data,
473            pMbLayer->residual.level);
474    }
475    else
476    {
477        h264bsdWriteMacroblock(currImage, data);
478    }
479
480    return(HANTRO_OK);
481}
482#endif /* H264DEC_OMXDL */
483
484/*------------------------------------------------------------------------------
485
486    Function: MvPrediction16x16
487
488        Functional description:
489            Motion vector prediction for 16x16 partition mode
490
491------------------------------------------------------------------------------*/
492
493u32 MvPrediction16x16(mbStorage_t *pMb, mbPred_t *mbPred, dpbStorage_t *dpb)
494{
495
496/* Variables */
497
498    mv_t mv;
499    mv_t mvPred;
500    interNeighbour_t a[3]; /* A, B, C */
501    u32 refIndex;
502    u8 *tmp;
503    u32 *tmpMv1, *tmpMv2;
504
505/* Code */
506
507    refIndex = mbPred->refIdxL0[0];
508
509    GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 5);
510    GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 10);
511    /*lint --e(740)  Unusual pointer cast (incompatible indirect types) */
512    tmpMv1 = (u32*)(&a[0].mv); /* we test just that both MVs are zero */
513    /*lint --e(740) */
514    tmpMv2 = (u32*)(&a[1].mv); /* i.e. a[0].mv.hor == 0 && a[0].mv.ver == 0 */
515    if (pMb->mbType == P_Skip &&
516        (!a[0].available || !a[1].available ||
517         ( a[0].refIndex == 0 && ((u32)(*tmpMv1) == 0) ) ||
518         ( a[1].refIndex == 0 && ((u32)(*tmpMv2) == 0) )))
519    {
520            mv.hor = mv.ver = 0;
521    }
522    else
523    {
524        mv = mbPred->mvdL0[0];
525        GetInterNeighbour(pMb->sliceId, pMb->mbC, a+2, 10);
526        if (!a[2].available)
527        {
528            GetInterNeighbour(pMb->sliceId, pMb->mbD, a+2, 15);
529        }
530
531        GetPredictionMv(&mvPred, a, refIndex);
532
533        mv.hor += mvPred.hor;
534        mv.ver += mvPred.ver;
535
536        /* horizontal motion vector range [-2048, 2047.75] */
537        if ((u32)(i32)(mv.hor+8192) >= (16384))
538            return(HANTRO_NOK);
539
540        /* vertical motion vector range [-512, 511.75]
541         * (smaller for low levels) */
542        if ((u32)(i32)(mv.ver+2048) >= (4096))
543            return(HANTRO_NOK);
544    }
545
546    tmp = h264bsdGetRefPicData(dpb, refIndex);
547    if (tmp == NULL)
548        return(HANTRO_NOK);
549
550    pMb->mv[0] = pMb->mv[1] = pMb->mv[2] = pMb->mv[3] =
551    pMb->mv[4] = pMb->mv[5] = pMb->mv[6] = pMb->mv[7] =
552    pMb->mv[8] = pMb->mv[9] = pMb->mv[10] = pMb->mv[11] =
553    pMb->mv[12] = pMb->mv[13] = pMb->mv[14] = pMb->mv[15] = mv;
554
555    pMb->refPic[0] = refIndex;
556    pMb->refPic[1] = refIndex;
557    pMb->refPic[2] = refIndex;
558    pMb->refPic[3] = refIndex;
559    pMb->refAddr[0] = tmp;
560    pMb->refAddr[1] = tmp;
561    pMb->refAddr[2] = tmp;
562    pMb->refAddr[3] = tmp;
563
564    return(HANTRO_OK);
565
566}
567
568/*------------------------------------------------------------------------------
569
570    Function: MvPrediction16x8
571
572        Functional description:
573            Motion vector prediction for 16x8 partition mode
574
575------------------------------------------------------------------------------*/
576
577u32 MvPrediction16x8(mbStorage_t *pMb, mbPred_t *mbPred, dpbStorage_t *dpb)
578{
579
580/* Variables */
581
582    mv_t mv;
583    mv_t mvPred;
584    interNeighbour_t a[3]; /* A, B, C */
585    u32 refIndex;
586    u8 *tmp;
587
588/* Code */
589
590    mv = mbPred->mvdL0[0];
591    refIndex = mbPred->refIdxL0[0];
592
593    GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 10);
594
595    if (a[1].refIndex == refIndex)
596        mvPred = a[1].mv;
597    else
598    {
599        GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 5);
600        GetInterNeighbour(pMb->sliceId, pMb->mbC, a+2, 10);
601        if (!a[2].available)
602        {
603            GetInterNeighbour(pMb->sliceId, pMb->mbD, a+2, 15);
604        }
605
606        GetPredictionMv(&mvPred, a, refIndex);
607
608    }
609    mv.hor += mvPred.hor;
610    mv.ver += mvPred.ver;
611
612    /* horizontal motion vector range [-2048, 2047.75] */
613    if ((u32)(i32)(mv.hor+8192) >= (16384))
614        return(HANTRO_NOK);
615
616    /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
617    if ((u32)(i32)(mv.ver+2048) >= (4096))
618        return(HANTRO_NOK);
619
620    tmp = h264bsdGetRefPicData(dpb, refIndex);
621    if (tmp == NULL)
622        return(HANTRO_NOK);
623
624    pMb->mv[0] = pMb->mv[1] = pMb->mv[2] = pMb->mv[3] =
625    pMb->mv[4] = pMb->mv[5] = pMb->mv[6] = pMb->mv[7] = mv;
626    pMb->refPic[0] = refIndex;
627    pMb->refPic[1] = refIndex;
628    pMb->refAddr[0] = tmp;
629    pMb->refAddr[1] = tmp;
630
631    mv = mbPred->mvdL0[1];
632    refIndex = mbPred->refIdxL0[1];
633
634    GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 13);
635    if (a[0].refIndex == refIndex)
636        mvPred = a[0].mv;
637    else
638    {
639        a[1].available = HANTRO_TRUE;
640        a[1].refIndex = pMb->refPic[0];
641        a[1].mv = pMb->mv[0];
642
643        /* c is not available */
644        GetInterNeighbour(pMb->sliceId, pMb->mbA, a+2, 7);
645
646        GetPredictionMv(&mvPred, a, refIndex);
647
648    }
649    mv.hor += mvPred.hor;
650    mv.ver += mvPred.ver;
651
652    /* horizontal motion vector range [-2048, 2047.75] */
653    if ((u32)(i32)(mv.hor+8192) >= (16384))
654        return(HANTRO_NOK);
655
656    /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
657    if ((u32)(i32)(mv.ver+2048) >= (4096))
658        return(HANTRO_NOK);
659
660    tmp = h264bsdGetRefPicData(dpb, refIndex);
661    if (tmp == NULL)
662        return(HANTRO_NOK);
663
664    pMb->mv[8] = pMb->mv[9] = pMb->mv[10] = pMb->mv[11] =
665    pMb->mv[12] = pMb->mv[13] = pMb->mv[14] = pMb->mv[15] = mv;
666    pMb->refPic[2] = refIndex;
667    pMb->refPic[3] = refIndex;
668    pMb->refAddr[2] = tmp;
669    pMb->refAddr[3] = tmp;
670
671    return(HANTRO_OK);
672
673}
674
675/*------------------------------------------------------------------------------
676
677    Function: MvPrediction8x16
678
679        Functional description:
680            Motion vector prediction for 8x16 partition mode
681
682------------------------------------------------------------------------------*/
683
684u32 MvPrediction8x16(mbStorage_t *pMb, mbPred_t *mbPred, dpbStorage_t *dpb)
685{
686
687/* Variables */
688
689    mv_t mv;
690    mv_t mvPred;
691    interNeighbour_t a[3]; /* A, B, C */
692    u32 refIndex;
693    u8 *tmp;
694
695/* Code */
696
697    mv = mbPred->mvdL0[0];
698    refIndex = mbPred->refIdxL0[0];
699
700    GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 5);
701
702    if (a[0].refIndex == refIndex)
703        mvPred = a[0].mv;
704    else
705    {
706        GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 10);
707        GetInterNeighbour(pMb->sliceId, pMb->mbB, a+2, 14);
708        if (!a[2].available)
709        {
710            GetInterNeighbour(pMb->sliceId, pMb->mbD, a+2, 15);
711        }
712
713        GetPredictionMv(&mvPred, a, refIndex);
714
715    }
716    mv.hor += mvPred.hor;
717    mv.ver += mvPred.ver;
718
719    /* horizontal motion vector range [-2048, 2047.75] */
720    if ((u32)(i32)(mv.hor+8192) >= (16384))
721        return(HANTRO_NOK);
722
723    /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
724    if ((u32)(i32)(mv.ver+2048) >= (4096))
725        return(HANTRO_NOK);
726
727    tmp = h264bsdGetRefPicData(dpb, refIndex);
728    if (tmp == NULL)
729        return(HANTRO_NOK);
730
731    pMb->mv[0] = pMb->mv[1] = pMb->mv[2] = pMb->mv[3] =
732    pMb->mv[8] = pMb->mv[9] = pMb->mv[10] = pMb->mv[11] = mv;
733    pMb->refPic[0] = refIndex;
734    pMb->refPic[2] = refIndex;
735    pMb->refAddr[0] = tmp;
736    pMb->refAddr[2] = tmp;
737
738    mv = mbPred->mvdL0[1];
739    refIndex = mbPred->refIdxL0[1];
740
741    GetInterNeighbour(pMb->sliceId, pMb->mbC, a+2, 10);
742    if (!a[2].available)
743    {
744        GetInterNeighbour(pMb->sliceId, pMb->mbB, a+2, 11);
745    }
746    if (a[2].refIndex == refIndex)
747        mvPred = a[2].mv;
748    else
749    {
750        a[0].available = HANTRO_TRUE;
751        a[0].refIndex = pMb->refPic[0];
752        a[0].mv = pMb->mv[0];
753
754        GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 14);
755
756        GetPredictionMv(&mvPred, a, refIndex);
757
758    }
759    mv.hor += mvPred.hor;
760    mv.ver += mvPred.ver;
761
762    /* horizontal motion vector range [-2048, 2047.75] */
763    if ((u32)(i32)(mv.hor+8192) >= (16384))
764        return(HANTRO_NOK);
765
766    /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
767    if ((u32)(i32)(mv.ver+2048) >= (4096))
768        return(HANTRO_NOK);
769
770    tmp = h264bsdGetRefPicData(dpb, refIndex);
771    if (tmp == NULL)
772        return(HANTRO_NOK);
773
774    pMb->mv[4] = pMb->mv[5] = pMb->mv[6] = pMb->mv[7] =
775    pMb->mv[12] = pMb->mv[13] = pMb->mv[14] = pMb->mv[15] = mv;
776    pMb->refPic[1] = refIndex;
777    pMb->refPic[3] = refIndex;
778    pMb->refAddr[1] = tmp;
779    pMb->refAddr[3] = tmp;
780
781    return(HANTRO_OK);
782
783}
784
785/*------------------------------------------------------------------------------
786
787    Function: MvPrediction8x8
788
789        Functional description:
790            Motion vector prediction for 8x8 partition mode
791
792------------------------------------------------------------------------------*/
793
794u32 MvPrediction8x8(mbStorage_t *pMb, subMbPred_t *subMbPred, dpbStorage_t *dpb)
795{
796
797/* Variables */
798
799    u32 i, j;
800    u32 numSubMbPart;
801
802/* Code */
803
804    for (i = 0; i < 4; i++)
805    {
806        numSubMbPart = h264bsdNumSubMbPart(subMbPred->subMbType[i]);
807        pMb->refPic[i] = subMbPred->refIdxL0[i];
808        pMb->refAddr[i] = h264bsdGetRefPicData(dpb, subMbPred->refIdxL0[i]);
809        if (pMb->refAddr[i] == NULL)
810            return(HANTRO_NOK);
811        for (j = 0; j < numSubMbPart; j++)
812        {
813            if (MvPrediction(pMb, subMbPred, i, j) != HANTRO_OK)
814                return(HANTRO_NOK);
815        }
816    }
817
818    return(HANTRO_OK);
819
820}
821
822/*------------------------------------------------------------------------------
823
824    Function: MvPrediction
825
826        Functional description:
827            Perform motion vector prediction for sub-partition
828
829------------------------------------------------------------------------------*/
830
831u32 MvPrediction(mbStorage_t *pMb, subMbPred_t *subMbPred, u32 mbPartIdx,
832    u32 subMbPartIdx)
833{
834
835/* Variables */
836
837    mv_t mv, mvPred;
838    u32 refIndex;
839    subMbPartMode_e subMbPartMode;
840    const neighbour_t *n;
841    mbStorage_t *nMb;
842    interNeighbour_t a[3]; /* A, B, C */
843
844/* Code */
845
846    mv = subMbPred->mvdL0[mbPartIdx][subMbPartIdx];
847    subMbPartMode = h264bsdSubMbPartMode(subMbPred->subMbType[mbPartIdx]);
848    refIndex = subMbPred->refIdxL0[mbPartIdx];
849
850    n = N_A_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
851    nMb = h264bsdGetNeighbourMb(pMb, n->mb);
852    GetInterNeighbour(pMb->sliceId, nMb, a, n->index);
853
854    n = N_B_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
855    nMb = h264bsdGetNeighbourMb(pMb, n->mb);
856    GetInterNeighbour(pMb->sliceId, nMb, a+1, n->index);
857
858    n = N_C_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
859    nMb = h264bsdGetNeighbourMb(pMb, n->mb);
860    GetInterNeighbour(pMb->sliceId, nMb, a+2, n->index);
861
862    if (!a[2].available)
863    {
864        n = N_D_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
865        nMb = h264bsdGetNeighbourMb(pMb, n->mb);
866        GetInterNeighbour(pMb->sliceId, nMb, a+2, n->index);
867    }
868
869    GetPredictionMv(&mvPred, a, refIndex);
870
871    mv.hor += mvPred.hor;
872    mv.ver += mvPred.ver;
873
874    /* horizontal motion vector range [-2048, 2047.75] */
875    if (((u32)(i32)(mv.hor+8192) >= (16384)))
876        return(HANTRO_NOK);
877
878    /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
879    if (((u32)(i32)(mv.ver+2048) >= (4096)))
880        return(HANTRO_NOK);
881
882    switch (subMbPartMode)
883    {
884        case MB_SP_8x8:
885            pMb->mv[4*mbPartIdx] = mv;
886            pMb->mv[4*mbPartIdx + 1] = mv;
887            pMb->mv[4*mbPartIdx + 2] = mv;
888            pMb->mv[4*mbPartIdx + 3] = mv;
889            break;
890
891        case MB_SP_8x4:
892            pMb->mv[4*mbPartIdx + 2*subMbPartIdx] = mv;
893            pMb->mv[4*mbPartIdx + 2*subMbPartIdx + 1] = mv;
894            break;
895
896        case MB_SP_4x8:
897            pMb->mv[4*mbPartIdx + subMbPartIdx] = mv;
898            pMb->mv[4*mbPartIdx + subMbPartIdx + 2] = mv;
899            break;
900
901        case MB_SP_4x4:
902            pMb->mv[4*mbPartIdx + subMbPartIdx] = mv;
903            break;
904    }
905
906    return(HANTRO_OK);
907
908}
909
910/*------------------------------------------------------------------------------
911
912    Function: MedianFilter
913
914        Functional description:
915            Median filtering for motion vector prediction
916
917------------------------------------------------------------------------------*/
918
919i32 MedianFilter(i32 a, i32 b, i32 c)
920{
921
922/* Variables */
923
924    i32 max,min,med;
925
926/* Code */
927
928    max = min = med = a;
929    if (b > max)
930    {
931        max = b;
932    }
933    else if (b < min)
934    {
935        min = b;
936    }
937    if (c > max)
938    {
939        med = max;
940    }
941    else if (c < min)
942    {
943        med = min;
944    }
945    else
946    {
947        med = c;
948    }
949
950    return(med);
951}
952
953/*------------------------------------------------------------------------------
954
955    Function: GetInterNeighbour
956
957        Functional description:
958            Get availability, reference index and motion vector of a neighbour
959
960------------------------------------------------------------------------------*/
961
962void GetInterNeighbour(u32 sliceId, mbStorage_t *nMb,
963    interNeighbour_t *n, u32 index)
964{
965
966    n->available = HANTRO_FALSE;
967    n->refIndex = 0xFFFFFFFF;
968    n->mv.hor = n->mv.ver = 0;
969
970    if (nMb && (sliceId == nMb->sliceId))
971    {
972        u32 tmp;
973        mv_t tmpMv;
974
975        tmp = nMb->mbType;
976        n->available = HANTRO_TRUE;
977        /* MbPartPredMode "inlined" */
978        if (tmp <= P_8x8ref0)
979        {
980            tmpMv = nMb->mv[index];
981            tmp = nMb->refPic[index>>2];
982            n->refIndex = tmp;
983            n->mv = tmpMv;
984        }
985    }
986
987}
988
989/*------------------------------------------------------------------------------
990
991    Function: GetPredictionMv
992
993        Functional description:
994            Compute motion vector predictor based on neighbours A, B and C
995
996------------------------------------------------------------------------------*/
997
998void GetPredictionMv(mv_t *mv, interNeighbour_t *a, u32 refIndex)
999{
1000
1001    if ( a[1].available || a[2].available || !a[0].available)
1002    {
1003        u32 isA, isB, isC;
1004        isA = (a[0].refIndex == refIndex) ? HANTRO_TRUE : HANTRO_FALSE;
1005        isB = (a[1].refIndex == refIndex) ? HANTRO_TRUE : HANTRO_FALSE;
1006        isC = (a[2].refIndex == refIndex) ? HANTRO_TRUE : HANTRO_FALSE;
1007
1008        if (((u32)isA+(u32)isB+(u32)isC) != 1)
1009        {
1010            mv->hor = (i16)MedianFilter(a[0].mv.hor, a[1].mv.hor, a[2].mv.hor);
1011            mv->ver = (i16)MedianFilter(a[0].mv.ver, a[1].mv.ver, a[2].mv.ver);
1012        }
1013        else if (isA)
1014            *mv = a[0].mv;
1015        else if (isB)
1016            *mv = a[1].mv;
1017        else
1018            *mv = a[2].mv;
1019    }
1020    else
1021    {
1022        *mv = a[0].mv;
1023    }
1024
1025}
1026
1027
1028