mirror of
https://github.com/mpv-player/mpv
synced 2025-04-08 10:32:51 +00:00
demux: avoid a copy of demux packets with lavf, reduce padding
When demux_lavf read a new packet it used to copy the data from libavformat's struct AVPacket to struct demux_packet and then free the lavf packet. Change it to instead keep the AVPacket allocated and point demux_packet fields to the buffer in that. Also change MP_INPUT_BUFFER_PADDING_SIZE to 8 which matches FF_INPUT_BUFFER_PADDING SIZE; demux_lavf packets won't have more padding now anyway (it was increased from 8 earlier when FF_INPUT_BUFFER_PADDING_SIZE was increased in libavcodec, but that change was reverted).
This commit is contained in:
parent
6ec60c976f
commit
6e8d420a41
@ -743,10 +743,15 @@ static void check_internet_radio_hack(struct demuxer *demuxer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int destroy_avpacket(void *pkt)
|
||||||
|
{
|
||||||
|
av_free_packet(pkt);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds)
|
static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds)
|
||||||
{
|
{
|
||||||
lavf_priv_t *priv = demux->priv;
|
lavf_priv_t *priv = demux->priv;
|
||||||
AVPacket pkt;
|
|
||||||
demux_packet_t *dp;
|
demux_packet_t *dp;
|
||||||
demux_stream_t *ds;
|
demux_stream_t *ds;
|
||||||
int id;
|
int id;
|
||||||
@ -754,8 +759,12 @@ static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds)
|
|||||||
|
|
||||||
demux->filepos = stream_tell(demux->stream);
|
demux->filepos = stream_tell(demux->stream);
|
||||||
|
|
||||||
if (av_read_frame(priv->avfc, &pkt) < 0)
|
AVPacket *pkt = talloc(NULL, AVPacket);
|
||||||
|
if (av_read_frame(priv->avfc, pkt) < 0) {
|
||||||
|
talloc_free(pkt);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
talloc_set_destructor(pkt, destroy_avpacket);
|
||||||
|
|
||||||
// handle any new streams that might have been added
|
// handle any new streams that might have been added
|
||||||
for (id = priv->nb_streams_last; id < priv->avfc->nb_streams; id++)
|
for (id = priv->nb_streams_last; id < priv->avfc->nb_streams; id++)
|
||||||
@ -764,7 +773,7 @@ static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds)
|
|||||||
|
|
||||||
priv->nb_streams_last = priv->avfc->nb_streams;
|
priv->nb_streams_last = priv->avfc->nb_streams;
|
||||||
|
|
||||||
id = pkt.stream_index;
|
id = pkt->stream_index;
|
||||||
|
|
||||||
if (id == demux->audio->id || priv->internet_radio_hack) {
|
if (id == demux->audio->id || priv->internet_radio_hack) {
|
||||||
// audio
|
// audio
|
||||||
@ -787,39 +796,27 @@ static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds)
|
|||||||
ds = demux->sub;
|
ds = demux->sub;
|
||||||
sub_utf8 = 1;
|
sub_utf8 = 1;
|
||||||
} else {
|
} else {
|
||||||
av_free_packet(&pkt);
|
talloc_free(pkt);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 /*pkt.destruct == av_destruct_packet*/) {
|
dp = new_demux_packet_fromdata(pkt->data, pkt->size);
|
||||||
//ok kids, dont try this at home :)
|
dp->avpacket = pkt;
|
||||||
dp = malloc(sizeof(demux_packet_t));
|
|
||||||
dp->len = pkt.size;
|
|
||||||
dp->next = NULL;
|
|
||||||
dp->refcount = 1;
|
|
||||||
dp->master = NULL;
|
|
||||||
dp->buffer = pkt.data;
|
|
||||||
pkt.destruct = NULL;
|
|
||||||
} else {
|
|
||||||
dp = new_demux_packet(pkt.size);
|
|
||||||
memcpy(dp->buffer, pkt.data, pkt.size);
|
|
||||||
av_free_packet(&pkt);
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t ts = priv->use_dts ? pkt.dts : pkt.pts;
|
int64_t ts = priv->use_dts ? pkt->dts : pkt->pts;
|
||||||
if (ts != AV_NOPTS_VALUE) {
|
if (ts != AV_NOPTS_VALUE) {
|
||||||
dp->pts = ts * av_q2d(priv->avfc->streams[id]->time_base);
|
dp->pts = ts * av_q2d(priv->avfc->streams[id]->time_base);
|
||||||
priv->last_pts = dp->pts * AV_TIME_BASE;
|
priv->last_pts = dp->pts * AV_TIME_BASE;
|
||||||
// always set duration for subtitles, even if AV_PKT_FLAG_KEY isn't set,
|
// always set duration for subtitles, even if AV_PKT_FLAG_KEY isn't set,
|
||||||
// otherwise they will stay on screen to long if e.g. ASS is demuxed
|
// otherwise they will stay on screen to long if e.g. ASS is demuxed
|
||||||
// from mkv
|
// from mkv
|
||||||
if ((ds == demux->sub || (pkt.flags & AV_PKT_FLAG_KEY)) &&
|
if ((ds == demux->sub || (pkt->flags & AV_PKT_FLAG_KEY)) &&
|
||||||
pkt.convergence_duration > 0)
|
pkt->convergence_duration > 0)
|
||||||
dp->duration = pkt.convergence_duration *
|
dp->duration = pkt->convergence_duration *
|
||||||
av_q2d(priv->avfc->streams[id]->time_base);
|
av_q2d(priv->avfc->streams[id]->time_base);
|
||||||
}
|
}
|
||||||
dp->pos = demux->filepos;
|
dp->pos = demux->filepos;
|
||||||
dp->flags = !!(pkt.flags & AV_PKT_FLAG_KEY);
|
dp->flags = !!(pkt->flags & AV_PKT_FLAG_KEY);
|
||||||
// append packet to DS stream:
|
// append packet to DS stream:
|
||||||
ds_add_packet(ds, dp);
|
ds_add_packet(ds, dp);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -176,7 +176,7 @@ const demuxer_desc_t *const demuxer_list[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
struct demux_packet *new_demux_packet(size_t len)
|
static struct demux_packet *create_packet(size_t len)
|
||||||
{
|
{
|
||||||
if (len > 1000000000) {
|
if (len > 1000000000) {
|
||||||
mp_msg(MSGT_DEMUXER, MSGL_FATAL, "Attempt to allocate demux packet "
|
mp_msg(MSGT_DEMUXER, MSGL_FATAL, "Attempt to allocate demux packet "
|
||||||
@ -194,6 +194,13 @@ struct demux_packet *new_demux_packet(size_t len)
|
|||||||
dp->refcount = 1;
|
dp->refcount = 1;
|
||||||
dp->master = NULL;
|
dp->master = NULL;
|
||||||
dp->buffer = NULL;
|
dp->buffer = NULL;
|
||||||
|
dp->avpacket = NULL;
|
||||||
|
return dp;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct demux_packet *new_demux_packet(size_t len)
|
||||||
|
{
|
||||||
|
struct demux_packet *dp = create_packet(len);
|
||||||
dp->buffer = malloc(len + MP_INPUT_BUFFER_PADDING_SIZE);
|
dp->buffer = malloc(len + MP_INPUT_BUFFER_PADDING_SIZE);
|
||||||
if (!dp->buffer) {
|
if (!dp->buffer) {
|
||||||
mp_msg(MSGT_DEMUXER, MSGL_FATAL, "Memory allocation failure!\n");
|
mp_msg(MSGT_DEMUXER, MSGL_FATAL, "Memory allocation failure!\n");
|
||||||
@ -203,6 +210,14 @@ struct demux_packet *new_demux_packet(size_t len)
|
|||||||
return dp;
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// data must already have suitable padding
|
||||||
|
struct demux_packet *new_demux_packet_fromdata(void *data, size_t len)
|
||||||
|
{
|
||||||
|
struct demux_packet *dp = create_packet(len);
|
||||||
|
dp->buffer = data;
|
||||||
|
return dp;
|
||||||
|
}
|
||||||
|
|
||||||
void resize_demux_packet(struct demux_packet *dp, size_t len)
|
void resize_demux_packet(struct demux_packet *dp, size_t len)
|
||||||
{
|
{
|
||||||
if (len > 1000000000) {
|
if (len > 1000000000) {
|
||||||
@ -237,6 +252,9 @@ void free_demux_packet(struct demux_packet *dp)
|
|||||||
if (dp->master == NULL) { //dp is a master packet
|
if (dp->master == NULL) { //dp is a master packet
|
||||||
dp->refcount--;
|
dp->refcount--;
|
||||||
if (dp->refcount == 0) {
|
if (dp->refcount == 0) {
|
||||||
|
if (dp->avpacket)
|
||||||
|
talloc_free(dp->avpacket);
|
||||||
|
else
|
||||||
free(dp->buffer);
|
free(dp->buffer);
|
||||||
free(dp);
|
free(dp);
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,8 @@ enum timestamp_type {
|
|||||||
#define SEEK_FORWARD (1 << 2)
|
#define SEEK_FORWARD (1 << 2)
|
||||||
#define SEEK_BACKWARD (1 << 3)
|
#define SEEK_BACKWARD (1 << 3)
|
||||||
|
|
||||||
#define MP_INPUT_BUFFER_PADDING_SIZE 64
|
// demux_lavf can pass lavf buffers using FF_INPUT_BUFFER_PADDING_SIZE instead
|
||||||
|
#define MP_INPUT_BUFFER_PADDING_SIZE 8
|
||||||
|
|
||||||
// Holds one packet/frame/whatever
|
// Holds one packet/frame/whatever
|
||||||
typedef struct demux_packet {
|
typedef struct demux_packet {
|
||||||
@ -136,6 +137,7 @@ typedef struct demux_packet {
|
|||||||
int refcount; // counter for the master packet, if 0, buffer can be free()d
|
int refcount; // counter for the master packet, if 0, buffer can be free()d
|
||||||
struct demux_packet *master; //in clones, pointer to the master packet
|
struct demux_packet *master; //in clones, pointer to the master packet
|
||||||
struct demux_packet *next;
|
struct demux_packet *next;
|
||||||
|
struct AVPacket *avpacket; // original libavformat packet (demux_lavf)
|
||||||
} demux_packet_t;
|
} demux_packet_t;
|
||||||
|
|
||||||
typedef struct demux_stream {
|
typedef struct demux_stream {
|
||||||
@ -302,6 +304,8 @@ typedef struct {
|
|||||||
} demux_program_t;
|
} demux_program_t;
|
||||||
|
|
||||||
struct demux_packet *new_demux_packet(size_t len);
|
struct demux_packet *new_demux_packet(size_t len);
|
||||||
|
// data must already have suitable padding
|
||||||
|
struct demux_packet *new_demux_packet_fromdata(void *data, size_t len);
|
||||||
void resize_demux_packet(struct demux_packet *dp, size_t len);
|
void resize_demux_packet(struct demux_packet *dp, size_t len);
|
||||||
struct demux_packet *clone_demux_packet(struct demux_packet *pack);
|
struct demux_packet *clone_demux_packet(struct demux_packet *pack);
|
||||||
void free_demux_packet(struct demux_packet *dp);
|
void free_demux_packet(struct demux_packet *dp);
|
||||||
|
Loading…
Reference in New Issue
Block a user