diff mbox series

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

Message ID 20220905211634.1460-4-lukas.fellechner@gmx.net
State New
Headers show
Series lavf/dashdec: Multithreaded DASH initialization | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Lukas Fellechner Sept. 5, 2022, 9:16 p.m. UTC
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(-)

--
2.28.0.windows.1
diff mbox series

Patch

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();