xref: /third_party/ffmpeg/libavcodec/vc1_mc.c (revision cabdff1a)
1/*
2 * VC-1 and WMV3 decoder
3 * Copyright (c) 2011 Mashiat Sarker Shakkhar
4 * Copyright (c) 2006-2007 Konstantin Shishkov
5 * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24/**
25 * @file
26 * VC-1 and WMV3 block decoding routines
27 */
28
29#include "avcodec.h"
30#include "h264chroma.h"
31#include "mathops.h"
32#include "mpegvideo.h"
33#include "vc1.h"
34
35static av_always_inline void vc1_scale_luma(uint8_t *srcY,
36                                            int k, int linesize)
37{
38    int i, j;
39    for (j = 0; j < k; j++) {
40        for (i = 0; i < k; i++)
41            srcY[i] = ((srcY[i] - 128) >> 1) + 128;
42        srcY += linesize;
43    }
44}
45
46static av_always_inline void vc1_scale_chroma(uint8_t *srcU, uint8_t *srcV,
47                                              int k, int uvlinesize)
48{
49    int i, j;
50    for (j = 0; j < k; j++) {
51        for (i = 0; i < k; i++) {
52            srcU[i] = ((srcU[i] - 128) >> 1) + 128;
53            srcV[i] = ((srcV[i] - 128) >> 1) + 128;
54        }
55        srcU += uvlinesize;
56        srcV += uvlinesize;
57    }
58}
59
60static av_always_inline void vc1_lut_scale_luma(uint8_t *srcY,
61                                                uint8_t *lut1, uint8_t *lut2,
62                                                int k, int linesize)
63{
64    int i, j;
65
66    for (j = 0; j < k; j += 2) {
67        for (i = 0; i < k; i++)
68            srcY[i] = lut1[srcY[i]];
69        srcY += linesize;
70
71        if (j + 1 == k)
72            break;
73
74        for (i = 0; i < k; i++)
75            srcY[i] = lut2[srcY[i]];
76        srcY += linesize;
77    }
78}
79
80static av_always_inline void vc1_lut_scale_chroma(uint8_t *srcU, uint8_t *srcV,
81                                                  uint8_t *lut1, uint8_t *lut2,
82                                                  int k, int uvlinesize)
83{
84    int i, j;
85
86    for (j = 0; j < k; j += 2) {
87        for (i = 0; i < k; i++) {
88            srcU[i] = lut1[srcU[i]];
89            srcV[i] = lut1[srcV[i]];
90        }
91        srcU += uvlinesize;
92        srcV += uvlinesize;
93
94        if (j + 1 == k)
95            break;
96
97        for (i = 0; i < k; i++) {
98            srcU[i] = lut2[srcU[i]];
99            srcV[i] = lut2[srcV[i]];
100        }
101        srcU += uvlinesize;
102        srcV += uvlinesize;
103    }
104}
105
106static const uint8_t popcount4[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
107
108static av_always_inline int get_luma_mv(VC1Context *v, int dir, int16_t *tx, int16_t *ty)
109{
110    MpegEncContext *s = &v->s;
111    int idx = v->mv_f[dir][s->block_index[0] + v->blocks_off] |
112             (v->mv_f[dir][s->block_index[1] + v->blocks_off] << 1) |
113             (v->mv_f[dir][s->block_index[2] + v->blocks_off] << 2) |
114             (v->mv_f[dir][s->block_index[3] + v->blocks_off] << 3);
115    static const uint8_t index2[16] = { 0, 0, 0, 0x23, 0, 0x13, 0x03, 0, 0, 0x12, 0x02, 0, 0x01, 0, 0, 0 };
116    int opp_count = popcount4[idx];
117
118    switch (opp_count) {
119    case 0:
120    case 4:
121        *tx = median4(s->mv[dir][0][0], s->mv[dir][1][0], s->mv[dir][2][0], s->mv[dir][3][0]);
122        *ty = median4(s->mv[dir][0][1], s->mv[dir][1][1], s->mv[dir][2][1], s->mv[dir][3][1]);
123        break;
124    case 1:
125        *tx = mid_pred(s->mv[dir][idx < 2][0], s->mv[dir][1 + (idx < 4)][0], s->mv[dir][2 + (idx < 8)][0]);
126        *ty = mid_pred(s->mv[dir][idx < 2][1], s->mv[dir][1 + (idx < 4)][1], s->mv[dir][2 + (idx < 8)][1]);
127        break;
128    case 3:
129        *tx = mid_pred(s->mv[dir][idx > 0xd][0], s->mv[dir][1 + (idx > 0xb)][0], s->mv[dir][2 + (idx > 0x7)][0]);
130        *ty = mid_pred(s->mv[dir][idx > 0xd][1], s->mv[dir][1 + (idx > 0xb)][1], s->mv[dir][2 + (idx > 0x7)][1]);
131        break;
132    case 2:
133        *tx = (s->mv[dir][index2[idx] >> 4][0] + s->mv[dir][index2[idx] & 0xf][0]) / 2;
134        *ty = (s->mv[dir][index2[idx] >> 4][1] + s->mv[dir][index2[idx] & 0xf][1]) / 2;
135        break;
136    }
137    return opp_count;
138}
139
140static av_always_inline int get_chroma_mv(VC1Context *v, int dir, int16_t *tx, int16_t *ty)
141{
142    MpegEncContext *s = &v->s;
143    int idx = !v->mb_type[0][s->block_index[0]] |
144             (!v->mb_type[0][s->block_index[1]] << 1) |
145             (!v->mb_type[0][s->block_index[2]] << 2) |
146             (!v->mb_type[0][s->block_index[3]] << 3);
147    static const uint8_t index2[16] = { 0, 0, 0, 0x01, 0, 0x02, 0x12, 0, 0, 0x03, 0x13, 0, 0x23, 0, 0, 0 };
148    int valid_count = popcount4[idx];
149
150    switch (valid_count) {
151    case 4:
152        *tx = median4(s->mv[dir][0][0], s->mv[dir][1][0], s->mv[dir][2][0], s->mv[dir][3][0]);
153        *ty = median4(s->mv[dir][0][1], s->mv[dir][1][1], s->mv[dir][2][1], s->mv[dir][3][1]);
154        break;
155    case 3:
156        *tx = mid_pred(s->mv[dir][idx > 0xd][0], s->mv[dir][1 + (idx > 0xb)][0], s->mv[dir][2 + (idx > 0x7)][0]);
157        *ty = mid_pred(s->mv[dir][idx > 0xd][1], s->mv[dir][1 + (idx > 0xb)][1], s->mv[dir][2 + (idx > 0x7)][1]);
158        break;
159    case 2:
160        *tx = (s->mv[dir][index2[idx] >> 4][0] + s->mv[dir][index2[idx] & 0xf][0]) / 2;
161        *ty = (s->mv[dir][index2[idx] >> 4][1] + s->mv[dir][index2[idx] & 0xf][1]) / 2;
162        break;
163    default:
164        return 0;
165    }
166    return valid_count;
167}
168
169/** Do motion compensation over 1 macroblock
170 * Mostly adapted hpel_motion and qpel_motion from mpegvideo.c
171 */
172void ff_vc1_mc_1mv(VC1Context *v, int dir)
173{
174    MpegEncContext *s = &v->s;
175    H264ChromaContext *h264chroma = &v->h264chroma;
176    uint8_t *srcY, *srcU, *srcV;
177    int dxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y;
178    int v_edge_pos = s->v_edge_pos >> v->field_mode;
179    int i;
180    uint8_t (*luty)[256], (*lutuv)[256];
181    int use_ic;
182    int interlace;
183    int linesize, uvlinesize;
184
185    if ((!v->field_mode ||
186         (v->ref_field_type[dir] == 1 && v->cur_field_type == 1)) &&
187        !v->s.last_picture.f->data[0])
188        return;
189
190    linesize = s->current_picture_ptr->f->linesize[0];
191    uvlinesize = s->current_picture_ptr->f->linesize[1];
192
193    mx = s->mv[dir][0][0];
194    my = s->mv[dir][0][1];
195
196    // store motion vectors for further use in B-frames
197    if (s->pict_type == AV_PICTURE_TYPE_P) {
198        for (i = 0; i < 4; i++) {
199            s->current_picture.motion_val[1][s->block_index[i] + v->blocks_off][0] = mx;
200            s->current_picture.motion_val[1][s->block_index[i] + v->blocks_off][1] = my;
201        }
202    }
203
204    uvmx = (mx + ((mx & 3) == 3)) >> 1;
205    uvmy = (my + ((my & 3) == 3)) >> 1;
206    v->luma_mv[s->mb_x][0] = uvmx;
207    v->luma_mv[s->mb_x][1] = uvmy;
208
209    if (v->field_mode &&
210        v->cur_field_type != v->ref_field_type[dir]) {
211        my   = my   - 2 + 4 * v->cur_field_type;
212        uvmy = uvmy - 2 + 4 * v->cur_field_type;
213    }
214
215    // fastuvmc shall be ignored for interlaced frame picture
216    if (v->fastuvmc && (v->fcm != ILACE_FRAME)) {
217        uvmx = uvmx + ((uvmx < 0) ? (uvmx & 1) : -(uvmx & 1));
218        uvmy = uvmy + ((uvmy < 0) ? (uvmy & 1) : -(uvmy & 1));
219    }
220    if (!dir) {
221        if (v->field_mode && (v->cur_field_type != v->ref_field_type[dir]) && v->second_field) {
222            srcY = s->current_picture.f->data[0];
223            srcU = s->current_picture.f->data[1];
224            srcV = s->current_picture.f->data[2];
225            luty  = v->curr_luty;
226            lutuv = v->curr_lutuv;
227            use_ic = *v->curr_use_ic;
228            interlace = 1;
229        } else {
230            srcY = s->last_picture.f->data[0];
231            srcU = s->last_picture.f->data[1];
232            srcV = s->last_picture.f->data[2];
233            luty  = v->last_luty;
234            lutuv = v->last_lutuv;
235            use_ic = v->last_use_ic;
236            interlace = s->last_picture.f->interlaced_frame;
237        }
238    } else {
239        srcY = s->next_picture.f->data[0];
240        srcU = s->next_picture.f->data[1];
241        srcV = s->next_picture.f->data[2];
242        luty  = v->next_luty;
243        lutuv = v->next_lutuv;
244        use_ic = v->next_use_ic;
245        interlace = s->next_picture.f->interlaced_frame;
246    }
247
248    if (!srcY || !srcU) {
249        av_log(v->s.avctx, AV_LOG_ERROR, "Referenced frame missing.\n");
250        return;
251    }
252
253    src_x   = s->mb_x * 16 + (mx   >> 2);
254    src_y   = s->mb_y * 16 + (my   >> 2);
255    uvsrc_x = s->mb_x *  8 + (uvmx >> 2);
256    uvsrc_y = s->mb_y *  8 + (uvmy >> 2);
257
258    if (v->profile != PROFILE_ADVANCED) {
259        src_x   = av_clip(  src_x, -16, s->mb_width  * 16);
260        src_y   = av_clip(  src_y, -16, s->mb_height * 16);
261        uvsrc_x = av_clip(uvsrc_x,  -8, s->mb_width  *  8);
262        uvsrc_y = av_clip(uvsrc_y,  -8, s->mb_height *  8);
263    } else {
264        src_x   = av_clip(  src_x, -17, s->avctx->coded_width);
265        uvsrc_x = av_clip(uvsrc_x,  -8, s->avctx->coded_width  >> 1);
266        if (v->fcm == ILACE_FRAME) {
267            src_y = av_clip(src_y, -18 + (src_y & 1), s->avctx->coded_height + (src_y & 1));
268            uvsrc_y = av_clip(uvsrc_y, -8 + (uvsrc_y & 1), (s->avctx->coded_height >> 1) + (uvsrc_y & 1));
269        } else {
270            src_y = av_clip(src_y, -18, s->avctx->coded_height + 1);
271            uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1);
272        }
273    }
274
275    srcY += src_y   * s->linesize   + src_x;
276    srcU += uvsrc_y * s->uvlinesize + uvsrc_x;
277    srcV += uvsrc_y * s->uvlinesize + uvsrc_x;
278
279    if (v->field_mode && v->ref_field_type[dir]) {
280        srcY += linesize;
281        srcU += uvlinesize;
282        srcV += uvlinesize;
283    }
284
285    /* for grayscale we should not try to read from unknown area */
286    if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY) {
287        srcU = s->sc.edge_emu_buffer + 18 * s->linesize;
288        srcV = s->sc.edge_emu_buffer + 18 * s->linesize;
289    }
290
291    if (v->rangeredfrm || use_ic
292        || s->h_edge_pos < 22 || v_edge_pos < 22
293        || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx&3) - 16 - s->mspel * 3
294        || (unsigned)(src_y - 1)        > v_edge_pos    - (my&3) - 16 - 3) {
295        uint8_t *ubuf = s->sc.edge_emu_buffer + 19 * s->linesize;
296        uint8_t *vbuf = ubuf + 9 * s->uvlinesize;
297        const int k = 17 + s->mspel * 2;
298
299        srcY -= s->mspel * (1 + s->linesize);
300        if (interlace) {
301            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
302                                     srcY,
303                                     linesize << 1,
304                                     linesize << 1,
305                                     k,
306                                     v->field_mode ? k : k + 1 >> 1,
307                                     src_x - s->mspel,
308                                     src_y - s->mspel >> !v->field_mode,
309                                     s->h_edge_pos,
310                                     s->v_edge_pos >> 1);
311            if (!v->field_mode)
312                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + linesize,
313                                         srcY + linesize,
314                                         linesize << 1,
315                                         linesize << 1,
316                                         k,
317                                         k >> 1,
318                                         src_x - s->mspel,
319                                         src_y - s->mspel + 1 >> 1,
320                                         s->h_edge_pos,
321                                         s->v_edge_pos >> 1);
322        } else
323            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
324                                     srcY,
325                                     linesize,
326                                     linesize,
327                                     k,
328                                     v->field_mode ? (k << 1) - 1 : k,
329                                     src_x - s->mspel,
330                                     v->field_mode ? 2 * (src_y - s->mspel) + v->ref_field_type[dir] :
331                                                     src_y - s->mspel,
332                                     s->h_edge_pos,
333                                     s->v_edge_pos);
334        srcY = s->sc.edge_emu_buffer;
335        if (interlace) {
336            s->vdsp.emulated_edge_mc(ubuf,
337                                     srcU,
338                                     uvlinesize << 1,
339                                     uvlinesize << 1,
340                                     9,
341                                     v->field_mode ? 9 : 5,
342                                     uvsrc_x,
343                                     uvsrc_y >> !v->field_mode,
344                                     s->h_edge_pos >> 1,
345                                     s->v_edge_pos >> 2);
346            s->vdsp.emulated_edge_mc(vbuf,
347                                     srcV,
348                                     uvlinesize << 1,
349                                     uvlinesize << 1,
350                                     9,
351                                     v->field_mode ? 9 : 5,
352                                     uvsrc_x,
353                                     uvsrc_y >> !v->field_mode,
354                                     s->h_edge_pos >> 1,
355                                     s->v_edge_pos >> 2);
356            if (!v->field_mode) {
357                s->vdsp.emulated_edge_mc(ubuf + uvlinesize,
358                                         srcU + uvlinesize,
359                                         uvlinesize << 1,
360                                         uvlinesize << 1,
361                                         9,
362                                         4,
363                                         uvsrc_x,
364                                         uvsrc_y + 1 >> 1,
365                                         s->h_edge_pos >> 1,
366                                         s->v_edge_pos >> 2);
367                s->vdsp.emulated_edge_mc(vbuf + uvlinesize,
368                                         srcV + uvlinesize,
369                                         uvlinesize << 1,
370                                         uvlinesize << 1,
371                                         9,
372                                         4,
373                                         uvsrc_x,
374                                         uvsrc_y + 1 >> 1,
375                                         s->h_edge_pos >> 1,
376                                         s->v_edge_pos >> 2);
377            }
378        } else {
379            s->vdsp.emulated_edge_mc(ubuf,
380                                     srcU,
381                                     uvlinesize,
382                                     uvlinesize,
383                                     9,
384                                     v->field_mode ? 17 : 9,
385                                     uvsrc_x,
386                                     v->field_mode ? 2 * uvsrc_y + v->ref_field_type[dir] : uvsrc_y,
387                                     s->h_edge_pos >> 1,
388                                     s->v_edge_pos >> 1);
389            s->vdsp.emulated_edge_mc(vbuf,
390                                     srcV,
391                                     uvlinesize,
392                                     uvlinesize,
393                                     9,
394                                     v->field_mode ? 17 : 9,
395                                     uvsrc_x,
396                                     v->field_mode ? 2 * uvsrc_y + v->ref_field_type[dir] : uvsrc_y,
397                                     s->h_edge_pos >> 1,
398                                     s->v_edge_pos >> 1);
399        }
400        srcU = ubuf;
401        srcV = vbuf;
402        /* if we deal with range reduction we need to scale source blocks */
403        if (v->rangeredfrm) {
404            vc1_scale_luma(srcY, k, s->linesize);
405            vc1_scale_chroma(srcU, srcV, 9, s->uvlinesize);
406        }
407        /* if we deal with intensity compensation we need to scale source blocks */
408        if (use_ic) {
409            vc1_lut_scale_luma(srcY,
410                               luty[v->field_mode ? v->ref_field_type[dir] : ((0 + src_y - s->mspel) & 1)],
411                               luty[v->field_mode ? v->ref_field_type[dir] : ((1 + src_y - s->mspel) & 1)],
412                               k, s->linesize);
413            vc1_lut_scale_chroma(srcU, srcV,
414                                 lutuv[v->field_mode ? v->ref_field_type[dir] : ((0 + uvsrc_y) & 1)],
415                                 lutuv[v->field_mode ? v->ref_field_type[dir] : ((1 + uvsrc_y) & 1)],
416                                 9, s->uvlinesize);
417        }
418        srcY += s->mspel * (1 + s->linesize);
419    }
420
421    if (s->mspel) {
422        dxy = ((my & 3) << 2) | (mx & 3);
423        v->vc1dsp.put_vc1_mspel_pixels_tab[0][dxy](s->dest[0], srcY, s->linesize, v->rnd);
424    } else { // hpel mc - always used for luma
425        dxy = (my & 2) | ((mx & 2) >> 1);
426        if (!v->rnd)
427            s->hdsp.put_pixels_tab[0][dxy](s->dest[0], srcY, s->linesize, 16);
428        else
429            s->hdsp.put_no_rnd_pixels_tab[0][dxy](s->dest[0], srcY, s->linesize, 16);
430    }
431
432    if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY)
433        return;
434    /* Chroma MC always uses qpel bilinear */
435    uvmx = (uvmx & 3) << 1;
436    uvmy = (uvmy & 3) << 1;
437    if (!v->rnd) {
438        h264chroma->put_h264_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy);
439        h264chroma->put_h264_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy);
440    } else {
441        v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy);
442        v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy);
443    }
444    if (v->field_mode) {
445        v->mv_f[dir][s->block_index[4] + v->mb_off] = v->cur_field_type != v->ref_field_type[dir];
446        v->mv_f[dir][s->block_index[5] + v->mb_off] = v->cur_field_type != v->ref_field_type[dir];
447    }
448}
449
450/** Do motion compensation for 4-MV macroblock - luminance block
451 */
452void ff_vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg)
453{
454    MpegEncContext *s = &v->s;
455    uint8_t *srcY;
456    int dxy, mx, my, src_x, src_y;
457    int off;
458    int fieldmv = (v->fcm == ILACE_FRAME) ? v->blk_mv_type[s->block_index[n]] : 0;
459    int v_edge_pos = s->v_edge_pos >> v->field_mode;
460    uint8_t (*luty)[256];
461    int use_ic;
462    int interlace;
463    int linesize;
464
465    if ((!v->field_mode ||
466         (v->ref_field_type[dir] == 1 && v->cur_field_type == 1)) &&
467        !v->s.last_picture.f->data[0])
468        return;
469
470    linesize = s->current_picture_ptr->f->linesize[0];
471
472    mx = s->mv[dir][n][0];
473    my = s->mv[dir][n][1];
474
475    if (!dir) {
476        if (v->field_mode && (v->cur_field_type != v->ref_field_type[dir]) && v->second_field) {
477            srcY = s->current_picture.f->data[0];
478            luty = v->curr_luty;
479            use_ic = *v->curr_use_ic;
480            interlace = 1;
481        } else {
482            srcY = s->last_picture.f->data[0];
483            luty = v->last_luty;
484            use_ic = v->last_use_ic;
485            interlace = s->last_picture.f->interlaced_frame;
486        }
487    } else {
488        srcY = s->next_picture.f->data[0];
489        luty = v->next_luty;
490        use_ic = v->next_use_ic;
491        interlace = s->next_picture.f->interlaced_frame;
492    }
493
494    if (!srcY) {
495        av_log(v->s.avctx, AV_LOG_ERROR, "Referenced frame missing.\n");
496        return;
497    }
498
499    if (v->field_mode) {
500        if (v->cur_field_type != v->ref_field_type[dir])
501            my = my - 2 + 4 * v->cur_field_type;
502    }
503
504    if (s->pict_type == AV_PICTURE_TYPE_P && n == 3 && v->field_mode) {
505        int opp_count = get_luma_mv(v, 0,
506                                    &s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0],
507                                    &s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1]);
508        int k, f = opp_count > 2;
509        for (k = 0; k < 4; k++)
510            v->mv_f[1][s->block_index[k] + v->blocks_off] = f;
511    }
512
513    if (v->fcm == ILACE_FRAME) {  // not sure if needed for other types of picture
514        int qx, qy;
515        int width  = s->avctx->coded_width;
516        int height = s->avctx->coded_height >> 1;
517        if (s->pict_type == AV_PICTURE_TYPE_P) {
518            s->current_picture.motion_val[1][s->block_index[n] + v->blocks_off][0] = mx;
519            s->current_picture.motion_val[1][s->block_index[n] + v->blocks_off][1] = my;
520        }
521        qx = (s->mb_x * 16) + (mx >> 2);
522        qy = (s->mb_y *  8) + (my >> 3);
523
524        if (qx < -17)
525            mx -= 4 * (qx + 17);
526        else if (qx > width)
527            mx -= 4 * (qx - width);
528        if (qy < -18)
529            my -= 8 * (qy + 18);
530        else if (qy > height + 1)
531            my -= 8 * (qy - height - 1);
532    }
533
534    if ((v->fcm == ILACE_FRAME) && fieldmv)
535        off = ((n > 1) ? s->linesize : 0) + (n & 1) * 8;
536    else
537        off = s->linesize * 4 * (n & 2) + (n & 1) * 8;
538
539    src_x = s->mb_x * 16 + (n & 1) * 8 + (mx >> 2);
540    if (!fieldmv)
541        src_y = s->mb_y * 16 + (n & 2) * 4 + (my >> 2);
542    else
543        src_y = s->mb_y * 16 + ((n > 1) ? 1 : 0) + (my >> 2);
544
545    if (v->profile != PROFILE_ADVANCED) {
546        src_x = av_clip(src_x, -16, s->mb_width  * 16);
547        src_y = av_clip(src_y, -16, s->mb_height * 16);
548    } else {
549        src_x = av_clip(src_x, -17, s->avctx->coded_width);
550        if (v->fcm == ILACE_FRAME)
551            src_y = av_clip(src_y, -18 + (src_y & 1), s->avctx->coded_height + (src_y & 1));
552        else
553            src_y = av_clip(src_y, -18, s->avctx->coded_height + 1);
554    }
555
556    srcY += src_y * s->linesize + src_x;
557    if (v->field_mode && v->ref_field_type[dir])
558        srcY += linesize;
559
560    if (v->rangeredfrm || use_ic
561        || s->h_edge_pos < 13 || v_edge_pos < 23
562        || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx & 3) - 8 - s->mspel * 2
563        || (unsigned)(src_y - (s->mspel << fieldmv)) > v_edge_pos - (my & 3) - ((8 + s->mspel * 2) << fieldmv)) {
564        const int k = 9 + s->mspel * 2;
565
566        srcY -= s->mspel * (1 + (s->linesize << fieldmv));
567        /* check emulate edge stride and offset */
568        if (interlace) {
569            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
570                                     srcY,
571                                     linesize << 1,
572                                     linesize << 1,
573                                     k,
574                                     v->field_mode ? k : (k << fieldmv) + 1 >> 1,
575                                     src_x - s->mspel,
576                                     src_y - (s->mspel << fieldmv) >> !v->field_mode,
577                                     s->h_edge_pos,
578                                     s->v_edge_pos >> 1);
579            if (!v->field_mode && !fieldmv)
580                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + linesize,
581                                         srcY + linesize,
582                                         linesize << 1,
583                                         linesize << 1,
584                                         k,
585                                         k >> 1,
586                                         src_x - s->mspel,
587                                         src_y - s->mspel + 1 >> 1,
588                                         s->h_edge_pos,
589                                         s->v_edge_pos >> 1);
590        } else
591            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
592                                     srcY,
593                                     linesize,
594                                     linesize,
595                                     k,
596                                     v->field_mode ? (k << 1) - 1 : k << fieldmv,
597                                     src_x - s->mspel,
598                                     v->field_mode ? 2 * (src_y - s->mspel) + v->ref_field_type[dir] :
599                                                     src_y - (s->mspel << fieldmv),
600                                     s->h_edge_pos,
601                                     s->v_edge_pos);
602        srcY = s->sc.edge_emu_buffer;
603        /* if we deal with range reduction we need to scale source blocks */
604        if (v->rangeredfrm) {
605            vc1_scale_luma(srcY, k, s->linesize << fieldmv);
606        }
607        /* if we deal with intensity compensation we need to scale source blocks */
608        if (use_ic) {
609            vc1_lut_scale_luma(srcY,
610                               luty[v->field_mode ? v->ref_field_type[dir] : (((0<<fieldmv)+src_y - (s->mspel << fieldmv)) & 1)],
611                               luty[v->field_mode ? v->ref_field_type[dir] : (((1<<fieldmv)+src_y - (s->mspel << fieldmv)) & 1)],
612                               k, s->linesize << fieldmv);
613        }
614        srcY += s->mspel * (1 + (s->linesize << fieldmv));
615    }
616
617    if (s->mspel) {
618        dxy = ((my & 3) << 2) | (mx & 3);
619        if (avg)
620            v->vc1dsp.avg_vc1_mspel_pixels_tab[1][dxy](s->dest[0] + off, srcY, s->linesize << fieldmv, v->rnd);
621        else
622            v->vc1dsp.put_vc1_mspel_pixels_tab[1][dxy](s->dest[0] + off, srcY, s->linesize << fieldmv, v->rnd);
623    } else { // hpel mc - always used for luma
624        dxy = (my & 2) | ((mx & 2) >> 1);
625        if (!v->rnd)
626            s->hdsp.put_pixels_tab[1][dxy](s->dest[0] + off, srcY, s->linesize, 8);
627        else
628            s->hdsp.put_no_rnd_pixels_tab[1][dxy](s->dest[0] + off, srcY, s->linesize, 8);
629    }
630}
631
632/** Do motion compensation for 4-MV macroblock - both chroma blocks
633 */
634void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir)
635{
636    MpegEncContext *s = &v->s;
637    H264ChromaContext *h264chroma = &v->h264chroma;
638    uint8_t *srcU, *srcV;
639    int uvmx, uvmy, uvsrc_x, uvsrc_y;
640    int16_t tx, ty;
641    int chroma_ref_type;
642    int v_edge_pos = s->v_edge_pos >> v->field_mode;
643    uint8_t (*lutuv)[256];
644    int use_ic;
645    int interlace;
646    int uvlinesize;
647
648    if (!v->field_mode && !v->s.last_picture.f->data[0])
649        return;
650    if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY)
651        return;
652
653    /* calculate chroma MV vector from four luma MVs */
654    if (!v->field_mode || !v->numref) {
655        int valid_count = get_chroma_mv(v, dir, &tx, &ty);
656        if (!valid_count) {
657            s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = 0;
658            s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = 0;
659            v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0;
660            return; //no need to do MC for intra blocks
661        }
662        chroma_ref_type = v->ref_field_type[dir];
663    } else {
664        int opp_count = get_luma_mv(v, dir, &tx, &ty);
665        chroma_ref_type = v->cur_field_type ^ (opp_count > 2);
666    }
667    if (v->field_mode && chroma_ref_type == 1 && v->cur_field_type == 1 && !v->s.last_picture.f->data[0])
668        return;
669    s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = tx;
670    s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = ty;
671
672    uvlinesize = s->current_picture_ptr->f->linesize[1];
673
674    uvmx = (tx + ((tx & 3) == 3)) >> 1;
675    uvmy = (ty + ((ty & 3) == 3)) >> 1;
676
677    v->luma_mv[s->mb_x][0] = uvmx;
678    v->luma_mv[s->mb_x][1] = uvmy;
679
680    if (v->fastuvmc) {
681        uvmx = uvmx + ((uvmx < 0) ? (uvmx & 1) : -(uvmx & 1));
682        uvmy = uvmy + ((uvmy < 0) ? (uvmy & 1) : -(uvmy & 1));
683    }
684    // Field conversion bias
685    if (v->cur_field_type != chroma_ref_type)
686        uvmy += 2 - 4 * chroma_ref_type;
687
688    uvsrc_x = s->mb_x * 8 + (uvmx >> 2);
689    uvsrc_y = s->mb_y * 8 + (uvmy >> 2);
690
691    if (v->profile != PROFILE_ADVANCED) {
692        uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width  * 8);
693        uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8);
694    } else {
695        uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width  >> 1);
696        uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1);
697    }
698
699    if (!dir) {
700        if (v->field_mode && (v->cur_field_type != chroma_ref_type) && v->second_field) {
701            srcU = s->current_picture.f->data[1];
702            srcV = s->current_picture.f->data[2];
703            lutuv = v->curr_lutuv;
704            use_ic = *v->curr_use_ic;
705            interlace = 1;
706        } else {
707            srcU = s->last_picture.f->data[1];
708            srcV = s->last_picture.f->data[2];
709            lutuv = v->last_lutuv;
710            use_ic = v->last_use_ic;
711            interlace = s->last_picture.f->interlaced_frame;
712        }
713    } else {
714        srcU = s->next_picture.f->data[1];
715        srcV = s->next_picture.f->data[2];
716        lutuv = v->next_lutuv;
717        use_ic = v->next_use_ic;
718        interlace = s->next_picture.f->interlaced_frame;
719    }
720
721    if (!srcU) {
722        av_log(v->s.avctx, AV_LOG_ERROR, "Referenced frame missing.\n");
723        return;
724    }
725
726    srcU += uvsrc_y * s->uvlinesize + uvsrc_x;
727    srcV += uvsrc_y * s->uvlinesize + uvsrc_x;
728
729    if (v->field_mode) {
730        if (chroma_ref_type) {
731            srcU += uvlinesize;
732            srcV += uvlinesize;
733        }
734    }
735
736    if (v->rangeredfrm || use_ic
737        || s->h_edge_pos < 18 || v_edge_pos < 18
738        || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 9
739        || (unsigned)uvsrc_y > (v_edge_pos    >> 1) - 9) {
740        if (interlace) {
741            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
742                                     srcU,
743                                     uvlinesize << 1,
744                                     uvlinesize << 1,
745                                     9,
746                                     v->field_mode ? 9 : 5,
747                                     uvsrc_x,
748                                     uvsrc_y >> !v->field_mode,
749                                     s->h_edge_pos >> 1,
750                                     s->v_edge_pos >> 2);
751            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16,
752                                     srcV,
753                                     uvlinesize << 1,
754                                     uvlinesize << 1,
755                                     9,
756                                     v->field_mode ? 9 : 5,
757                                     uvsrc_x,
758                                     uvsrc_y >> !v->field_mode,
759                                     s->h_edge_pos >> 1,
760                                     s->v_edge_pos >> 2);
761            if (!v->field_mode) {
762                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + uvlinesize,
763                                         srcU + uvlinesize,
764                                         uvlinesize << 1,
765                                         uvlinesize << 1,
766                                         9,
767                                         4,
768                                         uvsrc_x,
769                                         uvsrc_y + 1 >> 1,
770                                         s->h_edge_pos >> 1,
771                                         s->v_edge_pos >> 2);
772                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16 + uvlinesize,
773                                         srcV + uvlinesize,
774                                         uvlinesize << 1,
775                                         uvlinesize << 1,
776                                         9,
777                                         4,
778                                         uvsrc_x,
779                                         uvsrc_y + 1 >> 1,
780                                         s->h_edge_pos >> 1,
781                                         s->v_edge_pos >> 2);
782            }
783        } else {
784            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
785                                     srcU,
786                                     uvlinesize,
787                                     uvlinesize,
788                                     9,
789                                     v->field_mode ? 17 : 9,
790                                     uvsrc_x,
791                                     v->field_mode ? 2 * uvsrc_y + chroma_ref_type : uvsrc_y,
792                                     s->h_edge_pos >> 1,
793                                     s->v_edge_pos >> 1);
794            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16,
795                                     srcV,
796                                     uvlinesize,
797                                     uvlinesize,
798                                     9,
799                                     v->field_mode ? 17 : 9,
800                                     uvsrc_x,
801                                     v->field_mode ? 2 * uvsrc_y + chroma_ref_type : uvsrc_y,
802                                     s->h_edge_pos >> 1,
803                                     s->v_edge_pos >> 1);
804        }
805        srcU = s->sc.edge_emu_buffer;
806        srcV = s->sc.edge_emu_buffer + 16;
807
808        /* if we deal with range reduction we need to scale source blocks */
809        if (v->rangeredfrm) {
810            vc1_scale_chroma(srcU, srcV, 9, s->uvlinesize);
811        }
812        /* if we deal with intensity compensation we need to scale source blocks */
813        if (use_ic) {
814            vc1_lut_scale_chroma(srcU, srcV,
815                                 lutuv[v->field_mode ? chroma_ref_type : ((0 + uvsrc_y) & 1)],
816                                 lutuv[v->field_mode ? chroma_ref_type : ((1 + uvsrc_y) & 1)],
817                                 9, s->uvlinesize);
818        }
819    }
820
821    /* Chroma MC always uses qpel bilinear */
822    uvmx = (uvmx & 3) << 1;
823    uvmy = (uvmy & 3) << 1;
824    if (!v->rnd) {
825        h264chroma->put_h264_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy);
826        h264chroma->put_h264_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy);
827    } else {
828        v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy);
829        v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy);
830    }
831    if (v->field_mode) {
832        v->mv_f[dir][s->block_index[4] + v->mb_off] = v->cur_field_type != chroma_ref_type;
833        v->mv_f[dir][s->block_index[5] + v->mb_off] = v->cur_field_type != chroma_ref_type;
834    }
835}
836
837/** Do motion compensation for 4-MV interlaced frame chroma macroblock (both U and V)
838 */
839void ff_vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg)
840{
841    MpegEncContext *s = &v->s;
842    H264ChromaContext *h264chroma = &v->h264chroma;
843    uint8_t *srcU, *srcV;
844    int uvsrc_x, uvsrc_y;
845    int uvmx_field[4], uvmy_field[4];
846    int i, off, tx, ty;
847    int fieldmv = v->blk_mv_type[s->block_index[0]];
848    static const uint8_t s_rndtblfield[16] = { 0, 0, 1, 2, 4, 4, 5, 6, 2, 2, 3, 8, 6, 6, 7, 12 };
849    int v_dist = fieldmv ? 1 : 4; // vertical offset for lower sub-blocks
850    int v_edge_pos = s->v_edge_pos >> 1;
851    int use_ic;
852    int interlace;
853    int uvlinesize;
854    uint8_t (*lutuv)[256];
855
856    if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY)
857        return;
858
859    uvlinesize = s->current_picture_ptr->f->linesize[1];
860
861    for (i = 0; i < 4; i++) {
862        int d = i < 2 ? dir: dir2;
863        tx = s->mv[d][i][0];
864        uvmx_field[i] = (tx + ((tx & 3) == 3)) >> 1;
865        ty = s->mv[d][i][1];
866        if (fieldmv)
867            uvmy_field[i] = (ty >> 4) * 8 + s_rndtblfield[ty & 0xF];
868        else
869            uvmy_field[i] = (ty + ((ty & 3) == 3)) >> 1;
870    }
871
872    for (i = 0; i < 4; i++) {
873        off = (i & 1) * 4 + ((i & 2) ? v_dist * s->uvlinesize : 0);
874        uvsrc_x = s->mb_x * 8 +  (i & 1) * 4           + (uvmx_field[i] >> 2);
875        uvsrc_y = s->mb_y * 8 + ((i & 2) ? v_dist : 0) + (uvmy_field[i] >> 2);
876        // FIXME: implement proper pull-back (see vc1cropmv.c, vc1CROPMV_ChromaPullBack())
877        uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width  >> 1);
878        if (v->fcm == ILACE_FRAME)
879            uvsrc_y = av_clip(uvsrc_y, -8 + (uvsrc_y & 1), (s->avctx->coded_height >> 1) + (uvsrc_y & 1));
880        else
881            uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1);
882        if (i < 2 ? dir : dir2) {
883            srcU = s->next_picture.f->data[1];
884            srcV = s->next_picture.f->data[2];
885            lutuv  = v->next_lutuv;
886            use_ic = v->next_use_ic;
887            interlace = s->next_picture.f->interlaced_frame;
888        } else {
889            srcU = s->last_picture.f->data[1];
890            srcV = s->last_picture.f->data[2];
891            lutuv  = v->last_lutuv;
892            use_ic = v->last_use_ic;
893            interlace = s->last_picture.f->interlaced_frame;
894        }
895        if (!srcU)
896            return;
897        srcU += uvsrc_y * s->uvlinesize + uvsrc_x;
898        srcV += uvsrc_y * s->uvlinesize + uvsrc_x;
899        uvmx_field[i] = (uvmx_field[i] & 3) << 1;
900        uvmy_field[i] = (uvmy_field[i] & 3) << 1;
901
902        if (use_ic
903            || s->h_edge_pos < 10 || v_edge_pos < (5 << fieldmv)
904            || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 5
905            || (unsigned)uvsrc_y > v_edge_pos - (5 << fieldmv)) {
906            if (interlace) {
907                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
908                                         srcU,
909                                         uvlinesize << 1,
910                                         uvlinesize << 1,
911                                         5,
912                                         (5 << fieldmv) + 1 >> 1,
913                                         uvsrc_x,
914                                         uvsrc_y >> 1,
915                                         s->h_edge_pos >> 1,
916                                         s->v_edge_pos >> 2);
917                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16,
918                                         srcV,
919                                         uvlinesize << 1,
920                                         uvlinesize << 1,
921                                         5,
922                                         (5 << fieldmv) + 1 >> 1,
923                                         uvsrc_x,
924                                         uvsrc_y >> 1,
925                                         s->h_edge_pos >> 1,
926                                         s->v_edge_pos >> 2);
927                if (!fieldmv) {
928                    s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + uvlinesize,
929                                             srcU + uvlinesize,
930                                             uvlinesize << 1,
931                                             uvlinesize << 1,
932                                             5,
933                                             2,
934                                             uvsrc_x,
935                                             uvsrc_y + 1 >> 1,
936                                             s->h_edge_pos >> 1,
937                                             s->v_edge_pos >> 2);
938                    s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16 + uvlinesize,
939                                             srcV + uvlinesize,
940                                             uvlinesize << 1,
941                                             uvlinesize << 1,
942                                             5,
943                                             2,
944                                             uvsrc_x,
945                                             uvsrc_y + 1 >> 1,
946                                             s->h_edge_pos >> 1,
947                                             s->v_edge_pos >> 2);
948                }
949            } else {
950                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
951                                         srcU,
952                                         uvlinesize,
953                                         uvlinesize,
954                                         5,
955                                         5 << fieldmv,
956                                         uvsrc_x,
957                                         uvsrc_y,
958                                         s->h_edge_pos >> 1,
959                                         s->v_edge_pos >> 1);
960                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16,
961                                         srcV,
962                                         uvlinesize,
963                                         uvlinesize,
964                                         5,
965                                         5 << fieldmv,
966                                         uvsrc_x,
967                                         uvsrc_y,
968                                         s->h_edge_pos >> 1,
969                                         s->v_edge_pos >> 1);
970            }
971            srcU = s->sc.edge_emu_buffer;
972            srcV = s->sc.edge_emu_buffer + 16;
973
974            /* if we deal with intensity compensation we need to scale source blocks */
975            if (use_ic) {
976                vc1_lut_scale_chroma(srcU, srcV,
977                                     lutuv[(uvsrc_y + (0 << fieldmv)) & 1],
978                                     lutuv[(uvsrc_y + (1 << fieldmv)) & 1],
979                                     5, s->uvlinesize << fieldmv);
980            }
981        }
982        if (avg) {
983            if (!v->rnd) {
984                h264chroma->avg_h264_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]);
985                h264chroma->avg_h264_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]);
986            } else {
987                v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]);
988                v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]);
989            }
990        } else {
991            if (!v->rnd) {
992                h264chroma->put_h264_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]);
993                h264chroma->put_h264_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]);
994            } else {
995                v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]);
996                v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]);
997            }
998        }
999    }
1000}
1001
1002/** Motion compensation for direct or interpolated blocks in B-frames
1003 */
1004void ff_vc1_interp_mc(VC1Context *v)
1005{
1006    MpegEncContext *s = &v->s;
1007    H264ChromaContext *h264chroma = &v->h264chroma;
1008    uint8_t *srcY, *srcU, *srcV;
1009    int dxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y;
1010    int v_edge_pos = s->v_edge_pos >> v->field_mode;
1011    int use_ic = v->next_use_ic;
1012    int interlace;
1013    int linesize, uvlinesize;
1014
1015    if (!v->field_mode && !v->s.next_picture.f->data[0])
1016        return;
1017
1018    linesize = s->current_picture_ptr->f->linesize[0];
1019    uvlinesize = s->current_picture_ptr->f->linesize[1];
1020
1021    mx   = s->mv[1][0][0];
1022    my   = s->mv[1][0][1];
1023    uvmx = (mx + ((mx & 3) == 3)) >> 1;
1024    uvmy = (my + ((my & 3) == 3)) >> 1;
1025    if (v->field_mode && v->cur_field_type != v->ref_field_type[1]) {
1026        my   = my   - 2 + 4 * v->cur_field_type;
1027        uvmy = uvmy - 2 + 4 * v->cur_field_type;
1028    }
1029    if (v->fastuvmc) {
1030        uvmx = uvmx + ((uvmx < 0) ? -(uvmx & 1) : (uvmx & 1));
1031        uvmy = uvmy + ((uvmy < 0) ? -(uvmy & 1) : (uvmy & 1));
1032    }
1033    srcY = s->next_picture.f->data[0];
1034    srcU = s->next_picture.f->data[1];
1035    srcV = s->next_picture.f->data[2];
1036
1037    interlace = s->next_picture.f->interlaced_frame;
1038
1039    src_x   = s->mb_x * 16 + (mx   >> 2);
1040    src_y   = s->mb_y * 16 + (my   >> 2);
1041    uvsrc_x = s->mb_x *  8 + (uvmx >> 2);
1042    uvsrc_y = s->mb_y *  8 + (uvmy >> 2);
1043
1044    if (v->profile != PROFILE_ADVANCED) {
1045        src_x   = av_clip(  src_x, -16, s->mb_width  * 16);
1046        src_y   = av_clip(  src_y, -16, s->mb_height * 16);
1047        uvsrc_x = av_clip(uvsrc_x,  -8, s->mb_width  *  8);
1048        uvsrc_y = av_clip(uvsrc_y,  -8, s->mb_height *  8);
1049    } else {
1050        src_x   = av_clip(  src_x, -17, s->avctx->coded_width);
1051        uvsrc_x = av_clip(uvsrc_x,  -8, s->avctx->coded_width  >> 1);
1052        if (v->fcm == ILACE_FRAME) {
1053            src_y = av_clip(src_y, -18 + (src_y & 1), s->avctx->coded_height + (src_y & 1));
1054            uvsrc_y = av_clip(uvsrc_y, -8 + (uvsrc_y & 1), (s->avctx->coded_height >> 1) + (uvsrc_y & 1));
1055        } else {
1056            src_y = av_clip(src_y, -18, s->avctx->coded_height + 1);
1057            uvsrc_y = av_clip(uvsrc_y,  -8, s->avctx->coded_height >> 1);
1058        }
1059    }
1060
1061    srcY += src_y   * s->linesize   + src_x;
1062    srcU += uvsrc_y * s->uvlinesize + uvsrc_x;
1063    srcV += uvsrc_y * s->uvlinesize + uvsrc_x;
1064
1065    if (v->field_mode && v->ref_field_type[1]) {
1066        srcY += linesize;
1067        srcU += uvlinesize;
1068        srcV += uvlinesize;
1069    }
1070
1071    /* for grayscale we should not try to read from unknown area */
1072    if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY) {
1073        srcU = s->sc.edge_emu_buffer + 18 * s->linesize;
1074        srcV = s->sc.edge_emu_buffer + 18 * s->linesize;
1075    }
1076
1077    if (v->rangeredfrm || s->h_edge_pos < 22 || v_edge_pos < 22 || use_ic
1078        || (unsigned)(src_x - 1) > s->h_edge_pos - (mx & 3) - 16 - 3
1079        || (unsigned)(src_y - 1) > v_edge_pos    - (my & 3) - 16 - 3) {
1080        uint8_t *ubuf = s->sc.edge_emu_buffer + 19 * s->linesize;
1081        uint8_t *vbuf = ubuf + 9 * s->uvlinesize;
1082        const int k = 17 + s->mspel * 2;
1083
1084        srcY -= s->mspel * (1 + s->linesize);
1085        if (interlace) {
1086            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
1087                                     srcY,
1088                                     linesize << 1,
1089                                     linesize << 1,
1090                                     k,
1091                                     v->field_mode ? k : (k + 1 >> 1),
1092                                     src_x - s->mspel,
1093                                     src_y - s->mspel >> !v->field_mode,
1094                                     s->h_edge_pos,
1095                                     s->v_edge_pos >> 1);
1096            if (!v->field_mode)
1097                s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + linesize,
1098                                         srcY + linesize,
1099                                         linesize << 1,
1100                                         linesize << 1,
1101                                         k,
1102                                         k >> 1,
1103                                         src_x - s->mspel,
1104                                         src_y - s->mspel + 1 >> 1,
1105                                         s->h_edge_pos,
1106                                         s->v_edge_pos >> 1);
1107        } else
1108            s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer,
1109                                     srcY,
1110                                     linesize,
1111                                     linesize,
1112                                     k,
1113                                     v->field_mode ? (k << 1) - 1 : k,
1114                                     src_x - s->mspel,
1115                                     v->field_mode ? 2 * (src_y - s->mspel) + v->ref_field_type[1] :
1116                                                     src_y - s->mspel,
1117                                     s->h_edge_pos,
1118                                     s->v_edge_pos);
1119        srcY = s->sc.edge_emu_buffer;
1120        if (interlace) {
1121            s->vdsp.emulated_edge_mc(ubuf,
1122                                     srcU,
1123                                     uvlinesize << 1,
1124                                     uvlinesize << 1,
1125                                     9,
1126                                     v->field_mode ? 9 : 5,
1127                                     uvsrc_x,
1128                                     uvsrc_y >> !v->field_mode,
1129                                     s->h_edge_pos >> 1,
1130                                     s->v_edge_pos >> 2);
1131            s->vdsp.emulated_edge_mc(vbuf,
1132                                     srcV,
1133                                     uvlinesize << 1,
1134                                     uvlinesize << 1,
1135                                     9,
1136                                     v->field_mode ? 9 : 5,
1137                                     uvsrc_x,
1138                                     uvsrc_y >> !v->field_mode,
1139                                     s->h_edge_pos >> 1,
1140                                     s->v_edge_pos >> 2);
1141            if (!v->field_mode) {
1142                s->vdsp.emulated_edge_mc(ubuf + uvlinesize,
1143                                         srcU + uvlinesize,
1144                                         uvlinesize << 1,
1145                                         uvlinesize << 1,
1146                                         9,
1147                                         4,
1148                                         uvsrc_x,
1149                                         uvsrc_y + 1 >> 1,
1150                                         s->h_edge_pos >> 1,
1151                                         s->v_edge_pos >> 2);
1152                s->vdsp.emulated_edge_mc(vbuf + uvlinesize,
1153                                         srcV + uvlinesize,
1154                                         uvlinesize << 1,
1155                                         uvlinesize << 1,
1156                                         9,
1157                                         4,
1158                                         uvsrc_x,
1159                                         uvsrc_y + 1 >> 1,
1160                                         s->h_edge_pos >> 1,
1161                                         s->v_edge_pos >> 2);
1162            }
1163        } else {
1164            s->vdsp.emulated_edge_mc(ubuf,
1165                                     srcU,
1166                                     uvlinesize,
1167                                     uvlinesize,
1168                                     9,
1169                                     v->field_mode ? 17 : 9,
1170                                     uvsrc_x,
1171                                     v->field_mode ? 2 * uvsrc_y + v->ref_field_type[1] : uvsrc_y,
1172                                     s->h_edge_pos >> 1,
1173                                     s->v_edge_pos >> 1);
1174            s->vdsp.emulated_edge_mc(vbuf,
1175                                     srcV,
1176                                     uvlinesize,
1177                                     uvlinesize,
1178                                     9,
1179                                     v->field_mode ? 17 : 9,
1180                                     uvsrc_x,
1181                                     v->field_mode ? 2 * uvsrc_y + v->ref_field_type[1] : uvsrc_y,
1182                                     s->h_edge_pos >> 1,
1183                                     s->v_edge_pos >> 1);
1184        }
1185        srcU = ubuf;
1186        srcV = vbuf;
1187        /* if we deal with range reduction we need to scale source blocks */
1188        if (v->rangeredfrm) {
1189            vc1_scale_luma(srcY, k, s->linesize);
1190            vc1_scale_chroma(srcU, srcV, 9, s->uvlinesize);
1191        }
1192
1193        if (use_ic) {
1194            uint8_t (*luty )[256] = v->next_luty;
1195            uint8_t (*lutuv)[256] = v->next_lutuv;
1196            vc1_lut_scale_luma(srcY,
1197                               luty[v->field_mode ? v->ref_field_type[1] : ((0+src_y - s->mspel) & 1)],
1198                               luty[v->field_mode ? v->ref_field_type[1] : ((1+src_y - s->mspel) & 1)],
1199                               k, s->linesize);
1200            vc1_lut_scale_chroma(srcU, srcV,
1201                                 lutuv[v->field_mode ? v->ref_field_type[1] : ((0+uvsrc_y) & 1)],
1202                                 lutuv[v->field_mode ? v->ref_field_type[1] : ((1+uvsrc_y) & 1)],
1203                                 9, s->uvlinesize);
1204        }
1205        srcY += s->mspel * (1 + s->linesize);
1206    }
1207
1208    if (s->mspel) {
1209        dxy = ((my & 3) << 2) | (mx & 3);
1210        v->vc1dsp.avg_vc1_mspel_pixels_tab[0][dxy](s->dest[0], srcY, s->linesize, v->rnd);
1211    } else { // hpel mc
1212        dxy = (my & 2) | ((mx & 2) >> 1);
1213
1214        if (!v->rnd)
1215            s->hdsp.avg_pixels_tab[0][dxy](s->dest[0], srcY, s->linesize, 16);
1216        else
1217            s->hdsp.avg_no_rnd_pixels_tab[dxy](s->dest[0], srcY, s->linesize, 16);
1218    }
1219
1220    if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY)
1221        return;
1222    /* Chroma MC always uses qpel bilinear */
1223    uvmx = (uvmx & 3) << 1;
1224    uvmy = (uvmy & 3) << 1;
1225    if (!v->rnd) {
1226        h264chroma->avg_h264_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy);
1227        h264chroma->avg_h264_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy);
1228    } else {
1229        v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy);
1230        v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy);
1231    }
1232}
1233