mirror of https://github.com/mpv-player/mpv
Compare commits
3 Commits
14c76bd20b
...
67b9ed152f
Author | SHA1 | Date |
---|---|---|
Kacper Michajłow | 67b9ed152f | |
Kacper Michajłow | 3237bcdb95 | |
Kacper Michajłow | 90579391cd |
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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.
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -104,6 +104,7 @@ sources = files(
|
|||
'demux/demux_timeline.c',
|
||||
'demux/ebml.c',
|
||||
'demux/packet.c',
|
||||
'demux/packet_pool.c',
|
||||
'demux/timeline.c',
|
||||
|
||||
## Filters
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue