vlc | branch: master | Francois Cartegnie <[email protected]> | 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; _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
