[vlc-devel] [PATCH 1/2] avcodec: fix data-race
Thomas Guillem
thomas at gllm.fr
Fri Sep 20 09:31:24 CEST 2019
There was a data-race between any avcodec threads and the pf_decode thread. The
scope of sem wait/post need to be increased. Indeed, dec->fmt_out must be
accessed while being protected, the same for lavc_UpdateVideoFormat() and
decoder_NewPicture().
PS: decoder_QueuePicture() doesn't have to be protected, it's better to release
the sempahore before calling it in order to unlock avcodec threads while the
picture is being queued.
---
modules/codec/avcodec/video.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c
index 2232b7a291..fea2a7979b 100644
--- a/modules/codec/avcodec/video.c
+++ b/modules/codec/avcodec/video.c
@@ -1120,6 +1120,7 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
b_error = true;
}
av_packet_unref( &pkt );
+ wait_mt( p_sys );
break;
}
@@ -1142,6 +1143,7 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
if (unlikely(frame == NULL))
{
b_error = true;
+ wait_mt( p_sys );
break;
}
@@ -1155,12 +1157,13 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
}
av_frame_free(&frame);
if( ret == AVERROR_EOF )
+ {
+ wait_mt( p_sys );
break;
+ }
}
bool not_received_frame = ret;
- wait_mt( p_sys );
-
if( p_block )
{
/* Consumed bytes */
@@ -1172,6 +1175,7 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
if( not_received_frame )
{
av_frame_free(&frame);
+ wait_mt( p_sys );
if( i_used == 0 ) break;
continue;
}
@@ -1207,6 +1211,7 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
!p_sys->b_show_corrupted ) )
{
av_frame_free(&frame);
+ wait_mt( p_sys );
continue;
}
@@ -1225,6 +1230,7 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
b_error = true;
av_frame_free(&frame);
+ wait_mt( p_sys );
break;
}
static_assert( sizeof(p_palette->palette) == AVPALETTE_SIZE,
@@ -1236,6 +1242,7 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
if( decoder_UpdateVideoFormat( p_dec ) )
{
av_frame_free(&frame);
+ wait_mt( p_sys );
continue;
}
}
@@ -1253,6 +1260,7 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
if( !p_pic )
{
av_frame_free(&frame);
+ wait_mt( p_sys );
break;
}
@@ -1261,6 +1269,7 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
av_frame_free(&frame);
picture_Release( p_pic );
+ wait_mt( p_sys );
break;
}
}
@@ -1275,6 +1284,7 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
if( unlikely(p_pic == NULL) )
{
av_frame_free(&frame);
+ wait_mt( p_sys );
break;
}
}
@@ -1312,11 +1322,14 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
if(p_frame_info->b_eos)
p_pic->b_still = true;
p_sys->b_first_frame = false;
+ wait_mt( p_sys );
decoder_QueueVideo( p_dec, p_pic );
}
else
+ {
+ wait_mt( p_sys );
picture_Release( p_pic );
-
+ }
} while( true );
/* After draining, we need to reset decoder with a flush */
--
2.20.1
More information about the vlc-devel
mailing list