diff options
author | Ian Armstrong <ian@iarmst.demon.co.uk> | 2007-08-03 09:01:39 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-10-09 21:04:29 -0400 |
commit | bfd7beacff2b5c811badb587a74c3dfbf7f98721 (patch) | |
tree | 47628dfa13bc221e2a5466934830ca54a6f46bc0 /drivers/media/video/ivtv/ivtv-yuv.c | |
parent | 943e8910db31e36d945f2bf7d4c273ca5fa01f6e (diff) |
V4L/DVB (5973): ivtv: attach yuv field order to each frame
In the current driver, the field order is global. As soon as it's changed it
takes immediate effect. This is a problem when the video changes order mid
stream. Although it mostly works okay, the video may judder / flicker.
This patch attaches the field order to the frame, so that any buffered frames
will not be displayed until the correct field. In the event that the field
order is changed mid stream, the driver will ensure that the previous frame
is displayed for a minimum of 3 fields. These are the two original fields the
frame should have occupied, plus the one extra since the new frame still has
to wait for the correct field.
Signed-off-by: Ian Armstrong <ian@iarmst.demon.co.uk>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/ivtv/ivtv-yuv.c')
-rw-r--r-- | drivers/media/video/ivtv/ivtv-yuv.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index 5c94d3282c82..fa8c76f3d359 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c | |||
@@ -612,7 +612,6 @@ static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *wi | |||
612 | itv->yuv_info.v_filter_2 = v_filter_2; | 612 | itv->yuv_info.v_filter_2 = v_filter_2; |
613 | } | 613 | } |
614 | 614 | ||
615 | itv->yuv_info.frame_interlaced_last = itv->yuv_info.frame_interlaced; | ||
616 | } | 615 | } |
617 | 616 | ||
618 | /* Modify the supplied coordinate information to fit the visible osd area */ | 617 | /* Modify the supplied coordinate information to fit the visible osd area */ |
@@ -799,6 +798,7 @@ static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *windo | |||
799 | (itv->yuv_info.old_frame_info.src_y != window->src_y) || | 798 | (itv->yuv_info.old_frame_info.src_y != window->src_y) || |
800 | (itv->yuv_info.old_frame_info.pan_y != window->pan_y) || | 799 | (itv->yuv_info.old_frame_info.pan_y != window->pan_y) || |
801 | (itv->yuv_info.old_frame_info.vis_h != window->vis_h) || | 800 | (itv->yuv_info.old_frame_info.vis_h != window->vis_h) || |
801 | (itv->yuv_info.old_frame_info.lace_mode != window->lace_mode) || | ||
802 | (itv->yuv_info.old_frame_info.interlaced_y != window->interlaced_y) || | 802 | (itv->yuv_info.old_frame_info.interlaced_y != window->interlaced_y) || |
803 | (itv->yuv_info.old_frame_info.interlaced_uv != window->interlaced_uv)) { | 803 | (itv->yuv_info.old_frame_info.interlaced_uv != window->interlaced_uv)) { |
804 | yuv_update |= IVTV_YUV_UPDATE_VERTICAL; | 804 | yuv_update |= IVTV_YUV_UPDATE_VERTICAL; |
@@ -970,6 +970,9 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) | |||
970 | itv->yuv_info.new_frame_info[frame].tru_w = args->src_width; | 970 | itv->yuv_info.new_frame_info[frame].tru_w = args->src_width; |
971 | itv->yuv_info.new_frame_info[frame].tru_h = args->src_height; | 971 | itv->yuv_info.new_frame_info[frame].tru_h = args->src_height; |
972 | 972 | ||
973 | /* Snapshot field order */ | ||
974 | itv->yuv_info.sync_field[frame] = itv->yuv_info.lace_sync_field; | ||
975 | |||
973 | /* Are we going to offset the Y plane */ | 976 | /* Are we going to offset the Y plane */ |
974 | if (args->src.height + args->src.top < 512-16) | 977 | if (args->src.height + args->src.top < 512-16) |
975 | itv->yuv_info.new_frame_info[frame].offset_y = 1; | 978 | itv->yuv_info.new_frame_info[frame].offset_y = 1; |
@@ -985,6 +988,7 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) | |||
985 | itv->yuv_info.new_frame_info[frame].update = 0; | 988 | itv->yuv_info.new_frame_info[frame].update = 0; |
986 | itv->yuv_info.new_frame_info[frame].interlaced_y = 0; | 989 | itv->yuv_info.new_frame_info[frame].interlaced_y = 0; |
987 | itv->yuv_info.new_frame_info[frame].interlaced_uv = 0; | 990 | itv->yuv_info.new_frame_info[frame].interlaced_uv = 0; |
991 | itv->yuv_info.new_frame_info[frame].lace_mode = itv->yuv_info.lace_mode; | ||
988 | 992 | ||
989 | if (memcmp (&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame], | 993 | if (memcmp (&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame], |
990 | sizeof (itv->yuv_info.new_frame_info[frame]))) { | 994 | sizeof (itv->yuv_info.new_frame_info[frame]))) { |
@@ -995,6 +999,12 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) | |||
995 | 999 | ||
996 | itv->yuv_info.new_frame_info[frame].update |= register_update; | 1000 | itv->yuv_info.new_frame_info[frame].update |= register_update; |
997 | 1001 | ||
1002 | /* Should this frame be delayed ? */ | ||
1003 | if (itv->yuv_info.sync_field[frame] != itv->yuv_info.sync_field[(frame - 1) & 3]) | ||
1004 | itv->yuv_info.field_delay[frame] = 1; | ||
1005 | else | ||
1006 | itv->yuv_info.field_delay[frame] = 0; | ||
1007 | |||
998 | /* DMA the frame */ | 1008 | /* DMA the frame */ |
999 | mutex_lock(&itv->udma.lock); | 1009 | mutex_lock(&itv->udma.lock); |
1000 | 1010 | ||