[vlc-devel] commit: Implemented auto deinterlace mode. (Laurent Aimar )
git version control
git at videolan.org
Tue Oct 6 22:47:59 CEST 2009
vlc | branch: master | Laurent Aimar <fenrir at videolan.org> | Tue Oct 6 22:32:20 2009 +0200| [f96b075043c421fb6466829a15ae0c8792b8ffe8] | committer: Laurent Aimar
Implemented auto deinterlace mode.
The detection is based on the progressive/interlaced flags transported at
the codec level. As such, it is not really reliable (for 25fps at least).
As soon as a picture is detected as interlaced, the configured deinterlace
mode is applied. After 30s of progressive video, the filter is removed.
The hysteresis helps with unreliable interlaced flags.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=f96b075043c421fb6466829a15ae0c8792b8ffe8
---
src/video_output/video_output.c | 64 +++++++++++++++++++++++++++++++++-----
src/video_output/vout_internal.h | 1 +
src/video_output/vout_pictures.c | 1 +
3 files changed, 58 insertions(+), 8 deletions(-)
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index e8a0c80..7d9b4ba 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -92,6 +92,7 @@ static int PostProcessCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
/* */
static void DeinterlaceEnable( vout_thread_t * );
+static void DeinterlaceNeeded( vout_thread_t *, bool );
/* From vout_intf.c */
int vout_Snapshot( vout_thread_t *, picture_t * );
@@ -396,6 +397,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
p_vout->p->b_picture_displayed = false;
p_vout->p->b_picture_empty = false;
p_vout->p->i_picture_qtype = QTYPE_NONE;
+ p_vout->p->b_picture_interlaced = false;
vlc_mouse_Init( &p_vout->p->mouse );
@@ -974,6 +976,8 @@ static void* RunThread( void *p_this )
vout_thread_t *p_vout = p_this;
int i_idle_loops = 0; /* loops without displaying a picture */
int i_picture_qtype_last = QTYPE_NONE;
+ bool b_picture_interlaced_last = false;
+ mtime_t i_picture_interlaced_last_date;
vlc_mutex_lock( &p_vout->change_lock );
@@ -999,6 +1003,7 @@ static void* RunThread( void *p_this )
/* */
const bool b_drop_late = var_CreateGetBool( p_vout, "drop-late-frames" );
+ i_picture_interlaced_last_date = mdate();
/*
* Main loop - it is not executed if an error occurred during
@@ -1131,6 +1136,9 @@ static void* RunThread( void *p_this )
const int i_postproc_type = p_vout->p->i_picture_qtype;
const int i_postproc_state = (p_vout->p->i_picture_qtype != QTYPE_NONE) - (i_picture_qtype_last != QTYPE_NONE);
+ const bool b_picture_interlaced = p_vout->p->b_picture_interlaced;
+ const int i_picture_interlaced_state = (!!p_vout->p->b_picture_interlaced) - (!!b_picture_interlaced_last);
+
vlc_mutex_unlock( &p_vout->picture_lock );
if( p_picture == NULL )
@@ -1361,6 +1369,18 @@ static void* RunThread( void *p_this )
if( i_postproc_state != 0 )
i_picture_qtype_last = i_postproc_type;
+ /* Deinterlacing
+ * Wait 30s before quiting interlacing mode */
+ if( ( i_picture_interlaced_state == 1 ) ||
+ ( i_picture_interlaced_state == -1 && i_picture_interlaced_last_date + 30000000 < current_date ) )
+ {
+ DeinterlaceNeeded( p_vout, b_picture_interlaced );
+ b_picture_interlaced_last = b_picture_interlaced;
+ }
+ if( b_picture_interlaced )
+ i_picture_interlaced_last_date = current_date;
+
+
/* Check for "video filter2" changes */
vlc_mutex_lock( &p_vout->p->vfilter_lock );
if( p_vout->p->psz_vf2 )
@@ -1881,7 +1901,7 @@ static void DeinterlaceAdd( vout_thread_t *p_vout, bool b_vout_filter )
}
}
-static void DeinterlaceSave( vout_thread_t *p_vout, int i_deinterlace, const char *psz_mode )
+static void DeinterlaceSave( vout_thread_t *p_vout, int i_deinterlace, const char *psz_mode, bool is_needed )
{
/* We have to set input variable to ensure restart support
* XXX it is only needed because of vout-filter but must be done
@@ -1890,6 +1910,10 @@ static void DeinterlaceSave( vout_thread_t *p_vout, int i_deinterlace, const cha
if( !p_input )
return;
+ /* Another hack for "vout filter" mode */
+ if( i_deinterlace < 0 )
+ i_deinterlace = is_needed ? -2 : -3;
+
var_Create( p_input, "deinterlace", VLC_VAR_INTEGER );
var_SetInteger( p_input, "deinterlace", i_deinterlace );
@@ -1914,12 +1938,13 @@ static int DeinterlaceCallback( vlc_object_t *p_this, char const *psz_cmd,
vout_thread_t *p_vout = (vout_thread_t *)p_this;
/* */
- const int i_deinterlace = var_GetInteger( p_this, "deinterlace" );
- char *psz_mode = var_GetString( p_this, "deinterlace-mode" );
+ const int i_deinterlace = var_GetInteger( p_this, "deinterlace" );
+ char *psz_mode = var_GetString( p_this, "deinterlace-mode" );
+ const bool is_needed = var_GetBool( p_this, "deinterlace-needed" );
if( !psz_mode )
return VLC_EGENERIC;
- DeinterlaceSave( p_vout, i_deinterlace, psz_mode );
+ DeinterlaceSave( p_vout, i_deinterlace, psz_mode, is_needed );
/* */
bool b_vout_filter = true;
@@ -1944,15 +1969,14 @@ static int DeinterlaceCallback( vlc_object_t *p_this, char const *psz_cmd,
var_SetString( p_vout, "sout-deinterlace-mode", psz_mode );
}
- if( i_deinterlace == 0 )
+ msg_Dbg( p_vout, "deinterlace %d, mode %s, is_needed %d", i_deinterlace, psz_mode, is_needed );
+ if( i_deinterlace == 0 || ( i_deinterlace == -1 && !is_needed ) )
{
DeinterlaceRemove( p_vout, false );
DeinterlaceRemove( p_vout, true );
}
else
{
- /* TODO auto mode(-1)
- * It is assumed equal to "on" for now */
if( !DeinterlaceIsPresent( p_vout, b_vout_filter ) )
{
DeinterlaceRemove( p_vout, !b_vout_filter );
@@ -2015,6 +2039,9 @@ static void DeinterlaceEnable( vout_thread_t *p_vout )
var_Change( p_vout, "deinterlace-mode", VLC_VAR_ADDCHOICE, &val, &text );
}
var_AddCallback( p_vout, "deinterlace-mode", DeinterlaceCallback, NULL );
+ /* */
+ var_Create( p_vout, "deinterlace-needed", VLC_VAR_BOOL );
+ var_AddCallback( p_vout, "deinterlace-needed", DeinterlaceCallback, NULL );
/* Override the initial value from filters if present */
char *psz_filter_mode = NULL;
@@ -2025,15 +2052,36 @@ static void DeinterlaceEnable( vout_thread_t *p_vout )
if( psz_filter_mode )
{
free( psz_deinterlace );
- i_deinterlace = 1;
+ if( i_deinterlace >= -1 )
+ i_deinterlace = 1;
psz_deinterlace = psz_filter_mode;
}
/* */
+ bool is_needed;
+ if( i_deinterlace == -2 )
+ is_needed = true;
+ else if( i_deinterlace == -3 )
+ is_needed = false;
+ if( i_deinterlace < 0 )
+ i_deinterlace = -1;
+
+ p_vout->p->b_picture_interlaced == is_needed;
+
+ /* */
val.psz_string = psz_deinterlace ? psz_deinterlace : p_optm->orig.psz;
var_Change( p_vout, "deinterlace-mode", VLC_VAR_SETVALUE, &val, NULL );
+ val.b_bool = is_needed;
+ var_Change( p_vout, "deinterlace-needed", VLC_VAR_SETVALUE, &val, NULL );
var_SetInteger( p_vout, "deinterlace", i_deinterlace );
free( psz_deinterlace );
}
+static void DeinterlaceNeeded( vout_thread_t *p_vout, bool is_interlaced )
+{
+ msg_Dbg( p_vout, "Detected %s video",
+ is_interlaced ? "interlaced" : "progressive" );
+ var_SetBool( p_vout, "deinterlace-needed", is_interlaced );
+}
+
diff --git a/src/video_output/vout_internal.h b/src/video_output/vout_internal.h
index c5750b3..ffbe222 100644
--- a/src/video_output/vout_internal.h
+++ b/src/video_output/vout_internal.h
@@ -56,6 +56,7 @@ struct vout_thread_sys_t
mtime_t i_picture_displayed_date;
picture_t *p_picture_displayed;
int i_picture_qtype;
+ bool b_picture_interlaced;
vlc_cond_t picture_wait;
/* */
diff --git a/src/video_output/vout_pictures.c b/src/video_output/vout_pictures.c
index f07d6c8..9429ac7 100644
--- a/src/video_output/vout_pictures.c
+++ b/src/video_output/vout_pictures.c
@@ -65,6 +65,7 @@ void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
p_pic, p_pic->i_status );
}
p_vout->p->i_picture_qtype = p_pic->i_qtype;
+ p_vout->p->b_picture_interlaced = !p_pic->b_progressive;
vlc_mutex_unlock( &p_vout->picture_lock );
}
More information about the vlc-devel
mailing list