diff options
Diffstat (limited to 'libavcodec/vc1_pred.c')
-rw-r--r-- | libavcodec/vc1_pred.c | 163 |
1 files changed, 78 insertions, 85 deletions
diff --git a/libavcodec/vc1_pred.c b/libavcodec/vc1_pred.c index 25be787..9e29b44 100644 --- a/libavcodec/vc1_pred.c +++ b/libavcodec/vc1_pred.c @@ -4,20 +4,20 @@ * Copyright (c) 2006-2007 Konstantin Shishkov * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * 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 - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -170,9 +170,9 @@ static av_always_inline int scaleforsame(VC1Context *v, int i, int n /* MV */, n >>= hpel; if (v->s.pict_type != AV_PICTURE_TYPE_B || v->second_field || !dir) { if (dim) - n = scaleforsame_y(v, i, n, dir) << hpel; + n = scaleforsame_y(v, i, n, dir) * (1 << hpel); else - n = scaleforsame_x(v, n, dir) << hpel; + n = scaleforsame_x(v, n, dir) * (1 << hpel); return n; } brfd = FFMIN(v->brfd, 3); @@ -202,7 +202,7 @@ static av_always_inline int scaleforopp(VC1Context *v, int n /* MV */, refdist = dir ? v->brfd : v->frfd; scaleopp = ff_vc1_field_mvpred_scales[dir ^ v->second_field][0][refdist]; - n = (n * scaleopp >> 8) << hpel; + n = (n * scaleopp >> 8) * (1 << hpel); return n; } @@ -231,8 +231,10 @@ void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, else mixedmv_pic = 0; /* scale MV difference to be quad-pel */ - dmv_x <<= 1 - s->quarter_sample; - dmv_y <<= 1 - s->quarter_sample; + if (!s->quarter_sample) { + dmv_x *= 2; + dmv_y *= 2; + } wrap = s->b8_stride; xy = s->block_index[n]; @@ -252,7 +254,7 @@ void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0; s->current_picture.motion_val[1][xy + 1 + v->blocks_off][0] = 0; s->current_picture.motion_val[1][xy + 1 + v->blocks_off][1] = 0; - s->current_picture.motion_val[1][xy + wrap][0] = 0; + s->current_picture.motion_val[1][xy + wrap + v->blocks_off][0] = 0; s->current_picture.motion_val[1][xy + wrap + v->blocks_off][1] = 0; s->current_picture.motion_val[1][xy + wrap + 1 + v->blocks_off][0] = 0; s->current_picture.motion_val[1][xy + wrap + 1 + v->blocks_off][1] = 0; @@ -260,18 +262,23 @@ void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, return; } - C = s->current_picture.motion_val[dir][xy - 1 + v->blocks_off]; - A = s->current_picture.motion_val[dir][xy - wrap + v->blocks_off]; + a_valid = !s->first_slice_line || (n == 2 || n == 3); + b_valid = a_valid; + c_valid = s->mb_x || (n == 1 || n == 3); if (mv1) { if (v->field_mode && mixedmv_pic) off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2; else off = (s->mb_x == (s->mb_width - 1)) ? -1 : 2; + b_valid = b_valid && s->mb_width > 1; } else { //in 4-MV mode different blocks have different B predictor position switch (n) { case 0: - off = (s->mb_x > 0) ? -1 : 1; + if (v->res_rtm_flag) + off = s->mb_x ? -1 : 1; + else + off = s->mb_x ? -1 : 2 * s->mb_width - wrap - 1; break; case 1: off = (s->mb_x == (s->mb_width - 1)) ? -1 : 1; @@ -282,12 +289,10 @@ void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, case 3: off = -1; } + if (v->field_mode && s->mb_width == 1) + b_valid = b_valid && c_valid; } - B = s->current_picture.motion_val[dir][xy - wrap + off + v->blocks_off]; - a_valid = !s->first_slice_line || (n == 2 || n == 3); - b_valid = a_valid && (s->mb_width > 1); - c_valid = s->mb_x || (n == 1 || n == 3); if (v->field_mode) { a_valid = a_valid && !is_intra[xy - wrap]; b_valid = b_valid && !is_intra[xy - wrap + off]; @@ -295,6 +300,7 @@ void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, } if (a_valid) { + A = s->current_picture.motion_val[dir][xy - wrap + v->blocks_off]; a_f = v->mv_f[dir][xy - wrap + v->blocks_off]; num_oppfield += a_f; num_samefield += 1 - a_f; @@ -305,6 +311,7 @@ void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, a_f = 0; } if (b_valid) { + B = s->current_picture.motion_val[dir][xy - wrap + off + v->blocks_off]; b_f = v->mv_f[dir][xy - wrap + off + v->blocks_off]; num_oppfield += b_f; num_samefield += 1 - b_f; @@ -315,6 +322,7 @@ void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, b_f = 0; } if (c_valid) { + C = s->current_picture.motion_val[dir][xy - 1 + v->blocks_off]; c_f = v->mv_f[dir][xy - 1 + v->blocks_off]; num_oppfield += c_f; num_samefield += 1 - c_f; @@ -339,6 +347,8 @@ void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, } else opposite = 0; if (opposite) { + v->mv_f[dir][xy + v->blocks_off] = 1; + v->ref_field_type[dir] = !v->cur_field_type; if (a_valid && !a_f) { field_predA[0] = scaleforopp(v, field_predA[0], 0, dir); field_predA[1] = scaleforopp(v, field_predA[1], 1, dir); @@ -351,9 +361,9 @@ void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, field_predC[0] = scaleforopp(v, field_predC[0], 0, dir); field_predC[1] = scaleforopp(v, field_predC[1], 1, dir); } - v->mv_f[dir][xy + v->blocks_off] = 1; - v->ref_field_type[dir] = !v->cur_field_type; } else { + v->mv_f[dir][xy + v->blocks_off] = 0; + v->ref_field_type[dir] = v->cur_field_type; if (a_valid && a_f) { field_predA[0] = scaleforsame(v, n, field_predA[0], 0, dir); field_predA[1] = scaleforsame(v, n, field_predA[1], 1, dir); @@ -366,8 +376,6 @@ void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, field_predC[0] = scaleforsame(v, n, field_predC[0], 0, dir); field_predC[1] = scaleforsame(v, n, field_predC[1], 1, dir); } - v->mv_f[dir][xy + v->blocks_off] = 0; - v->ref_field_type[dir] = v->cur_field_type; } if (a_valid) { @@ -392,17 +400,13 @@ void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, /* Pullback MV as specified in 8.3.5.3.4 */ if (!v->field_mode) { int qx, qy, X, Y; + int MV = mv1 ? -60 : -28; qx = (s->mb_x << 6) + ((n == 1 || n == 3) ? 32 : 0); qy = (s->mb_y << 6) + ((n == 2 || n == 3) ? 32 : 0); X = (s->mb_width << 6) - 4; Y = (s->mb_height << 6) - 4; - if (mv1) { - if (qx + px < -60) px = -60 - qx; - if (qy + py < -60) py = -60 - qy; - } else { - if (qx + px < -28) px = -28 - qx; - if (qy + py < -28) py = -28 - qy; - } + if (qx + px < MV) px = MV - qx; + if (qy + py < MV) py = MV - qy; if (qx + px > X) px = X - qx; if (qy + py > Y) py = Y - qy; } @@ -602,9 +606,9 @@ void ff_vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, px = mid_pred(A[0], B[0], C[0]); py = mid_pred(A[1], B[1], C[1]); } else if (total_valid) { - if (a_valid) { px = A[0]; py = A[1]; } - if (b_valid) { px = B[0]; py = B[1]; } - if (c_valid) { px = C[0]; py = C[1]; } + if (a_valid) { px = A[0]; py = A[1]; } + else if (b_valid) { px = B[0]; py = B[1]; } + else { px = C[0]; py = C[1]; } } } } else { @@ -644,7 +648,8 @@ void ff_vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, } else if (!field_b && b_valid) { px = B[0]; py = B[1]; - } else if (c_valid) { + } else /*if (c_valid)*/ { + av_assert1(c_valid); px = C[0]; py = C[1]; } @@ -652,7 +657,8 @@ void ff_vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, if (field_a && a_valid) { px = A[0]; py = A[1]; - } else if (field_b && b_valid) { + } else /*if (field_b && b_valid)*/ { + av_assert1(field_b && b_valid); px = B[0]; py = B[1]; } @@ -692,25 +698,31 @@ void ff_vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2], int r_x, r_y; const uint8_t *is_intra = v->mb_type[0]; + av_assert0(!v->field_mode); + r_x = v->range_x; r_y = v->range_y; /* scale MV difference to be quad-pel */ - dmv_x[0] <<= 1 - s->quarter_sample; - dmv_y[0] <<= 1 - s->quarter_sample; - dmv_x[1] <<= 1 - s->quarter_sample; - dmv_y[1] <<= 1 - s->quarter_sample; + if (!s->quarter_sample) { + dmv_x[0] *= 2; + dmv_y[0] *= 2; + dmv_x[1] *= 2; + dmv_y[1] *= 2; + } wrap = s->b8_stride; xy = s->block_index[0]; if (s->mb_intra) { - s->current_picture.motion_val[0][xy + v->blocks_off][0] = - s->current_picture.motion_val[0][xy + v->blocks_off][1] = - s->current_picture.motion_val[1][xy + v->blocks_off][0] = - s->current_picture.motion_val[1][xy + v->blocks_off][1] = 0; + s->current_picture.motion_val[0][xy][0] = + s->current_picture.motion_val[0][xy][1] = + s->current_picture.motion_val[1][xy][0] = + s->current_picture.motion_val[1][xy][1] = 0; return; } - if (!v->field_mode) { + if (direct && s->next_picture_ptr->field_picture) + av_log(s->avctx, AV_LOG_WARNING, "Mixed frame/field direct mode not supported\n"); + s->mv[0][0][0] = scale_mv(s->next_picture.motion_val[1][xy][0], v->bfraction, 0, s->quarter_sample); s->mv[0][0][1] = scale_mv(s->next_picture.motion_val[1][xy][1], v->bfraction, 0, s->quarter_sample); s->mv[1][0][0] = scale_mv(s->next_picture.motion_val[1][xy][0], v->bfraction, 1, s->quarter_sample); @@ -721,12 +733,11 @@ void ff_vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2], s->mv[0][0][1] = av_clip(s->mv[0][0][1], -60 - (s->mb_y << 6), (s->mb_height << 6) - 4 - (s->mb_y << 6)); s->mv[1][0][0] = av_clip(s->mv[1][0][0], -60 - (s->mb_x << 6), (s->mb_width << 6) - 4 - (s->mb_x << 6)); s->mv[1][0][1] = av_clip(s->mv[1][0][1], -60 - (s->mb_y << 6), (s->mb_height << 6) - 4 - (s->mb_y << 6)); - } if (direct) { - s->current_picture.motion_val[0][xy + v->blocks_off][0] = s->mv[0][0][0]; - s->current_picture.motion_val[0][xy + v->blocks_off][1] = s->mv[0][0][1]; - s->current_picture.motion_val[1][xy + v->blocks_off][0] = s->mv[1][0][0]; - s->current_picture.motion_val[1][xy + v->blocks_off][1] = s->mv[1][0][1]; + s->current_picture.motion_val[0][xy][0] = s->mv[0][0][0]; + s->current_picture.motion_val[0][xy][1] = s->mv[0][0][1]; + s->current_picture.motion_val[1][xy][0] = s->mv[1][0][0]; + s->current_picture.motion_val[1][xy][1] = s->mv[1][0][1]; return; } @@ -754,25 +765,16 @@ void ff_vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2], /* Pullback MV as specified in 8.3.5.3.4 */ { int qx, qy, X, Y; - if (v->profile < PROFILE_ADVANCED) { - qx = (s->mb_x << 5); - qy = (s->mb_y << 5); - X = (s->mb_width << 5) - 4; - Y = (s->mb_height << 5) - 4; - if (qx + px < -28) px = -28 - qx; - if (qy + py < -28) py = -28 - qy; - if (qx + px > X) px = X - qx; - if (qy + py > Y) py = Y - qy; - } else { - qx = (s->mb_x << 6); - qy = (s->mb_y << 6); - X = (s->mb_width << 6) - 4; - Y = (s->mb_height << 6) - 4; - if (qx + px < -60) px = -60 - qx; - if (qy + py < -60) py = -60 - qy; - if (qx + px > X) px = X - qx; - if (qy + py > Y) py = Y - qy; - } + int sh = v->profile < PROFILE_ADVANCED ? 5 : 6; + int MV = 4 - (1 << sh); + qx = (s->mb_x << sh); + qy = (s->mb_y << sh); + X = (s->mb_width << sh) - 4; + Y = (s->mb_height << sh) - 4; + if (qx + px < MV) px = MV - qx; + if (qy + py < MV) py = MV - qy; + if (qx + px > X) px = X - qx; + if (qy + py > Y) py = Y - qy; } /* Calculate hybrid prediction as specified in 8.3.5.3.5 */ if (0 && !s->first_slice_line && s->mb_x) { @@ -833,25 +835,16 @@ void ff_vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2], /* Pullback MV as specified in 8.3.5.3.4 */ { int qx, qy, X, Y; - if (v->profile < PROFILE_ADVANCED) { - qx = (s->mb_x << 5); - qy = (s->mb_y << 5); - X = (s->mb_width << 5) - 4; - Y = (s->mb_height << 5) - 4; - if (qx + px < -28) px = -28 - qx; - if (qy + py < -28) py = -28 - qy; - if (qx + px > X) px = X - qx; - if (qy + py > Y) py = Y - qy; - } else { - qx = (s->mb_x << 6); - qy = (s->mb_y << 6); - X = (s->mb_width << 6) - 4; - Y = (s->mb_height << 6) - 4; - if (qx + px < -60) px = -60 - qx; - if (qy + py < -60) py = -60 - qy; - if (qx + px > X) px = X - qx; - if (qy + py > Y) py = Y - qy; - } + int sh = v->profile < PROFILE_ADVANCED ? 5 : 6; + int MV = 4 - (1 << sh); + qx = (s->mb_x << sh); + qy = (s->mb_y << sh); + X = (s->mb_width << sh) - 4; + Y = (s->mb_height << sh) - 4; + if (qx + px < MV) px = MV - qx; + if (qy + py < MV) py = MV - qy; + if (qx + px > X) px = X - qx; + if (qy + py > Y) py = Y - qy; } /* Calculate hybrid prediction as specified in 8.3.5.3.5 */ if (0 && !s->first_slice_line && s->mb_x) { |