Commit 9d44913e authored by Christophe Massiot's avatar Christophe Massiot

* ALL : ported the deinterlace module to video filter2. New

   --sout-transcode-deinterlace-module and --sout-deinterlace-mode options.
parent f2c7bb7c
...@@ -51,6 +51,9 @@ struct filter_t ...@@ -51,6 +51,9 @@ struct filter_t
/* Output format of filter */ /* Output format of filter */
es_format_t fmt_out; es_format_t fmt_out;
/* Filter configuration */
sout_cfg_t * p_cfg;
picture_t * ( * pf_video_filter ) ( filter_t *, picture_t * ); picture_t * ( * pf_video_filter ) ( filter_t *, picture_t * );
block_t * ( * pf_audio_filter ) ( filter_t *, block_t * ); block_t * ( * pf_audio_filter ) ( filter_t *, block_t * );
void ( * pf_video_blend ) ( filter_t *, picture_t *, void ( * pf_video_blend ) ( filter_t *, picture_t *,
......
...@@ -181,7 +181,7 @@ vlc_module_begin(); ...@@ -181,7 +181,7 @@ vlc_module_begin();
set_capability( "video filter2", 0 ); set_capability( "video filter2", 0 );
set_callbacks( E_(OpenDeinterlace), E_(CloseDeinterlace) ); set_callbacks( E_(OpenDeinterlace), E_(CloseDeinterlace) );
set_description( _("ffmpeg deinterlace video filter") ); set_description( _("ffmpeg deinterlace video filter") );
add_shortcut( "deinterlace" ); add_shortcut( "ffmpeg-deinterlace" );
var_Create( p_module->p_libvlc, "avcodec", VLC_VAR_MUTEX ); var_Create( p_module->p_libvlc, "avcodec", VLC_VAR_MUTEX );
vlc_module_end(); vlc_module_end();
......
...@@ -61,6 +61,10 @@ ...@@ -61,6 +61,10 @@
#define DEINTERLACE_TEXT N_("Deinterlace video") #define DEINTERLACE_TEXT N_("Deinterlace video")
#define DEINTERLACE_LONGTEXT N_( \ #define DEINTERLACE_LONGTEXT N_( \
"Allows you to deinterlace the video before encoding." ) "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_TEXT N_("Video width")
#define WIDTH_LONGTEXT N_( \ #define WIDTH_LONGTEXT N_( \
"Allows you to specify the output video width." ) "Allows you to specify the output video width." )
...@@ -157,6 +161,9 @@ vlc_module_begin(); ...@@ -157,6 +161,9 @@ vlc_module_begin();
HURRYUP_LONGTEXT, VLC_FALSE ); HURRYUP_LONGTEXT, VLC_FALSE );
add_bool( SOUT_CFG_PREFIX "deinterlace", 0, NULL, DEINTERLACE_TEXT, add_bool( SOUT_CFG_PREFIX "deinterlace", 0, NULL, DEINTERLACE_TEXT,
DEINTERLACE_LONGTEXT, VLC_FALSE ); 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, add_integer( SOUT_CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
WIDTH_LONGTEXT, VLC_TRUE ); WIDTH_LONGTEXT, VLC_TRUE );
add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT, add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
...@@ -204,8 +211,8 @@ vlc_module_end(); ...@@ -204,8 +211,8 @@ vlc_module_end();
static const char *ppsz_sout_options[] = { static const char *ppsz_sout_options[] = {
"venc", "vcodec", "vb", "croptop", "cropbottom", "cropleft", "cropright", "venc", "vcodec", "vb", "croptop", "cropbottom", "cropleft", "cropright",
"scale", "fps", "width", "height", "deinterlace", "threads", "hurry-up", "scale", "fps", "width", "height", "deinterlace", "deinterlace-module",
"aenc", "acodec", "ab", "samplerate", "channels", "threads", "hurry-up", "aenc", "acodec", "ab", "samplerate", "channels",
"senc", "scodec", "soverlay", "sfilter", "senc", "scodec", "soverlay", "sfilter",
"audio-sync", NULL "audio-sync", NULL
}; };
...@@ -290,6 +297,8 @@ struct sout_stream_sys_t ...@@ -290,6 +297,8 @@ struct sout_stream_sys_t
int i_width; int i_width;
int i_height; int i_height;
vlc_bool_t b_deinterlace; vlc_bool_t b_deinterlace;
char *psz_deinterlace;
sout_cfg_t *p_deinterlace_cfg;
int i_threads; int i_threads;
vlc_bool_t b_hurry_up; vlc_bool_t b_hurry_up;
...@@ -428,6 +437,19 @@ static int Open( vlc_object_t *p_this ) ...@@ -428,6 +437,19 @@ static int Open( vlc_object_t *p_this )
var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val ); var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val );
p_sys->b_deinterlace = val.b_bool; 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 ); var_Get( p_stream, SOUT_CFG_PREFIX "croptop", &val );
p_sys->i_crop_top = val.i_int; p_sys->i_crop_top = val.i_int;
var_Get( p_stream, SOUT_CFG_PREFIX "cropbottom", &val ); var_Get( p_stream, SOUT_CFG_PREFIX "cropbottom", &val );
...@@ -540,6 +562,20 @@ static void Close( vlc_object_t * p_this ) ...@@ -540,6 +562,20 @@ static void Close( vlc_object_t * p_this )
} }
if( p_sys->psz_venc ) free( p_sys->psz_venc ); 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 ) while( p_sys->p_spu_cfg != NULL )
{ {
sout_cfg_t *p_next = p_sys->p_spu_cfg->p_next; 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, ...@@ -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_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]->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 = id->pp_filter[id->i_filter]->p_module =
module_Need( id->pp_filter[id->i_filter], 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 ) if( id->pp_filter[id->i_filter]->p_module )
{ {
id->pp_filter[id->i_filter]->p_owner = id->pp_filter[id->i_filter]->p_owner =
...@@ -1608,6 +1645,7 @@ static int transcode_video_process( sout_stream_t *p_stream, ...@@ -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_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]->fmt_out = id->p_encoder->fmt_in;
id->pp_filter[id->i_filter]->p_cfg = NULL;
id->pp_filter[id->i_filter]->p_module = id->pp_filter[id->i_filter]->p_module =
module_Need( id->pp_filter[id->i_filter], module_Need( id->pp_filter[id->i_filter],
"video filter2", 0, 0 ); "video filter2", 0, 0 );
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/vout.h> #include <vlc/vout.h>
#include <vlc/sout.h>
#include "vlc_filter.h"
#ifdef HAVE_ALTIVEC_H #ifdef HAVE_ALTIVEC_H
# include <altivec.h> # include <altivec.h>
...@@ -85,6 +87,9 @@ static int SendEvents ( vlc_object_t *, char const *, ...@@ -85,6 +87,9 @@ static int SendEvents ( vlc_object_t *, char const *,
static void SetFilterMethod( vout_thread_t *p_vout, char *psz_method ); static void SetFilterMethod( vout_thread_t *p_vout, char *psz_method );
static vout_thread_t *SpawnRealVout( vout_thread_t *p_vout ); 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 * Callback prototypes
*****************************************************************************/ *****************************************************************************/
...@@ -97,6 +102,8 @@ static int FilterCallback ( vlc_object_t *, char const *, ...@@ -97,6 +102,8 @@ static int FilterCallback ( vlc_object_t *, char const *,
#define MODE_TEXT N_("Deinterlace mode") #define MODE_TEXT N_("Deinterlace mode")
#define MODE_LONGTEXT N_("You can choose the default 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[] = { "discard", "blend", "mean", "bob", "linear", "x" };
static char *mode_list_text[] = { N_("Discard"), N_("Blend"), N_("Mean"), static char *mode_list_text[] = { N_("Discard"), N_("Blend"), N_("Mean"),
N_("Bob"), N_("Linear"), N_("X") }; N_("Bob"), N_("Linear"), N_("X") };
...@@ -114,8 +121,19 @@ vlc_module_begin(); ...@@ -114,8 +121,19 @@ vlc_module_begin();
add_shortcut( "deinterlace" ); add_shortcut( "deinterlace" );
set_callbacks( Create, Destroy ); 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(); vlc_module_end();
static const char *ppsz_filter_options[] = {
"mode", NULL
};
/***************************************************************************** /*****************************************************************************
* vout_sys_t: Deinterlace video output method descriptor * vout_sys_t: Deinterlace video output method descriptor
***************************************************************************** *****************************************************************************
...@@ -224,8 +242,6 @@ static int Create( vlc_object_t *p_this ) ...@@ -224,8 +242,6 @@ static int Create( vlc_object_t *p_this )
free( val.psz_string ); free( val.psz_string );
var_AddCallback( p_vout, "deinterlace-mode", FilterCallback, NULL );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -316,6 +332,8 @@ static int Init( vout_thread_t *p_vout ) ...@@ -316,6 +332,8 @@ static int Init( vout_thread_t *p_vout )
return VLC_EGENERIC; return VLC_EGENERIC;
} }
var_AddCallback( p_vout, "deinterlace-mode", FilterCallback, NULL );
ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES ); ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents ); ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
...@@ -390,16 +408,6 @@ static void End( vout_thread_t *p_vout ) ...@@ -390,16 +408,6 @@ static void End( vout_thread_t *p_vout )
i_index--; i_index--;
free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig ); 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 ) if( p_vout->p_sys->p_vout )
{ {
...@@ -409,7 +417,17 @@ static void Destroy( vlc_object_t *p_this ) ...@@ -409,7 +417,17 @@ static void Destroy( vlc_object_t *p_this )
} }
DEL_PARENT_CALLBACKS( SendEventsToChild ); 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 ); free( p_vout->p_sys );
} }
...@@ -818,8 +836,8 @@ static void RenderBlend( vout_thread_t *p_vout, ...@@ -818,8 +836,8 @@ static void RenderBlend( vout_thread_t *p_vout,
/* Remaining lines: mean value */ /* Remaining lines: mean value */
for( ; p_out < p_out_end ; ) for( ; p_out < p_out_end ; )
{ {
Merge( p_out, p_in, p_in + 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_pic->p[i_plane].i_pitch );
p_out += 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; 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, ...@@ -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 ); var_Set( p_vout->p_sys->p_vout, psz_var, newval );
return VLC_SUCCESS; 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 );
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment