diff --git a/common/playlist.c b/common/playlist.c index 5504b185bc..7572e67780 100644 --- a/common/playlist.c +++ b/common/playlist.c @@ -297,7 +297,7 @@ struct playlist *playlist_parse_file(const char *file, struct mp_cancel *cancel, "pass it to the player\ndirectly. Don't use --playlist.\n"); } } - free_demuxer_and_stream(d); + demux_free(d); if (ret) { mp_verbose(log, "Playlist successfully parsed\n"); 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); } diff --git a/player/loadfile.c b/player/loadfile.c index a948d1d03d..297ab8ba97 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -136,7 +136,7 @@ static void cancel_and_free_demuxer(struct MPContext *mpctx, if (cancel) mp_cancel_trigger(cancel); - free_demuxer_and_stream(*demuxer); + demux_free(*demuxer); *demuxer = NULL; talloc_free(cancel);