summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/post/deinterlace/deinterlace.h1
-rw-r--r--src/post/deinterlace/plugins/double.c1
-rw-r--r--src/post/deinterlace/plugins/greedy.c3
-rw-r--r--src/post/deinterlace/plugins/greedy2frame.c3
-rw-r--r--src/post/deinterlace/plugins/linear.c1
-rw-r--r--src/post/deinterlace/plugins/linearblend.c2
-rw-r--r--src/post/deinterlace/plugins/scalerbob.c1
-rw-r--r--src/post/deinterlace/plugins/vfir.c1
-rw-r--r--src/post/deinterlace/plugins/weave.c1
-rw-r--r--src/post/deinterlace/xine_plugin.c156
10 files changed, 110 insertions, 60 deletions
diff --git a/src/post/deinterlace/deinterlace.h b/src/post/deinterlace/deinterlace.h
index 6475aaefd..8fa65224d 100644
--- a/src/post/deinterlace/deinterlace.h
+++ b/src/post/deinterlace/deinterlace.h
@@ -169,6 +169,7 @@ struct deinterlace_method_s
deinterlace_interp_scanline_t interpolate_scanline;
deinterlace_copy_scanline_t copy_scanline;
deinterlace_frame_t deinterlace_frame;
+ int delaysfield; /* delays output by one field relative to input */
};
/**
diff --git a/src/post/deinterlace/plugins/double.c b/src/post/deinterlace/plugins/double.c
index b2d9ba8ca..bb9c6c790 100644
--- a/src/post/deinterlace/plugins/double.c
+++ b/src/post/deinterlace/plugins/double.c
@@ -62,6 +62,7 @@ static deinterlace_method_t doublemethod =
1,
deinterlace_scanline_double,
copy_scanline,
+ 0,
0
};
diff --git a/src/post/deinterlace/plugins/greedy.c b/src/post/deinterlace/plugins/greedy.c
index 68792734e..07f17acfa 100644
--- a/src/post/deinterlace/plugins/greedy.c
+++ b/src/post/deinterlace/plugins/greedy.c
@@ -187,7 +187,8 @@ static deinterlace_method_t greedymethod =
1,
copy_scanline,
deinterlace_greedy_packed422_scanline_mmxext,
- 0
+ 0,
+ 1
};
#ifdef BUILD_TVTIME_PLUGINS
diff --git a/src/post/deinterlace/plugins/greedy2frame.c b/src/post/deinterlace/plugins/greedy2frame.c
index 5a54bf53e..739f13538 100644
--- a/src/post/deinterlace/plugins/greedy2frame.c
+++ b/src/post/deinterlace/plugins/greedy2frame.c
@@ -82,7 +82,8 @@ static deinterlace_method_t greedymethod =
0,
0,
0,
- DeinterlaceGreedy2Frame_SSE
+ DeinterlaceGreedy2Frame_SSE,
+ 1
};
#ifdef BUILD_TVTIME_PLUGINS
diff --git a/src/post/deinterlace/plugins/linear.c b/src/post/deinterlace/plugins/linear.c
index f5cc92e1b..a3488da70 100644
--- a/src/post/deinterlace/plugins/linear.c
+++ b/src/post/deinterlace/plugins/linear.c
@@ -60,6 +60,7 @@ static deinterlace_method_t linearmethod =
1,
deinterlace_scanline_linear,
copy_scanline,
+ 0,
0
};
diff --git a/src/post/deinterlace/plugins/linearblend.c b/src/post/deinterlace/plugins/linearblend.c
index 372db5ce1..abde146db 100644
--- a/src/post/deinterlace/plugins/linearblend.c
+++ b/src/post/deinterlace/plugins/linearblend.c
@@ -317,6 +317,7 @@ static deinterlace_method_t linearblendmethod_mmxext =
1,
deinterlace_scanline_linear_blend_mmxext,
deinterlace_scanline_linear_blend2_mmxext,
+ 0,
0
};
@@ -339,6 +340,7 @@ static deinterlace_method_t linearblendmethod =
1,
deinterlace_scanline_linear_blend,
deinterlace_scanline_linear_blend2,
+ 0,
0
};
diff --git a/src/post/deinterlace/plugins/scalerbob.c b/src/post/deinterlace/plugins/scalerbob.c
index 0f9dd2777..e0f4dbf5e 100644
--- a/src/post/deinterlace/plugins/scalerbob.c
+++ b/src/post/deinterlace/plugins/scalerbob.c
@@ -48,6 +48,7 @@ static deinterlace_method_t scalerbobmethod =
1,
0,
0,
+ 0,
0
};
diff --git a/src/post/deinterlace/plugins/vfir.c b/src/post/deinterlace/plugins/vfir.c
index 9a2d89ee8..b2d8fe0d4 100644
--- a/src/post/deinterlace/plugins/vfir.c
+++ b/src/post/deinterlace/plugins/vfir.c
@@ -156,6 +156,7 @@ static deinterlace_method_t vfirmethod =
1,
deinterlace_scanline_vfir,
copy_scanline,
+ 0,
0
};
diff --git a/src/post/deinterlace/plugins/weave.c b/src/post/deinterlace/plugins/weave.c
index 109cafe2d..95fa979d2 100644
--- a/src/post/deinterlace/plugins/weave.c
+++ b/src/post/deinterlace/plugins/weave.c
@@ -62,6 +62,7 @@ static deinterlace_method_t weavemethod =
1,
deinterlace_scanline_weave,
copy_scanline,
+ 0,
0
};
diff --git a/src/post/deinterlace/xine_plugin.c b/src/post/deinterlace/xine_plugin.c
index 64c2762e5..cb54d6870 100644
--- a/src/post/deinterlace/xine_plugin.c
+++ b/src/post/deinterlace/xine_plugin.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine_plugin.c,v 1.34 2004/07/14 02:44:15 miguelfreitas Exp $
+ * $Id: xine_plugin.c,v 1.35 2004/07/17 16:35:16 miguelfreitas Exp $
*
* advanced video deinterlacer plugin
* Jun/2003 by Miguel Freitas
@@ -645,7 +645,9 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream)
post_plugin_deinterlace_t *this = (post_plugin_deinterlace_t *)port->post;
vo_frame_t *orig_frame;
vo_frame_t *yuy2_frame;
- int i, skip, progressive = 0;
+ int i, skip = 0, progressive = 0;
+ int fields[2];
+ int framerate_mode;
orig_frame = frame;
_x_post_frame_copy_down(frame, frame->next);
@@ -673,16 +675,30 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream)
frame->progressive_frame, frame->repeat_first_field,
frame->top_field_first, frame->duration);
- /* this should be used to detect any special rff pattern */
+ /* detect special rff patterns */
this->rff_pattern = this->rff_pattern << 1;
this->rff_pattern |= !!frame->repeat_first_field;
if( ((this->rff_pattern & 0xff) == 0xaa ||
(this->rff_pattern & 0xff) == 0x55) ) {
- /* special case for ntsc 3:2 pulldown */
+ /*
+ * special case for ntsc 3:2 pulldown (called flags or soft pulldown).
+ * we know all frames are indeed progressive.
+ */
progressive = 1;
}
+ /* using frame->progressive_frame may help displaying still menus.
+ * however, it is known that some rare material set it wrong.
+ *
+ * we also assume that repeat_first_field is progressive (it doesn't
+ * make much sense to display interlaced fields out of order)
+ */
+ if( this->use_progressive_frame_flag &&
+ (frame->repeat_first_field || frame->progressive_frame) ) {
+ progressive = 1;
+ }
+
if( !frame->bad_frame &&
(frame->flags & VO_INTERLACED_FLAG) &&
this->tvtime->curmethod ) {
@@ -724,70 +740,91 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream)
}
}
-
- /* using frame->progressive_frame may help displaying still menus.
- * however, it is known that some rare material set it wrong.
- *
- * we assume that repeat_first_field is progressive (it doesn't make
- * much sense to display interlaced fields out of order)
- */
- if( progressive || frame->repeat_first_field ||
- (this->use_progressive_frame_flag && frame->progressive_frame) ) {
-
+ if( !this->cheap_mode ) {
+ framerate_mode = this->framerate_mode;
+ this->tvtime->pulldown_alg = this->pulldown;
+ } else {
+ framerate_mode = FRAMERATE_HALF_TFF;
+ this->tvtime->pulldown_alg = PULLDOWN_NONE;
+ }
+
+ if( framerate_mode == FRAMERATE_FULL ) {
+ int top_field_first = frame->top_field_first;
+
+ /* if i understood mpeg2 specs correctly, top_field_first
+ * shall be zero for field pictures and the output order
+ * is the same that the fields are decoded.
+ * frame->flags allow us to find the first decoded field.
+ *
+ * note: frame->field() is called later to switch decoded
+ * field but frame->flags do not change.
+ */
+ if ( (frame->flags & VO_BOTH_FIELDS) != VO_BOTH_FIELDS ) {
+ top_field_first = (frame->flags & VO_TOP_FIELD) ? 1 : 0;
+ }
+
+ if ( top_field_first ) {
+ fields[0] = 0;
+ fields[1] = 1;
+ } else {
+ fields[0] = 1;
+ fields[1] = 0;
+ }
+ } else if ( framerate_mode == FRAMERATE_HALF_TFF ) {
+ fields[0] = 0;
+ } else if ( framerate_mode == FRAMERATE_HALF_BFF ) {
+ fields[0] = 1;
+ }
+
+
+ if( progressive ) {
+
+ /* If the previous field was interlaced and this one is progressive
+ * we need to run a deinterlace on the first field of this frame
+ * in order to let output for the previous frames last field be
+ * generated. This is only necessary for the deinterlacers that
+ * delay output by one field. This is signaled by the delaysfield
+ * flag in the deinterlace method structure. The previous frames
+ * duration is used in the calculation because the generated frame
+ * represents the second half of the previous frame.
+ */
+ if (this->recent_frame[0] && !this->recent_frame[0]->progressive_frame &&
+ this->tvtime->curmethod->delaysfield)
+ {
+ skip = deinterlace_build_output_field(
+ this, port, stream,
+ frame, yuy2_frame,
+ fields[0], 0,
+ 0,
+ (framerate_mode == FRAMERATE_FULL) ? this->recent_frame[0]->duration/2 : this->recent_frame[0]->duration,
+ 0);
+ }
pthread_mutex_unlock (&this->lock);
skip = yuy2_frame->draw(yuy2_frame, stream);
pthread_mutex_lock (&this->lock);
_x_post_frame_copy_up(frame, yuy2_frame);
} else {
- int fields[2];
- int framerate_mode;
- if( !this->cheap_mode ) {
- framerate_mode = this->framerate_mode;
- this->tvtime->pulldown_alg = this->pulldown;
- } else {
- framerate_mode = FRAMERATE_HALF_TFF;
- this->tvtime->pulldown_alg = PULLDOWN_NONE;
- }
- if( framerate_mode == FRAMERATE_FULL ) {
- int top_field_first = frame->top_field_first;
-
- /* if i understood mpeg2 specs correctly, top_field_first
- * shall be zero for field pictures and the output order
- * is the same that the fields are decoded.
- * frame->flags allow us to find the first decoded field.
- *
- * note: frame->field() is called later to switch decoded
- * field but frame->flags do not change.
- */
- if ( (frame->flags & VO_BOTH_FIELDS) != VO_BOTH_FIELDS ) {
- top_field_first = (frame->flags & VO_TOP_FIELD) ? 1 : 0;
- }
-
- if ( top_field_first ) {
- fields[0] = 0;
- fields[1] = 1;
- } else {
- fields[0] = 1;
- fields[1] = 0;
- }
- } else if ( framerate_mode == FRAMERATE_HALF_TFF ) {
- fields[0] = 0;
- } else if ( framerate_mode == FRAMERATE_HALF_BFF ) {
- fields[0] = 1;
- }
+ /* If the previous field was progressive and we are using a
+ * filter that delays it's output by one field then we need
+ * to skip the first field's output. Otherwise the effective
+ * display duration of the previous frame will be extended
+ * by 1/2 of this frames duration when output is generated
+ * using the last field of the progressive frame. */
/* Build the output from the first field. */
- skip = deinterlace_build_output_field(
- this, port, stream,
- frame, yuy2_frame,
- fields[0], 0,
- frame->pts,
- (framerate_mode == FRAMERATE_FULL) ? frame->duration/2 : frame->duration,
- 0);
-
+ if ( !(this->recent_frame[0] && this->recent_frame[0]->progressive_frame &&
+ this->tvtime->curmethod->delaysfield) ) {
+ skip = deinterlace_build_output_field(
+ this, port, stream,
+ frame, yuy2_frame,
+ fields[0], 0,
+ frame->pts,
+ (framerate_mode == FRAMERATE_FULL) ? frame->duration/2 : frame->duration,
+ 0);
+ }
if( framerate_mode == FRAMERATE_FULL ) {
@@ -808,6 +845,9 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream)
if( this->pulldown )
skip = 0;
+ /* store back progressive flag for frame history */
+ yuy2_frame->progressive_frame = progressive;
+
/* keep track of recent frames */
i = NUM_RECENT_FRAMES-1;
if( this->recent_frame[i] )