cavs.c 27.8 KB
Newer Older
1 2 3 4
/*
 * Chinese AVS video (AVS1-P2, JiZhun profile) decoder.
 * Copyright (c) 2006  Stefan Gehrer <stefan.gehrer@gmx.de>
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13 14 15 16 17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 21
 */

Stefan Gehrer's avatar
Stefan Gehrer committed
22
/**
23
 * @file
Stefan Gehrer's avatar
Stefan Gehrer committed
24 25 26 27
 * Chinese AVS video (AVS1-P2, JiZhun profile) decoder
 * @author Stefan Gehrer <stefan.gehrer@gmx.de>
 */

28
#include "avcodec.h"
29
#include "get_bits.h"
30
#include "golomb.h"
31
#include "h264chroma.h"
32
#include "mathops.h"
33
#include "cavs.h"
34

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
static const uint8_t alpha_tab[64] = {
   0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  2,  2,  3,  3,
   4,  4,  5,  5,  6,  7,  8,  9, 10, 11, 12, 13, 15, 16, 18, 20,
  22, 24, 26, 28, 30, 33, 33, 35, 35, 36, 37, 37, 39, 39, 42, 44,
  46, 48, 50, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
};

static const uint8_t beta_tab[64] = {
   0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,
   2,  2,  3,  3,  3,  3,  4,  4,  4,  4,  5,  5,  5,  5,  6,  6,
   6,  7,  7,  7,  8,  8,  8,  9,  9, 10, 10, 11, 11, 12, 13, 14,
  15, 16, 17, 18, 19, 20, 21, 22, 23, 23, 24, 24, 25, 25, 26, 27
};

static const uint8_t tc_tab[64] = {
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
  2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
  5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9
};

/** mark block as unavailable, i.e. out of picture
    or not yet decoded */
static const cavs_vector un_mv = { 0, 0, 1, NOT_AVAIL };

static const int8_t left_modifier_l[8] = {  0, -1,  6, -1, -1, 7, 6, 7 };
static const int8_t top_modifier_l[8]  = { -1,  1,  5, -1, -1, 5, 7, 7 };
static const int8_t left_modifier_c[7] = {  5, -1,  2, -1,  6, 5, 6 };
static const int8_t top_modifier_c[7]  = {  4,  1, -1, -1,  4, 6, 6 };
64 65 66 67 68 69 70

/*****************************************************************************
 *
 * in-loop deblocking filter
 *
 ****************************************************************************/

71 72 73
static inline int get_bs(cavs_vector *mvP, cavs_vector *mvQ, int b)
{
    if ((mvP->ref == REF_INTRA) || (mvQ->ref == REF_INTRA))
74
        return 2;
75
    if ((abs(mvP->x - mvQ->x) >= 4) || (abs(mvP->y - mvQ->y) >= 4))
76
        return 1;
77
    if (b) {
Michael Niedermayer's avatar
Michael Niedermayer committed
78 79
        mvP += MV_BWD_OFFS;
        mvQ += MV_BWD_OFFS;
80
        if ((abs(mvP->x - mvQ->x) >= 4) ||  (abs(mvP->y - mvQ->y) >= 4))
Michael Niedermayer's avatar
Michael Niedermayer committed
81
            return 1;
82 83
    } else {
        if (mvP->ref != mvQ->ref)
84 85 86 87 88
            return 1;
    }
    return 0;
}

89 90 91 92
#define SET_PARAMS                                                \
    alpha = alpha_tab[av_clip(qp_avg + h->alpha_offset, 0, 63)];  \
    beta  =  beta_tab[av_clip(qp_avg + h->beta_offset,  0, 63)];  \
    tc    =    tc_tab[av_clip(qp_avg + h->alpha_offset, 0, 63)];
Stefan Gehrer's avatar
Stefan Gehrer committed
93 94 95 96 97

/**
 * in-loop deblocking filter for a single macroblock
 *
 * boundary strength (bs) mapping:
98 99 100 101 102 103 104 105
 *
 * --4---5--
 * 0   2   |
 * | 6 | 7 |
 * 1   3   |
 * ---------
 *
 */
106 107
void ff_cavs_filter(AVSContext *h, enum cavs_mb mb_type)
{
108
    uint8_t bs[8];
109 110 111 112
    int qp_avg, alpha, beta, tc;
    int i;

    /* save un-deblocked lines */
113 114 115 116 117 118 119 120 121 122 123
    h->topleft_border_y = h->top_border_y[h->mbx * 16 + 15];
    h->topleft_border_u = h->top_border_u[h->mbx * 10 + 8];
    h->topleft_border_v = h->top_border_v[h->mbx * 10 + 8];
    memcpy(&h->top_border_y[h->mbx * 16],     h->cy + 15 * h->l_stride, 16);
    memcpy(&h->top_border_u[h->mbx * 10 + 1], h->cu +  7 * h->c_stride, 8);
    memcpy(&h->top_border_v[h->mbx * 10 + 1], h->cv +  7 * h->c_stride, 8);
    for (i = 0; i < 8; i++) {
        h->left_border_y[i * 2 + 1] = *(h->cy + 15 + (i * 2 + 0) * h->l_stride);
        h->left_border_y[i * 2 + 2] = *(h->cy + 15 + (i * 2 + 1) * h->l_stride);
        h->left_border_u[i + 1]     = *(h->cu + 7  +  i          * h->c_stride);
        h->left_border_v[i + 1]     = *(h->cv + 7  +  i          * h->c_stride);
124
    }
125
    if (!h->loop_filter_disable) {
126
        /* determine bs */
127 128
        if (mb_type == I_8X8)
            memset(bs, 2, 8);
Michael Niedermayer's avatar
Michael Niedermayer committed
129
        else{
130 131
            memset(bs, 0, 8);
            if (ff_cavs_partition_flags[mb_type] & SPLITV) {
Michael Niedermayer's avatar
Michael Niedermayer committed
132 133
                bs[2] = get_bs(&h->mv[MV_FWD_X0], &h->mv[MV_FWD_X1], mb_type > P_8X8);
                bs[3] = get_bs(&h->mv[MV_FWD_X2], &h->mv[MV_FWD_X3], mb_type > P_8X8);
134
            }
135
            if (ff_cavs_partition_flags[mb_type] & SPLITH) {
Michael Niedermayer's avatar
Michael Niedermayer committed
136 137 138 139 140 141 142
                bs[6] = get_bs(&h->mv[MV_FWD_X0], &h->mv[MV_FWD_X2], mb_type > P_8X8);
                bs[7] = get_bs(&h->mv[MV_FWD_X1], &h->mv[MV_FWD_X3], mb_type > P_8X8);
            }
            bs[0] = get_bs(&h->mv[MV_FWD_A1], &h->mv[MV_FWD_X0], mb_type > P_8X8);
            bs[1] = get_bs(&h->mv[MV_FWD_A3], &h->mv[MV_FWD_X2], mb_type > P_8X8);
            bs[4] = get_bs(&h->mv[MV_FWD_B2], &h->mv[MV_FWD_X0], mb_type > P_8X8);
            bs[5] = get_bs(&h->mv[MV_FWD_B3], &h->mv[MV_FWD_X1], mb_type > P_8X8);
143
        }
144 145
        if (AV_RN64(bs)) {
            if (h->flags & A_AVAIL) {
146 147
                qp_avg = (h->qp + h->left_qp + 1) >> 1;
                SET_PARAMS;
148 149 150
                h->cdsp.cavs_filter_lv(h->cy, h->l_stride, alpha, beta, tc, bs[0], bs[1]);
                h->cdsp.cavs_filter_cv(h->cu, h->c_stride, alpha, beta, tc, bs[0], bs[1]);
                h->cdsp.cavs_filter_cv(h->cv, h->c_stride, alpha, beta, tc, bs[0], bs[1]);
151 152 153
            }
            qp_avg = h->qp;
            SET_PARAMS;
154 155
            h->cdsp.cavs_filter_lv(h->cy + 8,               h->l_stride, alpha, beta, tc, bs[2], bs[3]);
            h->cdsp.cavs_filter_lh(h->cy + 8 * h->l_stride, h->l_stride, alpha, beta, tc, bs[6], bs[7]);
156

157
            if (h->flags & B_AVAIL) {
158 159
                qp_avg = (h->qp + h->top_qp[h->mbx] + 1) >> 1;
                SET_PARAMS;
160 161 162
                h->cdsp.cavs_filter_lh(h->cy, h->l_stride, alpha, beta, tc, bs[4], bs[5]);
                h->cdsp.cavs_filter_ch(h->cu, h->c_stride, alpha, beta, tc, bs[4], bs[5]);
                h->cdsp.cavs_filter_ch(h->cv, h->c_stride, alpha, beta, tc, bs[4], bs[5]);
163 164 165
            }
        }
    }
166
    h->left_qp        = h->qp;
167 168 169 170 171 172 173 174 175 176 177
    h->top_qp[h->mbx] = h->qp;
}

#undef SET_PARAMS

/*****************************************************************************
 *
 * spatial intra prediction
 *
 ****************************************************************************/

178
void ff_cavs_load_intra_pred_luma(AVSContext *h, uint8_t *top,
179 180
                                  uint8_t **left, int block)
{
181 182
    int i;

183
    switch (block) {
184
    case 0:
185
        *left               = h->left_border_y;
186
        h->left_border_y[0] = h->left_border_y[1];
187 188
        memset(&h->left_border_y[17], h->left_border_y[16], 9);
        memcpy(&top[1], &h->top_border_y[h->mbx * 16], 16);
189
        top[17] = top[16];
190 191
        top[0]  = top[1];
        if ((h->flags & A_AVAIL) && (h->flags & B_AVAIL))
192 193 194 195
            h->left_border_y[0] = top[0] = h->topleft_border_y;
        break;
    case 1:
        *left = h->intern_border_y;
196 197 198
        for (i = 0; i < 8; i++)
            h->intern_border_y[i + 1] = *(h->cy + 7 + i * h->l_stride);
        memset(&h->intern_border_y[9], h->intern_border_y[8], 9);
199
        h->intern_border_y[0] = h->intern_border_y[1];
200 201 202
        memcpy(&top[1], &h->top_border_y[h->mbx * 16 + 8], 8);
        if (h->flags & C_AVAIL)
            memcpy(&top[9], &h->top_border_y[(h->mbx + 1) * 16], 8);
203
        else
204
            memset(&top[9], top[8], 9);
205
        top[17] = top[16];
206 207 208
        top[0]  = top[1];
        if (h->flags & B_AVAIL)
            h->intern_border_y[0] = top[0] = h->top_border_y[h->mbx * 16 + 7];
209 210 211
        break;
    case 2:
        *left = &h->left_border_y[8];
212
        memcpy(&top[1], h->cy + 7 * h->l_stride, 16);
213
        top[17] = top[16];
214 215
        top[0]  = top[1];
        if (h->flags & A_AVAIL)
216 217 218 219
            top[0] = h->left_border_y[8];
        break;
    case 3:
        *left = &h->intern_border_y[8];
220 221 222 223 224
        for (i = 0; i < 8; i++)
            h->intern_border_y[i + 9] = *(h->cy + 7 + (i + 8) * h->l_stride);
        memset(&h->intern_border_y[17], h->intern_border_y[16], 9);
        memcpy(&top[0], h->cy + 7 + 7 * h->l_stride, 9);
        memset(&top[9], top[8], 9);
225 226 227 228
        break;
    }
}

229 230
void ff_cavs_load_intra_pred_chroma(AVSContext *h)
{
231 232 233
    /* extend borders by one pixel */
    h->left_border_u[9] = h->left_border_u[8];
    h->left_border_v[9] = h->left_border_v[8];
234 235 236 237 238
    h->top_border_u[h->mbx * 10 + 9] = h->top_border_u[h->mbx * 10 + 8];
    h->top_border_v[h->mbx * 10 + 9] = h->top_border_v[h->mbx * 10 + 8];
    if (h->mbx && h->mby) {
        h->top_border_u[h->mbx * 10] = h->left_border_u[0] = h->topleft_border_u;
        h->top_border_v[h->mbx * 10] = h->left_border_v[0] = h->topleft_border_v;
239 240 241
    } else {
        h->left_border_u[0] = h->left_border_u[1];
        h->left_border_v[0] = h->left_border_v[1];
242 243
        h->top_border_u[h->mbx * 10] = h->top_border_u[h->mbx * 10 + 1];
        h->top_border_v[h->mbx * 10] = h->top_border_v[h->mbx * 10 + 1];
244 245 246
    }
}

247 248
static void intra_pred_vert(uint8_t *d,uint8_t *top,uint8_t *left,int stride)
{
249
    int y;
250
    uint64_t a = AV_RN64(&top[1]);
251 252
    for (y = 0; y < 8; y++) {
        *((uint64_t *)(d + y * stride)) = a;
253 254 255
    }
}

256 257
static void intra_pred_horiz(uint8_t *d,uint8_t *top,uint8_t *left,int stride)
{
258 259
    int y;
    uint64_t a;
260 261 262
    for (y = 0; y < 8; y++) {
        a = left[y + 1] * 0x0101010101010101ULL;
        *((uint64_t *)(d + y * stride)) = a;
263 264 265
    }
}

266 267
static void intra_pred_dc_128(uint8_t *d,uint8_t *top,uint8_t *left,int stride)
{
268 269
    int y;
    uint64_t a = 0x8080808080808080ULL;
270 271
    for (y = 0; y < 8; y++)
        *((uint64_t *)(d + y * stride)) = a;
272 273
}

274 275 276
static void intra_pred_plane(uint8_t *d,uint8_t *top,uint8_t *left,int stride)
{
    int x, y, ia;
277 278
    int ih = 0;
    int iv = 0;
279
    uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
280

281 282 283
    for (x = 0; x < 4; x++) {
        ih += (x + 1) * (top [5 + x] - top [3 - x]);
        iv += (x + 1) * (left[5 + x] - left[3 - x]);
284
    }
285 286 287 288 289 290
    ia = (top[8] + left[8]) << 4;
    ih = (17 * ih + 16) >> 5;
    iv = (17 * iv + 16) >> 5;
    for (y = 0; y < 8; y++)
        for (x = 0; x < 8; x++)
            d[y * stride + x] = cm[(ia + (x - 3) * ih + (y - 3) * iv + 16) >> 5];
291 292 293
}

#define LOWPASS(ARRAY,INDEX)                                            \
294
    ((ARRAY[(INDEX) - 1] + 2 * ARRAY[(INDEX)] + ARRAY[(INDEX) + 1] + 2) >> 2)
295

296 297 298 299 300 301
static void intra_pred_lp(uint8_t *d,uint8_t *top,uint8_t *left,int stride)
{
    int x, y;
    for (y = 0; y < 8; y++)
        for (x = 0; x < 8; x++)
            d[y * stride + x] = (LOWPASS(top, x + 1) + LOWPASS(left, y + 1)) >> 1;
302 303
}

304 305 306 307 308 309
static void intra_pred_down_left(uint8_t *d,uint8_t *top,uint8_t *left,int stride)
{
    int x, y;
    for (y = 0; y < 8; y++)
        for (x = 0; x < 8; x++)
            d[y * stride + x] = (LOWPASS(top, x + y + 2) + LOWPASS(left, x + y + 2)) >> 1;
310 311
}

312 313 314 315 316 317 318 319 320
static void intra_pred_down_right(uint8_t *d,uint8_t *top,uint8_t *left,int stride)
{
    int x, y;
    for (y = 0; y < 8; y++)
        for (x = 0; x < 8; x++)
            if (x == y)
                d[y * stride + x] = (left[1] + 2 * top[0] + top[1] + 2) >> 2;
            else if (x > y)
                d[y * stride + x] = LOWPASS(top, x - y);
321
            else
322
                d[y * stride + x] = LOWPASS(left, y - x);
323 324
}

325 326 327 328 329 330
static void intra_pred_lp_left(uint8_t *d,uint8_t *top,uint8_t *left,int stride)
{
    int x, y;
    for (y = 0; y < 8; y++)
        for (x = 0; x < 8; x++)
            d[y * stride + x] = LOWPASS(left, y + 1);
331 332
}

333 334 335 336 337 338
static void intra_pred_lp_top(uint8_t *d,uint8_t *top,uint8_t *left,int stride)
{
    int x, y;
    for (y = 0; y < 8; y++)
        for (x = 0; x < 8; x++)
            d[y * stride + x] = LOWPASS(top, x + 1);
339 340 341 342
}

#undef LOWPASS

343 344 345
static inline void modify_pred(const int8_t *mod_table, int *mode)
{
    *mode = mod_table[*mode];
346
    if (*mode < 0) {
347 348 349 350 351
        av_log(NULL, AV_LOG_ERROR, "Illegal intra prediction mode\n");
        *mode = 0;
    }
}

352 353
void ff_cavs_modify_mb_i(AVSContext *h, int *pred_mode_uv)
{
354 355 356
    /* save pred modes before they get modified */
    h->pred_mode_Y[3] =  h->pred_mode_Y[5];
    h->pred_mode_Y[6] =  h->pred_mode_Y[8];
357 358
    h->top_pred_Y[h->mbx * 2 + 0] = h->pred_mode_Y[7];
    h->top_pred_Y[h->mbx * 2 + 1] = h->pred_mode_Y[8];
359 360

    /* modify pred modes according to availability of neighbour samples */
361
    if (!(h->flags & A_AVAIL)) {
362 363 364
        modify_pred(left_modifier_l, &h->pred_mode_Y[4]);
        modify_pred(left_modifier_l, &h->pred_mode_Y[7]);
        modify_pred(left_modifier_c, pred_mode_uv);
365
    }
366
    if (!(h->flags & B_AVAIL)) {
367 368 369
        modify_pred(top_modifier_l, &h->pred_mode_Y[4]);
        modify_pred(top_modifier_l, &h->pred_mode_Y[5]);
        modify_pred(top_modifier_c, pred_mode_uv);
370 371 372
    }
}

373 374 375 376 377 378
/*****************************************************************************
 *
 * motion compensation
 *
 ****************************************************************************/

379
static inline void mc_dir_part(AVSContext *h, AVFrame *pic,
Aneesh Dogra's avatar
Aneesh Dogra committed
380 381 382 383 384
                               int chroma_height,int delta,int list,uint8_t *dest_y,
                               uint8_t *dest_cb,uint8_t *dest_cr,int src_x_offset,
                               int src_y_offset,qpel_mc_func *qpix_op,
                               h264_chroma_mc_func chroma_op,cavs_vector *mv)
{
385 386 387
    const int mx= mv->x + src_x_offset*8;
    const int my= mv->y + src_y_offset*8;
    const int luma_xy= (mx&3) + ((my&3)<<2);
388 389 390 391
    uint8_t * src_y  = pic->data[0] + (mx >> 2) + (my >> 2) * h->l_stride;
    uint8_t * src_cb = pic->data[1] + (mx >> 3) + (my >> 3) * h->c_stride;
    uint8_t * src_cr = pic->data[2] + (mx >> 3) + (my >> 3) * h->c_stride;
    int extra_width = 0;
392 393 394 395 396 397 398
    int extra_height= extra_width;
    int emu=0;
    const int full_mx= mx>>2;
    const int full_my= my>>2;
    const int pic_width  = 16*h->mb_width;
    const int pic_height = 16*h->mb_height;

399
    if (!pic->data[0])
400 401 402 403 404 405 406 407
        return;
    if(mx&7) extra_width -= 3;
    if(my&7) extra_height -= 3;

    if(   full_mx < 0-extra_width
          || full_my < 0-extra_height
          || full_mx + 16/*FIXME*/ > pic_width + extra_width
          || full_my + 16/*FIXME*/ > pic_height + extra_height){
408
        h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src_y - 2 - 2*h->l_stride, h->l_stride,
409
                            16+5, 16+5/*FIXME*/, full_mx-2, full_my-2, pic_width, pic_height);
410
        src_y= h->edge_emu_buffer + 2 + 2*h->l_stride;
411 412 413 414 415 416
        emu=1;
    }

    qpix_op[luma_xy](dest_y, src_y, h->l_stride); //FIXME try variable height perhaps?

    if(emu){
417
        h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src_cb, h->c_stride,
418
                            9, 9/*FIXME*/, (mx>>3), (my>>3), pic_width>>1, pic_height>>1);
419
        src_cb= h->edge_emu_buffer;
420 421 422 423
    }
    chroma_op(dest_cb, src_cb, h->c_stride, chroma_height, mx&7, my&7);

    if(emu){
424
        h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src_cr, h->c_stride,
425
                            9, 9/*FIXME*/, (mx>>3), (my>>3), pic_width>>1, pic_height>>1);
426
        src_cr= h->edge_emu_buffer;
427 428 429 430
    }
    chroma_op(dest_cr, src_cr, h->c_stride, chroma_height, mx&7, my&7);
}

Aneesh Dogra's avatar
Aneesh Dogra committed
431 432 433 434 435 436
static inline void mc_part_std(AVSContext *h,int chroma_height,int delta,
                               uint8_t *dest_y,uint8_t *dest_cb,uint8_t *dest_cr,
                               int x_offset, int y_offset,qpel_mc_func *qpix_put,
                               h264_chroma_mc_func chroma_put,qpel_mc_func *qpix_avg,
                               h264_chroma_mc_func chroma_avg, cavs_vector *mv)
{
437 438 439 440 441 442 443 444 445 446
    qpel_mc_func *qpix_op=  qpix_put;
    h264_chroma_mc_func chroma_op= chroma_put;

    dest_y  += 2*x_offset + 2*y_offset*h->l_stride;
    dest_cb +=   x_offset +   y_offset*h->c_stride;
    dest_cr +=   x_offset +   y_offset*h->c_stride;
    x_offset += 8*h->mbx;
    y_offset += 8*h->mby;

    if(mv->ref >= 0){
447
        AVFrame *ref = h->DPB[mv->ref].f;
Aneesh Dogra's avatar
Aneesh Dogra committed
448
        mc_dir_part(h, ref, chroma_height, delta, 0,
449 450 451 452 453 454 455 456
                    dest_y, dest_cb, dest_cr, x_offset, y_offset,
                    qpix_op, chroma_op, mv);

        qpix_op=  qpix_avg;
        chroma_op= chroma_avg;
    }

    if((mv+MV_BWD_OFFS)->ref >= 0){
457
        AVFrame *ref = h->DPB[0].f;
Aneesh Dogra's avatar
Aneesh Dogra committed
458
        mc_dir_part(h, ref, chroma_height, delta, 1,
459 460 461 462 463
                    dest_y, dest_cb, dest_cr, x_offset, y_offset,
                    qpix_op, chroma_op, mv+MV_BWD_OFFS);
    }
}

464
void ff_cavs_inter(AVSContext *h, enum cavs_mb mb_type) {
465
    if(ff_cavs_partition_flags[mb_type] == 0){ // 16x16
Aneesh Dogra's avatar
Aneesh Dogra committed
466
        mc_part_std(h, 8, 0, h->cy, h->cu, h->cv, 0, 0,
467
                h->cdsp.put_cavs_qpel_pixels_tab[0],
468
                h->h264chroma.put_h264_chroma_pixels_tab[0],
469
                h->cdsp.avg_cavs_qpel_pixels_tab[0],
470 471
                h->h264chroma.avg_h264_chroma_pixels_tab[0],
                &h->mv[MV_FWD_X0]);
Michael Niedermayer's avatar
Michael Niedermayer committed
472
    }else{
Aneesh Dogra's avatar
Aneesh Dogra committed
473
        mc_part_std(h, 4, 0, h->cy, h->cu, h->cv, 0, 0,
474
                h->cdsp.put_cavs_qpel_pixels_tab[1],
475
                h->h264chroma.put_h264_chroma_pixels_tab[1],
476
                h->cdsp.avg_cavs_qpel_pixels_tab[1],
477 478
                h->h264chroma.avg_h264_chroma_pixels_tab[1],
                &h->mv[MV_FWD_X0]);
Aneesh Dogra's avatar
Aneesh Dogra committed
479
        mc_part_std(h, 4, 0, h->cy, h->cu, h->cv, 4, 0,
480
                h->cdsp.put_cavs_qpel_pixels_tab[1],
481
                h->h264chroma.put_h264_chroma_pixels_tab[1],
482
                h->cdsp.avg_cavs_qpel_pixels_tab[1],
483 484
                h->h264chroma.avg_h264_chroma_pixels_tab[1],
                &h->mv[MV_FWD_X1]);
Aneesh Dogra's avatar
Aneesh Dogra committed
485
        mc_part_std(h, 4, 0, h->cy, h->cu, h->cv, 0, 4,
486
                h->cdsp.put_cavs_qpel_pixels_tab[1],
487
                h->h264chroma.put_h264_chroma_pixels_tab[1],
488
                h->cdsp.avg_cavs_qpel_pixels_tab[1],
489 490
                h->h264chroma.avg_h264_chroma_pixels_tab[1],
                &h->mv[MV_FWD_X2]);
Aneesh Dogra's avatar
Aneesh Dogra committed
491
        mc_part_std(h, 4, 0, h->cy, h->cu, h->cv, 4, 4,
492
                h->cdsp.put_cavs_qpel_pixels_tab[1],
493
                h->h264chroma.put_h264_chroma_pixels_tab[1],
494
                h->cdsp.avg_cavs_qpel_pixels_tab[1],
495 496
                h->h264chroma.avg_h264_chroma_pixels_tab[1],
                &h->mv[MV_FWD_X3]);
497
    }
498 499 500 501 502 503 504 505
}

/*****************************************************************************
 *
 * motion vector prediction
 *
 ****************************************************************************/

506
static inline void scale_mv(AVSContext *h, int *d_x, int *d_y, cavs_vector *src, int distp) {
507 508 509 510 511 512
    int den = h->scale_den[src->ref];

    *d_x = (src->x*distp*den + 256 + (src->x>>31)) >> 9;
    *d_y = (src->y*distp*den + 256 + (src->y>>31)) >> 9;
}

513 514
static inline void mv_pred_median(AVSContext *h, cavs_vector *mvP,
                        cavs_vector *mvA, cavs_vector *mvB, cavs_vector *mvC) {
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
    int ax, ay, bx, by, cx, cy;
    int len_ab, len_bc, len_ca, len_mid;

    /* scale candidates according to their temporal span */
    scale_mv(h, &ax, &ay, mvA, mvP->dist);
    scale_mv(h, &bx, &by, mvB, mvP->dist);
    scale_mv(h, &cx, &cy, mvC, mvP->dist);
    /* find the geometrical median of the three candidates */
    len_ab = abs(ax - bx) + abs(ay - by);
    len_bc = abs(bx - cx) + abs(by - cy);
    len_ca = abs(cx - ax) + abs(cy - ay);
    len_mid = mid_pred(len_ab, len_bc, len_ca);
    if(len_mid == len_ab) {
        mvP->x = cx;
        mvP->y = cy;
    } else if(len_mid == len_bc) {
        mvP->x = ax;
        mvP->y = ay;
    } else {
        mvP->x = bx;
        mvP->y = by;
    }
}

539 540
void ff_cavs_mv(AVSContext *h, enum cavs_mv_loc nP, enum cavs_mv_loc nC,
                enum cavs_mv_pred mode, enum cavs_block size, int ref) {
541 542 543 544 545
    cavs_vector *mvP = &h->mv[nP];
    cavs_vector *mvA = &h->mv[nP-1];
    cavs_vector *mvB = &h->mv[nP-4];
    cavs_vector *mvC = &h->mv[nC];
    const cavs_vector *mvP2 = NULL;
546 547 548 549 550

    mvP->ref = ref;
    mvP->dist = h->dist[mvP->ref];
    if(mvC->ref == NOT_AVAIL)
        mvC = &h->mv[nP-5]; // set to top-left (mvD)
551 552
    if((mode == MV_PRED_PSKIP) &&
       ((mvA->ref == NOT_AVAIL) || (mvB->ref == NOT_AVAIL) ||
553
           ((mvA->x | mvA->y | mvA->ref) == 0)  ||
554
           ((mvB->x | mvB->y | mvB->ref) == 0) )) {
555
        mvP2 = &un_mv;
556
    /* if there is only one suitable candidate, take it */
557
    } else if((mvA->ref >= 0) && (mvB->ref < 0) && (mvC->ref < 0)) {
Michael Niedermayer's avatar
Michael Niedermayer committed
558
        mvP2= mvA;
559
    } else if((mvA->ref < 0) && (mvB->ref >= 0) && (mvC->ref < 0)) {
Michael Niedermayer's avatar
Michael Niedermayer committed
560
        mvP2= mvB;
561
    } else if((mvA->ref < 0) && (mvB->ref < 0) && (mvC->ref >= 0)) {
Michael Niedermayer's avatar
Michael Niedermayer committed
562 563 564 565 566 567 568
        mvP2= mvC;
    } else if(mode == MV_PRED_LEFT     && mvA->ref == ref){
        mvP2= mvA;
    } else if(mode == MV_PRED_TOP      && mvB->ref == ref){
        mvP2= mvB;
    } else if(mode == MV_PRED_TOPRIGHT && mvC->ref == ref){
        mvP2= mvC;
569
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
570 571 572 573 574 575
    if(mvP2){
        mvP->x = mvP2->x;
        mvP->y = mvP2->y;
    }else
        mv_pred_median(h, mvP, mvA, mvB, mvC);

576
    if(mode < MV_PRED_PSKIP) {
577 578
        mvP->x += get_se_golomb(&h->gb);
        mvP->y += get_se_golomb(&h->gb);
579 580 581 582
    }
    set_mvs(mvP,size);
}

583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
/*****************************************************************************
 *
 * macroblock level
 *
 ****************************************************************************/

/**
 * initialise predictors for motion vectors and intra prediction
 */
void ff_cavs_init_mb(AVSContext *h) {
    int i;

    /* copy predictors from top line (MB B and C) into cache */
    for(i=0;i<3;i++) {
        h->mv[MV_FWD_B2+i] = h->top_mv[0][h->mbx*2+i];
        h->mv[MV_BWD_B2+i] = h->top_mv[1][h->mbx*2+i];
    }
    h->pred_mode_Y[1] = h->top_pred_Y[h->mbx*2+0];
    h->pred_mode_Y[2] = h->top_pred_Y[h->mbx*2+1];
    /* clear top predictors if MB B is not available */
    if(!(h->flags & B_AVAIL)) {
604 605 606 607
        h->mv[MV_FWD_B2] = un_mv;
        h->mv[MV_FWD_B3] = un_mv;
        h->mv[MV_BWD_B2] = un_mv;
        h->mv[MV_BWD_B3] = un_mv;
608 609 610 611 612 613 614 615 616
        h->pred_mode_Y[1] = h->pred_mode_Y[2] = NOT_AVAIL;
        h->flags &= ~(C_AVAIL|D_AVAIL);
    } else if(h->mbx) {
        h->flags |= D_AVAIL;
    }
    if(h->mbx == h->mb_width-1) //MB C not available
        h->flags &= ~C_AVAIL;
    /* clear top-right predictors if MB C is not available */
    if(!(h->flags & C_AVAIL)) {
617 618
        h->mv[MV_FWD_C2] = un_mv;
        h->mv[MV_BWD_C2] = un_mv;
619 620 621
    }
    /* clear top-left predictors if MB D is not available */
    if(!(h->flags & D_AVAIL)) {
622 623
        h->mv[MV_FWD_D3] = un_mv;
        h->mv[MV_BWD_D3] = un_mv;
624 625 626 627 628 629
    }
}

/**
 * save predictors for later macroblocks and increase
 * macroblock address
630
 * @return 0 if end of frame is reached, 1 otherwise
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
 */
int ff_cavs_next_mb(AVSContext *h) {
    int i;

    h->flags |= A_AVAIL;
    h->cy += 16;
    h->cu += 8;
    h->cv += 8;
    /* copy mvs as predictors to the left */
    for(i=0;i<=20;i+=4)
        h->mv[i] = h->mv[i+2];
    /* copy bottom mvs from cache to top line */
    h->top_mv[0][h->mbx*2+0] = h->mv[MV_FWD_X2];
    h->top_mv[0][h->mbx*2+1] = h->mv[MV_FWD_X3];
    h->top_mv[1][h->mbx*2+0] = h->mv[MV_BWD_X2];
    h->top_mv[1][h->mbx*2+1] = h->mv[MV_BWD_X3];
    /* next MB address */
648
    h->mbidx++;
649 650 651 652 653 654 655
    h->mbx++;
    if(h->mbx == h->mb_width) { //new mb line
        h->flags = B_AVAIL|C_AVAIL;
        /* clear left pred_modes */
        h->pred_mode_Y[3] = h->pred_mode_Y[6] = NOT_AVAIL;
        /* clear left mv predictors */
        for(i=0;i<=20;i+=4)
656
            h->mv[i] = un_mv;
657 658 659
        h->mbx = 0;
        h->mby++;
        /* re-calculate sample pointers */
660 661 662
        h->cy = h->cur.f->data[0] + h->mby * 16 * h->l_stride;
        h->cu = h->cur.f->data[1] + h->mby *  8 * h->c_stride;
        h->cv = h->cur.f->data[2] + h->mby *  8 * h->c_stride;
663 664 665 666 667 668 669
        if(h->mby == h->mb_height) { //frame end
            return 0;
        }
    }
    return 1;
}

670 671 672 673 674 675
/*****************************************************************************
 *
 * frame level
 *
 ****************************************************************************/

676
int ff_cavs_init_pic(AVSContext *h) {
677 678 679 680
    int i;

    /* clear some predictors */
    for(i=0;i<=20;i+=4)
681
        h->mv[i] = un_mv;
682
    h->mv[MV_BWD_X0] = ff_cavs_dir_mv;
683
    set_mvs(&h->mv[MV_BWD_X0], BLK_16X16);
684
    h->mv[MV_FWD_X0] = ff_cavs_dir_mv;
685 686
    set_mvs(&h->mv[MV_FWD_X0], BLK_16X16);
    h->pred_mode_Y[3] = h->pred_mode_Y[6] = NOT_AVAIL;
687 688 689 690 691
    h->cy           = h->cur.f->data[0];
    h->cu           = h->cur.f->data[1];
    h->cv           = h->cur.f->data[2];
    h->l_stride     = h->cur.f->linesize[0];
    h->c_stride     = h->cur.f->linesize[1];
692 693
    h->luma_scan[2] = 8*h->l_stride;
    h->luma_scan[3] = 8*h->l_stride+8;
694
    h->mbx = h->mby = h->mbidx = 0;
695
    h->flags = 0;
696 697

    return 0;
698 699 700 701 702 703 704 705
}

/*****************************************************************************
 *
 * headers and interface
 *
 ****************************************************************************/

Stefan Gehrer's avatar
Stefan Gehrer committed
706 707 708 709 710
/**
 * some predictions require data from the top-neighbouring macroblock.
 * this data has to be stored for one complete row of macroblocks
 * and this storage space is allocated here
 */
711
void ff_cavs_init_top_lines(AVSContext *h) {
712
    /* alloc top line of predictors */
713 714 715 716 717 718 719
    h->top_qp       = av_mallocz( h->mb_width);
    h->top_mv[0]    = av_mallocz((h->mb_width*2+1)*sizeof(cavs_vector));
    h->top_mv[1]    = av_mallocz((h->mb_width*2+1)*sizeof(cavs_vector));
    h->top_pred_Y   = av_mallocz( h->mb_width*2*sizeof(*h->top_pred_Y));
    h->top_border_y = av_mallocz((h->mb_width+1)*16);
    h->top_border_u = av_mallocz( h->mb_width * 10);
    h->top_border_v = av_mallocz( h->mb_width * 10);
720 721

    /* alloc space for co-located MVs and types */
722 723
    h->col_mv       = av_mallocz( h->mb_width*h->mb_height*4*sizeof(cavs_vector));
    h->col_type_base = av_mallocz(h->mb_width*h->mb_height);
Diego Biurrun's avatar
Diego Biurrun committed
724
    h->block        = av_mallocz(64*sizeof(int16_t));
725 726
}

727
av_cold int ff_cavs_init(AVCodecContext *avctx) {
Måns Rullgård's avatar
Måns Rullgård committed
728
    AVSContext *h = avctx->priv_data;
729

730
    ff_dsputil_init(&h->dsp, avctx);
731
    ff_h264chroma_init(&h->h264chroma, 8);
732
    ff_videodsp_init(&h->vdsp, 8);
733
    ff_cavsdsp_init(&h->cdsp, avctx);
734 735 736
    ff_init_scantable_permutation(h->dsp.idct_permutation,
                                  h->cdsp.idct_perm);
    ff_init_scantable(h->dsp.idct_permutation, &h->scantable, ff_zigzag_direct);
737

738
    h->avctx = avctx;
739
    avctx->pix_fmt= AV_PIX_FMT_YUV420P;
740

741 742 743
    h->cur.f    = av_frame_alloc();
    h->DPB[0].f = av_frame_alloc();
    h->DPB[1].f = av_frame_alloc();
744 745 746 747 748
    if (!h->cur.f || !h->DPB[0].f || !h->DPB[1].f) {
        ff_cavs_end(avctx);
        return AVERROR(ENOMEM);
    }

749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
    h->luma_scan[0] = 0;
    h->luma_scan[1] = 8;
    h->intra_pred_l[      INTRA_L_VERT] = intra_pred_vert;
    h->intra_pred_l[     INTRA_L_HORIZ] = intra_pred_horiz;
    h->intra_pred_l[        INTRA_L_LP] = intra_pred_lp;
    h->intra_pred_l[ INTRA_L_DOWN_LEFT] = intra_pred_down_left;
    h->intra_pred_l[INTRA_L_DOWN_RIGHT] = intra_pred_down_right;
    h->intra_pred_l[   INTRA_L_LP_LEFT] = intra_pred_lp_left;
    h->intra_pred_l[    INTRA_L_LP_TOP] = intra_pred_lp_top;
    h->intra_pred_l[    INTRA_L_DC_128] = intra_pred_dc_128;
    h->intra_pred_c[        INTRA_C_LP] = intra_pred_lp;
    h->intra_pred_c[     INTRA_C_HORIZ] = intra_pred_horiz;
    h->intra_pred_c[      INTRA_C_VERT] = intra_pred_vert;
    h->intra_pred_c[     INTRA_C_PLANE] = intra_pred_plane;
    h->intra_pred_c[   INTRA_C_LP_LEFT] = intra_pred_lp_left;
    h->intra_pred_c[    INTRA_C_LP_TOP] = intra_pred_lp_top;
    h->intra_pred_c[    INTRA_C_DC_128] = intra_pred_dc_128;
766 767
    h->mv[ 7] = un_mv;
    h->mv[19] = un_mv;
768 769 770
    return 0;
}

771
av_cold int ff_cavs_end(AVCodecContext *avctx) {
Måns Rullgård's avatar
Måns Rullgård committed
772
    AVSContext *h = avctx->priv_data;
773

774 775 776
    av_frame_free(&h->cur.f);
    av_frame_free(&h->DPB[0].f);
    av_frame_free(&h->DPB[1].f);
Michael Niedermayer's avatar
Michael Niedermayer committed
777

778 779 780 781 782 783 784 785 786
    av_free(h->top_qp);
    av_free(h->top_mv[0]);
    av_free(h->top_mv[1]);
    av_free(h->top_pred_Y);
    av_free(h->top_border_y);
    av_free(h->top_border_u);
    av_free(h->top_border_v);
    av_free(h->col_mv);
    av_free(h->col_type_base);
787
    av_free(h->block);
788
    av_freep(&h->edge_emu_buffer);
789 790
    return 0;
}