summaryrefslogtreecommitdiffstats
path: root/demux/packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'demux/packet.c')
-rw-r--r--demux/packet.c75
1 files changed, 32 insertions, 43 deletions
diff --git a/demux/packet.c b/demux/packet.c
index 77ea78f7cc..2008113600 100644
--- a/demux/packet.c
+++ b/demux/packet.c
@@ -29,55 +29,58 @@
static void packet_destroy(void *ptr)
{
struct demux_packet *dp = ptr;
- talloc_free(dp->avpacket);
- av_free(dp->allocation);
+ av_packet_unref(dp->avpacket);
}
-static struct demux_packet *create_packet(size_t len)
+// 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)
{
- if (len > 1000000000) {
+ if (avpkt->size > 1000000000) {
fprintf(stderr, "Attempt to allocate demux packet over 1 GB!\n");
abort();
}
struct demux_packet *dp = talloc(NULL, struct demux_packet);
talloc_set_destructor(dp, packet_destroy);
*dp = (struct demux_packet) {
- .len = len,
.pts = MP_NOPTS_VALUE,
.dts = MP_NOPTS_VALUE,
.duration = -1,
.pos = -1,
.stream = -1,
+ .avpacket = talloc_zero(dp, AVPacket),
};
- return dp;
-}
-
-struct demux_packet *new_demux_packet(size_t len)
-{
- struct demux_packet *dp = create_packet(len);
- dp->buffer = av_malloc(len + FF_INPUT_BUFFER_PADDING_SIZE);
- if (!dp->buffer) {
- fprintf(stderr, "Memory allocation failure!\n");
+ av_init_packet(dp->avpacket);
+ int r = -1;
+ if (avpkt->data) {
+ // We hope that this function won't need/access AVPacket input padding,
+ // because otherwise new_demux_packet_from() wouldn't work.
+ r = av_packet_ref(dp->avpacket, avpkt);
+ } else {
+ r = av_new_packet(dp->avpacket, avpkt->size);
+ }
+ if (r < 0) {
+ fprintf(stderr, "Out of memory when referencing packet.\n");
abort();
}
- memset(dp->buffer + len, 0, FF_INPUT_BUFFER_PADDING_SIZE);
- dp->allocation = dp->buffer;
+ dp->buffer = dp->avpacket->data;
+ dp->len = dp->avpacket->size;
return dp;
}
-// data must already have suitable padding, and does not copy the data
-struct demux_packet *new_demux_packet_fromdata(void *data, size_t len)
+// Input data doesn't need to be padded.
+struct demux_packet *new_demux_packet_from(void *data, size_t len)
{
- struct demux_packet *dp = create_packet(len);
- dp->buffer = data;
- return dp;
+ AVPacket pkt = { .data = data, .size = len };
+ return new_demux_packet_from_avpacket(&pkt);
}
-struct demux_packet *new_demux_packet_from(void *data, size_t len)
+struct demux_packet *new_demux_packet(size_t len)
{
- struct demux_packet *dp = new_demux_packet(len);
- memcpy(dp->buffer, data, len);
- return dp;
+ assert(len <= INT_MAX);
+ AVPacket pkt = { .data = NULL, .size = len };
+ return new_demux_packet_from_avpacket(&pkt);
}
void demux_packet_shorten(struct demux_packet *dp, size_t len)
@@ -92,28 +95,14 @@ void free_demux_packet(struct demux_packet *dp)
talloc_free(dp);
}
-static void destroy_avpacket(void *pkt)
-{
- av_free_packet(pkt);
-}
-
struct demux_packet *demux_copy_packet(struct demux_packet *dp)
{
struct demux_packet *new = NULL;
if (dp->avpacket) {
- assert(dp->buffer == dp->avpacket->data);
- assert(dp->len == dp->avpacket->size);
- AVPacket *newavp = talloc_zero(NULL, AVPacket);
- talloc_set_destructor(newavp, destroy_avpacket);
- av_init_packet(newavp);
- if (av_packet_ref(newavp, dp->avpacket) < 0)
- abort();
- new = new_demux_packet_fromdata(newavp->data, newavp->size);
- new->avpacket = newavp;
- }
- if (!new) {
- new = new_demux_packet(dp->len);
- memcpy(new->buffer, dp->buffer, new->len);
+ new = new_demux_packet_from_avpacket(dp->avpacket);
+ } else {
+ // Some packets might be not created by new_demux_packet*().
+ new = new_demux_packet_from(dp->buffer, dp->len);
}
new->pts = dp->pts;
new->dts = dp->dts;