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
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
This commit is contained in:
Kacper Michajłow
2023-10-05 18:05:44 +02:00
parent c0366cfa42
commit 038d66549d
24 changed files with 299 additions and 55 deletions
+1
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
+4 -1
View File
@@ -25,6 +25,7 @@
#include "common/msg.h"
#include "demux/demux.h"
#include "demux/packet.h"
#include "demux/packet_pool.h"
#include "demux/stheader.h"
#include "recorder.h"
@@ -41,6 +42,7 @@
struct mp_recorder {
struct mpv_global *global;
struct mp_log *log;
struct demux_packet_pool *packet_pool;
struct mp_recorder_sink **streams;
int num_streams;
@@ -137,6 +139,7 @@ struct mp_recorder *mp_recorder_create(struct mpv_global *global,
priv->global = global;
priv->log = mp_log_new(priv, global->log, "recorder");
priv->packet_pool = demux_packet_pool_get(global);
if (!num_streams) {
MP_ERR(priv, "No streams.\n");
@@ -412,7 +415,7 @@ void mp_recorder_feed_packet(struct mp_recorder_sink *rst,
return;
}
pkt = demux_copy_packet(pkt);
pkt = demux_copy_packet(rst->owner->packet_pool, pkt);
if (!pkt)
return;
MP_TARRAY_APPEND(rst, rst->packets, rst->num_packets, pkt);
+4 -1
View File
@@ -25,6 +25,7 @@
#include "common/msg.h"
#include "common/av_common.h"
#include "demux.h"
#include "demux/packet_pool.h"
#include "misc/io_utils.h"
#include "options/path.h"
#include "options/m_config.h"
@@ -55,6 +56,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;
@@ -98,6 +100,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 = demux_packet_pool_get(global);
cache->fd = -1;
char *cache_dir = cache->opts->cache_dir;
@@ -292,7 +295,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;
+10 -11
View File
@@ -44,6 +44,7 @@
#include "stream/stream.h"
#include "demux.h"
#include "packet_pool.h"
#include "timeline.h"
#include "stheader.h"
#include "cue.h"
@@ -150,6 +151,7 @@ const struct m_sub_options demux_conf = {
struct demux_internal {
struct mp_log *log;
struct mpv_global *global;
struct demux_packet_pool *packet_pool;
struct stats_ctx *stats;
bool can_cache; // not a slave demuxer; caching makes sense
@@ -701,7 +703,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->packet_pool, dp);
}
static void free_index(struct demux_queue *queue)
@@ -726,13 +728,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->packet_pool, queue->head, queue->tail);
queue->head = queue->tail = NULL;
queue->keyframe_first = NULL;
queue->keyframe_latest = NULL;
@@ -2043,7 +2039,7 @@ static void add_packet_locked(struct sh_stream *stream, demux_packet_t *dp)
}
if (drop) {
talloc_free(dp);
demux_packet_pool_push(in->packet_pool, dp);
return;
}
@@ -2613,7 +2609,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->packet_pool, pkt);
}
return pkt;
@@ -2638,7 +2634,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->packet_pool,
ds->sh->attached_picture);
MP_HANDLE_OOM(pkt);
pkt->stream = ds->sh->index;
*res = pkt;
@@ -3281,6 +3278,7 @@ static struct demuxer *open_given_type(struct mpv_global *global,
.filepos = -1,
.global = global,
.log = mp_log_new(demuxer, log, desc->name),
.packet_pool = demux_packet_pool_get(global),
.glog = log,
.filename = talloc_strdup(demuxer, sinfo->filename),
.is_network = sinfo->is_network,
@@ -3297,6 +3295,7 @@ static struct demuxer *open_given_type(struct mpv_global *global,
*in = (struct demux_internal){
.global = global,
.log = demuxer->log,
.packet_pool = demux_packet_pool_get(global),
.stats = stats_ctx_create(in, global, "demuxer"),
.can_cache = params && params->is_top_level,
.can_record = params && params->stream_record,
+1
View File
@@ -265,6 +265,7 @@ typedef struct demuxer {
void *priv; // demuxer-specific internal data
struct mpv_global *global;
struct mp_log *log, *glog;
struct demux_packet_pool *packet_pool;
struct demuxer_params *params;
// internal to demux.c
+2 -2
View File
@@ -718,7 +718,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->packet_pool, &st->attached_pic);
if (sh->attached_picture) {
sh->attached_picture->pts = 0;
talloc_steal(sh, sh->attached_picture);
@@ -1222,7 +1222,7 @@ static bool demux_lavf_read_packet(struct demuxer *demux,
return true;
}
struct demux_packet *dp = new_demux_packet_from_avpacket(pkt);
struct demux_packet *dp = new_demux_packet_from_avpacket(demux->packet_pool, pkt);
if (!dp) {
av_packet_unref(pkt);
return true;
+1 -1
View File
@@ -261,7 +261,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->packet_pool, data.len);
if (dp) {
memcpy(dp->buffer, data.start, data.len);
dp->pts = mf->curr_frame / mf->sh->codec->fps;
+16 -10
View File
@@ -55,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"
@@ -1486,7 +1487,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->packet_pool,
att->data, att->data_size);
if (sh->attached_picture) {
sh->attached_picture->pts = 0;
talloc_steal(sh, sh->attached_picture);
@@ -2229,7 +2231,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->packet_pool,
nblock.start, nblock.len);
talloc_steal(mkv_d, sh->codec->first_packet);
if (nblock.start != sblock.start)
@@ -2629,8 +2632,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->packet_pool,
track->audio_buf + x * apk_usize,
apk_usize);
if (!dp)
goto error;
/* Put timestamp only on packets that correspond to original
@@ -2767,7 +2771,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->packet_pool,
parsed, size);
if (new) {
demux_packet_copy_attribs(new, dp);
talloc_free(dp);
@@ -2779,7 +2784,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->packet_pool, newlen);
if (new) {
AV_WB32(new->buffer + 0, newlen);
AV_WB32(new->buffer + 4, MKBETAG('i', 'c', 'p', 'f'));
@@ -2825,7 +2830,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->packet_pool,
data, size);
if (!new)
break;
if (copy_sidedata)
@@ -2846,7 +2852,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->packet_pool, dp);
}
}
@@ -2999,9 +3005,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->packet_pool, nblock.start, nblock.len);
} else {
dp = new_demux_packet_from_buf(data);
dp = new_demux_packet_from_buf(demuxer->packet_pool, data);
}
if (!dp)
break;
+2 -1
View File
@@ -273,7 +273,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->packet_pool,
p->frame_size * p->read_frames);
if (!dp) {
MP_ERR(demuxer, "Can't read packet.\n");
return true;
+20 -14
View File
@@ -28,6 +28,7 @@
#include "common/common.h"
#include "demux.h"
#include "demux/ebml.h"
#include "packet_pool.h"
#include "packet.h"
@@ -51,9 +52,12 @@ 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 = dp ? dp->avpacket : NULL;
if (!dp)
dp = talloc(NULL, struct demux_packet);
talloc_set_destructor(dp, packet_destroy);
*dp = (struct demux_packet) {
.pts = MP_NOPTS_VALUE,
@@ -63,9 +67,9 @@ static struct demux_packet *packet_create(void)
.start = MP_NOPTS_VALUE,
.end = MP_NOPTS_VALUE,
.stream = -1,
.avpacket = av_packet_alloc(),
.animated = -1,
};
dp->avpacket = avpkt ? avpkt : av_packet_alloc();
MP_HANDLE_OOM(dp->avpacket);
return dp;
}
@@ -73,11 +77,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,
@@ -96,14 +101,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);
@@ -115,21 +121,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);
@@ -170,14 +176,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;
+9 -5
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);
+115
View File
@@ -0,0 +1,115 @@
/*
* 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 <libavcodec/packet.h>
#include "common/global.h"
#include "osdep/threads.h"
#include "packet.h"
struct demux_packet_pool {
mp_mutex lock;
struct demux_packet *packets;
};
static void uninit(void *p)
{
struct demux_packet_pool *pool = p;
demux_packet_pool_clear(pool);
mp_mutex_destroy(&pool->lock);
}
void demux_packet_pool_init(struct mpv_global *global)
{
struct demux_packet_pool *pool = talloc(global, struct demux_packet_pool);
talloc_set_destructor(pool, uninit);
mp_mutex_init(&pool->lock);
pool->packets = NULL;
assert(!global->packet_pool);
global->packet_pool = pool;
}
struct demux_packet_pool *demux_packet_pool_get(struct mpv_global *global)
{
// Currently all clients use the same packet pool. There is no additional
// state for each client, may be extended in the future.
return global->packet_pool;
}
void demux_packet_pool_clear(struct demux_packet_pool *pool)
{
mp_mutex_lock(&pool->lock);
struct demux_packet *dp = pool->packets;
pool->packets = NULL;
mp_mutex_unlock(&pool->lock);
while (dp) {
struct demux_packet *next = dp->next;
free_demux_packet(dp);
dp = next;
}
}
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);
// Clear the packet from possible external references. This is done in the
// pop function instead of prepend to distribute the load of clearing packets.
// packet_create() is called at a reasonable rate, so it's fine to clear
// a single packet at a time. This avoids the need to clear potentially
// hundreds of thousands of packets at once when file playback is stopped,
// which would require a significant amount of time to iterate over all packets.
if (dp) {
if (dp->avpacket)
av_packet_unref(dp->avpacket);
ta_free_children(dp);
}
return dp;
}
+88
View File
@@ -0,0 +1,88 @@
/*
* 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
struct demux_packet_pool;
struct demux_packet;
struct mpv_global;
/**
* Initializes the demux packet pool.
*
* This function creates a new shaderd demux packet pool. Should be done only
* once per mpv context.
*
* @param global Pointer to the global context.
*/
void demux_packet_pool_init(struct mpv_global *global);
/**
* Returns the demux packet pool context for client use.
*
* @param global Pointer to the global context.
* @return Pointer to the demux packet context.
*/
struct demux_packet_pool *demux_packet_pool_get(struct mpv_global *global);
/**
* Clears the demux packet pool.
*
* This function frees all the packets in the pool.
* This function is thread-safe.
*
* @param pool Pointer to the demux packet pool.
*/
void demux_packet_pool_clear(struct demux_packet_pool *pool);
/**
* Pushes a packet into the demux packet pool.
*
* This function pushes a new demux packet to the pool by appending
* it to the list. If the packet is NULL, the function returns immediately.
* This function is thread-safe.
*
* @param pool Pointer to the demux packet pool.
* @param dp Pointer to the demux packet to be added.
*/
void demux_packet_pool_push(struct demux_packet_pool *pool,
struct demux_packet *dp);
/**
* Prepends a linked list of demux packets to the pool.
*
* This function prepends a list of demux packets to the packet pool.
* The head is the first packet to be inserted, and the tail is the
* last one. This function is thread-safe.
*
* @param pool Pointer to the demux packet pool.
* @param head Pointer to the head of the list of packets to be added.
* @param tail Pointer to the tail of the list of packets to be added.
*/
void demux_packet_pool_prepend(struct demux_packet_pool *pool,
struct demux_packet *head, struct demux_packet *tail);
/**
* Pops a packet from the demux packet pool.
*
* This function removes and returns the first packet from the pool's
* linked list. This function is thread-safe.
*
* @param pool Pointer to the demux packet pool.
* @return Pointer to the demux packet, or NULL if the pool is empty.
*/
struct demux_packet *demux_packet_pool_pop(struct demux_packet_pool *pool);
+4 -2
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"
@@ -694,7 +695,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->packet_pool,
mpi->a53_cc);
if (ccpkt) {
av_buffer_unref(&mpi->a53_cc);
ccpkt->pts = mpi->pts;
@@ -1315,7 +1317,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->packet_pool, pkt);
mp_filter_internal_mark_progress(f);
} else {
// Decoding error, or hwdec fallback recovery. Just try again.
+2
View File
@@ -6,6 +6,7 @@
#include "common/common.h"
#include "common/global.h"
#include "common/msg.h"
#include "demux/packet_pool.h"
#include "osdep/threads.h"
#include "osdep/timer.h"
#include "video/hwdec.h"
@@ -803,6 +804,7 @@ struct mp_filter *mp_filter_create_with_params(struct mp_filter_params *params)
.priv = params->info->priv_size ?
talloc_zero_size(f, params->info->priv_size) : NULL,
.global = params->global,
.packet_pool = demux_packet_pool_get(params->parent ? params->parent->global : params->global),
.in = talloc(f, struct mp_filter_internal),
};
*f->in = (struct mp_filter_internal){
+1
View File
@@ -312,6 +312,7 @@ struct mp_filter {
struct mpv_global *global;
struct mp_log *log;
struct demux_packet_pool *packet_pool;
// Array of public pins. API users can read this, but are not allowed to
// modify the array. Filter implementations use mp_filter_add_pin() to add
+1 -1
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[] = {
+1
View File
@@ -106,6 +106,7 @@ sources = files(
'demux/demux_timeline.c',
'demux/ebml.c',
'demux/packet.c',
'demux/packet_pool.c',
'demux/timeline.c',
## Filters
+2
View File
@@ -57,6 +57,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"
@@ -284,6 +285,7 @@ struct MPContext *mp_create(void)
mpctx->global = talloc_zero(mpctx, struct mpv_global);
demux_packet_pool_init(mpctx->global);
stats_global_init(mpctx->global);
// Nothing must call mp_msg*() and related before this
+8 -3
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"
@@ -47,6 +48,7 @@ struct dec_sub {
struct mp_log *log;
struct mpv_global *global;
struct demux_packet_pool *packet_pool;
struct mp_subtitle_opts *opts;
struct mp_subtitle_shared_opts *shared_opts;
struct m_config_cache *opts_cache;
@@ -127,7 +129,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->packet_pool, sub->cached_pkts[index]);
sub->cached_pkts[index] = NULL;
++index;
}
sub->cached_pkt_pos = 0;
@@ -190,6 +193,7 @@ struct dec_sub *sub_create(struct mpv_global *global, struct track *track,
*sub = (struct dec_sub){
.log = mp_log_new(sub, global->log, "sub"),
.global = global,
.packet_pool = demux_packet_pool_get(global),
.opts_cache = m_config_cache_alloc(sub, global, &mp_subtitle_sub_opts),
.shared_opts_cache = m_config_cache_alloc(sub, global, &mp_subtitle_shared_sub_opts),
.sh = track->stream,
@@ -375,7 +379,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->packet_pool, pkt);
// Note that this can be delayed to a much later point in time.
update_segment(sub);
break;
@@ -482,7 +486,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->packet_pool, sub->new_segment);
sub->new_segment = NULL;
mp_mutex_unlock(&sub->lock);
}
+1 -1
View File
@@ -483,7 +483,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->packet_pool, line, strlen(line));
if (npkt)
demux_packet_copy_attribs(npkt, pkt);
+1
View File
@@ -81,6 +81,7 @@ struct mp_sub_filter_opts {
struct sd_filter {
struct mpv_global *global;
struct mp_log *log;
struct demux_packet_pool *packet_pool;
struct mp_sub_filter_opts *opts;
const struct sd_filter_functions *driver;
+2
View File
@@ -33,6 +33,7 @@
#include "common/common.h"
#include "common/msg.h"
#include "demux/demux.h"
#include "demux/packet_pool.h"
#include "video/csputils.h"
#include "video/mp_image.h"
#include "dec_sub.h"
@@ -209,6 +210,7 @@ static void filters_init(struct sd *sd)
*ft = (struct sd_filter){
.global = sd->global,
.log = sd->log,
.packet_pool = demux_packet_pool_get(sd->global),
.opts = mp_get_config_group(ft, sd->global, &mp_sub_filter_opts),
.driver = filters[n],
.codec = "ass",
+3 -2
View File
@@ -49,6 +49,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"
@@ -1175,7 +1176,7 @@ static int send_packet(struct mp_filter *vd, struct demux_packet *pkt)
if (ctx->hw_probing && ctx->num_sent_packets < 32 &&
ctx->hwdec_opts->software_fallback <= 32)
{
pkt = pkt ? demux_copy_packet(pkt) : NULL;
pkt = pkt ? demux_copy_packet(vd->packet_pool, pkt) : NULL;
MP_TARRAY_APPEND(ctx, ctx->sent_packets, ctx->num_sent_packets, pkt);
}
@@ -1332,7 +1333,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->packet_pool, ctx->sent_packets[n]);
ctx->num_sent_packets = 0;
ctx->hw_probing = false;
}