mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-03 05:10:03 +02:00
fe6037fd04
There are two types of MPVPictures: Three (cur_pic, last_pic, next_pic) that are directly part of MpegEncContext and an array of MPVPictures that are separately allocated and are mostly accessed via pointers (cur|last|next)_pic_ptr; they are also used to store AVFrames in the encoder (necessary due to B-frames). As the name implies, each of the former is directly associated with one of the _ptr pointers: They actually share the same underlying buffers, but the ones that are part of the context can have their data pointers offset and their linesize doubled for field pictures. Up until now, each of these had their own references; in particular, there was an underlying av_frame_ref() to sync cur_pic and cur_pic_ptr etc. This is wasteful. This commit changes this relationship: cur_pic, last_pic and next_pic now become MPVWorkPictures; this structure does not have an AVFrame at all any more, but only the cached values of data and linesize. It also contains a pointer to the corresponding MPVPicture, establishing a more natural relationsship between the two. This already means that creating the context-pictures from the pointers can no longer fail. What has not been changed is the fact that the MPVPicture* pointers are not ownership pointers and that the MPVPictures are part of an array of MPVPictures that is owned by a single AVCodecContext. Doing so will be done in a latter commit. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
946 lines
37 KiB
C
946 lines
37 KiB
C
/*
|
|
* VC-1 and WMV3 decoder
|
|
* Copyright (c) 2011 Mashiat Sarker Shakkhar
|
|
* Copyright (c) 2006-2007 Konstantin Shishkov
|
|
* Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer
|
|
*
|
|
* This file is part of FFmpeg.
|
|
*
|
|
* 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.
|
|
*
|
|
* 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 FFmpeg; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* VC-1 and WMV3 block decoding routines
|
|
*/
|
|
|
|
#include "mathops.h"
|
|
#include "mpegutils.h"
|
|
#include "mpegvideo.h"
|
|
#include "vc1.h"
|
|
#include "vc1_pred.h"
|
|
#include "vc1data.h"
|
|
|
|
static av_always_inline int scaleforsame_x(const VC1Context *v, int n /* MV */, int dir)
|
|
{
|
|
int scaledvalue, refdist;
|
|
int scalesame1, scalesame2;
|
|
int scalezone1_x, zone1offset_x;
|
|
int table_index = dir ^ v->second_field;
|
|
|
|
if (v->s.pict_type != AV_PICTURE_TYPE_B)
|
|
refdist = v->refdist;
|
|
else
|
|
refdist = dir ? v->brfd : v->frfd;
|
|
if (refdist > 3)
|
|
refdist = 3;
|
|
scalesame1 = ff_vc1_field_mvpred_scales[table_index][1][refdist];
|
|
scalesame2 = ff_vc1_field_mvpred_scales[table_index][2][refdist];
|
|
scalezone1_x = ff_vc1_field_mvpred_scales[table_index][3][refdist];
|
|
zone1offset_x = ff_vc1_field_mvpred_scales[table_index][5][refdist];
|
|
|
|
if (FFABS(n) > 255)
|
|
scaledvalue = n;
|
|
else {
|
|
if (FFABS(n) < scalezone1_x)
|
|
scaledvalue = (n * scalesame1) >> 8;
|
|
else {
|
|
if (n < 0)
|
|
scaledvalue = ((n * scalesame2) >> 8) - zone1offset_x;
|
|
else
|
|
scaledvalue = ((n * scalesame2) >> 8) + zone1offset_x;
|
|
}
|
|
}
|
|
return av_clip(scaledvalue, -v->range_x, v->range_x - 1);
|
|
}
|
|
|
|
static av_always_inline int scaleforsame_y(const VC1Context *v, int n /* MV */, int dir)
|
|
{
|
|
int scaledvalue, refdist;
|
|
int scalesame1, scalesame2;
|
|
int scalezone1_y, zone1offset_y;
|
|
int table_index = dir ^ v->second_field;
|
|
|
|
if (v->s.pict_type != AV_PICTURE_TYPE_B)
|
|
refdist = v->refdist;
|
|
else
|
|
refdist = dir ? v->brfd : v->frfd;
|
|
if (refdist > 3)
|
|
refdist = 3;
|
|
scalesame1 = ff_vc1_field_mvpred_scales[table_index][1][refdist];
|
|
scalesame2 = ff_vc1_field_mvpred_scales[table_index][2][refdist];
|
|
scalezone1_y = ff_vc1_field_mvpred_scales[table_index][4][refdist];
|
|
zone1offset_y = ff_vc1_field_mvpred_scales[table_index][6][refdist];
|
|
|
|
if (FFABS(n) > 63)
|
|
scaledvalue = n;
|
|
else {
|
|
if (FFABS(n) < scalezone1_y)
|
|
scaledvalue = (n * scalesame1) >> 8;
|
|
else {
|
|
if (n < 0)
|
|
scaledvalue = ((n * scalesame2) >> 8) - zone1offset_y;
|
|
else
|
|
scaledvalue = ((n * scalesame2) >> 8) + zone1offset_y;
|
|
}
|
|
}
|
|
|
|
if (v->cur_field_type && !v->ref_field_type[dir])
|
|
return av_clip(scaledvalue, -v->range_y / 2 + 1, v->range_y / 2);
|
|
else
|
|
return av_clip(scaledvalue, -v->range_y / 2, v->range_y / 2 - 1);
|
|
}
|
|
|
|
static av_always_inline int scaleforopp_x(const VC1Context *v, int n /* MV */)
|
|
{
|
|
int scalezone1_x, zone1offset_x;
|
|
int scaleopp1, scaleopp2, brfd;
|
|
int scaledvalue;
|
|
|
|
brfd = FFMIN(v->brfd, 3);
|
|
scalezone1_x = ff_vc1_b_field_mvpred_scales[3][brfd];
|
|
zone1offset_x = ff_vc1_b_field_mvpred_scales[5][brfd];
|
|
scaleopp1 = ff_vc1_b_field_mvpred_scales[1][brfd];
|
|
scaleopp2 = ff_vc1_b_field_mvpred_scales[2][brfd];
|
|
|
|
if (FFABS(n) > 255)
|
|
scaledvalue = n;
|
|
else {
|
|
if (FFABS(n) < scalezone1_x)
|
|
scaledvalue = (n * scaleopp1) >> 8;
|
|
else {
|
|
if (n < 0)
|
|
scaledvalue = ((n * scaleopp2) >> 8) - zone1offset_x;
|
|
else
|
|
scaledvalue = ((n * scaleopp2) >> 8) + zone1offset_x;
|
|
}
|
|
}
|
|
return av_clip(scaledvalue, -v->range_x, v->range_x - 1);
|
|
}
|
|
|
|
static av_always_inline int scaleforopp_y(const VC1Context *v, int n /* MV */, int dir)
|
|
{
|
|
int scalezone1_y, zone1offset_y;
|
|
int scaleopp1, scaleopp2, brfd;
|
|
int scaledvalue;
|
|
|
|
brfd = FFMIN(v->brfd, 3);
|
|
scalezone1_y = ff_vc1_b_field_mvpred_scales[4][brfd];
|
|
zone1offset_y = ff_vc1_b_field_mvpred_scales[6][brfd];
|
|
scaleopp1 = ff_vc1_b_field_mvpred_scales[1][brfd];
|
|
scaleopp2 = ff_vc1_b_field_mvpred_scales[2][brfd];
|
|
|
|
if (FFABS(n) > 63)
|
|
scaledvalue = n;
|
|
else {
|
|
if (FFABS(n) < scalezone1_y)
|
|
scaledvalue = (n * scaleopp1) >> 8;
|
|
else {
|
|
if (n < 0)
|
|
scaledvalue = ((n * scaleopp2) >> 8) - zone1offset_y;
|
|
else
|
|
scaledvalue = ((n * scaleopp2) >> 8) + zone1offset_y;
|
|
}
|
|
}
|
|
if (v->cur_field_type && !v->ref_field_type[dir]) {
|
|
return av_clip(scaledvalue, -v->range_y / 2 + 1, v->range_y / 2);
|
|
} else {
|
|
return av_clip(scaledvalue, -v->range_y / 2, v->range_y / 2 - 1);
|
|
}
|
|
}
|
|
|
|
static av_always_inline int scaleforsame(const VC1Context *v, int n /* MV */,
|
|
int dim, int dir)
|
|
{
|
|
int brfd, scalesame;
|
|
int hpel = 1 - v->s.quarter_sample;
|
|
|
|
n >>= hpel;
|
|
if (v->s.pict_type != AV_PICTURE_TYPE_B || v->second_field || !dir) {
|
|
if (dim)
|
|
n = scaleforsame_y(v, n, dir) * (1 << hpel);
|
|
else
|
|
n = scaleforsame_x(v, n, dir) * (1 << hpel);
|
|
return n;
|
|
}
|
|
brfd = FFMIN(v->brfd, 3);
|
|
scalesame = ff_vc1_b_field_mvpred_scales[0][brfd];
|
|
|
|
n = (n * scalesame >> 8) * (1 << hpel);
|
|
return n;
|
|
}
|
|
|
|
static av_always_inline int scaleforopp(const VC1Context *v, int n /* MV */,
|
|
int dim, int dir)
|
|
{
|
|
int refdist, scaleopp;
|
|
int hpel = 1 - v->s.quarter_sample;
|
|
|
|
n >>= hpel;
|
|
if (v->s.pict_type == AV_PICTURE_TYPE_B && !v->second_field && dir == 1) {
|
|
if (dim)
|
|
n = scaleforopp_y(v, n, dir) * (1 << hpel);
|
|
else
|
|
n = scaleforopp_x(v, n) * (1 << hpel);
|
|
return n;
|
|
}
|
|
if (v->s.pict_type != AV_PICTURE_TYPE_B)
|
|
refdist = v->refdist;
|
|
else
|
|
refdist = dir ? v->brfd : v->frfd;
|
|
refdist = FFMIN(refdist, 3);
|
|
scaleopp = ff_vc1_field_mvpred_scales[dir ^ v->second_field][0][refdist];
|
|
|
|
n = (n * scaleopp >> 8) * (1 << hpel);
|
|
return n;
|
|
}
|
|
|
|
/** Predict and set motion vector
|
|
*/
|
|
void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y,
|
|
int mv1, int r_x, int r_y, uint8_t* is_intra,
|
|
int pred_flag, int dir)
|
|
{
|
|
MpegEncContext *s = &v->s;
|
|
int xy, wrap, off = 0;
|
|
int px, py;
|
|
int sum;
|
|
int mixedmv_pic, num_samefield = 0, num_oppfield = 0;
|
|
int opposite, a_f, b_f, c_f;
|
|
int16_t field_predA[2];
|
|
int16_t field_predB[2];
|
|
int16_t field_predC[2];
|
|
int a_valid, b_valid, c_valid;
|
|
int hybridmv_thresh, y_bias = 0;
|
|
|
|
if (v->mv_mode == MV_PMODE_MIXED_MV ||
|
|
((v->mv_mode == MV_PMODE_INTENSITY_COMP) && (v->mv_mode2 == MV_PMODE_MIXED_MV)))
|
|
mixedmv_pic = 1;
|
|
else
|
|
mixedmv_pic = 0;
|
|
/* scale MV difference to be quad-pel */
|
|
if (!s->quarter_sample) {
|
|
dmv_x *= 2;
|
|
dmv_y *= 2;
|
|
}
|
|
|
|
wrap = s->b8_stride;
|
|
xy = s->block_index[n];
|
|
|
|
if (s->mb_intra) {
|
|
s->mv[0][n][0] = s->cur_pic.motion_val[0][xy + v->blocks_off][0] = 0;
|
|
s->mv[0][n][1] = s->cur_pic.motion_val[0][xy + v->blocks_off][1] = 0;
|
|
s->cur_pic.motion_val[1][xy + v->blocks_off][0] = 0;
|
|
s->cur_pic.motion_val[1][xy + v->blocks_off][1] = 0;
|
|
if (mv1) { /* duplicate motion data for 1-MV block */
|
|
s->cur_pic.motion_val[0][xy + 1 + v->blocks_off][0] = 0;
|
|
s->cur_pic.motion_val[0][xy + 1 + v->blocks_off][1] = 0;
|
|
s->cur_pic.motion_val[0][xy + wrap + v->blocks_off][0] = 0;
|
|
s->cur_pic.motion_val[0][xy + wrap + v->blocks_off][1] = 0;
|
|
s->cur_pic.motion_val[0][xy + wrap + 1 + v->blocks_off][0] = 0;
|
|
s->cur_pic.motion_val[0][xy + wrap + 1 + v->blocks_off][1] = 0;
|
|
v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0;
|
|
s->cur_pic.motion_val[1][xy + 1 + v->blocks_off][0] = 0;
|
|
s->cur_pic.motion_val[1][xy + 1 + v->blocks_off][1] = 0;
|
|
s->cur_pic.motion_val[1][xy + wrap + v->blocks_off][0] = 0;
|
|
s->cur_pic.motion_val[1][xy + wrap + v->blocks_off][1] = 0;
|
|
s->cur_pic.motion_val[1][xy + wrap + 1 + v->blocks_off][0] = 0;
|
|
s->cur_pic.motion_val[1][xy + wrap + 1 + v->blocks_off][1] = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
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:
|
|
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;
|
|
break;
|
|
case 2:
|
|
off = 1;
|
|
break;
|
|
case 3:
|
|
off = -1;
|
|
}
|
|
if (v->field_mode && s->mb_width == 1)
|
|
b_valid = b_valid && c_valid;
|
|
}
|
|
|
|
if (v->field_mode) {
|
|
a_valid = a_valid && !is_intra[xy - wrap];
|
|
b_valid = b_valid && !is_intra[xy - wrap + off];
|
|
c_valid = c_valid && !is_intra[xy - 1];
|
|
}
|
|
|
|
if (a_valid) {
|
|
const int16_t *A = s->cur_pic.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;
|
|
field_predA[0] = A[0];
|
|
field_predA[1] = A[1];
|
|
} else {
|
|
field_predA[0] = field_predA[1] = 0;
|
|
a_f = 0;
|
|
}
|
|
if (b_valid) {
|
|
const int16_t *B = s->cur_pic.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;
|
|
field_predB[0] = B[0];
|
|
field_predB[1] = B[1];
|
|
} else {
|
|
field_predB[0] = field_predB[1] = 0;
|
|
b_f = 0;
|
|
}
|
|
if (c_valid) {
|
|
const int16_t *C = s->cur_pic.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;
|
|
field_predC[0] = C[0];
|
|
field_predC[1] = C[1];
|
|
} else {
|
|
field_predC[0] = field_predC[1] = 0;
|
|
c_f = 0;
|
|
}
|
|
|
|
if (v->field_mode) {
|
|
if (!v->numref)
|
|
// REFFIELD determines if the last field or the second-last field is
|
|
// to be used as reference
|
|
opposite = 1 - v->reffield;
|
|
else {
|
|
if (num_samefield <= num_oppfield)
|
|
opposite = 1 - pred_flag;
|
|
else
|
|
opposite = pred_flag;
|
|
}
|
|
} 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);
|
|
}
|
|
if (b_valid && !b_f) {
|
|
field_predB[0] = scaleforopp(v, field_predB[0], 0, dir);
|
|
field_predB[1] = scaleforopp(v, field_predB[1], 1, dir);
|
|
}
|
|
if (c_valid && !c_f) {
|
|
field_predC[0] = scaleforopp(v, field_predC[0], 0, dir);
|
|
field_predC[1] = scaleforopp(v, field_predC[1], 1, dir);
|
|
}
|
|
} 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, field_predA[0], 0, dir);
|
|
field_predA[1] = scaleforsame(v, field_predA[1], 1, dir);
|
|
}
|
|
if (b_valid && b_f) {
|
|
field_predB[0] = scaleforsame(v, field_predB[0], 0, dir);
|
|
field_predB[1] = scaleforsame(v, field_predB[1], 1, dir);
|
|
}
|
|
if (c_valid && c_f) {
|
|
field_predC[0] = scaleforsame(v, field_predC[0], 0, dir);
|
|
field_predC[1] = scaleforsame(v, field_predC[1], 1, dir);
|
|
}
|
|
}
|
|
|
|
if (a_valid) {
|
|
px = field_predA[0];
|
|
py = field_predA[1];
|
|
} else if (c_valid) {
|
|
px = field_predC[0];
|
|
py = field_predC[1];
|
|
} else if (b_valid) {
|
|
px = field_predB[0];
|
|
py = field_predB[1];
|
|
} else {
|
|
px = 0;
|
|
py = 0;
|
|
}
|
|
|
|
if (num_samefield + num_oppfield > 1) {
|
|
px = mid_pred(field_predA[0], field_predB[0], field_predC[0]);
|
|
py = mid_pred(field_predA[1], field_predB[1], field_predC[1]);
|
|
}
|
|
|
|
/* 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 (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;
|
|
}
|
|
|
|
if (!v->field_mode || s->pict_type != AV_PICTURE_TYPE_B) {
|
|
/* Calculate hybrid prediction as specified in 8.3.5.3.5 (also 10.3.5.4.3.5) */
|
|
hybridmv_thresh = 32;
|
|
if (a_valid && c_valid) {
|
|
if (is_intra[xy - wrap])
|
|
sum = FFABS(px) + FFABS(py);
|
|
else
|
|
sum = FFABS(px - field_predA[0]) + FFABS(py - field_predA[1]);
|
|
if (sum > hybridmv_thresh) {
|
|
if (get_bits1(&s->gb)) { // read HYBRIDPRED bit
|
|
px = field_predA[0];
|
|
py = field_predA[1];
|
|
} else {
|
|
px = field_predC[0];
|
|
py = field_predC[1];
|
|
}
|
|
} else {
|
|
if (is_intra[xy - 1])
|
|
sum = FFABS(px) + FFABS(py);
|
|
else
|
|
sum = FFABS(px - field_predC[0]) + FFABS(py - field_predC[1]);
|
|
if (sum > hybridmv_thresh) {
|
|
if (get_bits1(&s->gb)) {
|
|
px = field_predA[0];
|
|
py = field_predA[1];
|
|
} else {
|
|
px = field_predC[0];
|
|
py = field_predC[1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (v->field_mode && v->numref)
|
|
r_y >>= 1;
|
|
if (v->field_mode && v->cur_field_type && v->ref_field_type[dir] == 0)
|
|
y_bias = 1;
|
|
/* store MV using signed modulus of MV range defined in 4.11 */
|
|
s->mv[dir][n][0] = s->cur_pic.motion_val[dir][xy + v->blocks_off][0] = ((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x;
|
|
s->mv[dir][n][1] = s->cur_pic.motion_val[dir][xy + v->blocks_off][1] = ((py + dmv_y + r_y - y_bias) & ((r_y << 1) - 1)) - r_y + y_bias;
|
|
if (mv1) { /* duplicate motion data for 1-MV block */
|
|
s->cur_pic.motion_val[dir][xy + 1 + v->blocks_off][0] = s->cur_pic.motion_val[dir][xy + v->blocks_off][0];
|
|
s->cur_pic.motion_val[dir][xy + 1 + v->blocks_off][1] = s->cur_pic.motion_val[dir][xy + v->blocks_off][1];
|
|
s->cur_pic.motion_val[dir][xy + wrap + v->blocks_off][0] = s->cur_pic.motion_val[dir][xy + v->blocks_off][0];
|
|
s->cur_pic.motion_val[dir][xy + wrap + v->blocks_off][1] = s->cur_pic.motion_val[dir][xy + v->blocks_off][1];
|
|
s->cur_pic.motion_val[dir][xy + wrap + 1 + v->blocks_off][0] = s->cur_pic.motion_val[dir][xy + v->blocks_off][0];
|
|
s->cur_pic.motion_val[dir][xy + wrap + 1 + v->blocks_off][1] = s->cur_pic.motion_val[dir][xy + v->blocks_off][1];
|
|
v->mv_f[dir][xy + 1 + v->blocks_off] = v->mv_f[dir][xy + v->blocks_off];
|
|
v->mv_f[dir][xy + wrap + v->blocks_off] = v->mv_f[dir][xy + wrap + 1 + v->blocks_off] = v->mv_f[dir][xy + v->blocks_off];
|
|
}
|
|
}
|
|
|
|
/** Predict and set motion vector for interlaced frame picture MBs
|
|
*/
|
|
void ff_vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y,
|
|
int mvn, int r_x, int r_y, int dir)
|
|
{
|
|
MpegEncContext *s = &v->s;
|
|
int xy, wrap, off = 0;
|
|
int A[2], B[2], C[2];
|
|
int px = 0, py = 0;
|
|
int a_valid = 0, b_valid = 0, c_valid = 0;
|
|
int field_a, field_b, field_c; // 0: same, 1: opposite
|
|
int total_valid, num_samefield, num_oppfield;
|
|
int pos_c, pos_b, n_adj;
|
|
|
|
wrap = s->b8_stride;
|
|
xy = s->block_index[n];
|
|
|
|
if (s->mb_intra) {
|
|
s->mv[0][n][0] = s->cur_pic.motion_val[0][xy][0] = 0;
|
|
s->mv[0][n][1] = s->cur_pic.motion_val[0][xy][1] = 0;
|
|
s->cur_pic.motion_val[1][xy][0] = 0;
|
|
s->cur_pic.motion_val[1][xy][1] = 0;
|
|
if (mvn == 1) { /* duplicate motion data for 1-MV block */
|
|
s->cur_pic.motion_val[0][xy + 1][0] = 0;
|
|
s->cur_pic.motion_val[0][xy + 1][1] = 0;
|
|
s->cur_pic.motion_val[0][xy + wrap][0] = 0;
|
|
s->cur_pic.motion_val[0][xy + wrap][1] = 0;
|
|
s->cur_pic.motion_val[0][xy + wrap + 1][0] = 0;
|
|
s->cur_pic.motion_val[0][xy + wrap + 1][1] = 0;
|
|
v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0;
|
|
s->cur_pic.motion_val[1][xy + 1][0] = 0;
|
|
s->cur_pic.motion_val[1][xy + 1][1] = 0;
|
|
s->cur_pic.motion_val[1][xy + wrap][0] = 0;
|
|
s->cur_pic.motion_val[1][xy + wrap][1] = 0;
|
|
s->cur_pic.motion_val[1][xy + wrap + 1][0] = 0;
|
|
s->cur_pic.motion_val[1][xy + wrap + 1][1] = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
off = ((n == 0) || (n == 1)) ? 1 : -1;
|
|
/* predict A */
|
|
if (s->mb_x || (n == 1) || (n == 3)) {
|
|
if ((v->blk_mv_type[xy]) // current block (MB) has a field MV
|
|
|| (!v->blk_mv_type[xy] && !v->blk_mv_type[xy - 1])) { // or both have frame MV
|
|
A[0] = s->cur_pic.motion_val[dir][xy - 1][0];
|
|
A[1] = s->cur_pic.motion_val[dir][xy - 1][1];
|
|
a_valid = 1;
|
|
} else { // current block has frame mv and cand. has field MV (so average)
|
|
A[0] = (s->cur_pic.motion_val[dir][xy - 1][0]
|
|
+ s->cur_pic.motion_val[dir][xy - 1 + off * wrap][0] + 1) >> 1;
|
|
A[1] = (s->cur_pic.motion_val[dir][xy - 1][1]
|
|
+ s->cur_pic.motion_val[dir][xy - 1 + off * wrap][1] + 1) >> 1;
|
|
a_valid = 1;
|
|
}
|
|
if (!(n & 1) && v->is_intra[s->mb_x - 1]) {
|
|
a_valid = 0;
|
|
A[0] = A[1] = 0;
|
|
}
|
|
} else
|
|
A[0] = A[1] = 0;
|
|
/* Predict B and C */
|
|
B[0] = B[1] = C[0] = C[1] = 0;
|
|
if (n == 0 || n == 1 || v->blk_mv_type[xy]) {
|
|
if (!s->first_slice_line) {
|
|
if (!v->is_intra[s->mb_x - s->mb_stride]) {
|
|
b_valid = 1;
|
|
n_adj = n | 2;
|
|
pos_b = s->block_index[n_adj] - 2 * wrap;
|
|
if (v->blk_mv_type[pos_b] && v->blk_mv_type[xy]) {
|
|
n_adj = (n & 2) | (n & 1);
|
|
}
|
|
B[0] = s->cur_pic.motion_val[dir][s->block_index[n_adj] - 2 * wrap][0];
|
|
B[1] = s->cur_pic.motion_val[dir][s->block_index[n_adj] - 2 * wrap][1];
|
|
if (v->blk_mv_type[pos_b] && !v->blk_mv_type[xy]) {
|
|
B[0] = (B[0] + s->cur_pic.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][0] + 1) >> 1;
|
|
B[1] = (B[1] + s->cur_pic.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][1] + 1) >> 1;
|
|
}
|
|
}
|
|
if (s->mb_width > 1) {
|
|
if (!v->is_intra[s->mb_x - s->mb_stride + 1]) {
|
|
c_valid = 1;
|
|
n_adj = 2;
|
|
pos_c = s->block_index[2] - 2 * wrap + 2;
|
|
if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) {
|
|
n_adj = n & 2;
|
|
}
|
|
C[0] = s->cur_pic.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][0];
|
|
C[1] = s->cur_pic.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][1];
|
|
if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) {
|
|
C[0] = (1 + C[0] + (s->cur_pic.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 2][0])) >> 1;
|
|
C[1] = (1 + C[1] + (s->cur_pic.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 2][1])) >> 1;
|
|
}
|
|
if (s->mb_x == s->mb_width - 1) {
|
|
if (!v->is_intra[s->mb_x - s->mb_stride - 1]) {
|
|
c_valid = 1;
|
|
n_adj = 3;
|
|
pos_c = s->block_index[3] - 2 * wrap - 2;
|
|
if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) {
|
|
n_adj = n | 1;
|
|
}
|
|
C[0] = s->cur_pic.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][0];
|
|
C[1] = s->cur_pic.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][1];
|
|
if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) {
|
|
C[0] = (1 + C[0] + s->cur_pic.motion_val[dir][s->block_index[1] - 2 * wrap - 2][0]) >> 1;
|
|
C[1] = (1 + C[1] + s->cur_pic.motion_val[dir][s->block_index[1] - 2 * wrap - 2][1]) >> 1;
|
|
}
|
|
} else
|
|
c_valid = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
pos_b = s->block_index[1];
|
|
b_valid = 1;
|
|
B[0] = s->cur_pic.motion_val[dir][pos_b][0];
|
|
B[1] = s->cur_pic.motion_val[dir][pos_b][1];
|
|
pos_c = s->block_index[0];
|
|
c_valid = 1;
|
|
C[0] = s->cur_pic.motion_val[dir][pos_c][0];
|
|
C[1] = s->cur_pic.motion_val[dir][pos_c][1];
|
|
}
|
|
|
|
total_valid = a_valid + b_valid + c_valid;
|
|
// check if predictor A is out of bounds
|
|
if (!s->mb_x && !(n == 1 || n == 3)) {
|
|
A[0] = A[1] = 0;
|
|
}
|
|
// check if predictor B is out of bounds
|
|
if ((s->first_slice_line && v->blk_mv_type[xy]) || (s->first_slice_line && !(n & 2))) {
|
|
B[0] = B[1] = C[0] = C[1] = 0;
|
|
}
|
|
if (!v->blk_mv_type[xy]) {
|
|
if (s->mb_width == 1) {
|
|
px = B[0];
|
|
py = B[1];
|
|
} else {
|
|
if (total_valid >= 2) {
|
|
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]; }
|
|
else if (b_valid) { px = B[0]; py = B[1]; }
|
|
else { px = C[0]; py = C[1]; }
|
|
}
|
|
}
|
|
} else {
|
|
if (a_valid)
|
|
field_a = (A[1] & 4) ? 1 : 0;
|
|
else
|
|
field_a = 0;
|
|
if (b_valid)
|
|
field_b = (B[1] & 4) ? 1 : 0;
|
|
else
|
|
field_b = 0;
|
|
if (c_valid)
|
|
field_c = (C[1] & 4) ? 1 : 0;
|
|
else
|
|
field_c = 0;
|
|
|
|
num_oppfield = field_a + field_b + field_c;
|
|
num_samefield = total_valid - num_oppfield;
|
|
if (total_valid == 3) {
|
|
if ((num_samefield == 3) || (num_oppfield == 3)) {
|
|
px = mid_pred(A[0], B[0], C[0]);
|
|
py = mid_pred(A[1], B[1], C[1]);
|
|
} else if (num_samefield >= num_oppfield) {
|
|
/* take one MV from same field set depending on priority
|
|
the check for B may not be necessary */
|
|
px = !field_a ? A[0] : B[0];
|
|
py = !field_a ? A[1] : B[1];
|
|
} else {
|
|
px = field_a ? A[0] : B[0];
|
|
py = field_a ? A[1] : B[1];
|
|
}
|
|
} else if (total_valid == 2) {
|
|
if (num_samefield >= num_oppfield) {
|
|
if (!field_a && a_valid) {
|
|
px = A[0];
|
|
py = A[1];
|
|
} else if (!field_b && b_valid) {
|
|
px = B[0];
|
|
py = B[1];
|
|
} else /*if (c_valid)*/ {
|
|
av_assert1(c_valid);
|
|
px = C[0];
|
|
py = C[1];
|
|
}
|
|
} else {
|
|
if (field_a && a_valid) {
|
|
px = A[0];
|
|
py = A[1];
|
|
} else /*if (field_b && b_valid)*/ {
|
|
av_assert1(field_b && b_valid);
|
|
px = B[0];
|
|
py = B[1];
|
|
}
|
|
}
|
|
} else if (total_valid == 1) {
|
|
px = (a_valid) ? A[0] : ((b_valid) ? B[0] : C[0]);
|
|
py = (a_valid) ? A[1] : ((b_valid) ? B[1] : C[1]);
|
|
}
|
|
}
|
|
|
|
/* store MV using signed modulus of MV range defined in 4.11 */
|
|
s->mv[dir][n][0] = s->cur_pic.motion_val[dir][xy][0] = ((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x;
|
|
s->mv[dir][n][1] = s->cur_pic.motion_val[dir][xy][1] = ((py + dmv_y + r_y) & ((r_y << 1) - 1)) - r_y;
|
|
if (mvn == 1) { /* duplicate motion data for 1-MV block */
|
|
s->cur_pic.motion_val[dir][xy + 1 ][0] = s->cur_pic.motion_val[dir][xy][0];
|
|
s->cur_pic.motion_val[dir][xy + 1 ][1] = s->cur_pic.motion_val[dir][xy][1];
|
|
s->cur_pic.motion_val[dir][xy + wrap ][0] = s->cur_pic.motion_val[dir][xy][0];
|
|
s->cur_pic.motion_val[dir][xy + wrap ][1] = s->cur_pic.motion_val[dir][xy][1];
|
|
s->cur_pic.motion_val[dir][xy + wrap + 1][0] = s->cur_pic.motion_val[dir][xy][0];
|
|
s->cur_pic.motion_val[dir][xy + wrap + 1][1] = s->cur_pic.motion_val[dir][xy][1];
|
|
} else if (mvn == 2) { /* duplicate motion data for 2-Field MV block */
|
|
s->cur_pic.motion_val[dir][xy + 1][0] = s->cur_pic.motion_val[dir][xy][0];
|
|
s->cur_pic.motion_val[dir][xy + 1][1] = s->cur_pic.motion_val[dir][xy][1];
|
|
s->mv[dir][n + 1][0] = s->mv[dir][n][0];
|
|
s->mv[dir][n + 1][1] = s->mv[dir][n][1];
|
|
}
|
|
}
|
|
|
|
void ff_vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2],
|
|
int direct, int mvtype)
|
|
{
|
|
MpegEncContext *s = &v->s;
|
|
int xy, wrap;
|
|
int px, py;
|
|
int sum;
|
|
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 */
|
|
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->cur_pic.motion_val[0][xy][0] =
|
|
s->cur_pic.motion_val[0][xy][1] =
|
|
s->cur_pic.motion_val[1][xy][0] =
|
|
s->cur_pic.motion_val[1][xy][1] = 0;
|
|
return;
|
|
}
|
|
if (direct && s->next_pic.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_pic.motion_val[1][xy][0], v->bfraction, 0, s->quarter_sample);
|
|
s->mv[0][0][1] = scale_mv(s->next_pic.motion_val[1][xy][1], v->bfraction, 0, s->quarter_sample);
|
|
s->mv[1][0][0] = scale_mv(s->next_pic.motion_val[1][xy][0], v->bfraction, 1, s->quarter_sample);
|
|
s->mv[1][0][1] = scale_mv(s->next_pic.motion_val[1][xy][1], v->bfraction, 1, s->quarter_sample);
|
|
|
|
/* Pullback predicted motion vectors as specified in 8.4.5.4 */
|
|
s->mv[0][0][0] = av_clip(s->mv[0][0][0], -60 - (s->mb_x << 6), (s->mb_width << 6) - 4 - (s->mb_x << 6));
|
|
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->cur_pic.motion_val[0][xy][0] = s->mv[0][0][0];
|
|
s->cur_pic.motion_val[0][xy][1] = s->mv[0][0][1];
|
|
s->cur_pic.motion_val[1][xy][0] = s->mv[1][0][0];
|
|
s->cur_pic.motion_val[1][xy][1] = s->mv[1][0][1];
|
|
return;
|
|
}
|
|
|
|
if ((mvtype == BMV_TYPE_FORWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) {
|
|
int16_t *C = s->cur_pic.motion_val[0][xy - 2];
|
|
const int16_t *A = s->cur_pic.motion_val[0][xy - wrap * 2];
|
|
int off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2;
|
|
const int16_t *B = s->cur_pic.motion_val[0][xy - wrap * 2 + off];
|
|
|
|
if (!s->mb_x) C[0] = C[1] = 0;
|
|
if (!s->first_slice_line) { // predictor A is not out of bounds
|
|
if (s->mb_width == 1) {
|
|
px = A[0];
|
|
py = A[1];
|
|
} else {
|
|
px = mid_pred(A[0], B[0], C[0]);
|
|
py = mid_pred(A[1], B[1], C[1]);
|
|
}
|
|
} else if (s->mb_x) { // predictor C is not out of bounds
|
|
px = C[0];
|
|
py = C[1];
|
|
} else {
|
|
px = py = 0;
|
|
}
|
|
/* Pullback MV as specified in 8.3.5.3.4 */
|
|
{
|
|
int qx, qy, X, Y;
|
|
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) {
|
|
if (is_intra[xy - wrap])
|
|
sum = FFABS(px) + FFABS(py);
|
|
else
|
|
sum = FFABS(px - A[0]) + FFABS(py - A[1]);
|
|
if (sum > 32) {
|
|
if (get_bits1(&s->gb)) {
|
|
px = A[0];
|
|
py = A[1];
|
|
} else {
|
|
px = C[0];
|
|
py = C[1];
|
|
}
|
|
} else {
|
|
if (is_intra[xy - 2])
|
|
sum = FFABS(px) + FFABS(py);
|
|
else
|
|
sum = FFABS(px - C[0]) + FFABS(py - C[1]);
|
|
if (sum > 32) {
|
|
if (get_bits1(&s->gb)) {
|
|
px = A[0];
|
|
py = A[1];
|
|
} else {
|
|
px = C[0];
|
|
py = C[1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* store MV using signed modulus of MV range defined in 4.11 */
|
|
s->mv[0][0][0] = ((px + dmv_x[0] + r_x) & ((r_x << 1) - 1)) - r_x;
|
|
s->mv[0][0][1] = ((py + dmv_y[0] + r_y) & ((r_y << 1) - 1)) - r_y;
|
|
}
|
|
if ((mvtype == BMV_TYPE_BACKWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) {
|
|
int16_t *C = s->cur_pic.motion_val[1][xy - 2];
|
|
const int16_t *A = s->cur_pic.motion_val[1][xy - wrap * 2];
|
|
int off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2;
|
|
const int16_t *B = s->cur_pic.motion_val[1][xy - wrap * 2 + off];
|
|
|
|
if (!s->mb_x)
|
|
C[0] = C[1] = 0;
|
|
if (!s->first_slice_line) { // predictor A is not out of bounds
|
|
if (s->mb_width == 1) {
|
|
px = A[0];
|
|
py = A[1];
|
|
} else {
|
|
px = mid_pred(A[0], B[0], C[0]);
|
|
py = mid_pred(A[1], B[1], C[1]);
|
|
}
|
|
} else if (s->mb_x) { // predictor C is not out of bounds
|
|
px = C[0];
|
|
py = C[1];
|
|
} else {
|
|
px = py = 0;
|
|
}
|
|
/* Pullback MV as specified in 8.3.5.3.4 */
|
|
{
|
|
int qx, qy, X, Y;
|
|
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) {
|
|
if (is_intra[xy - wrap])
|
|
sum = FFABS(px) + FFABS(py);
|
|
else
|
|
sum = FFABS(px - A[0]) + FFABS(py - A[1]);
|
|
if (sum > 32) {
|
|
if (get_bits1(&s->gb)) {
|
|
px = A[0];
|
|
py = A[1];
|
|
} else {
|
|
px = C[0];
|
|
py = C[1];
|
|
}
|
|
} else {
|
|
if (is_intra[xy - 2])
|
|
sum = FFABS(px) + FFABS(py);
|
|
else
|
|
sum = FFABS(px - C[0]) + FFABS(py - C[1]);
|
|
if (sum > 32) {
|
|
if (get_bits1(&s->gb)) {
|
|
px = A[0];
|
|
py = A[1];
|
|
} else {
|
|
px = C[0];
|
|
py = C[1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* store MV using signed modulus of MV range defined in 4.11 */
|
|
|
|
s->mv[1][0][0] = ((px + dmv_x[1] + r_x) & ((r_x << 1) - 1)) - r_x;
|
|
s->mv[1][0][1] = ((py + dmv_y[1] + r_y) & ((r_y << 1) - 1)) - r_y;
|
|
}
|
|
s->cur_pic.motion_val[0][xy][0] = s->mv[0][0][0];
|
|
s->cur_pic.motion_val[0][xy][1] = s->mv[0][0][1];
|
|
s->cur_pic.motion_val[1][xy][0] = s->mv[1][0][0];
|
|
s->cur_pic.motion_val[1][xy][1] = s->mv[1][0][1];
|
|
}
|
|
|
|
void ff_vc1_pred_b_mv_intfi(VC1Context *v, int n, int *dmv_x, int *dmv_y,
|
|
int mv1, int *pred_flag)
|
|
{
|
|
int dir = (v->bmvtype == BMV_TYPE_BACKWARD) ? 1 : 0;
|
|
MpegEncContext *s = &v->s;
|
|
int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
|
|
|
|
if (v->bmvtype == BMV_TYPE_DIRECT) {
|
|
int total_opp, k, f;
|
|
if (s->next_pic.mb_type[mb_pos + v->mb_off] != MB_TYPE_INTRA) {
|
|
s->mv[0][0][0] = scale_mv(s->next_pic.motion_val[1][s->block_index[0] + v->blocks_off][0],
|
|
v->bfraction, 0, s->quarter_sample);
|
|
s->mv[0][0][1] = scale_mv(s->next_pic.motion_val[1][s->block_index[0] + v->blocks_off][1],
|
|
v->bfraction, 0, s->quarter_sample);
|
|
s->mv[1][0][0] = scale_mv(s->next_pic.motion_val[1][s->block_index[0] + v->blocks_off][0],
|
|
v->bfraction, 1, s->quarter_sample);
|
|
s->mv[1][0][1] = scale_mv(s->next_pic.motion_val[1][s->block_index[0] + v->blocks_off][1],
|
|
v->bfraction, 1, s->quarter_sample);
|
|
|
|
total_opp = v->mv_f_next[0][s->block_index[0] + v->blocks_off]
|
|
+ v->mv_f_next[0][s->block_index[1] + v->blocks_off]
|
|
+ v->mv_f_next[0][s->block_index[2] + v->blocks_off]
|
|
+ v->mv_f_next[0][s->block_index[3] + v->blocks_off];
|
|
f = (total_opp > 2) ? 1 : 0;
|
|
} else {
|
|
s->mv[0][0][0] = s->mv[0][0][1] = 0;
|
|
s->mv[1][0][0] = s->mv[1][0][1] = 0;
|
|
f = 0;
|
|
}
|
|
v->ref_field_type[0] = v->ref_field_type[1] = v->cur_field_type ^ f;
|
|
for (k = 0; k < 4; k++) {
|
|
s->cur_pic.motion_val[0][s->block_index[k] + v->blocks_off][0] = s->mv[0][0][0];
|
|
s->cur_pic.motion_val[0][s->block_index[k] + v->blocks_off][1] = s->mv[0][0][1];
|
|
s->cur_pic.motion_val[1][s->block_index[k] + v->blocks_off][0] = s->mv[1][0][0];
|
|
s->cur_pic.motion_val[1][s->block_index[k] + v->blocks_off][1] = s->mv[1][0][1];
|
|
v->mv_f[0][s->block_index[k] + v->blocks_off] = f;
|
|
v->mv_f[1][s->block_index[k] + v->blocks_off] = f;
|
|
}
|
|
return;
|
|
}
|
|
if (v->bmvtype == BMV_TYPE_INTERPOLATED) {
|
|
ff_vc1_pred_mv(v, 0, dmv_x[0], dmv_y[0], 1, v->range_x, v->range_y, v->mb_type[0], pred_flag[0], 0);
|
|
ff_vc1_pred_mv(v, 0, dmv_x[1], dmv_y[1], 1, v->range_x, v->range_y, v->mb_type[0], pred_flag[1], 1);
|
|
return;
|
|
}
|
|
if (dir) { // backward
|
|
ff_vc1_pred_mv(v, n, dmv_x[1], dmv_y[1], mv1, v->range_x, v->range_y, v->mb_type[0], pred_flag[1], 1);
|
|
if (n == 3 || mv1) {
|
|
ff_vc1_pred_mv(v, 0, dmv_x[0], dmv_y[0], 1, v->range_x, v->range_y, v->mb_type[0], 0, 0);
|
|
}
|
|
} else { // forward
|
|
ff_vc1_pred_mv(v, n, dmv_x[0], dmv_y[0], mv1, v->range_x, v->range_y, v->mb_type[0], pred_flag[0], 0);
|
|
if (n == 3 || mv1) {
|
|
ff_vc1_pred_mv(v, 0, dmv_x[1], dmv_y[1], 1, v->range_x, v->range_y, v->mb_type[0], 0, 1);
|
|
}
|
|
}
|
|
}
|