[vlc-commits] sout: lock sout_stream_t individually
Rémi Denis-Courmont
git at videolan.org
Tue Jan 19 18:20:19 UTC 2021
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sun Oct 11 17:17:29 2020 +0300| [3a6927053cc8522bff8862c92cc0267dfa0a1341] | committer: Rémi Denis-Courmont
sout: lock sout_stream_t individually
The stream output is called from multiple threads without
synchronisation, notably at least one thread per ES decoder. Normally,
the stream output instance (sout_instance_t) lock will serialise all
calls to the first stream output module instance (sout_stream_t) in the
stream output chain.
This is not practical if there is also concurrency within the chain.
One notable case is when the select/duplicate module is used in filter
mode and one of the select/duplicate target is threaded, e.g.:
#duplicate{dst=transcode{...},dst=transcode{...}}:std{...}
In that example, the standard output can be called from both transcode
filters.
To solve this, add a lock for each element in the stream output chain.
Alternatively, we could drop filter mode from select/duplicate, leaving
only the (more common) output mode where duplicate is the last element
in the chain.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=3a6927053cc8522bff8862c92cc0267dfa0a1341
---
src/stream_output/stream_output.c | 44 ++++++++++++++++++++++++++++++++++-----
1 file changed, 39 insertions(+), 5 deletions(-)
diff --git a/src/stream_output/stream_output.c b/src/stream_output/stream_output.c
index ce46cf3ea4..b39b976c44 100644
--- a/src/stream_output/stream_output.c
+++ b/src/stream_output/stream_output.c
@@ -743,38 +743,71 @@ static void mrl_Clean( mrl_t *p_mrl )
struct sout_stream_private {
sout_stream_t stream;
+ vlc_mutex_t lock;
module_t *module;
};
#define sout_stream_priv(s) \
container_of(s, struct sout_stream_private, stream)
+static void sout_StreamLock(sout_stream_t *s)
+{
+ vlc_mutex_lock(&sout_stream_priv(s)->lock);
+}
+
+static void sout_StreamUnlock(sout_stream_t *s)
+{
+ vlc_mutex_unlock(&sout_stream_priv(s)->lock);
+}
+
void *sout_StreamIdAdd(sout_stream_t *s, const es_format_t *fmt)
{
- return s->ops->add(s, fmt);
+ void *id;
+
+ sout_StreamLock(s);
+ id = s->ops->add(s, fmt);
+ sout_StreamUnlock(s);
+ return id;
}
void sout_StreamIdDel(sout_stream_t *s, void *id)
{
+ sout_StreamLock(s);
s->ops->del(s, id);
+ sout_StreamUnlock(s);
}
int sout_StreamIdSend(sout_stream_t *s, void *id, block_t *b)
{
- return s->ops->send(s, id, b);
+ int val;
+
+ sout_StreamLock(s);
+ val = s->ops->send(s, id, b);
+ sout_StreamUnlock(s);
+ return val;
}
void sout_StreamFlush(sout_stream_t *s, void *id)
{
if (s->ops->flush != NULL)
+ {
+ sout_StreamLock(s);
s->ops->flush(s, id);
+ sout_StreamUnlock(s);
+ }
}
int sout_StreamControlVa(sout_stream_t *s, int i_query, va_list args)
{
- if (s->ops->control == NULL)
- return VLC_EGENERIC;
- return s->ops->control(s, i_query, args);
+ int val = VLC_EGENERIC;
+
+ if (s->ops->control != NULL)
+ {
+ sout_StreamLock(s);
+ val = s->ops->control(s, i_query, args);
+ sout_StreamUnlock(s);
+ }
+ return val;
}
/* Destroy a "stream_out" module */
@@ -830,6 +863,7 @@ static sout_stream_t *sout_StreamNew( vlc_object_t *parent, char *psz_name,
if (unlikely(priv == NULL))
return NULL;
+ vlc_mutex_init(&priv->lock);
p_stream = &priv->stream;
p_stream->psz_name = psz_name;
p_stream->p_cfg = p_cfg;
More information about the vlc-commits
mailing list