From 88ae9aff6ed66109fa4c0807fa616a7e6f5c8761 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Sun, 4 Jun 2017 00:38:29 -0700 Subject: [PATCH] deps/media-playback: Fix lockup issues Certain functions such as avformat_open_input and av_read_frame can block, causing the program to someone wait very long periods of time when a network URL is used with the media source. The interrupt_callback member variable in AVFormatContext allows safely canceling IO operations when trying to shut down or stop the media-playback interface. --- deps/media-playback/media-playback/media.c | 23 +++++++++++++++++++++- deps/media-playback/media-playback/media.h | 2 ++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/deps/media-playback/media-playback/media.c b/deps/media-playback/media-playback/media.c index f7ad781d6..c291e447e 100644 --- a/deps/media-playback/media-playback/media.c +++ b/deps/media-playback/media-playback/media.c @@ -486,6 +486,23 @@ static inline bool mp_media_eof(mp_media_t *m) return eof; } +static int interrupt_callback(void *data) +{ + mp_media_t *m = data; + bool stop = false; + uint64_t ts = os_gettime_ns(); + + if ((ts - m->interrupt_poll_ts) > 20000000) { + pthread_mutex_lock(&m->mutex); + stop = m->kill || m->stopping; + pthread_mutex_unlock(&m->mutex); + + m->interrupt_poll_ts = ts; + } + + return stop; +} + static bool init_avformat(mp_media_t *m) { AVInputFormat *format = NULL; @@ -501,6 +518,10 @@ static bool init_avformat(mp_media_t *m) if (m->buffering && m->is_network) av_dict_set_int(&opts, "buffer_size", m->buffering, 0); + m->fmt = avformat_alloc_context(); + m->fmt->interrupt_callback.callback = interrupt_callback; + m->fmt->interrupt_callback.opaque = m; + int ret = avformat_open_input(&m->fmt, m->path, format, opts ? &opts : NULL); av_dict_free(&opts); @@ -695,9 +716,9 @@ void mp_media_free(mp_media_t *media) mp_kill_thread(media); mp_decode_free(&media->v); mp_decode_free(&media->a); + avformat_close_input(&media->fmt); pthread_mutex_destroy(&media->mutex); os_sem_destroy(media->sem); - avformat_close_input(&media->fmt); sws_freeContext(media->swscale); av_freep(&media->scale_pic[0]); bfree(media->path); diff --git a/deps/media-playback/media-playback/media.h b/deps/media-playback/media-playback/media.h index 0cf7b9f87..e7c39c695 100644 --- a/deps/media-playback/media-playback/media.h +++ b/deps/media-playback/media-playback/media.h @@ -80,6 +80,8 @@ struct mp_media { int64_t start_ts; int64_t base_ts; + uint64_t interrupt_poll_ts; + pthread_mutex_t mutex; os_sem_t *sem; bool stopping;