From 4e05f75261d997cfc48227f5ac1ab8f18101c437 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 13 May 2018 12:56:03 +0200 Subject: demux_lavf: remove ffm blacklist entry ffm (ffserver) was removed from ffmpeg. --- demux/demux_lavf.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'demux') diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 555df9406d..60ae878398 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -186,8 +186,6 @@ static const struct format_hack format_hacks[] = { BLACKLIST("bin"), // Useless, does not work with custom streams. BLACKLIST("image2"), - // Probably a security risk. - BLACKLIST("ffm"), // Image demuxers ("_pipe" is detected explicitly) {"image2pipe", .image_format = true}, {0} -- cgit v1.2.3 From 9ceccd6fca553ec4f310685d02b1f088117cd9ba Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 13 May 2018 16:22:57 +0200 Subject: demux: fix/improve aspects of EOF signaling When the current packet queue was completely empty, and EOF was reached, the queue->is_eof flag was not correctly set to true. Change this by reading ds->eof to check whether the stream is considered EOF. We also need to make sure update_seek_ranges() is called in this case, so change the code to simply call it when queue->is_eof changes. Also, read_packet() needs to call adjust_seek_range_on_packet() if ds->eof changes. In that case, the decoder also needs to be notified about EOF. So both of these should be called when ds->eof changes to true. (Other code outside of this function deals with the case when ds->eof is changed to false.) In addition, this code was kind of shoddy about calling wakeup_ds() correctly. It looks like there was an inverted condition, and sent a wakeup to the decoder only when ds->eof was already true, which is obviously bogus. The final EOF case tried to be somehow clever about checking in->last_eof for notifying the codec, which is sort of OK, but seems to be strictly worse than just checking whether ds->eof changed. Fix these things. --- demux/demux.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'demux') diff --git a/demux/demux.c b/demux/demux.c index 40a68eacae..73d4927002 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -1236,6 +1236,7 @@ static void adjust_seek_range_on_packet(struct demux_stream *ds, { struct demux_queue *queue = ds->queue; bool attempt_range_join = false; + bool prev_eof = queue->is_eof; if (!ds->in->seekable_cache) return; @@ -1253,6 +1254,8 @@ static void adjust_seek_range_on_packet(struct demux_stream *ds, attempt_range_join = queue->range->seek_end > old_end; if (queue->keyframe_latest->kf_seek_pts != MP_NOPTS_VALUE) add_index_entry(queue, queue->keyframe_latest); + } else { + queue->is_eof |= ds->eof; } queue->keyframe_latest = dp; queue->keyframe_pts = queue->keyframe_end_pts = MP_NOPTS_VALUE; @@ -1268,12 +1271,12 @@ static void adjust_seek_range_on_packet(struct demux_stream *ds, queue->keyframe_pts = MP_PTS_MIN(queue->keyframe_pts, ts); queue->keyframe_end_pts = MP_PTS_MAX(queue->keyframe_end_pts, ts); - if (queue->is_eof) { - queue->is_eof = false; - update_seek_ranges(queue->range); - } + queue->is_eof = false; } + if (queue->is_eof != prev_eof) + update_seek_ranges(queue->range); + if (attempt_range_join) attempt_range_joining(ds->in); } @@ -1443,9 +1446,11 @@ static bool read_packet(struct demux_internal *in) for (int n = 0; n < in->num_streams; n++) { struct demux_stream *ds = in->streams[n]->ds; bool eof = !ds->reader_head; - if (eof && ds->eof) + if (!ds->eof && eof) { + ds->eof = true; + adjust_seek_range_on_packet(ds, NULL); wakeup_ds(ds); - ds->eof |= eof; + } } return false; } @@ -1477,11 +1482,11 @@ static bool read_packet(struct demux_internal *in) if (eof) { for (int n = 0; n < in->num_streams; n++) { struct demux_stream *ds = in->streams[n]->ds; - if (!ds->eof) + if (!ds->eof) { + ds->eof = true; adjust_seek_range_on_packet(ds, NULL); - ds->eof = true; - if (!in->last_eof && ds->wakeup_cb) wakeup_ds(ds); + } } // If we had EOF previously, then don't wakeup (avoids wakeup loop) if (!in->last_eof) { -- cgit v1.2.3 From 2fc59ea8b34691a66811a6481b2a6f0a61ed62e5 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 13 May 2018 16:25:39 +0200 Subject: demux: streams that reached EOF shouldn't restrict the seek range Normally, the seek range is the minimum overlap of the cached ranges of each stream. But if one of the streams ends earlier, this leads to the seek range getting cut off, even if you could seek there. Change it so that EOF streams cannot restrict the end of the seek range. They can only extend it. This is the opposite from not-EOF streams, so they need to be handled separately. In particular, they get exluded from normal end range calculation, but when full EOF is reached, all streams are EOF, and the maximum end time can be used to set the seek end time. (In theory we could also take the max with the demuxer signaled total file duration, but let's not for now.) Also, if a stream is completely empty, essentially skip it, instead of considering the range unseekable. (Also, we don't need to mess with seek_start in this case, because it will be NOPTS and is skipped anyway.) --- demux/demux.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'demux') diff --git a/demux/demux.c b/demux/demux.c index 73d4927002..aba950b9ab 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -508,23 +508,32 @@ static void update_seek_ranges(struct demux_cached_range *range) range->is_bof = true; range->is_eof = true; + double max_end_pts = MP_NOPTS_VALUE; + for (int n = 0; n < range->num_streams; n++) { struct demux_queue *queue = range->streams[n]; if (queue->ds->selected && queue->ds->eager) { range->seek_start = MP_PTS_MAX(range->seek_start, queue->seek_start); - range->seek_end = MP_PTS_MIN(range->seek_end, queue->seek_end); + + if (queue->is_eof) { + max_end_pts = MP_PTS_MAX(max_end_pts, queue->seek_end); + } else { + range->seek_end = MP_PTS_MIN(range->seek_end, queue->seek_end); + } range->is_eof &= queue->is_eof; range->is_bof &= queue->is_bof; - if (queue->seek_start >= queue->seek_end) { - range->seek_start = range->seek_end = MP_NOPTS_VALUE; - break; - } + bool empty = queue->is_eof && !queue->head; + if (queue->seek_start >= queue->seek_end && !empty) + goto broken; } } + if (range->is_eof) + range->seek_end = max_end_pts; + // Sparse stream behavior is not very clearly defined, but usually we don't // want it to restrict the range of other streams, unless // This is incorrect in any of these cases: @@ -552,7 +561,12 @@ static void update_seek_ranges(struct demux_cached_range *range) } if (range->seek_start >= range->seek_end) - range->seek_start = range->seek_end = MP_NOPTS_VALUE; + goto broken; + + return; + +broken: + range->seek_start = range->seek_end = MP_NOPTS_VALUE; } // Remove queue->head from the queue. Does not update in->fw_bytes/in->fw_packs. -- cgit v1.2.3 From 75b2e6ed67f429835e555ebea894e14d036fde46 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 13 May 2018 16:32:12 +0200 Subject: demux: late streams on start shouldn't restrict the seek range If a stream starts later than the others at the start of the file, it shouldn't restrict the seek range to the time stamp where it begins. This is similar to the previous commit, just for the other end. --- demux/demux.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'demux') diff --git a/demux/demux.c b/demux/demux.c index aba950b9ab..f386c3c2ae 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -508,13 +508,19 @@ static void update_seek_ranges(struct demux_cached_range *range) range->is_bof = true; range->is_eof = true; + double min_start_pts = MP_NOPTS_VALUE; double max_end_pts = MP_NOPTS_VALUE; for (int n = 0; n < range->num_streams; n++) { struct demux_queue *queue = range->streams[n]; if (queue->ds->selected && queue->ds->eager) { - range->seek_start = MP_PTS_MAX(range->seek_start, queue->seek_start); + if (queue->is_bof) { + min_start_pts = MP_PTS_MIN(min_start_pts, queue->seek_start); + } else { + range->seek_start = + MP_PTS_MAX(range->seek_start, queue->seek_start); + } if (queue->is_eof) { max_end_pts = MP_PTS_MAX(max_end_pts, queue->seek_end); @@ -533,6 +539,8 @@ static void update_seek_ranges(struct demux_cached_range *range) if (range->is_eof) range->seek_end = max_end_pts; + if (range->is_bof) + range->seek_start = min_start_pts; // Sparse stream behavior is not very clearly defined, but usually we don't // want it to restrict the range of other streams, unless -- cgit v1.2.3 From 31b78ad7fa97d8047b609c1647a273e72612d425 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 17 May 2018 20:58:49 +0200 Subject: misc: move mp_cancel from stream.c to thread_tools.c It seems a bit inappropriate to have dumped this into stream.c, even if it's roughly speaking its main user. At least it made its way somewhat unfortunately to other components not related to the stream or demuxer layer at all. I'm too greedy to give this weird helper its own file, so dump it into thread_tools.c. Probably a somewhat pointless change. --- demux/demux.c | 1 + demux/demux_lavf.c | 1 + demux/demux_mkv_timeline.c | 1 + demux/demux_playlist.c | 1 + 4 files changed, 4 insertions(+) (limited to 'demux') diff --git a/demux/demux.c b/demux/demux.c index f386c3c2ae..0edfaa95bf 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -34,6 +34,7 @@ #include "mpv_talloc.h" #include "common/msg.h" #include "common/global.h" +#include "misc/thread_tools.h" #include "osdep/atomic.h" #include "osdep/threads.h" diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 60ae878398..a0b5ff7472 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -42,6 +42,7 @@ #include "common/av_common.h" #include "misc/bstr.h" #include "misc/charset_conv.h" +#include "misc/thread_tools.h" #include "stream/stream.h" #include "demux.h" diff --git a/demux/demux_mkv_timeline.c b/demux/demux_mkv_timeline.c index 3ad24eb8a5..277ff9c1ee 100644 --- a/demux/demux_mkv_timeline.c +++ b/demux/demux_mkv_timeline.c @@ -39,6 +39,7 @@ #include "options/options.h" #include "options/path.h" #include "misc/bstr.h" +#include "misc/thread_tools.h" #include "common/common.h" #include "common/playlist.h" #include "stream/stream.h" diff --git a/demux/demux_playlist.c b/demux/demux_playlist.c index 3a65ada451..0aa542534d 100644 --- a/demux/demux_playlist.c +++ b/demux/demux_playlist.c @@ -25,6 +25,7 @@ #include "options/options.h" #include "common/msg.h" #include "common/playlist.h" +#include "misc/thread_tools.h" #include "options/path.h" #include "stream/stream.h" #include "osdep/io.h" -- cgit v1.2.3 From f9713921a372aa14ea631b0c546d3fbeade32b71 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 18 May 2018 15:48:14 +0200 Subject: demux: add a "cancel" field Instead of relying on demuxer->stream->cancel. This is better because the stream is potentially closed and replaced. --- demux/demux.c | 3 ++- demux/demux.h | 3 +++ demux/demux_lavf.c | 3 +-- demux/demux_timeline.c | 2 +- demux/timeline.c | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) (limited to 'demux') diff --git a/demux/demux.c b/demux/demux.c index 0edfaa95bf..5f4c93b84f 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -2200,6 +2200,7 @@ static struct demuxer *open_given_type(struct mpv_global *global, *demuxer = (struct demuxer) { .desc = desc, .stream = stream, + .cancel = stream->cancel, .seekable = stream->seekable, .filepos = -1, .global = global, @@ -3136,7 +3137,7 @@ int demux_stream_control(demuxer_t *demuxer, int ctrl, void *arg) bool demux_cancel_test(struct demuxer *demuxer) { - return mp_cancel_test(demuxer->stream->cancel); + return mp_cancel_test(demuxer->cancel); } struct demux_chapter *demux_copy_chapter_data(struct demux_chapter *c, int num) diff --git a/demux/demux.h b/demux/demux.h index 0150ce1a1a..ccbc6ae94a 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -233,6 +233,9 @@ typedef struct demuxer { struct mp_tags **update_stream_tags; int num_update_stream_tags; + // Triggered when ending demuxing forcefully. Usually bound to the stream too. + struct mp_cancel *cancel; + // Since the demuxer can run in its own thread, and the stream is not // thread-safe, only the demuxer is allowed to access the stream directly. // You can freely use demux_stream_control() to send STREAM_CTRLs. diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index a0b5ff7472..41c334d309 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -775,8 +775,7 @@ static void update_metadata(demuxer_t *demuxer) static int interrupt_cb(void *ctx) { struct demuxer *demuxer = ctx; - lavf_priv_t *priv = demuxer->priv; - return mp_cancel_test(priv->stream->cancel); + return mp_cancel_test(demuxer->cancel); } static int block_io_open(struct AVFormatContext *s, AVIOContext **pb, diff --git a/demux/demux_timeline.c b/demux/demux_timeline.c index 4b9b3124fa..9d92d1879d 100644 --- a/demux/demux_timeline.c +++ b/demux/demux_timeline.c @@ -167,7 +167,7 @@ static void reopen_lazy_segments(struct demuxer *demuxer) .skip_lavf_probing = true, }; p->current->d = demux_open_url(p->current->url, ¶ms, - demuxer->stream->cancel, demuxer->global); + demuxer->cancel, demuxer->global); if (!p->current->d && !demux_cancel_test(demuxer)) MP_ERR(demuxer, "failed to load segment\n"); if (p->current->d) diff --git a/demux/timeline.c b/demux/timeline.c index 700a6dfd05..c53170b623 100644 --- a/demux/timeline.c +++ b/demux/timeline.c @@ -14,7 +14,7 @@ struct timeline *timeline_load(struct mpv_global *global, struct mp_log *log, *tl = (struct timeline){ .global = global, .log = log, - .cancel = demuxer->stream->cancel, + .cancel = demuxer->cancel, .demuxer = demuxer, .track_layout = demuxer, }; -- cgit v1.2.3 From 76dc5d9aa92f5c91c728004214f7b08c3a85a5f6 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 18 May 2018 22:19:10 +0200 Subject: command: make loadlist command async and abortable Don't allow it to freeze everything when loading a playlist from network (although you definitely shouldn't do that, but whatever). This also affects the really obscure --ordered-chapters-files option. The --playlist option on the other hand has no choice but to freeze the shit, because there's no concept of aborting the player during command line parsing. --- demux/demux_mkv_timeline.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'demux') diff --git a/demux/demux_mkv_timeline.c b/demux/demux_mkv_timeline.c index 277ff9c1ee..48d8c444b3 100644 --- a/demux/demux_mkv_timeline.c +++ b/demux/demux_mkv_timeline.c @@ -264,7 +264,8 @@ static void find_ordered_chapter_sources(struct tl_ctx *ctx) MP_INFO(ctx, "Loading references from '%s'.\n", opts->ordered_chapters_files); struct playlist *pl = - playlist_parse_file(opts->ordered_chapters_files, ctx->global); + playlist_parse_file(opts->ordered_chapters_files, + ctx->tl->cancel, ctx->global); talloc_steal(tmp, pl); for (struct playlist_entry *e = pl ? pl->first : NULL; e; e = e->next) MP_TARRAY_APPEND(tmp, filenames, num_filenames, e->filename); -- cgit v1.2.3 From d7ca95c3ea90782c786a6a607d3713bb42a104b1 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 19 May 2018 12:08:48 +0200 Subject: command: whitelist some blocking accesses for certain demuxers/streams The properties/commands touched in this commit are all for obscure special inputs (BD/DVD/DVB/TV), and they all block on the demuxer/stream layer. For network streams, this blocking is very unwelcome. They will affect playback and probably introduce pauses and frame drops. The player can even freeze fully, and the logic that tries to make playback abortable even if frozen complicates the player. Since the mentioned accesses are not needed for network streams, but they will block on network streams even though they're going to fail, add a flag that coarsely enables/disables these accesses. Essentially it establishes a whitelist of demuxers/streams which support them. In theory you could to access BD/DVD images over network (or add such support, I don't think it's a thing in mpv). In these cases these controls still can block and could even "freeze" the player completely. Writing to the "program" and "cache-size" properties still can block even for network streams. Just don't use them if you don't want freezes. --- demux/demux.c | 1 + demux/demux.h | 1 + demux/demux_disc.c | 2 ++ demux/demux_tv.c | 2 ++ 4 files changed, 6 insertions(+) (limited to 'demux') diff --git a/demux/demux.c b/demux/demux.c index 5f4c93b84f..ef420eb5ab 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -2211,6 +2211,7 @@ static struct demuxer *open_given_type(struct mpv_global *global, .access_references = opts->access_references, .events = DEMUX_EVENT_ALL, .duration = -1, + .extended_ctrls = stream->extended_ctrls, }; demuxer->seekable = stream->seekable; if (demuxer->stream->underlying && !demuxer->stream->underlying->seekable) diff --git a/demux/demux.h b/demux/demux.h index ccbc6ae94a..25cefd115f 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -202,6 +202,7 @@ typedef struct demuxer { bool fully_read; bool is_network; // opened directly from a network stream bool access_references; // allow opening other files/URLs + bool extended_ctrls; // supports some of BD/DVD/DVB/TV controls // Bitmask of DEMUX_EVENT_* int events; diff --git a/demux/demux_disc.c b/demux/demux_disc.c index 6ab17e69c8..2b81350ea4 100644 --- a/demux/demux_disc.c +++ b/demux/demux_disc.c @@ -342,6 +342,8 @@ static int d_open(demuxer_t *demuxer, enum demux_check check) if (stream_control(demuxer->stream, STREAM_CTRL_GET_TIME_LENGTH, &len) >= 1) demuxer->duration = len; + demuxer->extended_ctrls = true; + return 0; } diff --git a/demux/demux_tv.c b/demux/demux_tv.c index 0e9bee4317..79cff5d79d 100644 --- a/demux/demux_tv.c +++ b/demux/demux_tv.c @@ -181,6 +181,8 @@ no_audio: if(funcs->control(tvh->priv,TVI_CONTROL_VID_SET_GAIN,&tvh->tv_param->gain)!=TVI_CONTROL_TRUE) MP_WARN(tvh, "Unable to set gain control!\n"); + demuxer->extended_ctrls = true; + return 0; } -- cgit v1.2.3 From d33e5972b38c1a8d1ed2c19095a94c70c33881c3 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 19 May 2018 14:41:06 +0200 Subject: demux: get rid of free_demuxer[_and_stream]() Them being separate is just dumb. Replace them with a single demux_free() function, and free its stream by default. Not freeing the stream is only needed in 1 special case (demux_disc.c), use a special flag to not free the stream in this case. --- demux/demux.c | 31 ++++++++++++++++--------------- demux/demux.h | 4 ++-- demux/demux_disc.c | 7 +++++-- demux/demux_mkv_timeline.c | 4 ++-- demux/demux_timeline.c | 4 ++-- demux/timeline.c | 4 ++-- 6 files changed, 29 insertions(+), 25 deletions(-) (limited to 'demux') diff --git a/demux/demux.c b/demux/demux.c index ef420eb5ab..7807a919ae 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -130,6 +130,8 @@ struct demux_internal { struct demuxer *d_thread; // accessed by demuxer impl. (producer) struct demuxer *d_user; // accessed by player (consumer) + bool owns_stream; + // The lock protects the packet queues (struct demux_stream), // and the fields below. pthread_mutex_t lock; @@ -943,7 +945,7 @@ int demux_get_num_stream(struct demuxer *demuxer) return r; } -void free_demuxer(demuxer_t *demuxer) +void demux_free(struct demuxer *demuxer) { if (!demuxer) return; @@ -958,6 +960,9 @@ void free_demuxer(demuxer_t *demuxer) demux_flush(demuxer); assert(in->total_bytes == 0); + if (in->owns_stream) + free_stream(demuxer->stream); + for (int n = 0; n < in->num_streams; n++) talloc_free(in->streams[n]); pthread_mutex_destroy(&in->lock); @@ -965,15 +970,6 @@ void free_demuxer(demuxer_t *demuxer) talloc_free(demuxer); } -void free_demuxer_and_stream(struct demuxer *demuxer) -{ - if (!demuxer) - return; - struct stream *s = demuxer->stream; - free_demuxer(demuxer); - free_stream(s); -} - // Start the demuxer thread, which reads ahead packets on its own. void demux_start_thread(struct demuxer *demuxer) { @@ -2307,7 +2303,7 @@ static struct demuxer *open_given_type(struct mpv_global *global, return demuxer; } - free_demuxer(demuxer); + demux_free(demuxer); return NULL; } @@ -2316,6 +2312,9 @@ static const int d_request[] = {DEMUX_CHECK_REQUEST, -1}; static const int d_force[] = {DEMUX_CHECK_FORCE, -1}; // params can be NULL +// If params->does_not_own_stream==false, this does _not_ free the stream if +// opening fails. But if it succeeds, a later demux_free() call will free the +// stream. struct demuxer *demux_open(struct stream *stream, struct demuxer_params *params, struct mpv_global *global) { @@ -2355,6 +2354,8 @@ struct demuxer *demux_open(struct stream *stream, struct demuxer_params *params, if (demuxer) { talloc_steal(demuxer, log); log = NULL; + demuxer->in->owns_stream = + params ? !params->does_not_own_stream : false; goto done; } } @@ -2368,16 +2369,16 @@ done: // Convenience function: open the stream, enable the cache (according to params // and global opts.), open the demuxer. -// (use free_demuxer_and_stream() to free the underlying stream too) // Also for some reason may close the opened stream if it's not needed. struct demuxer *demux_open_url(const char *url, - struct demuxer_params *params, - struct mp_cancel *cancel, - struct mpv_global *global) + struct demuxer_params *params, + struct mp_cancel *cancel, + struct mpv_global *global) { struct demuxer_params dummy = {0}; if (!params) params = &dummy; + assert(!params->does_not_own_stream); // API user error struct stream *s = stream_create(url, STREAM_READ | params->stream_flags, cancel, global); if (!s) diff --git a/demux/demux.h b/demux/demux.h index 25cefd115f..6a8a08d8df 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -177,6 +177,7 @@ struct demuxer_params { bool initial_readahead; bstr init_fragment; bool skip_lavf_probing; + bool does_not_own_stream; // if false, stream is free'd on demux_free() // -- demux_open_url() only int stream_flags; bool disable_cache; @@ -249,8 +250,7 @@ typedef struct { int aid, vid, sid; //audio, video and subtitle id } demux_program_t; -void free_demuxer(struct demuxer *demuxer); -void free_demuxer_and_stream(struct demuxer *demuxer); +void demux_free(struct demuxer *demuxer); void demux_add_packet(struct sh_stream *stream, demux_packet_t *dp); void demuxer_feed_caption(struct sh_stream *stream, demux_packet_t *dp); diff --git a/demux/demux_disc.c b/demux/demux_disc.c index 2b81350ea4..15ccb2313d 100644 --- a/demux/demux_disc.c +++ b/demux/demux_disc.c @@ -285,7 +285,10 @@ static int d_open(demuxer_t *demuxer, enum demux_check check) if (check != DEMUX_CHECK_FORCE) return -1; - struct demuxer_params params = {.force_format = "+lavf"}; + struct demuxer_params params = { + .force_format = "+lavf", + .does_not_own_stream = true, + }; struct stream *cur = demuxer->stream; const char *sname = ""; @@ -350,7 +353,7 @@ static int d_open(demuxer_t *demuxer, enum demux_check check) static void d_close(demuxer_t *demuxer) { struct priv *p = demuxer->priv; - free_demuxer(p->slave); + demux_free(p->slave); } static int d_control(demuxer_t *demuxer, int cmd, void *arg) diff --git a/demux/demux_mkv_timeline.c b/demux/demux_mkv_timeline.c index 48d8c444b3..2a02a35dc5 100644 --- a/demux/demux_mkv_timeline.c +++ b/demux/demux_mkv_timeline.c @@ -217,7 +217,7 @@ static bool check_file_seg(struct tl_ctx *ctx, char *filename, int segment) } if (stream_wants_cache(d->stream, ctx->opts->stream_cache)) { - free_demuxer_and_stream(d); + demux_free(d); params.disable_cache = false; params.matroska_wanted_uids = ctx->uids; // potentially reallocated, same data d = demux_open_url(filename, ¶ms, cancel, ctx->global); @@ -230,7 +230,7 @@ static bool check_file_seg(struct tl_ctx *ctx, char *filename, int segment) } } - free_demuxer_and_stream(d); + demux_free(d); return was_valid; } diff --git a/demux/demux_timeline.c b/demux/demux_timeline.c index 9d92d1879d..1eb73956c3 100644 --- a/demux/demux_timeline.c +++ b/demux/demux_timeline.c @@ -147,7 +147,7 @@ static void close_lazy_segments(struct demuxer *demuxer) for (int n = 0; n < p->num_segments; n++) { struct segment *seg = p->segments[n]; if (seg != p->current && seg->d && seg->lazy) { - free_demuxer_and_stream(seg->d); + demux_free(seg->d); seg->d = NULL; } } @@ -431,7 +431,7 @@ static void d_close(struct demuxer *demuxer) p->current = NULL; close_lazy_segments(demuxer); timeline_destroy(p->tl); - free_demuxer(master); + demux_free(master); } static int d_control(struct demuxer *demuxer, int cmd, void *arg) diff --git a/demux/timeline.c b/demux/timeline.c index c53170b623..c44f67b166 100644 --- a/demux/timeline.c +++ b/demux/timeline.c @@ -34,9 +34,9 @@ void timeline_destroy(struct timeline *tl) for (int n = 0; n < tl->num_sources; n++) { struct demuxer *d = tl->sources[n]; if (d != tl->demuxer && d != tl->track_layout) - free_demuxer_and_stream(d); + demux_free(d); } if (tl->track_layout && tl->track_layout != tl->demuxer) - free_demuxer_and_stream(tl->track_layout); + demux_free(tl->track_layout); talloc_free(tl); } -- cgit v1.2.3 From 29a51900c6047798244afaca271618caeeeeeee8 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 19 May 2018 17:06:00 +0200 Subject: player: some further cleanup of the mp_cancel crap Alway give each demuxer its own mp_cancel instance. This makes management of the mp_cancel things much easier. Also, instead of having add/remove functions for mp_cancel slaves, replace them with a simpler to use set_parent function. Remove cancel_and_free_demuxer(), which had mpctx as parameter only to check an assumption. With this commit, demuxers have their own mp_cancel, so add demux_cancel_and_free() which makes use of it. --- demux/demux.c | 25 +++++++++++++++++++++++-- demux/demux.h | 1 + 2 files changed, 24 insertions(+), 2 deletions(-) (limited to 'demux') diff --git a/demux/demux.c b/demux/demux.c index 7807a919ae..33e3351b9e 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -970,6 +970,17 @@ void demux_free(struct demuxer *demuxer) talloc_free(demuxer); } +// Like demux_free(), but trigger an abort, which will force the demuxer to +// terminate immediately. If this wasn't opened with demux_open_url(), there is +// some chance this will accidentally abort other things via demuxer->cancel. +void demux_cancel_and_free(struct demuxer *demuxer) +{ + if (!demuxer) + return; + mp_cancel_trigger(demuxer->cancel); + demux_free(demuxer); +} + // Start the demuxer thread, which reads ahead packets on its own. void demux_start_thread(struct demuxer *demuxer) { @@ -2370,6 +2381,9 @@ done: // Convenience function: open the stream, enable the cache (according to params // and global opts.), open the demuxer. // Also for some reason may close the opened stream if it's not needed. +// demuxer->cancel is not the cancel parameter, but is its own object that will +// be a slave (mp_cancel_set_parent()) to provided cancel object. +// demuxer->cancel is automatically freed. struct demuxer *demux_open_url(const char *url, struct demuxer_params *params, struct mp_cancel *cancel, @@ -2379,18 +2393,25 @@ struct demuxer *demux_open_url(const char *url, if (!params) params = &dummy; assert(!params->does_not_own_stream); // API user error + struct mp_cancel *priv_cancel = mp_cancel_new(NULL); + if (cancel) + mp_cancel_set_parent(priv_cancel, cancel); struct stream *s = stream_create(url, STREAM_READ | params->stream_flags, - cancel, global); - if (!s) + priv_cancel, global); + if (!s) { + talloc_free(priv_cancel); return NULL; + } if (!params->disable_cache) stream_enable_cache_defaults(&s); struct demuxer *d = demux_open(s, params, global); if (d) { + talloc_steal(d->in, priv_cancel); demux_maybe_replace_stream(d); } else { params->demuxer_failed = true; free_stream(s); + talloc_free(priv_cancel); } return d; } diff --git a/demux/demux.h b/demux/demux.h index 6a8a08d8df..f5b203590f 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -251,6 +251,7 @@ typedef struct { } demux_program_t; void demux_free(struct demuxer *demuxer); +void demux_cancel_and_free(struct demuxer *demuxer); void demux_add_packet(struct sh_stream *stream, demux_packet_t *dp); void demuxer_feed_caption(struct sh_stream *stream, demux_packet_t *dp); -- cgit v1.2.3 From c24520b7f3651dbd4cbdffe93a187c3d213ff845 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 19 May 2018 18:19:07 +0200 Subject: demux: add a way to destroy the demuxer asynchronously This will enable the player core to terminate the demuxers in a "nicer" way without having to block on network. If it just used demux_free(), it would either have to block on network, or like currently, essentially kill all I/O forcefully. The API is slightly awkward, because demuxer lifetime is bound to its allocation. On the other hand, changing that would also be awkward, and introduce weird in-between states that would have to be handled in tons of places. Currently unused, to be user later. --- demux/demux.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- demux/demux.h | 5 ++++ 2 files changed, 93 insertions(+), 8 deletions(-) (limited to 'demux') diff --git a/demux/demux.c b/demux/demux.c index 33e3351b9e..c31dfcf809 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -142,6 +142,7 @@ struct demux_internal { bool thread_terminate; bool threading; + bool shutdown_async; void (*wakeup_cb)(void *ctx); void *wakeup_cb_ctx; @@ -945,29 +946,97 @@ int demux_get_num_stream(struct demuxer *demuxer) return r; } -void demux_free(struct demuxer *demuxer) +static void demux_shutdown(struct demux_internal *in) { - if (!demuxer) - return; - struct demux_internal *in = demuxer->in; - assert(demuxer == in->d_user); - - demux_stop_thread(demuxer); + struct demuxer *demuxer = in->d_user; if (demuxer->desc->close) demuxer->desc->close(in->d_thread); + demuxer->priv = NULL; + in->d_thread->priv = NULL; demux_flush(demuxer); assert(in->total_bytes == 0); if (in->owns_stream) free_stream(demuxer->stream); + demuxer->stream = NULL; +} +static void demux_dealloc(struct demux_internal *in) +{ for (int n = 0; n < in->num_streams; n++) talloc_free(in->streams[n]); pthread_mutex_destroy(&in->lock); pthread_cond_destroy(&in->wakeup); - talloc_free(demuxer); + talloc_free(in->d_user); +} + +void demux_free(struct demuxer *demuxer) +{ + if (!demuxer) + return; + struct demux_internal *in = demuxer->in; + assert(demuxer == in->d_user); + + demux_stop_thread(demuxer); + demux_shutdown(in); + demux_dealloc(in); +} + +// Start closing the demuxer and eventually freeing the demuxer asynchronously. +// You must not access the demuxer once this has been started. Once the demuxer +// is shutdown, the wakeup callback is invoked. Then you need to call +// demux_free_async_finish() to end the operation (it must not be called from +// the wakeup callback). +// This can return NULL. Then the demuxer cannot be free'd asynchronously, and +// you need to call demux_free() instead. +struct demux_free_async_state *demux_free_async(struct demuxer *demuxer) +{ + struct demux_internal *in = demuxer->in; + assert(demuxer == in->d_user); + + if (!in->threading) + return NULL; + + pthread_mutex_lock(&in->lock); + in->thread_terminate = true; + in->shutdown_async = true; + pthread_cond_signal(&in->wakeup); + pthread_mutex_unlock(&in->lock); + + return (struct demux_free_async_state *)demuxer->in; // lies +} + +// As long as state is valid, you can call this to request immediate abort. +// Roughly behaves as demux_cancel_and_free(), except you still need to wait +// for the result. +void demux_free_async_force(struct demux_free_async_state *state) +{ + struct demux_internal *in = (struct demux_internal *)state; // reverse lies + + mp_cancel_trigger(in->d_user->cancel); +} + +// Check whether the demuxer is shutdown yet. If not, return false, and you +// need to call this again in the future (preferably after you were notified by +// the wakeup callback). If yes, deallocate all state, and return true (in +// particular, the state ptr becomes invalid, and the wakeup callback will never +// be called again). +bool demux_free_async_finish(struct demux_free_async_state *state) +{ + struct demux_internal *in = (struct demux_internal *)state; // reverse lies + + pthread_mutex_lock(&in->lock); + bool busy = in->shutdown_async; + pthread_mutex_unlock(&in->lock); + + if (busy) + return false; + + demux_stop_thread(in->d_user); + demux_dealloc(in); + return true; } // Like demux_free(), but trigger an abort, which will force the demuxer to @@ -1688,12 +1757,23 @@ static void *demux_thread(void *pctx) struct demux_internal *in = pctx; mpthread_set_name("demux"); pthread_mutex_lock(&in->lock); + while (!in->thread_terminate) { if (thread_work(in)) continue; pthread_cond_signal(&in->wakeup); pthread_cond_wait(&in->wakeup, &in->lock); } + + if (in->shutdown_async) { + pthread_mutex_unlock(&in->lock); + demux_shutdown(in); + pthread_mutex_lock(&in->lock); + in->shutdown_async = false; + if (in->wakeup_cb) + in->wakeup_cb(in->wakeup_cb_ctx); + } + pthread_mutex_unlock(&in->lock); return NULL; } diff --git a/demux/demux.h b/demux/demux.h index f5b203590f..7d2924000a 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -253,6 +253,11 @@ typedef struct { void demux_free(struct demuxer *demuxer); void demux_cancel_and_free(struct demuxer *demuxer); +struct demux_free_async_state; +struct demux_free_async_state *demux_free_async(struct demuxer *demuxer); +void demux_free_async_force(struct demux_free_async_state *state); +bool demux_free_async_finish(struct demux_free_async_state *state); + void demux_add_packet(struct sh_stream *stream, demux_packet_t *dp); void demuxer_feed_caption(struct sh_stream *stream, demux_packet_t *dp); -- cgit v1.2.3 From fe6b2f9103450679a07da44bdad31707b597cd20 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 21 May 2018 15:21:09 +0200 Subject: m_config: add a special define to access main config Passing NULL to mp_get_config_group() returns the main option struct. This is just a dumb hack to deal with inconsistencies caused by legacy things (as I'll claim), and will probably be changed in the future. So before littering the whole code base with hard to find NULL parameters, require using callers an easy to find separate define. --- demux/demux_mkv_timeline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'demux') diff --git a/demux/demux_mkv_timeline.c b/demux/demux_mkv_timeline.c index 2a02a35dc5..32eab2ca8f 100644 --- a/demux/demux_mkv_timeline.c +++ b/demux/demux_mkv_timeline.c @@ -517,7 +517,7 @@ void build_ordered_chapter_timeline(struct timeline *tl) .global = tl->global, .tl = tl, .demuxer = demuxer, - .opts = mp_get_config_group(ctx, tl->global, NULL), + .opts = mp_get_config_group(ctx, tl->global, GLOBAL_CONFIG), }; if (!ctx->opts->ordered_chapters || !demuxer->access_references) { -- cgit v1.2.3 From 982416266c9596bec0ee4a1b1098d37a0f79ad94 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 24 May 2018 19:33:25 +0200 Subject: demux_lavf: drop obscure genpts option This code shouldn't even exist in libavformat. If you still need it, you can enable it via --demuxer-lavf-o. --- demux/demux_lavf.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'demux') diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 41c334d309..ee81ff2773 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -77,7 +77,6 @@ struct demux_lavf_opts { char *format; char **avopts; int hacks; - int genptsmode; char *sub_cp; int rtsp_transport; }; @@ -96,8 +95,6 @@ const struct m_sub_options demux_lavf_conf = { OPT_INTRANGE("demuxer-lavf-probescore", probescore, 0, 1, AVPROBE_SCORE_MAX), OPT_FLAG("demuxer-lavf-hacks", hacks, 0), - OPT_CHOICE("demuxer-lavf-genpts-mode", genptsmode, 0, - ({"lavf", 1}, {"no", 0})), OPT_KEYVALUELIST("demuxer-lavf-o", avopts, 0), OPT_STRING("sub-codepage", sub_cp, 0), OPT_CHOICE("rtsp-transport", rtsp_transport, 0, @@ -814,8 +811,6 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check) if (!avfc) return -1; - if (lavfdopts->genptsmode) - avfc->flags |= AVFMT_FLAG_GENPTS; if (index_mode != 1) avfc->flags |= AVFMT_FLAG_IGNIDX; -- cgit v1.2.3 From 9467e90c5bc1c15245acf27afd6dc83287beba9d Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 24 Aug 2018 12:55:10 +0200 Subject: demux_lavf: v4l streams are not seekable FFmpeg is retarded enough not to give us any indication whether it is (unless we query fields not in the ABI/API). I bet FFmpeg developers love it when library users have to litter their code with duplicated information. --- demux/demux_lavf.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'demux') diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index ee81ff2773..333d707028 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -163,6 +163,8 @@ static const struct format_hack format_hacks[] = { {"mp4", .skipinfo = true, .fix_editlists = true}, {"matroska", .skipinfo = true}, + {"v4l2", .no_seek = true}, + // In theory, such streams might contain timestamps, but virtually none do. {"h264", .if_flags = AVFMT_NOTIMESTAMPS }, {"hevc", .if_flags = AVFMT_NOTIMESTAMPS }, -- cgit v1.2.3 From 120dcdf5ccac8f7ea7d4c5de34d5a28c90bc521b Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 24 Aug 2018 12:56:41 +0200 Subject: demux: allow cache sizes > 2GB There was no reason to limit this. Only some int fields had to be changed to size_t. --- demux/demux.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'demux') diff --git a/demux/demux.c b/demux/demux.c index c31dfcf809..3e9d897bb2 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -98,11 +98,15 @@ struct demux_opts { #define OPT_BASE_STRUCT struct demux_opts +#define MAX_BYTES MPMIN(INT64_MAX, (size_t)-1 / 2) + const struct m_sub_options demux_conf = { .opts = (const struct m_option[]){ OPT_DOUBLE("demuxer-readahead-secs", min_secs, M_OPT_MIN, .min = 0), - OPT_BYTE_SIZE("demuxer-max-bytes", max_bytes, 0, 0, INT_MAX), - OPT_BYTE_SIZE("demuxer-max-back-bytes", max_bytes_bw, 0, 0, INT_MAX), + // (The MAX_BYTES sizes may not be accurate because the max field is + // of double type.) + OPT_BYTE_SIZE("demuxer-max-bytes", max_bytes, 0, 0, MAX_BYTES), + OPT_BYTE_SIZE("demuxer-max-back-bytes", max_bytes_bw, 0, 0, MAX_BYTES), OPT_FLAG("force-seekable", force_seekable, 0), OPT_DOUBLE("cache-secs", min_secs_cache, M_OPT_MIN, .min = 0), OPT_FLAG("access-references", access_references, 0), @@ -164,8 +168,8 @@ struct demux_internal { bool idle; bool autoselect; double min_secs; - int max_bytes; - int max_bytes_bw; + size_t max_bytes; + size_t max_bytes_bw; bool seekable_cache; // At least one decoder actually requested data since init or the last seek. -- cgit v1.2.3 From 559a400ac36e75a8d73ba263fd7fa6736df1c2da Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 31 Aug 2018 12:48:36 +0200 Subject: demux, stream: rip out the classic stream cache The demuxer cache is the only cache now. Might need another change to combat seeking failures in mp4 etc. The only bad thing is the loss of cache-speed, which was sort of nice to have. --- demux/demux.c | 54 ++++++++++++++++++---------------------------- demux/demux.h | 3 +-- demux/demux_disc.c | 7 ++---- demux/demux_mkv_timeline.c | 10 --------- 4 files changed, 24 insertions(+), 50 deletions(-) (limited to 'demux') diff --git a/demux/demux.c b/demux/demux.c index 3e9d897bb2..45f472cfc9 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -86,6 +86,7 @@ const demuxer_desc_t *const demuxer_list[] = { }; struct demux_opts { + int enable_cache; int64_t max_bytes; int64_t max_bytes_bw; double min_secs; @@ -102,6 +103,8 @@ struct demux_opts { const struct m_sub_options demux_conf = { .opts = (const struct m_option[]){ + OPT_CHOICE("cache", enable_cache, 0, + ({"no", 0}, {"auto", -1}, {"yes", 1})), OPT_DOUBLE("demuxer-readahead-secs", min_secs, M_OPT_MIN, .min = 0), // (The MAX_BYTES sizes may not be accurate because the max field is // of double type.) @@ -117,6 +120,7 @@ const struct m_sub_options demux_conf = { }, .size = sizeof(struct demux_opts), .defaults = &(const struct demux_opts){ + .enable_cache = -1, // auto .max_bytes = 150 * 1024 * 1024, .max_bytes_bw = 50 * 1024 * 1024, .min_secs = 1.0, @@ -129,6 +133,8 @@ const struct m_sub_options demux_conf = { struct demux_internal { struct mp_log *log; + struct demux_opts *opts; + // The demuxer runs potentially in another thread, so we keep two demuxer // structs; the real demuxer can access the shadow struct only. struct demuxer *d_thread; // accessed by demuxer impl. (producer) @@ -215,8 +221,6 @@ struct demux_internal { // Transient state. double duration; // Cached state. - bool force_cache_update; - struct stream_cache_info stream_cache_info; int64_t stream_size; // Updated during init only. char *stream_base_filename; @@ -1695,9 +1699,6 @@ static void execute_trackswitch(struct demux_internal *in) if (in->d_thread->desc->control) in->d_thread->desc->control(in->d_thread, DEMUXER_CTRL_SWITCHED_TRACKS, 0); - stream_control(in->d_thread->stream, STREAM_CTRL_SET_READAHEAD, - &(int){any_selected}); - pthread_mutex_lock(&in->lock); } @@ -1746,13 +1747,6 @@ static bool thread_work(struct demux_internal *in) if (read_packet(in)) return true; // read_packet unlocked, so recheck conditions } - if (in->force_cache_update) { - pthread_mutex_unlock(&in->lock); - update_cache(in); - pthread_mutex_lock(&in->lock); - in->force_cache_update = false; - return true; - } return false; } @@ -2276,6 +2270,19 @@ static void fixup_metadata(struct demux_internal *in) } } +// Return whether "heavy" caching on this stream is enabled. By default, this +// corresponds to whether the source stream is considered in the network. The +// only effect should be adjusting display behavior (of cache stats etc.), and +// possibly switching between which set of options influence cache settings. +bool demux_is_network_cached(demuxer_t *demuxer) +{ + struct demux_internal *in = demuxer->in; + bool use_cache = demuxer->is_network; + if (in->opts->enable_cache >= 0) + use_cache = in->opts->enable_cache == 1; + return use_cache; +} + static struct demuxer *open_given_type(struct mpv_global *global, struct mp_log *log, const struct demuxer_desc *desc, @@ -2305,12 +2312,11 @@ static struct demuxer *open_given_type(struct mpv_global *global, .extended_ctrls = stream->extended_ctrls, }; demuxer->seekable = stream->seekable; - if (demuxer->stream->underlying && !demuxer->stream->underlying->seekable) - demuxer->seekable = false; struct demux_internal *in = demuxer->in = talloc_ptrtype(demuxer, in); *in = (struct demux_internal){ .log = demuxer->log, + .opts = opts, .d_thread = talloc(demuxer, struct demuxer), .d_user = demuxer, .min_secs = opts->min_secs, @@ -2371,10 +2377,8 @@ static struct demuxer *open_given_type(struct mpv_global *global, fixup_metadata(in); in->events = DEMUX_EVENT_ALL; demux_update(demuxer); - stream_control(demuxer->stream, STREAM_CTRL_SET_READAHEAD, - &(int){params ? params->initial_readahead : false}); int seekable = opts->seekable_cache; - if (demuxer->is_network || stream->caching) { + if (demux_is_network_cached(demuxer)) { in->min_secs = MPMAX(in->min_secs, opts->min_secs_cache); if (seekable < 0) seekable = 1; @@ -2486,8 +2490,6 @@ struct demuxer *demux_open_url(const char *url, talloc_free(priv_cancel); return NULL; } - if (!params->disable_cache) - stream_enable_cache_defaults(&s); struct demuxer *d = demux_open(s, params, global); if (d) { talloc_steal(d->in, priv_cancel); @@ -3042,15 +3044,12 @@ static void update_cache(struct demux_internal *in) // Don't lock while querying the stream. struct mp_tags *stream_metadata = NULL; - struct stream_cache_info stream_cache_info = {.size = -1}; int64_t stream_size = stream_get_size(stream); stream_control(stream, STREAM_CTRL_GET_METADATA, &stream_metadata); - stream_control(stream, STREAM_CTRL_GET_CACHE_INFO, &stream_cache_info); pthread_mutex_lock(&in->lock); in->stream_size = stream_size; - in->stream_cache_info = stream_cache_info; if (stream_metadata) { for (int n = 0; n < in->num_streams; n++) { struct demux_stream *ds = in->streams[n]->ds; @@ -3065,18 +3064,7 @@ static void update_cache(struct demux_internal *in) // must be called locked static int cached_stream_control(struct demux_internal *in, int cmd, void *arg) { - // If the cache is active, wake up the thread to possibly update cache state. - if (in->stream_cache_info.size >= 0) { - in->force_cache_update = true; - pthread_cond_signal(&in->wakeup); - } - switch (cmd) { - case STREAM_CTRL_GET_CACHE_INFO: - if (in->stream_cache_info.size < 0) - return STREAM_UNSUPPORTED; - *(struct stream_cache_info *)arg = in->stream_cache_info; - return STREAM_OK; case STREAM_CTRL_GET_SIZE: if (in->stream_size < 0) return STREAM_UNSUPPORTED; diff --git a/demux/demux.h b/demux/demux.h index 7d2924000a..5b92e97f49 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -174,13 +174,11 @@ struct demuxer_params { bool *matroska_was_valid; struct timeline *timeline; bool disable_timeline; - bool initial_readahead; bstr init_fragment; bool skip_lavf_probing; bool does_not_own_stream; // if false, stream is free'd on demux_free() // -- demux_open_url() only int stream_flags; - bool disable_cache; // result bool demuxer_failed; }; @@ -317,6 +315,7 @@ void demux_metadata_changed(demuxer_t *demuxer); void demux_update(demuxer_t *demuxer); void demux_disable_cache(demuxer_t *demuxer); +bool demux_is_network_cached(demuxer_t *demuxer); struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d, enum stream_type t, int id); diff --git a/demux/demux_disc.c b/demux/demux_disc.c index 15ccb2313d..e5c63cea17 100644 --- a/demux/demux_disc.c +++ b/demux/demux_disc.c @@ -292,11 +292,8 @@ static int d_open(demuxer_t *demuxer, enum demux_check check) struct stream *cur = demuxer->stream; const char *sname = ""; - while (cur) { - if (cur->info) - sname = cur->info->name; - cur = cur->underlying; // down the caching chain - } + if (cur->info) + sname = cur->info->name; p->is_cdda = strcmp(sname, "cdda") == 0; p->is_dvd = strcmp(sname, "dvd") == 0 || diff --git a/demux/demux_mkv_timeline.c b/demux/demux_mkv_timeline.c index 32eab2ca8f..69cf26e681 100644 --- a/demux/demux_mkv_timeline.c +++ b/demux/demux_mkv_timeline.c @@ -172,7 +172,6 @@ static bool check_file_seg(struct tl_ctx *ctx, char *filename, int segment) .matroska_wanted_segment = segment, .matroska_was_valid = &was_valid, .disable_timeline = true, - .disable_cache = true, }; struct mp_cancel *cancel = ctx->tl->cancel; if (mp_cancel_test(cancel)) @@ -216,15 +215,6 @@ static bool check_file_seg(struct tl_ctx *ctx, char *filename, int segment) } } - if (stream_wants_cache(d->stream, ctx->opts->stream_cache)) { - demux_free(d); - params.disable_cache = false; - params.matroska_wanted_uids = ctx->uids; // potentially reallocated, same data - d = demux_open_url(filename, ¶ms, cancel, ctx->global); - if (!d) - return false; - } - ctx->sources[i] = d; return true; } -- cgit v1.2.3