static av_always_inline void mc_chroma_scaled(VP9Context *s, vp9_scaled_mc_func smc,

                                              vp9_mc_func (*mc)[2],

                                              uint8_t *dst_u, uint8_t *dst_v,

                                              ptrdiff_t dst_stride,

                                              const uint8_t *ref_u, ptrdiff_t src_stride_u,

                                              const uint8_t *ref_v, ptrdiff_t src_stride_v,

                                              ThreadFrame *ref_frame,

                                              ptrdiff_t y, ptrdiff_t x, const VP56mv *in_mv,

                                              int px, int py, int pw, int ph,

                                              int bw, int bh, int w, int h, int bytesperpixel,

                                              const uint16_t *scale, const uint8_t *step)

{

    if (s->s.frames[CUR_FRAME].tf.f->width == ref_frame->f->width &&

        s->s.frames[CUR_FRAME].tf.f->height == ref_frame->f->height) {

        mc_chroma_unscaled(s, mc, dst_u, dst_v, dst_stride, ref_u, src_stride_u,

                           ref_v, src_stride_v, ref_frame,

                           y, x, in_mv, bw, bh, w, h, bytesperpixel);

    } else {

    int mx, my;

    int refbw_m1, refbh_m1;

    int th;

    VP56mv mv;



    if (s->ss_h) {

        // BUG https://code.google.com/p/webm/issues/detail?id=820

        mv.x = av_clip(in_mv->x, -(x + pw - px + 4) * 16, (s->cols * 4 - x + px + 3) * 16);

        mx = scale_mv(mv.x, 0) + (scale_mv(x * 16, 0) & ~15) + (scale_mv(x * 32, 0) & 15);

    } else {

        mv.x = av_clip(in_mv->x, -(x + pw - px + 4) * 8, (s->cols * 8 - x + px + 3) * 8);

        mx = scale_mv(mv.x * 2, 0) + scale_mv(x * 16, 0);

    }

    if (s->ss_v) {

        // BUG https://code.google.com/p/webm/issues/detail?id=820

        mv.y = av_clip(in_mv->y, -(y + ph - py + 4) * 16, (s->rows * 4 - y + py + 3) * 16);

        my = scale_mv(mv.y, 1) + (scale_mv(y * 16, 1) & ~15) + (scale_mv(y * 32, 1) & 15);

    } else {

        mv.y = av_clip(in_mv->y, -(y + ph - py + 4) * 8, (s->rows * 8 - y + py + 3) * 8);

        my = scale_mv(mv.y * 2, 1) + scale_mv(y * 16, 1);

    }

#undef scale_mv

    y = my >> 4;

    x = mx >> 4;

    ref_u += y * src_stride_u + x * bytesperpixel;

    ref_v += y * src_stride_v + x * bytesperpixel;

    mx &= 15;

    my &= 15;

    refbw_m1 = ((bw - 1) * step[0] + mx) >> 4;

    refbh_m1 = ((bh - 1) * step[1] + my) >> 4;

    // FIXME bilinear filter only needs 0/1 pixels, not 3/4

    // we use +7 because the last 7 pixels of each sbrow can be changed in

    // the longest loopfilter of the next sbrow

    th = (y + refbh_m1 + 4 + 7) >> (6 - s->ss_v);

    ff_thread_await_progress(ref_frame, FFMAX(th, 0), 0);

    if (x < 3 || y < 3 || x + 4 >= w - refbw_m1 || y + 4 >= h - refbh_m1) {

        s->vdsp.emulated_edge_mc(s->edge_emu_buffer,

                                 ref_u - 3 * src_stride_u - 3 * bytesperpixel,

                                 288, src_stride_u,

                                 refbw_m1 + 8, refbh_m1 + 8,

                                 x - 3, y - 3, w, h);

        ref_u = s->edge_emu_buffer + 3 * 288 + 3 * bytesperpixel;

        smc(dst_u, dst_stride, ref_u, 288, bh, mx, my, step[0], step[1]);



        s->vdsp.emulated_edge_mc(s->edge_emu_buffer,

                                 ref_v - 3 * src_stride_v - 3 * bytesperpixel,

                                 288, src_stride_v,

                                 refbw_m1 + 8, refbh_m1 + 8,

                                 x - 3, y - 3, w, h);

        ref_v = s->edge_emu_buffer + 3 * 288 + 3 * bytesperpixel;

        smc(dst_v, dst_stride, ref_v, 288, bh, mx, my, step[0], step[1]);

    } else {

        smc(dst_u, dst_stride, ref_u, src_stride_u, bh, mx, my, step[0], step[1]);

        smc(dst_v, dst_stride, ref_v, src_stride_v, bh, mx, my, step[0], step[1]);

    }

    }

}
