diff options
author | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2004-07-17 16:35:16 +0000 |
---|---|---|
committer | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2004-07-17 16:35:16 +0000 |
commit | e08f2fd5ee57a6147bd68b5be675222e79a27a39 (patch) | |
tree | 3169262f3063191505312c0a907d37a8d11d0f10 | |
parent | 4687279d233833ee188029c0316364d2e4719416 (diff) | |
download | xine-lib-e08f2fd5ee57a6147bd68b5be675222e79a27a39.tar.gz xine-lib-e08f2fd5ee57a6147bd68b5be675222e79a27a39.tar.bz2 |
Ryan Tadlock's patch for compensating the field delay of some deinterlacing algorithms
CVS patchset: 6801
CVS date: 2004/07/17 16:35:16
-rw-r--r-- | src/post/deinterlace/deinterlace.h | 1 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/double.c | 1 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/greedy.c | 3 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/greedy2frame.c | 3 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/linear.c | 1 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/linearblend.c | 2 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/scalerbob.c | 1 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/vfir.c | 1 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/weave.c | 1 | ||||
-rw-r--r-- | src/post/deinterlace/xine_plugin.c | 156 |
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] ) |