[vlc-commits] transcode: fix dec->fmt_out thread safety
Thomas Guillem
git at videolan.org
Tue Jan 2 11:48:32 CET 2018
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Thu Dec 21 15:45:56 2017 +0100| [3140efd2ed0601e4d0d548faf8780aeca616ea7d] | committer: Thomas Guillem
transcode: fix dec->fmt_out thread safety
dec->fmt_out can be written from any thread by the decoder module. It's only
safe to access it without any lock from the pf_vout_format_update() callback.
In order to fetch the last video_format_t from the decoder, we use the one from
decoded pictures (that are created from dec->fmt_out.video from the same thread
than pf_vout_format_update()).
Note for conversion_video_filter_append():
We feed to the video converter chain a new fmt created from the pic
video_format_t instead of the original dec->fmt_out. Normally, video filters
only use fmt*.video
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=3140efd2ed0601e4d0d548faf8780aeca616ea7d
---
modules/stream_out/transcode/transcode.h | 1 +
modules/stream_out/transcode/video.c | 113 +++++++++++++++++--------------
2 files changed, 62 insertions(+), 52 deletions(-)
diff --git a/modules/stream_out/transcode/transcode.h b/modules/stream_out/transcode/transcode.h
index 88b455bc7e..177217f24b 100644
--- a/modules/stream_out/transcode/transcode.h
+++ b/modules/stream_out/transcode/transcode.h
@@ -79,6 +79,7 @@ struct sout_stream_id_sys_t
/* Decoder */
decoder_t *p_decoder;
+ video_format_t video_dec_out; /* only rw from pf_vout_format_update() */
struct
{
diff --git a/modules/stream_out/transcode/video.c b/modules/stream_out/transcode/video.c
index 92b230adb8..cb9591933b 100644
--- a/modules/stream_out/transcode/video.c
+++ b/modules/stream_out/transcode/video.c
@@ -38,13 +38,16 @@
#define ENC_FRAMERATE (25 * 1000)
#define ENC_FRAMERATE_BASE 1000
-static const es_format_t* video_output_format( sout_stream_id_sys_t *id )
+static const video_format_t* video_output_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 );
+ return &filter_chain_GetFmtOut( id->p_uf_chain )->video;
else if( id->p_f_chain )
- return filter_chain_GetFmtOut( id->p_f_chain );
- return &id->p_decoder->fmt_out;
+ return &filter_chain_GetFmtOut( id->p_f_chain )->video;
+ else
+ return &p_pic->format;
}
static int video_update_format_decoder( decoder_t *p_dec )
@@ -62,9 +65,11 @@ static int video_update_format_decoder( decoder_t *p_dec )
return 0;
if( id->p_encoder->fmt_in.i_codec == p_dec->fmt_out.i_codec ||
- video_format_IsSimilar( &id->p_encoder->fmt_in.video,
- &video_output_format( id )->video ) )
+ video_format_IsSimilar( &id->video_dec_out,
+ &p_dec->fmt_out.video ) )
return 0;
+ id->video_dec_out = p_dec->fmt_out.video;
+ id->video_dec_out.p_palette = NULL;
msg_Dbg( stream, "Checking if filter chain %4.4s -> %4.4s is possible",
(char *)&p_dec->fmt_out.i_codec, (char*)&id->p_encoder->fmt_in.i_codec );
@@ -371,34 +376,38 @@ static void transcode_video_filter_init( sout_stream_t *p_stream,
}
/* Take care of the scaling and chroma conversions. */
-static void conversion_video_filter_append( sout_stream_id_sys_t *id )
+static void conversion_video_filter_append( sout_stream_id_sys_t *id,
+ picture_t *p_pic )
{
- const es_format_t *p_fmt_out = video_output_format( id );
+ const video_format_t *p_vid_out = video_output_format( id, p_pic );
- if( ( p_fmt_out->video.i_chroma != id->p_encoder->fmt_in.video.i_chroma ) ||
- ( p_fmt_out->video.i_width != id->p_encoder->fmt_in.video.i_width ) ||
- ( p_fmt_out->video.i_height != id->p_encoder->fmt_in.video.i_height ) )
+ if( ( p_vid_out->i_chroma != id->p_encoder->fmt_in.video.i_chroma ) ||
+ ( p_vid_out->i_width != id->p_encoder->fmt_in.video.i_width ) ||
+ ( p_vid_out->i_height != id->p_encoder->fmt_in.video.i_height ) )
{
+ es_format_t fmt_out;
+ es_format_Init( &fmt_out, VIDEO_ES, p_vid_out->i_chroma );
+ fmt_out.video = *p_vid_out;
filter_chain_AppendConverter( id->p_uf_chain ? id->p_uf_chain : id->p_f_chain,
- p_fmt_out, &id->p_encoder->fmt_in );
+ &fmt_out, &id->p_encoder->fmt_in );
}
}
static void transcode_video_framerate_init( sout_stream_t *p_stream,
sout_stream_id_sys_t *id,
- const es_format_t *p_fmt_out )
+ const video_format_t *p_vid_out )
{
/* Handle frame rate conversion */
if( !id->p_encoder->fmt_out.video.i_frame_rate ||
!id->p_encoder->fmt_out.video.i_frame_rate_base )
{
- if( p_fmt_out->video.i_frame_rate &&
- p_fmt_out->video.i_frame_rate_base )
+ if( p_vid_out->i_frame_rate &&
+ p_vid_out->i_frame_rate_base )
{
id->p_encoder->fmt_out.video.i_frame_rate =
- p_fmt_out->video.i_frame_rate;
+ p_vid_out->i_frame_rate;
id->p_encoder->fmt_out.video.i_frame_rate_base =
- p_fmt_out->video.i_frame_rate_base;
+ p_vid_out->i_frame_rate_base;
}
else
{
@@ -428,19 +437,19 @@ static void transcode_video_framerate_init( sout_stream_t *p_stream,
static void transcode_video_size_init( sout_stream_t *p_stream,
sout_stream_id_sys_t *id,
- const es_format_t *p_fmt_out )
+ const video_format_t *p_vid_out )
{
sout_stream_sys_t *p_sys = p_stream->p_sys;
/* Calculate scaling
* width/height of source */
- int i_src_visible_width = p_fmt_out->video.i_visible_width;
- int i_src_visible_height = p_fmt_out->video.i_visible_height;
+ int i_src_visible_width = p_vid_out->i_visible_width;
+ int i_src_visible_height = p_vid_out->i_visible_height;
if (i_src_visible_width == 0)
- i_src_visible_width = p_fmt_out->video.i_width;
+ i_src_visible_width = p_vid_out->i_width;
if (i_src_visible_height == 0)
- i_src_visible_height = p_fmt_out->video.i_height;
+ i_src_visible_height = p_vid_out->i_height;
/* with/height scaling */
@@ -448,10 +457,10 @@ static void transcode_video_size_init( sout_stream_t *p_stream,
float f_scale_height = 1;
/* aspect ratio */
- float f_aspect = (double)p_fmt_out->video.i_sar_num *
- p_fmt_out->video.i_width /
- p_fmt_out->video.i_sar_den /
- p_fmt_out->video.i_height;
+ float f_aspect = (double)p_vid_out->i_sar_num *
+ p_vid_out->i_width /
+ p_vid_out->i_sar_den /
+ p_vid_out->i_height;
msg_Dbg( p_stream, "decoder aspect is %f:1", f_aspect );
@@ -527,8 +536,8 @@ static void transcode_video_size_init( sout_stream_t *p_stream,
/* width/height of output stream */
int i_dst_visible_width = lroundf(f_scale_width*i_src_visible_width);
int i_dst_visible_height = lroundf(f_scale_height*i_src_visible_height);
- int i_dst_width = lroundf(f_scale_width*p_fmt_out->video.i_width);
- int i_dst_height = lroundf(f_scale_height*p_fmt_out->video.i_height);
+ int i_dst_width = lroundf(f_scale_width*p_vid_out->i_width);
+ int i_dst_height = lroundf(f_scale_height*p_vid_out->i_height);
if( i_dst_width & 1 ) ++i_dst_width;
if( i_dst_height & 1 ) ++i_dst_height;
@@ -552,15 +561,15 @@ static void transcode_video_size_init( sout_stream_t *p_stream,
static void transcode_video_sar_init( sout_stream_t *p_stream,
sout_stream_id_sys_t *id,
- const es_format_t *p_fmt_out )
+ const video_format_t *p_vid_out )
{
- int i_src_visible_width = p_fmt_out->video.i_visible_width;
- int i_src_visible_height = p_fmt_out->video.i_visible_height;
+ int i_src_visible_width = p_vid_out->i_visible_width;
+ int i_src_visible_height = p_vid_out->i_visible_height;
if (i_src_visible_width == 0)
- i_src_visible_width = p_fmt_out->video.i_width;
+ i_src_visible_width = p_vid_out->i_width;
if (i_src_visible_height == 0)
- i_src_visible_height = p_fmt_out->video.i_height;
+ i_src_visible_height = p_vid_out->i_height;
/* Check whether a particular aspect ratio was requested */
if( id->p_encoder->fmt_out.video.i_sar_num <= 0 ||
@@ -568,8 +577,8 @@ static void transcode_video_sar_init( sout_stream_t *p_stream,
{
vlc_ureduce( &id->p_encoder->fmt_out.video.i_sar_num,
&id->p_encoder->fmt_out.video.i_sar_den,
- (uint64_t)p_fmt_out->video.i_sar_num * id->p_encoder->fmt_out.video.i_width * p_fmt_out->video.i_height,
- (uint64_t)p_fmt_out->video.i_sar_den * id->p_encoder->fmt_out.video.i_height * p_fmt_out->video.i_width,
+ (uint64_t)p_vid_out->i_sar_num * id->p_encoder->fmt_out.video.i_width * p_vid_out->i_height,
+ (uint64_t)p_vid_out->i_sar_den * id->p_encoder->fmt_out.video.i_height * p_vid_out->i_width,
0 );
}
else
@@ -593,19 +602,19 @@ static void transcode_video_sar_init( sout_stream_t *p_stream,
}
static void transcode_video_encoder_init( sout_stream_t *p_stream,
- sout_stream_id_sys_t *id )
+ sout_stream_id_sys_t *id,
+ picture_t *p_pic )
{
- const es_format_t *p_fmt_out = video_output_format( id );
+ const video_format_t *p_vid_out = video_output_format( id, p_pic );
id->p_encoder->fmt_in.video.orientation =
id->p_encoder->fmt_out.video.orientation =
id->p_decoder->fmt_in.video.orientation;
- transcode_video_framerate_init( p_stream, id, p_fmt_out );
-
- transcode_video_size_init( p_stream, id, p_fmt_out );
- transcode_video_sar_init( p_stream, id, p_fmt_out );
+ transcode_video_framerate_init( p_stream, id, p_vid_out );
+ transcode_video_size_init( p_stream, id, p_vid_out );
+ transcode_video_sar_init( p_stream, id, p_vid_out );
}
static int transcode_video_encoder_open( sout_stream_t *p_stream,
@@ -778,14 +787,14 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
}
if( unlikely (
- id->p_encoder->p_module &&
- !video_format_IsSimilar( &id->fmt_input_video, &id->p_decoder->fmt_out.video )
+ id->p_encoder->p_module && p_pic &&
+ !video_format_IsSimilar( &id->fmt_input_video, &p_pic->format )
)
)
{
msg_Info( p_stream, "aspect-ratio changed, reiniting. %i -> %i : %i -> %i.",
- id->fmt_input_video.i_sar_num, id->p_decoder->fmt_out.video.i_sar_num,
- id->fmt_input_video.i_sar_den, id->p_decoder->fmt_out.video.i_sar_den
+ id->fmt_input_video.i_sar_num, p_pic->format.i_sar_num,
+ id->fmt_input_video.i_sar_den, p_pic->format.i_sar_den
);
/* Close filters */
if( id->p_f_chain )
@@ -800,14 +809,14 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
id->p_encoder->fmt_out.video.i_visible_height = p_sys->i_height & ~1;
id->p_encoder->fmt_out.video.i_sar_num = id->p_encoder->fmt_out.video.i_sar_den = 0;
- transcode_video_encoder_init( p_stream, id );
+ transcode_video_encoder_init( p_stream, id, p_pic );
transcode_video_filter_init( p_stream, id );
- conversion_video_filter_append( id );
- memcpy( &id->fmt_input_video, &id->p_decoder->fmt_out.video, sizeof(video_format_t));
+ conversion_video_filter_append( id, p_pic );
+ memcpy( &id->fmt_input_video, &p_pic->format, sizeof(video_format_t));
}
- if( unlikely( !id->p_encoder->p_module ) )
+ if( unlikely( !id->p_encoder->p_module && p_pic ) )
{
if( id->p_f_chain )
filter_chain_Delete( id->p_f_chain );
@@ -815,10 +824,10 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
filter_chain_Delete( id->p_uf_chain );
id->p_f_chain = id->p_uf_chain = NULL;
- transcode_video_encoder_init( p_stream, id );
+ transcode_video_encoder_init( p_stream, id, p_pic );
transcode_video_filter_init( p_stream, id );
- conversion_video_filter_append( id );
- memcpy( &id->fmt_input_video, &id->p_decoder->fmt_out.video, sizeof(video_format_t));
+ conversion_video_filter_append( id, p_pic );
+ memcpy( &id->fmt_input_video, &p_pic->format, sizeof(video_format_t));
if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
{
More information about the vlc-commits
mailing list