This was being performed to ensure that a complete packet was held in
contiguous memory, prior to parsing the packet. However, the source buffer
is typically large enough that the packet was already contiguous, so it is
beneficial to return the packet by reference in most cases.
Before After
Mean StdDev Mean StdDev Change
memcpy 720.7 32.7 649.8 25.1 +10.9%
Overall 2372.7 46.1 2291.7 21.8 +3.5%
---
libavformat/avio.h | 15 +++++++++++++++
libavformat/aviobuf.c | 12 ++++++++++++
libavformat/mpegts.c | 41 ++++++++++++++++++++++++++++-------------
3 files changed, 55 insertions(+), 13 deletions(-)
diff --git a/libavformat/avio.h b/libavformat/avio.h
index b6d3cb3..fb195ff 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -240,6 +240,21 @@ void avio_flush(AVIOContext *s);
int avio_read(AVIOContext *s, unsigned char *buf, int size);
/**
+ * Read size bytes from AVIOContext, returning a pointer.
+ * @param s IO context
+ * @param buf pointer to buffer into which to assemble the requested
+ * data if it is not available in contiguous addresses in the
+ * underlying buffer
+ * @param size number of bytes requested
+ * @param data address at which to store pointer: this will be a
+ * a direct pointer into the underlying buffer if the requested
+ * number of bytes are available at contiguous addresses, otherwise
+ * will be a copy of buf
+ * @return number of bytes read or AVERROR
+ */
+int avio_read_indirect(AVIOContext *s, unsigned char *buf, int size, unsigned
char **data);
+
+/**
* @name Functions for reading from AVIOContext
* @{
*
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index bc89768..5cc8c0d 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -490,6 +490,18 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size)
return size1 - size;
}
+int avio_read_indirect(AVIOContext *s, unsigned char *buf, int size, unsigned
char **data)
+{
+ if (s->buf_end - s->buf_ptr >= size && !s->write_flag) {
+ *data = s->buf_ptr;
+ s->buf_ptr += size;
+ return size;
+ } else {
+ *data = buf;
+ return avio_read(s, buf, size);
+ }
+}
+
int ffio_read_partial(AVIOContext *s, unsigned char *buf, int size)
{
int len;
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index 8e548d9..6554f41 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -1747,17 +1747,17 @@ static int mpegts_resync(AVFormatContext *s)
}
/* return -1 if error or EOF. Return 0 if OK. */
-static int read_packet(AVFormatContext *s, uint8_t *buf, int raw_packet_size)
+static int read_packet(AVFormatContext *s, uint8_t *buf, int raw_packet_size,
uint8_t **data)
{
AVIOContext *pb = s->pb;
- int skip, len;
+ int len;
for(;;) {
- len = avio_read(pb, buf, TS_PACKET_SIZE);
+ len = avio_read_indirect(pb, buf, TS_PACKET_SIZE, data);
if (len != TS_PACKET_SIZE)
return len < 0 ? len : AVERROR_EOF;
/* check packet sync byte */
- if (buf[0] != 0x47) {
+ if ((*data)[0] != 0x47) {
/* find a new packet start */
avio_seek(pb, -TS_PACKET_SIZE, SEEK_CUR);
if (mpegts_resync(s) < 0)
@@ -1765,19 +1765,25 @@ static int read_packet(AVFormatContext *s, uint8_t
*buf, int raw_packet_size)
else
continue;
} else {
- skip = raw_packet_size - TS_PACKET_SIZE;
- if (skip > 0)
- avio_skip(pb, skip);
break;
}
}
return 0;
}
+static void finished_reading_packet(AVFormatContext *s, int raw_packet_size)
+{
+ AVIOContext *pb = s->pb;
+ int skip = raw_packet_size - TS_PACKET_SIZE;
+ if (skip > 0)
+ avio_skip(pb, skip);
+}
+
static int handle_packets(MpegTSContext *ts, int nb_packets)
{
AVFormatContext *s = ts->stream;
uint8_t packet[TS_PACKET_SIZE+FF_INPUT_BUFFER_PADDING_SIZE];
+ uint8_t *data;
int packet_num, ret = 0;
if (avio_tell(s->pb) != ts->last_pos) {
@@ -1806,10 +1812,11 @@ static int handle_packets(MpegTSContext *ts, int
nb_packets)
packet_num++;
if (nb_packets != 0 && packet_num >= nb_packets)
break;
- ret = read_packet(s, packet, ts->raw_packet_size);
+ ret = read_packet(s, packet, ts->raw_packet_size, &data);
if (ret != 0)
break;
- ret = handle_packet(ts, packet);
+ ret = handle_packet(ts, data);
+ finished_reading_packet(s, ts->raw_packet_size);
if (ret != 0)
break;
}
@@ -1913,6 +1920,7 @@ static int mpegts_read_header(AVFormatContext *s)
int64_t pcrs[2], pcr_h;
int packet_count[2];
uint8_t packet[TS_PACKET_SIZE];
+ uint8_t *data;
/* only read packets */
@@ -1928,18 +1936,21 @@ static int mpegts_read_header(AVFormatContext *s)
nb_pcrs = 0;
nb_packets = 0;
for(;;) {
- ret = read_packet(s, packet, ts->raw_packet_size);
+ ret = read_packet(s, packet, ts->raw_packet_size, &data);
if (ret < 0)
return -1;
- pid = AV_RB16(packet + 1) & 0x1fff;
+ pid = AV_RB16(data + 1) & 0x1fff;
if ((pcr_pid == -1 || pcr_pid == pid) &&
- parse_pcr(&pcr_h, &pcr_l, packet) == 0) {
+ parse_pcr(&pcr_h, &pcr_l, data) == 0) {
+ finished_reading_packet(s, ts->raw_packet_size);
pcr_pid = pid;
packet_count[nb_pcrs] = nb_packets;
pcrs[nb_pcrs] = pcr_h * 300 + pcr_l;
nb_pcrs++;
if (nb_pcrs >= 2)
break;
+ } else {
+ finished_reading_packet(s, ts->raw_packet_size);
}
nb_packets++;
}
@@ -1971,15 +1982,19 @@ static int mpegts_raw_read_packet(AVFormatContext *s,
int64_t pcr_h, next_pcr_h, pos;
int pcr_l, next_pcr_l;
uint8_t pcr_buf[12];
+ uint8_t *data;
if (av_new_packet(pkt, TS_PACKET_SIZE) < 0)
return AVERROR(ENOMEM);
pkt->pos= avio_tell(s->pb);
- ret = read_packet(s, pkt->data, ts->raw_packet_size);
+ ret = read_packet(s, pkt->data, ts->raw_packet_size, &data);
if (ret < 0) {
av_free_packet(pkt);
return ret;
}
+ if (data != pkt->data)
+ memcpy(pkt->data, data, ts->raw_packet_size);
+ finished_reading_packet(s, ts->raw_packet_size);
if (ts->mpeg2ts_compute_pcr) {
/* compute exact PCR for each packet */
if (parse_pcr(&pcr_h, &pcr_l, pkt->data) == 0) {
--
1.7.5.4
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel