Compare commits

...

3 Commits

Author SHA1 Message Date
Kacper Michajłow 67b9ed152f
Merge 3237bcdb95 into 76367dae35 2024-04-27 02:01:12 +08:00
Kacper Michajłow 3237bcdb95 demux/packet_pool: add fast quit mode
A new field, MPContext::quit_fast, has been introduced. Setting this
field to true bypasses the time-consuming packet deallocation process.
This is particularly useful when exiting the process, as there's no need
to iterate over and free all packets. The cache, stored as a linked list
with potentially millions of small packets, requires significant time to
iterate through and deallocate, especially if the memory is swapped out.

This change significantly speeds up the player closure, especially when
a large demuxer cache is used.

Fixes: #12294
Fixes: #12563
2024-04-18 00:46:22 +02:00
Kacper Michajłow 90579391cd demux: reclaim demux_packets to reduce memory allocator pressure
This update introduces a demux_packet_pool, allowing for the reuse of
previously allocated packets when needed.

sizeof(AVPacket) is not a part of the lavc public ABI, which prevents us
to allocate memory in larger blocks. However, we can substantially
decrease the amount of alloc/free operations during playback by reusing
both mpv's demux_packet and AVPacket.

This adjustment addresses the root cause of issue #12076, which,
although resolved upstream, did not fully tackle the persistent problem
of allocating small blocks of aligned memory. This issue largely stems
from the FFmpeg design of the AVPacket API. After this change memory
will no longer be allocated once cache limits is reached.

The demux_packet_pool is shared as a global pool of packets for a given
MPContext.

This change significantly speeds up the demuxer deinitialization,
benefiting file switching scenarios, especially when a large demuxer
cache is used.

See: #12294
See: #12563
2024-04-18 00:46:22 +02:00
20 changed files with 238 additions and 59 deletions

View File

@ -10,6 +10,7 @@ struct mpv_global {
struct mp_client_api *client_api;
char *configdir;
struct stats_base *stats;
struct demux_packet_pool *packet_pool;
};
#endif

View File

@ -412,7 +412,7 @@ void mp_recorder_feed_packet(struct mp_recorder_sink *rst,
return;
}
pkt = demux_copy_packet(pkt);
pkt = demux_copy_packet(rst->owner->global->packet_pool, pkt);
if (!pkt)
return;
MP_TARRAY_APPEND(rst, rst->packets, rst->num_packets, pkt);

View File

@ -25,6 +25,7 @@
#include "cache.h"
#include "common/msg.h"
#include "common/av_common.h"
#include "common/global.h"
#include "demux.h"
#include "misc/io_utils.h"
#include "options/path.h"
@ -57,6 +58,7 @@ const struct m_sub_options demux_cache_conf = {
struct demux_cache {
struct mp_log *log;
struct demux_packet_pool *packet_pool;
struct demux_cache_opts *opts;
char *filename;
@ -100,6 +102,7 @@ struct demux_cache *demux_cache_create(struct mpv_global *global,
talloc_set_destructor(cache, cache_destroy);
cache->opts = mp_get_config_group(cache, global, &demux_cache_conf);
cache->log = log;
cache->packet_pool = global->packet_pool;
cache->fd = -1;
char *cache_dir = cache->opts->cache_dir;
@ -294,7 +297,7 @@ struct demux_packet *demux_cache_read(struct demux_cache *cache, uint64_t pos)
if (!read_raw(cache, &hd, sizeof(hd)))
return NULL;
struct demux_packet *dp = new_demux_packet(hd.data_len);
struct demux_packet *dp = new_demux_packet(cache->packet_pool, hd.data_len);
if (!dp)
goto fail;

View File

@ -45,6 +45,7 @@
#include "stream/stream.h"
#include "demux.h"
#include "packet_pool.h"
#include "timeline.h"
#include "stheader.h"
#include "cue.h"
@ -698,7 +699,7 @@ static void remove_head_packet(struct demux_queue *queue)
if (!queue->head)
queue->tail = NULL;
talloc_free(dp);
demux_packet_pool_push(queue->ds->in->global->packet_pool, dp);
}
static void free_index(struct demux_queue *queue)
@ -723,13 +724,7 @@ static void clear_queue(struct demux_queue *queue)
free_index(queue);
struct demux_packet *dp = queue->head;
while (dp) {
struct demux_packet *dn = dp->next;
assert(ds->reader_head != dp);
talloc_free(dp);
dp = dn;
}
demux_packet_pool_prepend(in->global->packet_pool, queue->head, queue->tail);
queue->head = queue->tail = NULL;
queue->keyframe_first = NULL;
queue->keyframe_latest = NULL;
@ -2040,7 +2035,7 @@ static void add_packet_locked(struct sh_stream *stream, demux_packet_t *dp)
}
if (drop) {
talloc_free(dp);
demux_packet_pool_push(in->global->packet_pool, dp);
return;
}
@ -2610,7 +2605,7 @@ static struct demux_packet *read_packet_from_cache(struct demux_internal *in,
}
} else {
// The returned packet is mutated etc. and will be owned by the user.
pkt = demux_copy_packet(pkt);
pkt = demux_copy_packet(in->global->packet_pool, pkt);
}
return pkt;
@ -2635,7 +2630,8 @@ static int dequeue_packet(struct demux_stream *ds, double min_pts,
if (ds->attached_picture_added)
return -1;
ds->attached_picture_added = true;
struct demux_packet *pkt = demux_copy_packet(ds->sh->attached_picture);
struct demux_packet *pkt = demux_copy_packet(in->global->packet_pool,
ds->sh->attached_picture);
MP_HANDLE_OOM(pkt);
pkt->stream = ds->sh->index;
*res = pkt;

View File

@ -44,6 +44,7 @@
#include "common/msg.h"
#include "common/tags.h"
#include "common/av_common.h"
#include "common/global.h"
#include "misc/bstr.h"
#include "misc/charset_conv.h"
#include "misc/thread_tools.h"
@ -753,7 +754,7 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
!(st->disposition & AV_DISPOSITION_TIMED_THUMBNAILS))
{
sh->attached_picture =
new_demux_packet_from_avpacket(&st->attached_pic);
new_demux_packet_from_avpacket(demuxer->global->packet_pool, &st->attached_pic);
if (sh->attached_picture) {
sh->attached_picture->pts = 0;
talloc_steal(sh, sh->attached_picture);
@ -1262,7 +1263,7 @@ static bool demux_lavf_read_packet(struct demuxer *demux,
return true; // don't signal EOF if skipping a packet
}
struct demux_packet *dp = new_demux_packet_from_avpacket(pkt);
struct demux_packet *dp = new_demux_packet_from_avpacket(demux->global->packet_pool, pkt);
if (!dp) {
av_packet_unref(pkt);
return true;

View File

@ -27,6 +27,7 @@
#include "osdep/io.h"
#include "mpv_talloc.h"
#include "common/global.h"
#include "common/msg.h"
#include "options/options.h"
#include "options/m_config.h"
@ -258,7 +259,7 @@ static bool demux_mf_read_packet(struct demuxer *demuxer,
stream_seek(stream, 0);
bstr data = stream_read_complete(stream, NULL, MF_MAX_FILE_SIZE);
if (data.len) {
demux_packet_t *dp = new_demux_packet(data.len);
demux_packet_t *dp = new_demux_packet(demuxer->global->packet_pool, data.len);
if (dp) {
memcpy(dp->buffer, data.start, data.len);
dp->pts = mf->curr_frame / mf->sh->codec->fps;

View File

@ -46,6 +46,7 @@
#include "mpv_talloc.h"
#include "common/av_common.h"
#include "common/global.h"
#include "options/m_config.h"
#include "options/m_option.h"
#include "options/options.h"
@ -54,6 +55,7 @@
#include "video/csputils.h"
#include "video/mp_image.h"
#include "demux.h"
#include "packet_pool.h"
#include "stheader.h"
#include "ebml.h"
#include "matroska.h"
@ -1397,7 +1399,8 @@ static void add_coverart(struct demuxer *demuxer)
continue;
struct sh_stream *sh = demux_alloc_sh_stream(STREAM_VIDEO);
sh->codec->codec = codec;
sh->attached_picture = new_demux_packet_from(att->data, att->data_size);
sh->attached_picture = new_demux_packet_from(demuxer->global->packet_pool,
att->data, att->data_size);
if (sh->attached_picture) {
sh->attached_picture->pts = 0;
talloc_steal(sh, sh->attached_picture);
@ -2097,7 +2100,8 @@ static void probe_x264_garbage(demuxer_t *demuxer)
if (!nblock.len)
continue;
sh->codec->first_packet = new_demux_packet_from(nblock.start, nblock.len);
sh->codec->first_packet = new_demux_packet_from(demuxer->global->packet_pool,
nblock.start, nblock.len);
talloc_steal(mkv_d, sh->codec->first_packet);
if (nblock.start != sblock.start)
@ -2497,8 +2501,9 @@ static bool handle_realaudio(demuxer_t *demuxer, mkv_track_t *track,
goto error;
// Release all the audio packets
for (int x = 0; x < sph * w / apk_usize; x++) {
dp = new_demux_packet_from(track->audio_buf + x * apk_usize,
apk_usize);
dp = new_demux_packet_from(demuxer->global->packet_pool,
track->audio_buf + x * apk_usize,
apk_usize);
if (!dp)
goto error;
/* Put timestamp only on packets that correspond to original
@ -2635,7 +2640,8 @@ static void mkv_parse_and_add_packet(demuxer_t *demuxer, mkv_track_t *track,
int size = dp->len;
uint8_t *parsed;
if (libav_parse_wavpack(track, dp->buffer, &parsed, &size) >= 0) {
struct demux_packet *new = new_demux_packet_from(parsed, size);
struct demux_packet *new = new_demux_packet_from(demuxer->global->packet_pool,
parsed, size);
if (new) {
demux_packet_copy_attribs(new, dp);
talloc_free(dp);
@ -2647,7 +2653,7 @@ static void mkv_parse_and_add_packet(demuxer_t *demuxer, mkv_track_t *track,
if (strcmp(stream->codec->codec, "prores") == 0) {
size_t newlen = dp->len + 8;
struct demux_packet *new = new_demux_packet(newlen);
struct demux_packet *new = new_demux_packet(demuxer->global->packet_pool, newlen);
if (new) {
AV_WB32(new->buffer + 0, newlen);
AV_WB32(new->buffer + 4, MKBETAG('i', 'c', 'p', 'f'));
@ -2689,7 +2695,8 @@ static void mkv_parse_and_add_packet(demuxer_t *demuxer, mkv_track_t *track,
dp->len -= len;
dp->pos += len;
if (size) {
struct demux_packet *new = new_demux_packet_from(data, size);
struct demux_packet *new = new_demux_packet_from(demuxer->global->packet_pool,
data, size);
if (!new)
break;
if (copy_sidedata)
@ -2710,7 +2717,7 @@ static void mkv_parse_and_add_packet(demuxer_t *demuxer, mkv_track_t *track,
if (dp->len) {
add_packet(demuxer, stream, dp);
} else {
talloc_free(dp);
demux_packet_pool_push(demuxer->global->packet_pool, dp);
}
}
@ -2863,9 +2870,9 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info)
if (block.start != nblock.start || block.len != nblock.len) {
// (avoidable copy of the entire data)
dp = new_demux_packet_from(nblock.start, nblock.len);
dp = new_demux_packet_from(demuxer->global->packet_pool, nblock.start, nblock.len);
} else {
dp = new_demux_packet_from_buf(data);
dp = new_demux_packet_from_buf(demuxer->global->packet_pool, data);
}
if (!dp)
break;

View File

@ -24,6 +24,7 @@
#include <libavutil/common.h>
#include "common/av_common.h"
#include "common/global.h"
#include "options/m_config.h"
#include "options/m_option.h"
@ -273,7 +274,8 @@ static bool raw_read_packet(struct demuxer *demuxer, struct demux_packet **pkt)
if (demuxer->stream->eof)
return false;
struct demux_packet *dp = new_demux_packet(p->frame_size * p->read_frames);
struct demux_packet *dp = new_demux_packet(demuxer->global->packet_pool,
p->frame_size * p->read_frames);
if (!dp) {
MP_ERR(demuxer, "Can't read packet.\n");
return true;

View File

@ -26,6 +26,7 @@
#include "common/av_common.h"
#include "common/common.h"
#include "demux.h"
#include "packet_pool.h"
#include "packet.h"
@ -49,9 +50,18 @@ static void packet_destroy(void *ptr)
demux_packet_unref_contents(dp);
}
static struct demux_packet *packet_create(void)
static struct demux_packet *packet_create(struct demux_packet_pool *pool)
{
struct demux_packet *dp = talloc(NULL, struct demux_packet);
struct demux_packet *dp = pool ? demux_packet_pool_pop(pool) : NULL;
struct AVPacket *avpkt = NULL;
if (dp) {
avpkt = dp->avpacket;
if (avpkt)
av_packet_unref(avpkt);
ta_free_children(dp);
} else {
dp = talloc(NULL, struct demux_packet);
}
talloc_set_destructor(dp, packet_destroy);
*dp = (struct demux_packet) {
.pts = MP_NOPTS_VALUE,
@ -61,8 +71,8 @@ static struct demux_packet *packet_create(void)
.start = MP_NOPTS_VALUE,
.end = MP_NOPTS_VALUE,
.stream = -1,
.avpacket = av_packet_alloc(),
};
dp->avpacket = avpkt ? avpkt : av_packet_alloc();
MP_HANDLE_OOM(dp->avpacket);
return dp;
}
@ -70,11 +80,12 @@ static struct demux_packet *packet_create(void)
// This actually preserves only data and side data, not PTS/DTS/pos/etc.
// It also allows avpkt->data==NULL with avpkt->size!=0 - the libavcodec API
// does not allow it, but we do it to simplify new_demux_packet().
struct demux_packet *new_demux_packet_from_avpacket(struct AVPacket *avpkt)
struct demux_packet *new_demux_packet_from_avpacket(struct demux_packet_pool *pool,
struct AVPacket *avpkt)
{
if (avpkt->size > 1000000000)
return NULL;
struct demux_packet *dp = packet_create();
struct demux_packet *dp = packet_create(pool);
int r = -1;
if (avpkt->data) {
// We hope that this function won't need/access AVPacket input padding,
@ -93,14 +104,15 @@ struct demux_packet *new_demux_packet_from_avpacket(struct AVPacket *avpkt)
}
// (buf must include proper padding)
struct demux_packet *new_demux_packet_from_buf(struct AVBufferRef *buf)
struct demux_packet *new_demux_packet_from_buf(struct demux_packet_pool *pool,
struct AVBufferRef *buf)
{
if (!buf)
return NULL;
if (buf->size > 1000000000)
return NULL;
struct demux_packet *dp = packet_create();
struct demux_packet *dp = packet_create(pool);
dp->avpacket->buf = av_buffer_ref(buf);
if (!dp->avpacket->buf) {
talloc_free(dp);
@ -112,21 +124,21 @@ struct demux_packet *new_demux_packet_from_buf(struct AVBufferRef *buf)
}
// Input data doesn't need to be padded.
struct demux_packet *new_demux_packet_from(void *data, size_t len)
struct demux_packet *new_demux_packet_from(struct demux_packet_pool *pool, void *data, size_t len)
{
struct demux_packet *dp = new_demux_packet(len);
struct demux_packet *dp = new_demux_packet(pool, len);
if (!dp)
return NULL;
memcpy(dp->avpacket->data, data, len);
return dp;
}
struct demux_packet *new_demux_packet(size_t len)
struct demux_packet *new_demux_packet(struct demux_packet_pool *pool, size_t len)
{
if (len > INT_MAX)
return NULL;
struct demux_packet *dp = packet_create();
struct demux_packet *dp = packet_create(pool);
int r = av_new_packet(dp->avpacket, len);
if (r < 0) {
talloc_free(dp);
@ -167,14 +179,14 @@ void demux_packet_copy_attribs(struct demux_packet *dst, struct demux_packet *sr
dst->stream = src->stream;
}
struct demux_packet *demux_copy_packet(struct demux_packet *dp)
struct demux_packet *demux_copy_packet(struct demux_packet_pool *pool, struct demux_packet *dp)
{
struct demux_packet *new = NULL;
if (dp->avpacket) {
new = new_demux_packet_from_avpacket(dp->avpacket);
new = new_demux_packet_from_avpacket(pool, dp->avpacket);
} else {
// Some packets might be not created by new_demux_packet*().
new = new_demux_packet_from(dp->buffer, dp->len);
new = new_demux_packet_from(pool, dp->buffer, dp->len);
}
if (!new)
return NULL;

View File

@ -71,14 +71,18 @@ typedef struct demux_packet {
} demux_packet_t;
struct AVBufferRef;
struct demux_packet_pool;
struct demux_packet *new_demux_packet(size_t len);
struct demux_packet *new_demux_packet_from_avpacket(struct AVPacket *avpkt);
struct demux_packet *new_demux_packet_from(void *data, size_t len);
struct demux_packet *new_demux_packet_from_buf(struct AVBufferRef *buf);
struct demux_packet *new_demux_packet(struct demux_packet_pool *pool, size_t len);
struct demux_packet *new_demux_packet_from_avpacket(struct demux_packet_pool *pool,
struct AVPacket *avpkt);
struct demux_packet *new_demux_packet_from(struct demux_packet_pool *pool,
void *data, size_t len);
struct demux_packet *new_demux_packet_from_buf(struct demux_packet_pool *pool,
struct AVBufferRef *buf);
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);
struct demux_packet *demux_copy_packet(struct demux_packet_pool *pool, 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);

85
demux/packet_pool.c Normal file
View File

@ -0,0 +1,85 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include "packet_pool.h"
#include "osdep/threads.h"
#include "player/core.h"
#include "packet.h"
void demux_packet_pool_init(struct demux_packet_pool *pool, struct MPContext *parent)
{
mp_mutex_init(&pool->lock);
pool->packets = NULL;
pool->parent = parent;
}
void demux_packet_pool_uninit(void *p)
{
struct demux_packet_pool *pool = p;
if (!pool->parent->quit_fast)
demux_packet_pool_clear(pool);
mp_mutex_destroy(&pool->lock);
}
void demux_packet_pool_clear(struct demux_packet_pool *pool)
{
mp_mutex_lock(&pool->lock);
struct demux_packet *dp = pool->packets;
while (dp) {
struct demux_packet *next = dp->next;
free_demux_packet(dp);
dp = next;
}
pool->packets = NULL;
mp_mutex_unlock(&pool->lock);
}
void demux_packet_pool_push(struct demux_packet_pool *pool,
struct demux_packet *dp)
{
if (!dp)
return;
dp->next = NULL;
demux_packet_pool_prepend(pool, dp, dp);
}
void demux_packet_pool_prepend(struct demux_packet_pool *pool,
struct demux_packet *head, struct demux_packet *tail)
{
if (!head)
return;
assert(tail);
assert(head != tail ? !!head->next : !head->next);
mp_mutex_lock(&pool->lock);
tail->next = pool->packets;
pool->packets = head;
mp_mutex_unlock(&pool->lock);
}
struct demux_packet *demux_packet_pool_pop(struct demux_packet_pool *pool)
{
mp_mutex_lock(&pool->lock);
struct demux_packet *dp = pool->packets;
if (dp) {
pool->packets = dp->next;
dp->next = NULL;
}
mp_mutex_unlock(&pool->lock);
return dp;
}

38
demux/packet_pool.h Normal file
View File

@ -0,0 +1,38 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "osdep/threads.h"
struct demux_packet;
struct MPContext;
struct demux_packet_pool {
mp_mutex lock;
struct demux_packet *packets;
struct MPContext *parent;
};
void demux_packet_pool_init(struct demux_packet_pool *pool, struct MPContext *parent);
void demux_packet_pool_uninit(void *p);
void demux_packet_pool_clear(struct demux_packet_pool *pool);
void demux_packet_pool_push(struct demux_packet_pool *pool,
struct demux_packet *dp);
void demux_packet_pool_prepend(struct demux_packet_pool *pool,
struct demux_packet *head, struct demux_packet *tail);
struct demux_packet *demux_packet_pool_pop(struct demux_packet_pool *pool);

View File

@ -34,6 +34,7 @@
#include "demux/demux.h"
#include "demux/packet.h"
#include "demux/packet_pool.h"
#include "common/codecs.h"
#include "common/global.h"
@ -691,7 +692,8 @@ static bool process_decoded_frame(struct priv *p, struct mp_frame *frame)
crazy_video_pts_stuff(p, mpi);
struct demux_packet *ccpkt = new_demux_packet_from_buf(mpi->a53_cc);
struct demux_packet *ccpkt = new_demux_packet_from_buf(p->public.f->global->packet_pool,
mpi->a53_cc);
if (ccpkt) {
av_buffer_unref(&mpi->a53_cc);
ccpkt->pts = mpi->pts;
@ -1313,7 +1315,7 @@ void lavc_process(struct mp_filter *f, struct lavc_state *state,
return;
}
state->packets_sent = true;
talloc_free(pkt);
demux_packet_pool_push(f->global->packet_pool, pkt);
mp_filter_internal_mark_progress(f);
} else {
// Decoding error, or hwdec fallback recovery. Just try again.

View File

@ -82,7 +82,7 @@ static void *audio_from_av_ref(AVFrame *data)
static void *packet_ref(void *data)
{
return demux_copy_packet(data);
return demux_copy_packet(NULL, data);
}
static const struct frame_handler frame_handlers[] = {

View File

@ -104,6 +104,7 @@ sources = files(
'demux/demux_timeline.c',
'demux/ebml.c',
'demux/packet.c',
'demux/packet_pool.c',
'demux/timeline.c',
## Filters

View File

@ -286,6 +286,13 @@ typedef struct MPContext {
int quit_custom_rc;
bool has_quit_custom_rc;
// If set to true, specific deinitialization steps can be omitted during
// the destruction of MPContext (e.g., when exiting the process). This is
// beneficial to prevent delays caused by unnecessary cleanup operations.
// However, be aware that leak checkers might flag this, so they must be
// configured accordingly.
bool quit_fast;
// Global file statistics
int files_played; // played without issues (even if stopped by user)
int files_errored; // played, but errors happened at one point

View File

@ -55,6 +55,7 @@
#include "options/options.h"
#include "options/path.h"
#include "input/input.h"
#include "demux/packet_pool.h"
#include "audio/out/ao.h"
#include "misc/thread_tools.h"
@ -238,6 +239,14 @@ static bool check_locale(void)
return !name || strcmp(name, "C") == 0 || strcmp(name, "C.UTF-8") == 0;
}
static bool ta_report_enabled(void)
{
char *enable_talloc = getenv("MPV_LEAK_REPORT");
if (!enable_talloc)
enable_talloc = HAVE_TA_LEAK_REPORT ? "1" : "0";
return strcmp(enable_talloc, "1") == 0;
}
struct MPContext *mp_create(void)
{
if (!check_locale()) {
@ -248,10 +257,7 @@ struct MPContext *mp_create(void)
return NULL;
}
char *enable_talloc = getenv("MPV_LEAK_REPORT");
if (!enable_talloc)
enable_talloc = HAVE_TA_LEAK_REPORT ? "1" : "0";
if (strcmp(enable_talloc, "1") == 0)
if (ta_report_enabled())
talloc_enable_leak_report();
mp_time_init();
@ -273,6 +279,10 @@ struct MPContext *mp_create(void)
mpctx->global = talloc_zero(mpctx, struct mpv_global);
mpctx->global->packet_pool = talloc(mpctx->global, struct demux_packet_pool);
demux_packet_pool_init(mpctx->global->packet_pool, mpctx);
talloc_set_destructor(mpctx->global->packet_pool, demux_packet_pool_uninit);
stats_global_init(mpctx->global);
// Nothing must call mp_msg*() and related before this
@ -428,6 +438,10 @@ int mpv_main(int argc, char *argv[])
char **options = argv && argv[0] ? argv + 1 : NULL; // skips program name
int r = mp_initialize(mpctx, options);
#if !defined(__SANITIZE_ADDRESS__)
// allow fast exit on standalone player, unless leak detection is enabled
mpctx->quit_fast = !ta_report_enabled();
#endif
if (r == 0)
mp_play_files(mpctx);

View File

@ -23,6 +23,7 @@
#include <limits.h>
#include "demux/demux.h"
#include "demux/packet_pool.h"
#include "sd.h"
#include "dec_sub.h"
#include "options/m_config.h"
@ -127,7 +128,8 @@ static void destroy_cached_pkts(struct dec_sub *sub)
{
int index = 0;
while (index < sub->num_cached_pkts) {
TA_FREEP(&sub->cached_pkts[index]);
demux_packet_pool_push(sub->global->packet_pool, sub->cached_pkts[index]);
sub->cached_pkts[index] = NULL;
++index;
}
sub->cached_pkt_pos = 0;
@ -375,7 +377,7 @@ void sub_read_packets(struct dec_sub *sub, double video_pts, bool force,
MP_TARRAY_APPEND(sub, sub->cached_pkts, sub->num_cached_pkts, pkt);
if (is_new_segment(sub, pkt)) {
sub->new_segment = demux_copy_packet(pkt);
sub->new_segment = demux_copy_packet(sub->global->packet_pool, pkt);
// Note that this can be delayed to a much later point in time.
update_segment(sub);
break;
@ -482,7 +484,8 @@ void sub_reset(struct dec_sub *sub)
sub->last_pkt_pts = MP_NOPTS_VALUE;
sub->last_vo_pts = MP_NOPTS_VALUE;
destroy_cached_pkts(sub);
TA_FREEP(&sub->new_segment);
demux_packet_pool_push(sub->global->packet_pool, sub->new_segment);
sub->new_segment = NULL;
mp_mutex_unlock(&sub->lock);
}

View File

@ -23,6 +23,7 @@
#include "misc/ctype.h"
#include "common/common.h"
#include "common/global.h"
#include "common/msg.h"
#include "options/options.h"
#include "sd.h"
@ -483,7 +484,7 @@ static struct demux_packet *sdh_filter(struct sd_filter *ft,
// Stupidly, this copies it again. One could possibly allocate the packet
// for writing in the first place (new_demux_packet()) and use
// demux_packet_shorten().
struct demux_packet *npkt = new_demux_packet_from(line, strlen(line));
struct demux_packet *npkt = new_demux_packet_from(ft->global->packet_pool, line, strlen(line));
if (npkt)
demux_packet_copy_attribs(npkt, pkt);

View File

@ -50,6 +50,7 @@
#include "demux/demux.h"
#include "demux/stheader.h"
#include "demux/packet.h"
#include "demux/packet_pool.h"
#include "video/csputils.h"
#include "video/sws_utils.h"
#include "video/out/vo.h"
@ -1162,7 +1163,7 @@ static int send_packet(struct mp_filter *vd, struct demux_packet *pkt)
if (ctx->hw_probing && ctx->num_sent_packets < 32 &&
ctx->opts->software_fallback <= 32)
{
pkt = pkt ? demux_copy_packet(pkt) : NULL;
pkt = pkt ? demux_copy_packet(vd->global->packet_pool, pkt) : NULL;
MP_TARRAY_APPEND(ctx, ctx->sent_packets, ctx->num_sent_packets, pkt);
}
@ -1325,7 +1326,7 @@ static int receive_frame(struct mp_filter *vd, struct mp_frame *out_frame)
if (ctx->hw_probing) {
for (int n = 0; n < ctx->num_sent_packets; n++)
talloc_free(ctx->sent_packets[n]);
demux_packet_pool_push(vd->global->packet_pool, ctx->sent_packets[n]);
ctx->num_sent_packets = 0;
ctx->hw_probing = false;
}