[FFmpeg-devel] [PATCH v4 3/4] lavf/dashdec: Prevent cross-thread avio_opts modification

Lukas Fellechner lukas.fellechner at gmx.net
Tue Sep 6 00:16:33 EEST 2022


open_url modifies the shared avio_opts dict (update cookies).
This can cause problems during multithreaded initialization.
To prevent this, I take a copy of avio_opts, use that in open_url,
and copy the updated dict back afterwards.
---
 libavformat/dashdec.c | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
index 0532e2c918..19e657d836 100644
--- a/libavformat/dashdec.c
+++ b/libavformat/dashdec.c
@@ -156,6 +156,11 @@ typedef struct DASHContext {

     int init_threads;

+#if HAVE_THREADS
+    /* Set during parallel initialization, to allow locking of avio_opts */
+    pthread_mutex_t *init_mutex;
+#endif
+
     /* Flags for init section*/
     int is_init_section_common_video;
     int is_init_section_common_audio;
@@ -1699,7 +1704,32 @@ static int open_input(DASHContext *c, struct representation *pls, struct fragmen
     ff_make_absolute_url(url, c->max_url_size, c->base_url, seg->url);
     av_log(pls->parent, AV_LOG_VERBOSE, "DASH request for url '%s', offset %"PRId64"\n",
            url, seg->url_offset);
-    ret = open_url(pls->parent, &pls->input, url, &c->avio_opts, opts, NULL);
+
+    AVDictionary *avio_opts = c->avio_opts;
+
+#if HAVE_THREADS
+    // If we are doing parallel initialization, take a snapshot of the avio_opts,
+    // and copy the modified dictionary ("cookies" updated) back, after the url is opened.
+    if (c->init_mutex) {
+        pthread_mutex_lock(c->init_mutex);
+        avio_opts = NULL;
+        ret = av_dict_copy(&avio_opts, c->avio_opts, 0);
+        pthread_mutex_unlock(c->init_mutex);
+        if (ret < 0)
+            goto cleanup;
+    }
+#endif
+
+    ret = open_url(pls->parent, &pls->input, url, &avio_opts, opts, NULL);
+
+#if HAVE_THREADS
+    if (c->init_mutex) {
+        pthread_mutex_lock(c->init_mutex);
+        av_dict_free(&c->avio_opts);
+        c->avio_opts = avio_opts;
+        pthread_mutex_unlock(c->init_mutex);
+    }
+#endif

 cleanup:
     av_free(url);
@@ -2192,7 +2222,7 @@ static int init_streams_multithreaded(AVFormatContext *s, int nstreams, int thre
     if (!avpriv_slicethread_create(&slice_thread, (void*)work_pool, &thread_worker, NULL, threads)) {
         av_free(work_pool);
         return AVERROR(ENOMEM);
-}
+    }

     // alloc mutex and conditions
     c->init_mutex = create_mutex();
--
2.28.0.windows.1



More information about the ffmpeg-devel mailing list