From 3709ce6718bed8a113d141cdf5e8198f22f3c5f7 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 14 Apr 2017 19:19:44 +0200 Subject: demux: estimate total packet size, deprecate packet number limits It's all explained in the DOCS changes. Although this option was always kind of obscure and pointless. Until it is removed, the only reason for setting it would be to raise the static default limit, so change its default to INT_MAX so that it does nothing by default. --- DOCS/interface-changes.rst | 1 + DOCS/man/options.rst | 18 ++++++++++++------ demux/demux.c | 9 +++++---- demux/packet.c | 26 ++++++++++++++++++++++++++ demux/packet.h | 1 + 5 files changed, 45 insertions(+), 10 deletions(-) diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index d2618e1945..0e1fa35666 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -44,6 +44,7 @@ Interface changes - deprecate --loop - after a deprecation period, it will be undeprecated, but changed to alias --loop-file - add --keep-open-pause=no + - deprecate --demuxer-max-packets --- mpv 0.24.0 --- - deprecate --hwdec-api and replace it with --opengl-hwdec-interop. The new option accepts both --hwdec values, as well as named backends. diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 5814a41634..7d3070fda0 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -2754,20 +2754,26 @@ Demuxer ``--demuxer-rawvideo-size=`` Frame size in bytes when using ``--demuxer=rawvideo``. -``--demuxer-max-packets=``, ``--demuxer-max-bytes=`` +``--demuxer-max-bytes=`` This controls how much the demuxer is allowed to buffer ahead. The demuxer will normally try to read ahead as much as necessary, or as much is - requested with ``--demuxer-readahead-secs``. The ``--demuxer-max-...`` - options can be used to restrict the maximum readahead. This limits excessive - readahead in case of broken files or desynced playback. The demuxer will - stop reading additional packets as soon as one of the limits is reached. - (The limits still can be slightly overstepped due to technical reasons.) + requested with ``--demuxer-readahead-secs``. The option can be used to + restrict the maximum readahead. This limits excessive readahead in case of + broken files or desynced playback. The demuxer will stop reading additional + packets as soon as one of the limits is reached. (The limits still can be + slightly overstepped due to technical reasons.) Set these limits higher if you get a packet queue overflow warning, and you think normal playback would be possible with a larger packet queue. See ``--list-options`` for defaults and value range. +``--demuxer-max-packets=`` + Quite similar ``--demuxer-max-bytes=``. Deprecated, because the + other option does basically the same job. Since mpv 0.25.0, the code + tries to account for per-packet overhead, which is why this option becomes + rather pointless. + ``--demuxer-thread=`` Run the demuxer in a separate thread, and let it prefetch a certain amount of packets (default: yes). Having this enabled may lead to smoother diff --git a/demux/demux.c b/demux/demux.c index 0c45083e2d..acccdf5363 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -97,7 +97,8 @@ struct demux_opts { 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_INTRANGE("demuxer-max-packets", max_packs, 0, 0, INT_MAX), + OPT_INTRANGE("demuxer-max-packets", max_packs, 0, 0, INT_MAX, + .deprecation_message = "use --demuxer-max-bytes"), OPT_INTRANGE("demuxer-max-bytes", max_bytes, 0, 0, INT_MAX), OPT_FLAG("force-seekable", force_seekable, 0), OPT_DOUBLE("cache-secs", min_secs_cache, M_OPT_MIN, .min = 0), @@ -106,7 +107,7 @@ const struct m_sub_options demux_conf = { }, .size = sizeof(struct demux_opts), .defaults = &(const struct demux_opts){ - .max_packs = 16000, + .max_packs = INT_MAX, .max_bytes = 400 * 1024 * 1024, .min_secs = 1.0, .min_secs_cache = 10.0, @@ -558,7 +559,7 @@ void demux_add_packet(struct sh_stream *stream, demux_packet_t *dp) dp->next = NULL; ds->packs++; - ds->bytes += dp->len; + ds->bytes += demux_packet_estimate_total_size(dp); if (ds->tail) { // next packet in stream ds->tail->next = dp; @@ -777,7 +778,7 @@ static struct demux_packet *dequeue_packet(struct demux_stream *ds) pkt->next = NULL; if (!ds->head) ds->tail = NULL; - ds->bytes -= pkt->len; + ds->bytes -= demux_packet_estimate_total_size(pkt); ds->packs--; double ts = pkt->dts == MP_NOPTS_VALUE ? pkt->pts : pkt->dts; diff --git a/demux/packet.c b/demux/packet.c index 47f0cb87dc..9f9f97ea53 100644 --- a/demux/packet.c +++ b/demux/packet.c @@ -130,6 +130,32 @@ struct demux_packet *demux_copy_packet(struct demux_packet *dp) return new; } +#define ROUND_ALLOC(s) MP_ALIGN_UP(s, 64) + +// Attempt to estimate the total memory consumption of the given packet. +// This is important if we store thousands of packets and not to exceed +// user-provided limits. Of course we can't know how much memory internal +// fragmentation of the libc memory allocator will waste. +// Note that this should return a "stable" value - e.g. if a new packet ref +// is created, this should return the same value with the new ref. (This +// implies the value is not exact and does not return the actual size of +// memory wasted due to internal fragmentation.) +size_t demux_packet_estimate_total_size(struct demux_packet *dp) +{ + size_t size = ROUND_ALLOC(sizeof(struct demux_packet)); + size += ROUND_ALLOC(dp->len); + if (dp->avpacket) { + size += ROUND_ALLOC(sizeof(AVPacket)); + size += ROUND_ALLOC(sizeof(AVBufferRef)); + size += 64; // upper bound estimate on sizeof(AVBuffer) + size += ROUND_ALLOC(dp->avpacket->side_data_elems * + sizeof(dp->avpacket->side_data[0])); + for (int n = 0; n < dp->avpacket->side_data_elems; n++) + size += ROUND_ALLOC(dp->avpacket->side_data[n].size); + } + return size; +} + int demux_packet_set_padding(struct demux_packet *dp, int start, int end) { #if LIBAVCODEC_VERSION_MICRO >= 100 diff --git a/demux/packet.h b/demux/packet.h index d669d02376..03204c8de2 100644 --- a/demux/packet.h +++ b/demux/packet.h @@ -51,6 +51,7 @@ struct demux_packet *new_demux_packet_from(void *data, size_t len); void demux_packet_shorten(struct demux_packet *dp, size_t len); void free_demux_packet(struct demux_packet *dp); struct demux_packet *demux_copy_packet(struct demux_packet *dp); +size_t demux_packet_estimate_total_size(struct demux_packet *dp); void demux_packet_copy_attribs(struct demux_packet *dst, struct demux_packet *src); -- cgit v1.2.3