diff options
Diffstat (limited to 'libavcodec/mpegvideo_motion.c')
-rw-r--r-- | libavcodec/mpegvideo_motion.c | 144 |
1 files changed, 79 insertions, 65 deletions
diff --git a/libavcodec/mpegvideo_motion.c b/libavcodec/mpegvideo_motion.c index 9b704ed3a1..df7ddf7c3b 100644 --- a/libavcodec/mpegvideo_motion.c +++ b/libavcodec/mpegvideo_motion.c @@ -747,6 +747,80 @@ static inline void apply_obmc(MpegEncContext *s, mx, my); } +static inline void apply_8x8(MpegEncContext *s, + uint8_t *dest_y, + uint8_t *dest_cb, + uint8_t *dest_cr, + int dir, + uint8_t **ref_picture, + qpel_mc_func (*qpix_op)[16], + op_pixels_func (*pix_op)[4]) +{ + int dxy, mx, my, src_x, src_y; + int i; + int mb_x = s->mb_x; + int mb_y = s->mb_y; + uint8_t *ptr, *dest; + + mx = 0; + my = 0; + if (s->quarter_sample) { + for (i = 0; i < 4; i++) { + int motion_x = s->mv[dir][i][0]; + int motion_y = s->mv[dir][i][1]; + + dxy = ((motion_y & 3) << 2) | (motion_x & 3); + src_x = mb_x * 16 + (motion_x >> 2) + (i & 1) * 8; + src_y = mb_y * 16 + (motion_y >> 2) + (i >> 1) * 8; + + /* WARNING: do no forget half pels */ + src_x = av_clip(src_x, -16, s->width); + if (src_x == s->width) + dxy &= ~3; + src_y = av_clip(src_y, -16, s->height); + if (src_y == s->height) + dxy &= ~12; + + ptr = ref_picture[0] + (src_y * s->linesize) + (src_x); + if (s->flags & CODEC_FLAG_EMU_EDGE) { + if ((unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x & 3) - 8, 0) || + (unsigned)src_y > FFMAX(s->v_edge_pos - (motion_y & 3) - 8, 0)) { + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, + s->linesize, + 9, 9, + src_x, src_y, + s->h_edge_pos, + s->v_edge_pos); + ptr = s->edge_emu_buffer; + } + } + dest = dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize; + qpix_op[1][dxy](dest, ptr, s->linesize); + + mx += s->mv[dir][i][0] / 2; + my += s->mv[dir][i][1] / 2; + } + } else { + for (i = 0; i < 4; i++) { + hpel_motion(s, + dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize, + ref_picture[0], + mb_x * 16 + (i & 1) * 8, + mb_y * 16 + (i >> 1) * 8, + pix_op[1], + s->mv[dir][i][0], + s->mv[dir][i][1]); + + mx += s->mv[dir][i][0]; + my += s->mv[dir][i][1]; + } + } + + if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) + chroma_4mv_motion(s, dest_cb, dest_cr, + ref_picture, pix_op[1], mx, my); +} + /** * motion compensation of a single macroblock * @param s context @@ -769,12 +843,8 @@ static av_always_inline void MPV_motion_internal(MpegEncContext *s, qpel_mc_func (*qpix_op)[16], int is_mpeg12) { - int dxy, mx, my, src_x, src_y, motion_x, motion_y; - int mb_x, mb_y, i; - uint8_t *ptr, *dest; - - mb_x = s->mb_x; - mb_y = s->mb_y; + int i; + int mb_y = s->mb_y; prefetch_motion(s, ref_picture, dir); @@ -810,65 +880,9 @@ static av_always_inline void MPV_motion_internal(MpegEncContext *s, } break; case MV_TYPE_8X8: - if (!is_mpeg12) { - mx = 0; - my = 0; - if (s->quarter_sample) { - for (i = 0; i < 4; i++) { - motion_x = s->mv[dir][i][0]; - motion_y = s->mv[dir][i][1]; - - dxy = ((motion_y & 3) << 2) | (motion_x & 3); - src_x = mb_x * 16 + (motion_x >> 2) + (i & 1) * 8; - src_y = mb_y * 16 + (motion_y >> 2) + (i >> 1) * 8; - - /* WARNING: do no forget half pels */ - src_x = av_clip(src_x, -16, s->width); - if (src_x == s->width) - dxy &= ~3; - src_y = av_clip(src_y, -16, s->height); - if (src_y == s->height) - dxy &= ~12; - - ptr = ref_picture[0] + (src_y * s->linesize) + (src_x); - if (s->flags & CODEC_FLAG_EMU_EDGE) { - if ((unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x & 3) - 8, 0) || - (unsigned)src_y > FFMAX(s->v_edge_pos - (motion_y & 3) - 8, 0)) { - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, - s->linesize, - 9, 9, - src_x, src_y, - s->h_edge_pos, - s->v_edge_pos); - ptr = s->edge_emu_buffer; - } - } - dest = dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize; - qpix_op[1][dxy](dest, ptr, s->linesize); - - mx += s->mv[dir][i][0] / 2; - my += s->mv[dir][i][1] / 2; - } - } else { - for (i = 0; i < 4; i++) { - hpel_motion(s, - dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize, - ref_picture[0], - mb_x * 16 + (i & 1) * 8, - mb_y * 16 + (i >> 1) * 8, - pix_op[1], - s->mv[dir][i][0], - s->mv[dir][i][1]); - - mx += s->mv[dir][i][0]; - my += s->mv[dir][i][1]; - } - } - - if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) - chroma_4mv_motion(s, dest_cb, dest_cr, - ref_picture, pix_op[1], mx, my); - } + if (!is_mpeg12) + apply_8x8(s, dest_y, dest_cb, dest_cr, + dir, ref_picture, qpix_op, pix_op); break; case MV_TYPE_FIELD: if (s->picture_structure == PICT_FRAME) { |