[vlc-commits] sout: transcoding: rework filters and orientation
Francois Cartegnie
git at videolan.org
Tue Aug 27 14:50:56 CEST 2019
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Thu Aug 22 16:58:28 2019 +0200| [4c5240a5bf3cc4c2e0f03b9c988f274c0a4d7404] | committer: Francois Cartegnie
sout: transcoding: rework filters and orientation
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=4c5240a5bf3cc4c2e0f03b9c988f274c0a4d7404
---
modules/stream_out/transcode/encoder/encoder.h | 1 -
modules/stream_out/transcode/encoder/video.c | 5 +-
modules/stream_out/transcode/transcode.c | 4 +
modules/stream_out/transcode/transcode.h | 13 ++
modules/stream_out/transcode/video.c | 212 ++++++++++++++++++-------
5 files changed, 173 insertions(+), 62 deletions(-)
diff --git a/modules/stream_out/transcode/encoder/encoder.h b/modules/stream_out/transcode/encoder/encoder.h
index 00827502e7..495c3f6426 100644
--- a/modules/stream_out/transcode/encoder/encoder.h
+++ b/modules/stream_out/transcode/encoder/encoder.h
@@ -85,7 +85,6 @@ int transcode_encoder_test( vlc_object_t *p_obj,
es_format_t *p_enc_wanted_in );
void transcode_encoder_video_configure( vlc_object_t *p_obj,
- const video_format_t *p_dec_in,
const video_format_t *p_dec_out,
const transcode_encoder_config_t *p_cfg,
const video_format_t *p_src,
diff --git a/modules/stream_out/transcode/encoder/video.c b/modules/stream_out/transcode/encoder/video.c
index 2fbb1f854c..670f5b819c 100644
--- a/modules/stream_out/transcode/encoder/video.c
+++ b/modules/stream_out/transcode/encoder/video.c
@@ -212,7 +212,6 @@ static void transcode_video_size_config_apply( vlc_object_t *p_obj,
}
void transcode_encoder_video_configure( vlc_object_t *p_obj,
- const video_format_t *p_dec_in,
const video_format_t *p_dec_out,
const transcode_encoder_config_t *p_cfg,
const video_format_t *p_src,
@@ -234,7 +233,9 @@ void transcode_encoder_video_configure( vlc_object_t *p_obj,
}
/* Complete source format */
- p_enc_in->orientation = p_enc_out->orientation = p_dec_in->orientation;
+ p_enc_in->orientation = ORIENT_NORMAL;
+ p_enc_out->orientation = p_enc_in->orientation;
+
p_enc_in->i_chroma = p_enc->p_encoder->fmt_in.i_codec;
transcode_video_framerate_apply( p_src, p_enc_out );
diff --git a/modules/stream_out/transcode/transcode.c b/modules/stream_out/transcode/transcode.c
index 4b5fc230e5..29ebde59fe 100644
--- a/modules/stream_out/transcode/transcode.c
+++ b/modules/stream_out/transcode/transcode.c
@@ -465,6 +465,10 @@ static int Open( vlc_object_t *p_this )
p_sys->senc_cfg.spu.i_height = (p_sys->venc_cfg.video.i_height) ? p_sys->venc_cfg.video.i_height : 720;
vlc_mutex_init( &p_sys->lock );
+ /* Blending can't work outside of normal orientation */
+ p_sys->vfilters_cfg.video.b_reorient = p_sys->b_soverlay ||
+ p_sys->vfilters_cfg.video.psz_spu_sources;
+
p_stream->pf_add = Add;
p_stream->pf_del = Del;
p_stream->pf_send = Send;
diff --git a/modules/stream_out/transcode/transcode.h b/modules/stream_out/transcode/transcode.h
index 0cce7eea97..f38e4892ad 100644
--- a/modules/stream_out/transcode/transcode.h
+++ b/modules/stream_out/transcode/transcode.h
@@ -16,6 +16,7 @@ typedef struct
char *psz_deinterlace;
config_chain_t *p_deinterlace_cfg;
char *psz_spu_sources;
+ bool b_reorient;
} video;
};
} sout_filters_config_t;
@@ -121,7 +122,10 @@ struct sout_stream_id_sys_t
struct
{
filter_chain_t *p_f_chain; /**< Video filters */
+ filter_chain_t *p_conv_nonstatic;
+ filter_chain_t *p_conv_static;
filter_chain_t *p_uf_chain; /**< User-specified video filters */
+ filter_chain_t *p_final_conv_static;
filter_t *p_spu_blender;
spu_t *p_spu;
video_format_t fmt_input_video;
@@ -172,6 +176,15 @@ static inline void es_format_SetMeta( es_format_t *p_dst, const es_format_t *p_s
}
}
+static inline void transcode_remove_filters( filter_chain_t **pp )
+{
+ if( *pp )
+ {
+ filter_chain_Delete( *pp );
+ *pp = NULL;
+ }
+}
+
/* SPU */
void transcode_spu_clean ( sout_stream_t *, sout_stream_id_sys_t * );
diff --git a/modules/stream_out/transcode/video.c b/modules/stream_out/transcode/video.c
index bd53124927..d7e64f8afd 100644
--- a/modules/stream_out/transcode/video.c
+++ b/modules/stream_out/transcode/video.c
@@ -44,13 +44,32 @@ static const video_format_t* filtered_video_format( sout_stream_id_sys_t *id,
picture_t *p_pic )
{
assert( id && p_pic );
- if( id->p_uf_chain )
- return &filter_chain_GetFmtOut( id->p_uf_chain )->video;
- if( id->p_f_chain )
- return &filter_chain_GetFmtOut( id->p_f_chain )->video;
+ const filter_chain_t * chains[] =
+ {
+ id->p_final_conv_static,
+ id->p_uf_chain,
+ id->p_conv_static,
+ id->p_conv_nonstatic,
+ id->p_f_chain,
+ };
+ for( size_t i=0; i<ARRAY_SIZE(chains); i++ )
+ {
+ if( chains[i] )
+ return &filter_chain_GetFmtOut( chains[i] )->video;
+ }
return &p_pic->format;
}
+static void debug_format( sout_stream_t *p_stream, const es_format_t *fmt )
+{
+ msg_Dbg( p_stream, "format now %4.4s/%4.4s %dx%d(%dx%d) ΓΈ%d",
+ (const char *) &fmt->i_codec,
+ (const char *) &fmt->video.i_chroma,
+ fmt->video.i_visible_width, fmt->video.i_visible_height,
+ fmt->video.i_width, fmt->video.i_height,
+ fmt->video.orientation );
+}
+
static int video_update_format_decoder( decoder_t *p_dec )
{
struct decoder_owner *p_owner = dec_get_owner( p_dec );
@@ -221,20 +240,90 @@ static const struct filter_video_callbacks transcode_filter_video_cbs =
transcode_video_filter_buffer_new,
};
-static void transcode_video_filter_init( sout_stream_t *p_stream,
+/* Take care of the scaling and chroma conversions. */
+static int transcode_video_set_conversions( sout_stream_t *p_stream,
+ sout_stream_id_sys_t *id,
+ const es_format_t **pp_src,
+ const es_format_t *p_dst,
+ bool b_reorient )
+{
+ filter_owner_t owner = {
+ .video = &transcode_filter_video_cbs,
+ .sys = id,
+ };
+
+ enum
+ {
+ STEP_NONSTATIC = 0,
+ STEP_STATIC,
+ };
+ for( int step = STEP_NONSTATIC; step <= STEP_STATIC; step++ )
+ {
+ const bool b_do_scale = (*pp_src)->video.i_width != p_dst->video.i_width ||
+ (*pp_src)->video.i_height != p_dst->video.i_height;
+ const bool b_do_chroma = (*pp_src)->video.i_chroma != p_dst->video.i_chroma;
+ const bool b_do_orient = ((*pp_src)->video.orientation != ORIENT_NORMAL) && b_reorient;
+
+ if( step == STEP_STATIC && b_do_orient )
+ return VLC_EGENERIC;
+
+ const es_format_t *p_tmpdst = p_dst;
+
+ if( ! (b_do_scale || b_do_chroma || b_do_orient) )
+ return VLC_SUCCESS;
+
+ es_format_t tmpdst;
+ if( b_do_orient )
+ {
+ es_format_Init( &tmpdst, VIDEO_ES, p_dst->video.i_chroma );
+ video_format_ApplyRotation( &tmpdst.video, &p_dst->video );
+ p_tmpdst = &tmpdst;
+ }
+
+ msg_Dbg( p_stream, "adding (scale %d,chroma %d, orient %d) converters",
+ b_do_scale, b_do_chroma, b_do_orient );
+
+ filter_chain_t **pp_chain = (step == STEP_NONSTATIC)
+ ? &id->p_conv_nonstatic
+ : &id->p_conv_static;
+
+ id->p_conv_nonstatic = filter_chain_NewVideo( p_stream,
+ step == STEP_NONSTATIC,
+ &owner );
+ if( !*pp_chain )
+ return VLC_EGENERIC;
+ filter_chain_Reset( *pp_chain, *pp_src, p_tmpdst );
+
+ if( filter_chain_AppendConverter( *pp_chain, *pp_src, p_tmpdst ) != VLC_SUCCESS )
+ return VLC_EGENERIC;
+
+ *pp_src = filter_chain_GetFmtOut( *pp_chain );
+ debug_format( p_stream, *pp_src );
+ }
+
+ return VLC_SUCCESS;
+}
+
+static inline bool transcode_video_filters_configured( const sout_stream_id_sys_t *id )
+{
+ return !!id->p_f_chain;
+}
+
+static int transcode_video_filters_init( sout_stream_t *p_stream,
const sout_filters_config_t *p_cfg,
bool b_master_sync,
+ const es_format_t *p_src,
+ const es_format_t *p_dst,
sout_stream_id_sys_t *id )
{
- const es_format_t *p_src = &id->p_decoder->fmt_out;
- const es_format_t *p_dst = transcode_encoder_format_in( id->encoder );
-
/* Build chain */
filter_owner_t owner = {
.video = &transcode_filter_video_cbs,
.sys = id,
};
id->p_f_chain = filter_chain_NewVideo( p_stream, false, &owner );
+ if( !id->p_f_chain )
+ return VLC_EGENERIC;
filter_chain_Reset( id->p_f_chain, p_src, p_src );
/* Deinterlace */
@@ -247,57 +336,43 @@ static void transcode_video_filter_init( sout_stream_t *p_stream,
p_src = filter_chain_GetFmtOut( id->p_f_chain );
}
- /* SPU Sources */
- if( p_cfg->video.psz_spu_sources )
- {
- if( id->p_spu || (id->p_spu = spu_Create( p_stream, NULL )) )
- spu_ChangeSources( id->p_spu, p_cfg->video.psz_spu_sources );
- }
-
if( b_master_sync )
{
filter_chain_AppendFilter( id->p_f_chain, "fps", NULL, p_src, p_dst );
p_src = filter_chain_GetFmtOut( id->p_f_chain );
}
+ /* Chroma and other conversions */
+ if( transcode_video_set_conversions( p_stream, id, &p_src, p_dst,
+ p_cfg->video.b_reorient ) != VLC_SUCCESS )
+ return VLC_EGENERIC;
+
+ /* User filters */
if( p_cfg->psz_filters )
{
+ msg_Dbg( p_stream, "adding user filters" );
id->p_uf_chain = filter_chain_NewVideo( p_stream, true, &owner );
+ if(!id->p_uf_chain)
+ return VLC_EGENERIC;
filter_chain_Reset( id->p_uf_chain, p_src, p_dst );
- if( p_src->video.i_chroma != p_dst->video.i_chroma )
- {
- filter_chain_AppendConverter( id->p_uf_chain, p_src, p_dst );
- }
filter_chain_AppendFromString( id->p_uf_chain, p_cfg->psz_filters );
p_src = filter_chain_GetFmtOut( id->p_uf_chain );
+ debug_format( p_stream, p_src );
+ }
- /* Update encoder so it matches filters output */
- transcode_encoder_update_format_in( id->encoder, p_src );
- }
-}
-
-/* Take care of the scaling and chroma conversions. */
-static int conversion_video_filter_append( sout_stream_id_sys_t *id,
- picture_t *p_pic )
-{
- const video_format_t *p_src = filtered_video_format( id, p_pic );
+ /* Update encoder so it matches filters output */
+ transcode_encoder_update_format_in( id->encoder, p_src );
- const es_format_t *p_enc_in = transcode_encoder_format_in( id->encoder );
-
- if( ( p_src->i_chroma != p_enc_in->video.i_chroma ) ||
- ( p_src->i_width != p_enc_in->video.i_width ) ||
- ( p_src->i_height != p_enc_in->video.i_height ) )
+ /* SPU Sources */
+ if( p_cfg->video.psz_spu_sources )
{
- es_format_t fmt_out;
- es_format_Init( &fmt_out, VIDEO_ES, p_src->i_chroma );
- fmt_out.video = *p_src;
- return filter_chain_AppendConverter( id->p_uf_chain ? id->p_uf_chain : id->p_f_chain,
- &fmt_out, p_enc_in );
+ if( id->p_spu || (id->p_spu = spu_Create( p_stream, NULL )) )
+ spu_ChangeSources( id->p_spu, p_cfg->video.psz_spu_sources );
}
+
return VLC_SUCCESS;
}
-
void transcode_video_clean( sout_stream_t *p_stream,
sout_stream_id_sys_t *id )
{
@@ -311,10 +386,11 @@ void transcode_video_clean( sout_stream_t *p_stream,
es_format_Clean( &id->decoder_out );
/* Close filters */
- if( id->p_f_chain )
- filter_chain_Delete( id->p_f_chain );
- if( id->p_uf_chain )
- filter_chain_Delete( id->p_uf_chain );
+ transcode_remove_filters( &id->p_f_chain );
+ transcode_remove_filters( &id->p_conv_nonstatic );
+ transcode_remove_filters( &id->p_conv_static );
+ transcode_remove_filters( &id->p_uf_chain );
+ transcode_remove_filters( &id->p_final_conv_static );
if( id->p_spu_blender )
filter_DeleteBlend( id->p_spu_blender );
if( id->p_spu )
@@ -445,8 +521,8 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
{
if( !transcode_encoder_opened(id->encoder) ) /* Configure Encoder input/output */
{
+ assert( !id->p_f_chain && !id->p_uf_chain );
transcode_encoder_video_configure( VLC_OBJECT(p_stream),
- &id->p_decoder->fmt_in.video,
&id->p_decoder->fmt_out.video,
id->p_enccfg,
filtered_video_format( id, p_pic ),
@@ -460,12 +536,11 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
id->fmt_input_video.i_sar_den, p_pic->format.i_sar_den
);
/* Close filters, encoder format input can't change */
- if( id->p_f_chain )
- filter_chain_Delete( id->p_f_chain );
- id->p_f_chain = NULL;
- if( id->p_uf_chain )
- filter_chain_Delete( id->p_uf_chain );
- id->p_uf_chain = NULL;
+ transcode_remove_filters( &id->p_f_chain );
+ transcode_remove_filters( &id->p_conv_nonstatic );
+ transcode_remove_filters( &id->p_conv_static );
+ transcode_remove_filters( &id->p_uf_chain );
+ transcode_remove_filters( &id->p_final_conv_static );
if( id->p_spu_blender )
filter_DeleteBlend( id->p_spu_blender );
id->p_spu_blender = NULL;
@@ -475,11 +550,17 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
video_format_Copy( &id->fmt_input_video, &p_pic->format );
- if( !id->p_f_chain && !id->p_uf_chain )
+ if( !transcode_video_filters_configured( id ) )
{
- transcode_video_filter_init( p_stream, id->p_filterscfg,
- (id->p_enccfg->video.fps.num > 0), id );
- if( conversion_video_filter_append( id, p_pic ) != VLC_SUCCESS )
+ es_format_t tmpfmt;
+ es_format_Init( &tmpfmt, VIDEO_ES, id->fmt_input_video.i_chroma );
+ tmpfmt.video = id->fmt_input_video;
+ if( transcode_video_filters_init( p_stream,
+ id->p_filterscfg,
+ (id->p_enccfg->video.fps.num > 0),
+ &tmpfmt,
+ transcode_encoder_format_in( id->encoder ),
+ id ) != VLC_SUCCESS )
goto error;
}
@@ -518,8 +599,15 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
for ( picture_t *p_in = p_pic; ; p_in = NULL /* drain second time */ )
{
/* Run filter chain */
- if( id->p_f_chain )
- p_in = filter_chain_VideoFilter( id->p_f_chain, p_in );
+ filter_chain_t * primary_chains[] = { id->p_f_chain,
+ id->p_conv_static,
+ id->p_conv_nonstatic };
+ for( size_t i=0; p_in && i<ARRAY_SIZE(primary_chains); i++ )
+ {
+ if( !primary_chains[i] )
+ continue;
+ p_in = filter_chain_VideoFilter( primary_chains[i], p_in );
+ }
if( !p_in )
break;
@@ -527,8 +615,14 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
for ( ;; p_in = NULL /* drain second time */ )
{
/* Run user specified filter chain */
- if( id->p_uf_chain )
- p_in = filter_chain_VideoFilter( id->p_uf_chain, p_in );
+ filter_chain_t * secondary_chains[] = { id->p_uf_chain,
+ id->p_final_conv_static };
+ for( size_t i=0; p_in && i<ARRAY_SIZE(secondary_chains); i++ )
+ {
+ if( !secondary_chains[i] )
+ continue;
+ p_in = filter_chain_VideoFilter( secondary_chains[i], p_in );
+ }
if( !p_in )
break;
More information about the vlc-commits
mailing list