diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 5409293b83..34cb39bac6 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -1108,34 +1108,37 @@ static int mpeg_decode_mb(MpegEncContext *s, s->last_mv[i][0][1] >> 1); dmy = get_dmv(s); s->mv_type = MV_TYPE_DMV; - /* XXX: totally broken */ + + + s->last_mv[i][0][1] = my<<1; + s->last_mv[i][1][1] = my<<1; + + s->mv[i][0][0] = mx; + s->mv[i][0][1] = my; + s->mv[i][1][0] = mx;//not used + s->mv[i][1][1] = my;//not used + if (s->picture_structure == PICT_FRAME) { mb_type |= MB_TYPE_16x16 | MB_TYPE_INTERLACED; - s->last_mv[i][0][1] = my << 1; - s->last_mv[i][1][1] = my << 1; - + //m = 1 + 2 * s->top_field_first; m = s->top_field_first ? 1 : 3; + /* top -> top pred */ - s->mv[i][0][0] = mx; - s->mv[i][0][1] = my << 1; - s->mv[i][1][0] = ((mx * m + (mx > 0)) >> 1) + dmx; - s->mv[i][1][1] = ((my * m + (my > 0)) >> 1) + dmy - 1; + s->mv[i][2][0] = ((mx * m + (mx > 0)) >> 1) + dmx; + s->mv[i][2][1] = ((my * m + (my > 0)) >> 1) + dmy - 1; m = 4 - m; - s->mv[i][2][0] = mx; - s->mv[i][2][1] = my << 1; s->mv[i][3][0] = ((mx * m + (mx > 0)) >> 1) + dmx; s->mv[i][3][1] = ((my * m + (my > 0)) >> 1) + dmy + 1; } else { mb_type |= MB_TYPE_16x16; - s->last_mv[i][0][1] = my; - s->last_mv[i][1][1] = my; - s->mv[i][0][0] = mx; - s->mv[i][0][1] = my; - s->mv[i][1][0] = ((mx + (mx > 0)) >> 1) + dmx; - s->mv[i][1][1] = ((my + (my > 0)) >> 1) + dmy - 1 - /* + 2 * cur_field */; + s->mv[i][2][0] = ((mx + (mx > 0)) >> 1) + dmx; + s->mv[i][2][1] = ((my + (my > 0)) >> 1) + dmy; + if(s->picture_structure == PICT_TOP_FIELD) + s->mv[i][2][1]--; + else + s->mv[i][2][1]++; } } break; diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 9aa258f956..fc8bb60ec6 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -2190,6 +2190,71 @@ static inline void MPV_motion(MpegEncContext *s, s->mv[dir][0][0], s->mv[dir][0][1], 16); } break; + case MV_TYPE_DMV: + { + op_pixels_func (*dmv_pix_op)[4]; + int offset; + + dmv_pix_op = s->dsp.put_pixels_tab; + + if(s->picture_structure == PICT_FRAME){ + //put top field from top field + mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, + ref_picture, 0, + 1, dmv_pix_op, + s->mv[dir][0][0], s->mv[dir][0][1], 8); + //put bottom field from bottom field + mpeg_motion(s, dest_y, dest_cb, dest_cr, s->linesize, + ref_picture, s->linesize, + 1, dmv_pix_op, + s->mv[dir][0][0], s->mv[dir][0][1], 8); + + dmv_pix_op = s->dsp.avg_pixels_tab; + + //avg top field from bottom field + mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, + ref_picture, s->linesize, + 1, dmv_pix_op, + s->mv[dir][2][0], s->mv[dir][2][1], 8); + //avg bottom field from top field + mpeg_motion(s, dest_y, dest_cb, dest_cr, s->linesize, + ref_picture, 0, + 1, dmv_pix_op, + s->mv[dir][3][0], s->mv[dir][3][1], 8); + + }else{ + offset=(s->picture_structure == PICT_BOTTOM_FIELD)? + s->linesize : 0; + + //put field from the same parity + //same parity is never in the same frame + mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, + ref_picture,offset, + 0,dmv_pix_op, + s->mv[dir][0][0],s->mv[dir][0][1],16); + + // after put we make avg of the same block + dmv_pix_op=s->dsp.avg_pixels_tab; + + //opposite parity is always in the same frame if this is second field + if(!s->first_field){ + ref_picture = s->current_picture.data; + //top field is one linesize from frame beginig + offset=(s->picture_structure == PICT_BOTTOM_FIELD)? + -s->linesize : s->linesize; + }else + offset=(s->picture_structure == PICT_BOTTOM_FIELD)? + 0 : s->linesize; + + //avg field from the opposite parity + mpeg_motion(s, dest_y, dest_cb, dest_cr,0, + ref_picture, offset, + 0,dmv_pix_op, + s->mv[dir][2][0],s->mv[dir][2][1],16); + } + } + break; + } }