summaryrefslogtreecommitdiff
path: root/libavcodec/mpegvideo_motion.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/mpegvideo_motion.c')
-rw-r--r--libavcodec/mpegvideo_motion.c191
1 files changed, 106 insertions, 85 deletions
diff --git a/libavcodec/mpegvideo_motion.c b/libavcodec/mpegvideo_motion.c
index f6d9613b3c..5624c10629 100644
--- a/libavcodec/mpegvideo_motion.c
+++ b/libavcodec/mpegvideo_motion.c
@@ -4,25 +4,26 @@
*
* 4MV & hq & B-frame encoding stuff by Michael Niedermayer <michaelni@gmx.at>
*
- * 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
*/
#include <string.h>
+#include "libavutil/avassert.h"
#include "libavutil/internal.h"
#include "avcodec.h"
#include "h261.h"
@@ -47,8 +48,8 @@ static void gmc1_motion(MpegEncContext *s,
motion_y = s->sprite_offset[0][1];
src_x = s->mb_x * 16 + (motion_x >> (s->sprite_warping_accuracy + 1));
src_y = s->mb_y * 16 + (motion_y >> (s->sprite_warping_accuracy + 1));
- motion_x <<= (3 - s->sprite_warping_accuracy);
- motion_y <<= (3 - s->sprite_warping_accuracy);
+ motion_x *= 1 << (3 - s->sprite_warping_accuracy);
+ motion_y *= 1 << (3 - s->sprite_warping_accuracy);
src_x = av_clip(src_x, -16, s->width);
if (src_x == s->width)
motion_x = 0;
@@ -94,8 +95,8 @@ static void gmc1_motion(MpegEncContext *s,
motion_y = s->sprite_offset[1][1];
src_x = s->mb_x * 8 + (motion_x >> (s->sprite_warping_accuracy + 1));
src_y = s->mb_y * 8 + (motion_y >> (s->sprite_warping_accuracy + 1));
- motion_x <<= (3 - s->sprite_warping_accuracy);
- motion_y <<= (3 - s->sprite_warping_accuracy);
+ motion_x *= 1 << (3 - s->sprite_warping_accuracy);
+ motion_y *= 1 << (3 - s->sprite_warping_accuracy);
src_x = av_clip(src_x, -8, s->width >> 1);
if (src_x == s->width >> 1)
motion_x = 0;
@@ -178,7 +179,7 @@ static void gmc_motion(MpegEncContext *s,
s->sprite_delta[0][0], s->sprite_delta[0][1],
s->sprite_delta[1][0], s->sprite_delta[1][1],
a + 1, (1 << (2 * a + 1)) - s->no_rounding,
- s->h_edge_pos >> 1, s->v_edge_pos >> 1);
+ (s->h_edge_pos + 1) >> 1, (s->v_edge_pos + 1) >> 1);
ptr = ref_picture[2];
s->mdsp.gmc(dest_cr, ptr, uvlinesize, 8,
@@ -186,7 +187,7 @@ static void gmc_motion(MpegEncContext *s,
s->sprite_delta[0][0], s->sprite_delta[0][1],
s->sprite_delta[1][0], s->sprite_delta[1][1],
a + 1, (1 << (2 * a + 1)) - s->no_rounding,
- s->h_edge_pos >> 1, s->v_edge_pos >> 1);
+ (s->h_edge_pos + 1) >> 1, (s->v_edge_pos + 1) >> 1);
}
static inline int hpel_motion(MpegEncContext *s,
@@ -210,52 +211,21 @@ static inline int hpel_motion(MpegEncContext *s,
dxy |= (motion_y & 1) << 1;
src += src_y * s->linesize + src_x;
- if ((unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x & 1) - 8, 0) ||
- (unsigned)src_y > FFMAX(s->v_edge_pos - (motion_y & 1) - 8, 0)) {
- s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, src,
- s->linesize, s->linesize,
- 9, 9, src_x, src_y,
- s->h_edge_pos, s->v_edge_pos);
- src = s->sc.edge_emu_buffer;
- emu = 1;
- }
+ if ((unsigned)src_x >= FFMAX(s->h_edge_pos - (motion_x & 1) - 7, 0) ||
+ (unsigned)src_y >= FFMAX(s->v_edge_pos - (motion_y & 1) - 7, 0)) {
+ s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, src,
+ s->linesize, s->linesize,
+ 9, 9,
+ src_x, src_y,
+ s->h_edge_pos, s->v_edge_pos);
+ src = s->sc.edge_emu_buffer;
+ emu = 1;
+ }
pix_op[dxy](dest, src, s->linesize, 8);
return emu;
}
static av_always_inline
-void emulated_edge_mc(MpegEncContext *s,
- int src_x, int src_y,
- int uvsrc_x, int uvsrc_y,
- int field_based,
- uint8_t **ptr_y,
- uint8_t **ptr_cb,
- uint8_t **ptr_cr)
-{
- s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, *ptr_y,
- s->linesize, s->linesize,
- 17, 17 + field_based,
- src_x, src_y * (1 << field_based),
- s->h_edge_pos, s->v_edge_pos);
- *ptr_y = s->sc.edge_emu_buffer;
- if (!CONFIG_GRAY || !(s->avctx->flags & AV_CODEC_FLAG_GRAY)) {
- uint8_t *uvbuf = s->sc.edge_emu_buffer + 18 * s->linesize;
- s->vdsp.emulated_edge_mc(uvbuf, *ptr_cb,
- s->uvlinesize, s->uvlinesize,
- 9, 9 + field_based,
- uvsrc_x, uvsrc_y * (1 << field_based),
- s->h_edge_pos >> 1, s->v_edge_pos >> 1);
- s->vdsp.emulated_edge_mc(uvbuf + 16, *ptr_cr,
- s->uvlinesize, s->uvlinesize,
- 9, 9 + field_based,
- uvsrc_x, uvsrc_y * (1 << field_based),
- s->h_edge_pos >> 1, s->v_edge_pos >> 1);
- *ptr_cb = uvbuf;
- *ptr_cr = uvbuf + 16;
- }
-}
-
-static av_always_inline
void mpeg_motion_internal(MpegEncContext *s,
uint8_t *dest_y,
uint8_t *dest_cb,
@@ -269,20 +239,22 @@ void mpeg_motion_internal(MpegEncContext *s,
int motion_y,
int h,
int is_mpeg12,
+ int is_16x8,
int mb_y)
{
uint8_t *ptr_y, *ptr_cb, *ptr_cr;
int dxy, uvdxy, mx, my, src_x, src_y,
- uvsrc_x, uvsrc_y, v_edge_pos;
+ uvsrc_x, uvsrc_y, v_edge_pos, block_y_half;
ptrdiff_t uvlinesize, linesize;
v_edge_pos = s->v_edge_pos >> field_based;
linesize = s->current_picture.f->linesize[0] << field_based;
uvlinesize = s->current_picture.f->linesize[1] << field_based;
+ block_y_half = (field_based | is_16x8);
dxy = ((motion_y & 1) << 1) | (motion_x & 1);
src_x = s->mb_x * 16 + (motion_x >> 1);
- src_y = (mb_y << (4 - field_based)) + (motion_y >> 1);
+ src_y = (mb_y << (4 - block_y_half)) + (motion_y >> 1);
if (!is_mpeg12 && s->out_format == FMT_H263) {
if ((s->workaround_bugs & FF_BUG_HPEL_CHROMA) && field_based) {
@@ -290,7 +262,7 @@ void mpeg_motion_internal(MpegEncContext *s,
my = motion_y >> 1;
uvdxy = ((my & 1) << 1) | (mx & 1);
uvsrc_x = s->mb_x * 8 + (mx >> 1);
- uvsrc_y = (mb_y << (3 - field_based)) + (my >> 1);
+ uvsrc_y = (mb_y << (3 - block_y_half)) + (my >> 1);
} else {
uvdxy = dxy | (motion_y & 2) | ((motion_x & 2) >> 1);
uvsrc_x = src_x >> 1;
@@ -309,7 +281,7 @@ void mpeg_motion_internal(MpegEncContext *s,
my = motion_y / 2;
uvdxy = ((my & 1) << 1) | (mx & 1);
uvsrc_x = s->mb_x * 8 + (mx >> 1);
- uvsrc_y = (mb_y << (3 - field_based)) + (my >> 1);
+ uvsrc_y = (mb_y << (3 - block_y_half)) + (my >> 1);
} else {
if (s->chroma_x_shift) {
// Chroma422
@@ -330,8 +302,8 @@ void mpeg_motion_internal(MpegEncContext *s,
ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x;
ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x;
- if ((unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x & 1) - 16, 0) ||
- (unsigned)src_y > FFMAX(v_edge_pos - (motion_y & 1) - h, 0)) {
+ if ((unsigned)src_x >= FFMAX(s->h_edge_pos - (motion_x & 1) - 15 , 0) ||
+ (unsigned)src_y >= FFMAX( v_edge_pos - (motion_y & 1) - h + 1, 0)) {
if (is_mpeg12 ||
s->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
s->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
@@ -340,8 +312,32 @@ void mpeg_motion_internal(MpegEncContext *s,
src_y);
return;
}
- emulated_edge_mc(s, src_x, src_y, uvsrc_x, uvsrc_y, field_based,
- &ptr_y, &ptr_cb, &ptr_cr);
+ src_y = (unsigned)src_y << field_based;
+ s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr_y,
+ s->linesize, s->linesize,
+ 17, 17 + field_based,
+ src_x, src_y,
+ s->h_edge_pos, s->v_edge_pos);
+ ptr_y = s->sc.edge_emu_buffer;
+ if (!CONFIG_GRAY || !(s->avctx->flags & AV_CODEC_FLAG_GRAY)) {
+ uint8_t *ubuf = s->sc.edge_emu_buffer + 18 * s->linesize;
+ uint8_t *vbuf = ubuf + 10 * s->uvlinesize;
+ if (s->workaround_bugs & FF_BUG_IEDGE)
+ vbuf -= s->uvlinesize;
+ uvsrc_y = (unsigned)uvsrc_y << field_based;
+ s->vdsp.emulated_edge_mc(ubuf, ptr_cb,
+ s->uvlinesize, s->uvlinesize,
+ 9, 9 + field_based,
+ uvsrc_x, uvsrc_y,
+ s->h_edge_pos >> 1, s->v_edge_pos >> 1);
+ s->vdsp.emulated_edge_mc(vbuf, ptr_cr,
+ s->uvlinesize, s->uvlinesize,
+ 9, 9 + field_based,
+ uvsrc_x, uvsrc_y,
+ s->h_edge_pos >> 1, s->v_edge_pos >> 1);
+ ptr_cb = ubuf;
+ ptr_cr = vbuf;
+ }
}
/* FIXME use this for field pix too instead of the obnoxious hack which
@@ -376,18 +372,18 @@ static void mpeg_motion(MpegEncContext *s,
uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
int field_select, uint8_t **ref_picture,
op_pixels_func (*pix_op)[4],
- int motion_x, int motion_y, int h, int mb_y)
+ int motion_x, int motion_y, int h, int is_16x8, int mb_y)
{
#if !CONFIG_SMALL
if (s->out_format == FMT_MPEG1)
mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 0, 0,
field_select, ref_picture, pix_op,
- motion_x, motion_y, h, 1, mb_y);
+ motion_x, motion_y, h, 1, is_16x8, mb_y);
else
#endif
mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 0, 0,
field_select, ref_picture, pix_op,
- motion_x, motion_y, h, 0, mb_y);
+ motion_x, motion_y, h, 0, is_16x8, mb_y);
}
static void mpeg_motion_field(MpegEncContext *s, uint8_t *dest_y,
@@ -398,15 +394,15 @@ static void mpeg_motion_field(MpegEncContext *s, uint8_t *dest_y,
int motion_x, int motion_y, int h, int mb_y)
{
#if !CONFIG_SMALL
- if(s->out_format == FMT_MPEG1)
+ if (s->out_format == FMT_MPEG1)
mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 1,
bottom_field, field_select, ref_picture, pix_op,
- motion_x, motion_y, h, 1, mb_y);
+ motion_x, motion_y, h, 1, 0, mb_y);
else
#endif
mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 1,
bottom_field, field_select, ref_picture, pix_op,
- motion_x, motion_y, h, 0, mb_y);
+ motion_x, motion_y, h, 0, 0, mb_y);
}
// FIXME: SIMDify, avg variant, 16x16 version
@@ -473,7 +469,7 @@ static inline void obmc_motion(MpegEncContext *s,
int i;
uint8_t *ptr[5];
- assert(s->quarter_sample == 0);
+ av_assert2(s->quarter_sample == 0);
for (i = 0; i < 5; i++) {
if (i && mv[i][0] == mv[MID][0] && mv[i][1] == mv[MID][1]) {
@@ -540,10 +536,32 @@ static inline void qpel_motion(MpegEncContext *s,
ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x;
ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x;
- if ((unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x & 3) - 16, 0) ||
- (unsigned)src_y > FFMAX(v_edge_pos - (motion_y & 3) - h, 0)) {
- emulated_edge_mc(s, src_x, src_y, uvsrc_x, uvsrc_y, field_based,
- &ptr_y, &ptr_cb, &ptr_cr);
+ if ((unsigned)src_x >= FFMAX(s->h_edge_pos - (motion_x & 3) - 15 , 0) ||
+ (unsigned)src_y >= FFMAX( v_edge_pos - (motion_y & 3) - h + 1, 0)) {
+ s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr_y,
+ s->linesize, s->linesize,
+ 17, 17 + field_based,
+ src_x, src_y * (1 << field_based),
+ s->h_edge_pos, s->v_edge_pos);
+ ptr_y = s->sc.edge_emu_buffer;
+ if (!CONFIG_GRAY || !(s->avctx->flags & AV_CODEC_FLAG_GRAY)) {
+ uint8_t *ubuf = s->sc.edge_emu_buffer + 18 * s->linesize;
+ uint8_t *vbuf = ubuf + 10 * s->uvlinesize;
+ if (s->workaround_bugs & FF_BUG_IEDGE)
+ vbuf -= s->uvlinesize;
+ s->vdsp.emulated_edge_mc(ubuf, ptr_cb,
+ s->uvlinesize, s->uvlinesize,
+ 9, 9 + field_based,
+ uvsrc_x, uvsrc_y * (1 << field_based),
+ s->h_edge_pos >> 1, s->v_edge_pos >> 1);
+ s->vdsp.emulated_edge_mc(vbuf, ptr_cr,
+ s->uvlinesize, s->uvlinesize,
+ 9, 9 + field_based,
+ uvsrc_x, uvsrc_y * (1 << field_based),
+ s->h_edge_pos >> 1, s->v_edge_pos >> 1);
+ ptr_cb = ubuf;
+ ptr_cr = vbuf;
+ }
}
if (!field_based)
@@ -604,8 +622,8 @@ static void chroma_4mv_motion(MpegEncContext *s,
offset = src_y * s->uvlinesize + src_x;
ptr = ref_picture[1] + offset;
- if ((unsigned)src_x > FFMAX((s->h_edge_pos >> 1) - (dxy & 1) - 8, 0) ||
- (unsigned)src_y > FFMAX((s->v_edge_pos >> 1) - (dxy >> 1) - 8, 0)) {
+ if ((unsigned)src_x >= FFMAX((s->h_edge_pos >> 1) - (dxy & 1) - 7, 0) ||
+ (unsigned)src_y >= FFMAX((s->v_edge_pos >> 1) - (dxy >> 1) - 7, 0)) {
s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
s->uvlinesize, s->uvlinesize,
9, 9, src_x, src_y,
@@ -656,7 +674,7 @@ static inline void apply_obmc(MpegEncContext *s,
const int mot_xy = mb_x * 2 + mb_y * 2 * mot_stride;
int mx, my, i;
- assert(!s->mb_skipped);
+ av_assert2(!s->mb_skipped);
AV_COPY32(mv_cache[1][1], cur_frame->motion_val[0][mot_xy]);
AV_COPY32(mv_cache[1][2], cur_frame->motion_val[0][mot_xy + 1]);
@@ -762,8 +780,8 @@ static inline void apply_8x8(MpegEncContext *s,
dxy &= ~12;
ptr = ref_picture[0] + (src_y * s->linesize) + (src_x);
- 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)) {
+ if ((unsigned)src_x >= FFMAX(s->h_edge_pos - (motion_x & 3) - 7, 0) ||
+ (unsigned)src_y >= FFMAX(s->v_edge_pos - (motion_y & 3) - 7, 0)) {
s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
s->linesize, s->linesize,
9, 9,
@@ -854,7 +872,7 @@ static av_always_inline void mpv_motion_internal(MpegEncContext *s,
} else {
mpeg_motion(s, dest_y, dest_cb, dest_cr, 0,
ref_picture, pix_op,
- s->mv[dir][0][0], s->mv[dir][0][1], 16, mb_y);
+ s->mv[dir][0][0], s->mv[dir][0][1], 16, 0, mb_y);
}
break;
case MV_TYPE_8X8:
@@ -883,23 +901,23 @@ static av_always_inline void mpv_motion_internal(MpegEncContext *s,
s->mv[dir][1][0], s->mv[dir][1][1], 8, mb_y);
}
} else {
- if (s->picture_structure != s->field_select[dir][0] + 1 &&
- s->pict_type != AV_PICTURE_TYPE_B && !s->first_field) {
+ if ( s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != AV_PICTURE_TYPE_B && !s->first_field
+ || !ref_picture[0]) {
ref_picture = s->current_picture_ptr->f->data;
}
mpeg_motion(s, dest_y, dest_cb, dest_cr,
s->field_select[dir][0],
ref_picture, pix_op,
- s->mv[dir][0][0], s->mv[dir][0][1], 16, mb_y >> 1);
+ s->mv[dir][0][0], s->mv[dir][0][1], 16, 0, mb_y >> 1);
}
break;
case MV_TYPE_16X8:
for (i = 0; i < 2; i++) {
uint8_t **ref2picture;
- if (s->picture_structure == s->field_select[dir][i] + 1
- || s->pict_type == AV_PICTURE_TYPE_B || s->first_field) {
+ if ((s->picture_structure == s->field_select[dir][i] + 1
+ || s->pict_type == AV_PICTURE_TYPE_B || s->first_field) && ref_picture[0]) {
ref2picture = ref_picture;
} else {
ref2picture = s->current_picture_ptr->f->data;
@@ -908,8 +926,8 @@ static av_always_inline void mpv_motion_internal(MpegEncContext *s,
mpeg_motion(s, dest_y, dest_cb, dest_cr,
s->field_select[dir][i],
ref2picture, pix_op,
- s->mv[dir][i][0], s->mv[dir][i][1] + 16 * i,
- 8, mb_y >> 1);
+ s->mv[dir][i][0], s->mv[dir][i][1],
+ 8, 1, (mb_y & ~1) + i);
dest_y += 16 * s->linesize;
dest_cb += (16 >> s->chroma_y_shift) * s->uvlinesize;
@@ -928,12 +946,15 @@ static av_always_inline void mpv_motion_internal(MpegEncContext *s,
pix_op = s->hdsp.avg_pixels_tab;
}
} else {
+ if (!ref_picture[0]) {
+ ref_picture = s->current_picture_ptr->f->data;
+ }
for (i = 0; i < 2; i++) {
mpeg_motion(s, dest_y, dest_cb, dest_cr,
s->picture_structure != i + 1,
ref_picture, pix_op,
s->mv[dir][2 * i][0], s->mv[dir][2 * i][1],
- 16, mb_y >> 1);
+ 16, 0, mb_y >> 1);
// after put we make avg of the same block
pix_op = s->hdsp.avg_pixels_tab;
@@ -946,7 +967,7 @@ static av_always_inline void mpv_motion_internal(MpegEncContext *s,
}
}
break;
- default: assert(0);
+ default: av_assert2(0);
}
}