[Ffmpeg-devel] interlace and motion artifacts
Dan Maas
dmaas
Wed Feb 15 20:55:25 CET 2006
> If the input is 480i or 1080i, the output often (not always)
> has massive amounts of motion artifacts.
I had this problem yesterday while transcoding from MPEG-2 to DV. The
field order of the resulting DV video was obviously wrong.
The solution is to shift the video image up or down by one
scanline. Unfortunately, ffmpeg's -pad/-crop options do not
work in increments of one pixel.
So, I hacked myself a new command-line switch that cycles the image up
by one scanline. Attached. Use "-shift 1" to reverse the field
order. I only implented this for PIX_FMT_YUV422P but it should be
easy to do for other formats.
Regards,
Dan
-------------- next part --------------
Index: ffmpeg.c
===================================================================
RCS file: /cvsroot/ffmpeg/ffmpeg/ffmpeg.c,v
retrieving revision 1.368
diff -u -p -r1.368 ffmpeg.c
--- ffmpeg.c 1 Feb 2006 11:31:33 -0000 1.368
+++ ffmpeg.c 15 Feb 2006 19:52:46 -0000
@@ -100,6 +100,7 @@ static int frame_topBand = 0;
static int frame_bottomBand = 0;
static int frame_leftBand = 0;
static int frame_rightBand = 0;
+static int frame_shift = 0;
static int max_frames[4] = {INT_MAX, INT_MAX, INT_MAX, INT_MAX};
static int frame_rate = 25;
static int frame_rate_base = 1;
@@ -280,6 +281,8 @@ typedef struct AVOutputStream {
int padleft;
int padright;
+ int video_shift; /* shift by N scanlines for manipulating field order */
+
/* audio only */
int audio_resample;
ReSampleContext *resample; /* for audio resampling */
@@ -913,6 +916,31 @@ static void do_video_out(AVFormatContext
} else {
final_picture = formatted_picture;
}
+
+ if(ost->video_shift != 0) {
+ uint8_t *tempbuf;
+ int chan;
+
+ if(enc->pix_fmt != PIX_FMT_YUV422P) {
+ fprintf(stderr, "shift only works in 4:2:2 mode\n");
+ goto the_end;
+ }
+
+ tempbuf = alloca(final_picture->linesize[0]);
+
+ for(chan = 0; chan < 3; chan++) {
+ int y;
+ memcpy(tempbuf, final_picture->data[chan], final_picture->linesize[chan]);
+ for(y = 1; y < enc->height; y++) {
+ memcpy(final_picture->data[chan] + (y-1)*final_picture->linesize[chan],
+ final_picture->data[chan] + (y)*final_picture->linesize[chan],
+ final_picture->linesize[chan]);
+ }
+ memcpy(final_picture->data[chan] + (enc->height-1) * final_picture->linesize[chan],
+ tempbuf, final_picture->linesize[chan]);
+ }
+ }
+
/* duplicates frame if needed */
for(i=0;i<nb_frames;i++) {
AVPacket pkt;
@@ -1771,6 +1799,7 @@ static int av_encode(AVFormatContext **o
ost->padright = frame_padright;
}
+ ost->video_shift = frame_shift;
ost->encoding_needed = 1;
ist->decoding_needed = 1;
break;
@@ -2450,6 +2479,14 @@ static void opt_frame_pad_right(const ch
}
}
+static void opt_frame_shift(const char *arg)
+{
+ frame_shift = atoi(arg);
+ if (frame_shift < -1 || frame_shift > 1) {
+ fprintf(stderr, "Frame shift must be -1, 0, or 1\n");
+ exit(1);
+ }
+}
static void opt_frame_pix_fmt(const char *arg)
{
@@ -4053,6 +4090,7 @@ const OptionDef options[] = {
{ "padleft", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_left}, "set left pad band size (in pixels)", "size" },
{ "padright", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_right}, "set right pad band size (in pixels)", "size" },
{ "padcolor", HAS_ARG | OPT_VIDEO, {(void*)opt_pad_color}, "set color of pad bands (Hex 000000 thru FFFFFF)", "color" },
+ { "shift", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_shift}, "shift image up or down by 1 pixel to change field order (-1, 0, or 1)", "size" },
{ "g", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_gop_size}, "set the group of picture size", "gop_size" },
{ "intra", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_only}, "use only intra frames"},
{ "vn", OPT_BOOL | OPT_VIDEO, {(void*)&video_disable}, "disable video" },
More information about the ffmpeg-devel
mailing list