* ALL : ported the deinterlace module to video filter2. New
authorChristophe Massiot <massiot@videolan.org>
Fri, 20 May 2005 15:02:25 +0000 (15:02 +0000)
committerChristophe Massiot <massiot@videolan.org>
Fri, 20 May 2005 15:02:25 +0000 (15:02 +0000)
   --sout-transcode-deinterlace-module and --sout-deinterlace-mode options.

include/vlc_filter.h
modules/codec/ffmpeg/ffmpeg.c
modules/stream_out/transcode.c
modules/video_filter/deinterlace.c

index 26d8ee0..761d8e5 100644 (file)
@@ -51,6 +51,9 @@ struct filter_t
     /* Output format of filter */
     es_format_t         fmt_out;
 
+    /* Filter configuration */
+    sout_cfg_t *        p_cfg;
+
     picture_t *         ( * pf_video_filter ) ( filter_t *, picture_t * );
     block_t *           ( * pf_audio_filter ) ( filter_t *, block_t * );
     void                ( * pf_video_blend )  ( filter_t *, picture_t *,
index f56d596..d12d773 100644 (file)
@@ -181,7 +181,7 @@ vlc_module_begin();
     set_capability( "video filter2", 0 );
     set_callbacks( E_(OpenDeinterlace), E_(CloseDeinterlace) );
     set_description( _("ffmpeg deinterlace video filter") );
-    add_shortcut( "deinterlace" );
+    add_shortcut( "ffmpeg-deinterlace" );
 
     var_Create( p_module->p_libvlc, "avcodec", VLC_VAR_MUTEX );
 vlc_module_end();
index a3fecfb..b1c4a0c 100644 (file)
 #define DEINTERLACE_TEXT N_("Deinterlace video")
 #define DEINTERLACE_LONGTEXT N_( \
     "Allows you to deinterlace the video before encoding." )
+#define DEINTERLACE_MODULE_TEXT N_("Deinterlace module")
+#define DEINTERLACE_MODULE_LONGTEXT N_( \
+    "Specifies the deinterlace module to use (ffmpeg-deinterlace or " \
+    "deinterlace)." )
 #define WIDTH_TEXT N_("Video width")
 #define WIDTH_LONGTEXT N_( \
     "Allows you to specify the output video width." )
@@ -157,6 +161,9 @@ vlc_module_begin();
                HURRYUP_LONGTEXT, VLC_FALSE );
     add_bool( SOUT_CFG_PREFIX "deinterlace", 0, NULL, DEINTERLACE_TEXT,
               DEINTERLACE_LONGTEXT, VLC_FALSE );
+    add_string( SOUT_CFG_PREFIX "deinterlace-module", "deinterlace", NULL,
+                DEINTERLACE_MODULE_TEXT, DEINTERLACE_MODULE_LONGTEXT,
+                VLC_FALSE );
     add_integer( SOUT_CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
                  WIDTH_LONGTEXT, VLC_TRUE );
     add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
@@ -204,8 +211,8 @@ vlc_module_end();
 
 static const char *ppsz_sout_options[] = {
     "venc", "vcodec", "vb", "croptop", "cropbottom", "cropleft", "cropright",
-    "scale", "fps", "width", "height", "deinterlace", "threads", "hurry-up",
-    "aenc", "acodec", "ab", "samplerate", "channels",
+    "scale", "fps", "width", "height", "deinterlace", "deinterlace-module",
+    "threads", "hurry-up", "aenc", "acodec", "ab", "samplerate", "channels",
     "senc", "scodec", "soverlay", "sfilter",
     "audio-sync", NULL
 };
@@ -290,6 +297,8 @@ struct sout_stream_sys_t
     int             i_width;
     int             i_height;
     vlc_bool_t      b_deinterlace;
+    char            *psz_deinterlace;
+    sout_cfg_t      *p_deinterlace_cfg;
     int             i_threads;
     vlc_bool_t      b_hurry_up;
 
@@ -428,6 +437,19 @@ static int Open( vlc_object_t *p_this )
     var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val );
     p_sys->b_deinterlace = val.b_bool;
 
+    var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace-module", &val );
+    p_sys->psz_deinterlace = NULL;
+    p_sys->p_deinterlace_cfg = NULL;
+    if( val.psz_string && *val.psz_string )
+    {
+        char *psz_next;
+        psz_next = sout_CfgCreate( &p_sys->psz_deinterlace,
+                                   &p_sys->p_deinterlace_cfg,
+                                   val.psz_string );
+        if( psz_next ) free( psz_next );
+    }
+    if( val.psz_string ) free( val.psz_string );
+
     var_Get( p_stream, SOUT_CFG_PREFIX "croptop", &val );
     p_sys->i_crop_top = val.i_int;
     var_Get( p_stream, SOUT_CFG_PREFIX "cropbottom", &val );
@@ -540,6 +562,20 @@ static void Close( vlc_object_t * p_this )
     }
     if( p_sys->psz_venc ) free( p_sys->psz_venc );
 
+    while( p_sys->p_deinterlace_cfg != NULL )
+    {
+        sout_cfg_t *p_next = p_sys->p_deinterlace_cfg->p_next;
+
+        if( p_sys->p_deinterlace_cfg->psz_name )
+            free( p_sys->p_deinterlace_cfg->psz_name );
+        if( p_sys->p_deinterlace_cfg->psz_value )
+            free( p_sys->p_deinterlace_cfg->psz_value );
+        free( p_sys->p_deinterlace_cfg );
+
+        p_sys->p_deinterlace_cfg = p_next;
+    }
+    if( p_sys->psz_deinterlace ) free( p_sys->psz_deinterlace );
+
     while( p_sys->p_spu_cfg != NULL )
     {
         sout_cfg_t *p_next = p_sys->p_spu_cfg->p_next;
@@ -1567,9 +1603,10 @@ static int transcode_video_process( sout_stream_t *p_stream,
 
                 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
                 id->pp_filter[id->i_filter]->fmt_out = id->p_decoder->fmt_out;
+                id->pp_filter[id->i_filter]->p_cfg = p_sys->p_deinterlace_cfg;
                 id->pp_filter[id->i_filter]->p_module =
                     module_Need( id->pp_filter[id->i_filter],
-                                 "video filter2", "deinterlace", 0 );
+                                 "video filter2", p_sys->psz_deinterlace, 0 );
                 if( id->pp_filter[id->i_filter]->p_module )
                 {
                     id->pp_filter[id->i_filter]->p_owner =
@@ -1608,6 +1645,7 @@ static int transcode_video_process( sout_stream_t *p_stream,
 
                 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
                 id->pp_filter[id->i_filter]->fmt_out = id->p_encoder->fmt_in;
+                id->pp_filter[id->i_filter]->p_cfg = NULL;
                 id->pp_filter[id->i_filter]->p_module =
                     module_Need( id->pp_filter[id->i_filter],
                                  "video filter2", 0, 0 );
index 60c3d4d..6bbd614 100644 (file)
@@ -30,6 +30,8 @@
 
 #include <vlc/vlc.h>
 #include <vlc/vout.h>
+#include <vlc/sout.h>
+#include "vlc_filter.h"
 
 #ifdef HAVE_ALTIVEC_H
 #   include <altivec.h>
@@ -85,6 +87,9 @@ static int  SendEvents   ( vlc_object_t *, char const *,
 static void SetFilterMethod( vout_thread_t *p_vout, char *psz_method );
 static vout_thread_t *SpawnRealVout( vout_thread_t *p_vout );
 
+static int OpenFilter( vlc_object_t *p_this );
+static void CloseFilter( vlc_object_t *p_this );
+
 /*****************************************************************************
  * Callback prototypes
  *****************************************************************************/
@@ -97,6 +102,8 @@ static int FilterCallback ( vlc_object_t *, char const *,
 #define MODE_TEXT N_("Deinterlace mode")
 #define MODE_LONGTEXT N_("You can choose the default deinterlace mode")
 
+#define FILTER_CFG_PREFIX "sout-deinterlace-"
+
 static char *mode_list[] = { "discard", "blend", "mean", "bob", "linear", "x" };
 static char *mode_list_text[] = { N_("Discard"), N_("Blend"), N_("Mean"),
                                   N_("Bob"), N_("Linear"), N_("X") };
@@ -114,8 +121,19 @@ vlc_module_begin();
 
     add_shortcut( "deinterlace" );
     set_callbacks( Create, Destroy );
+
+    add_submodule();
+    set_capability( "video filter2", 0 );
+    add_string( FILTER_CFG_PREFIX "mode", "blend", NULL, MODE_TEXT,
+                MODE_LONGTEXT, VLC_FALSE );
+        change_string_list( mode_list, mode_list_text, 0 );
+    set_callbacks( OpenFilter, CloseFilter );
 vlc_module_end();
 
+static const char *ppsz_filter_options[] = {
+    "mode", NULL
+};
+
 /*****************************************************************************
  * vout_sys_t: Deinterlace video output method descriptor
  *****************************************************************************
@@ -224,8 +242,6 @@ static int Create( vlc_object_t *p_this )
 
     free( val.psz_string );
 
-    var_AddCallback( p_vout, "deinterlace-mode", FilterCallback, NULL );
-
     return VLC_SUCCESS;
 }
 
@@ -316,6 +332,8 @@ static int Init( vout_thread_t *p_vout )
         return VLC_EGENERIC;
     }
 
+    var_AddCallback( p_vout, "deinterlace-mode", FilterCallback, NULL );
+
     ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
 
     ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
@@ -390,16 +408,6 @@ static void End( vout_thread_t *p_vout )
         i_index--;
         free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
     }
-}
-
-/*****************************************************************************
- * Destroy: destroy Deinterlace video thread output method
- *****************************************************************************
- * Terminate an output method created by DeinterlaceCreateOutputMethod
- *****************************************************************************/
-static void Destroy( vlc_object_t *p_this )
-{
-    vout_thread_t *p_vout = (vout_thread_t *)p_this;
 
     if( p_vout->p_sys->p_vout )
     {
@@ -409,7 +417,17 @@ static void Destroy( vlc_object_t *p_this )
     }
 
     DEL_PARENT_CALLBACKS( SendEventsToChild );
+}
 
+/*****************************************************************************
+ * Destroy: destroy Deinterlace video thread output method
+ *****************************************************************************
+ * Terminate an output method created by DeinterlaceCreateOutputMethod
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+    vout_thread_t *p_vout = (vout_thread_t *)p_this;
+    vlc_mutex_destroy( &p_vout->p_sys->filter_lock );
     free( p_vout->p_sys );
 }
 
@@ -818,8 +836,8 @@ static void RenderBlend( vout_thread_t *p_vout,
                 /* Remaining lines: mean value */
                 for( ; p_out < p_out_end ; )
                 {
-                   Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
-                          p_pic->p[i_plane].i_pitch );
+                    Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
+                           p_pic->p[i_plane].i_pitch );
 
                     p_out += p_pic->p[i_plane].i_pitch;
                     p_in += p_pic->p[i_plane].i_pitch;
@@ -2025,3 +2043,129 @@ static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
     var_Set( p_vout->p_sys->p_vout, psz_var, newval );
     return VLC_SUCCESS;
 }
+
+
+/*****************************************************************************
+ * video filter2 functions
+ *****************************************************************************/
+static picture_t *Deinterlace( filter_t *p_filter, picture_t *p_pic )
+{
+    vout_thread_t *p_vout = (vout_thread_t *)p_filter->p_sys;
+    picture_t *p_pic_dst;
+
+    /* Request output picture */
+    p_pic_dst = p_filter->pf_vout_buffer_new( p_filter );
+    if( p_pic_dst == NULL )
+    {
+        msg_Warn( p_filter, "can't get output picture" );
+        return NULL;
+    }
+
+    switch( p_vout->p_sys->i_mode )
+    {
+        case DEINTERLACE_DISCARD:
+#if 0
+            RenderDiscard( p_vout, p_pic_dst, p_pic, 0 );
+#endif
+            msg_Err( p_vout, "discarding lines is not supported yet" );
+            p_pic_dst->pf_release( p_pic_dst );
+            return p_pic;
+            break;
+
+        case DEINTERLACE_BOB:
+#if 0
+            RenderBob( p_vout, pp_outpic[0], p_pic, 0 );
+            RenderBob( p_vout, pp_outpic[1], p_pic, 1 );
+            break;
+#endif
+
+        case DEINTERLACE_LINEAR:
+#if 0
+            RenderLinear( p_vout, pp_outpic[0], p_pic, 0 );
+            RenderLinear( p_vout, pp_outpic[1], p_pic, 1 );
+#endif
+            msg_Err( p_vout, "doubling the frame rate is not supported yet" );
+            p_pic_dst->pf_release( p_pic_dst );
+            return p_pic;
+            break;
+
+        case DEINTERLACE_MEAN:
+            RenderMean( p_vout, p_pic_dst, p_pic );
+            break;
+
+        case DEINTERLACE_BLEND:
+            RenderBlend( p_vout, p_pic_dst, p_pic );
+            break;
+
+        case DEINTERLACE_X:
+            RenderX( p_vout, p_pic_dst, p_pic );
+            break;
+    }
+
+    p_pic_dst->date = p_pic->date;
+    p_pic_dst->b_force = p_pic->b_force;
+    p_pic_dst->i_nb_fields = p_pic->i_nb_fields;
+    p_pic_dst->b_progressive = VLC_TRUE;
+    p_pic_dst->b_top_field_first = p_pic->b_top_field_first;
+
+    p_pic->pf_release( p_pic );
+    return p_pic_dst;
+}
+
+/*****************************************************************************
+ * OpenFilter:
+ *****************************************************************************/
+static int OpenFilter( vlc_object_t *p_this )
+{
+    filter_t *p_filter = (filter_t*)p_this;
+    vout_thread_t *p_vout;
+    vlc_value_t val;
+
+    if( ( p_filter->fmt_in.video.i_chroma != VLC_FOURCC('I','4','2','0') &&
+          p_filter->fmt_in.video.i_chroma != VLC_FOURCC('I','Y','U','V') &&
+          p_filter->fmt_in.video.i_chroma != VLC_FOURCC('Y','V','1','2') ) ||
+        p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma )
+    {
+        return VLC_EGENERIC;
+    }
+
+    /* Impossible to use VLC_OBJECT_VOUT here because it would be used
+     * by spu filters */
+    p_vout = vlc_object_create( p_filter, sizeof(vout_thread_t) );
+    vlc_object_attach( p_vout, p_filter );
+    p_filter->p_sys = (filter_sys_t *)p_vout;
+    p_vout->render.i_chroma = p_filter->fmt_in.video.i_chroma;
+
+    sout_CfgParse( p_filter, FILTER_CFG_PREFIX, ppsz_filter_options,
+                   p_filter->p_cfg );
+    var_Get( p_filter, FILTER_CFG_PREFIX "mode", &val );
+    var_Create( p_filter, "deinterlace-mode", VLC_VAR_STRING );
+    var_Set( p_filter, "deinterlace-mode", val );
+
+    if ( Create( VLC_OBJECT(p_vout) ) != VLC_SUCCESS )
+    {
+        vlc_object_detach( p_vout );
+        vlc_object_release( p_vout );
+        return VLC_EGENERIC;
+    }
+
+    p_filter->pf_video_filter = Deinterlace;
+
+    msg_Dbg( p_filter, "deinterlacing" );
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * CloseFilter: clean up the filter
+ *****************************************************************************/
+static void CloseFilter( vlc_object_t *p_this )
+{
+    filter_t *p_filter = (filter_t*)p_this;
+    vout_thread_t *p_vout = (vout_thread_t *)p_filter->p_sys;
+
+    Destroy( VLC_OBJECT(p_vout) );
+    vlc_object_detach( p_vout );
+    vlc_object_release( p_vout );
+}
+