[FFmpeg-devel] [PATCH 03/10] avformat/aadec: Avoid copying data around
Andreas Rheinhardt
andreas.rheinhardt at outlook.com
Mon Dec 6 03:12:39 EET 2021
Up until now, the packets have been read in blocks of at most
eight bytes at a time; these blocks have then been decrypted
and then copied into a buffer on the stack (that was double
the size needed...). From there they have been copied to a packet.
This commit changes this: The data is read in one go; and
the decryption avoids temporary buffers, too, by making
use of the fact that src and dst of av_tea_crypt() can coincide.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>
---
libavformat/aadec.c | 42 +++++++++++++-----------------------------
1 file changed, 13 insertions(+), 29 deletions(-)
diff --git a/libavformat/aadec.c b/libavformat/aadec.c
index a3a7664469..7e97120070 100644
--- a/libavformat/aadec.c
+++ b/libavformat/aadec.c
@@ -32,7 +32,6 @@
#include "libavutil/opt.h"
#define AA_MAGIC 1469084982 /* this identifies an audible .aa file */
-#define MAX_CODEC_SECOND_SIZE 3982
#define MAX_TOC_ENTRIES 16
#define MAX_DICTIONARY_ENTRIES 128
#define TEA_BLOCK_SIZE 8
@@ -247,13 +246,9 @@ static int aa_read_header(AVFormatContext *s)
static int aa_read_packet(AVFormatContext *s, AVPacket *pkt)
{
- uint8_t dst[TEA_BLOCK_SIZE];
- uint8_t src[TEA_BLOCK_SIZE];
int i;
- int trailing_bytes;
int blocks;
- uint8_t buf[MAX_CODEC_SECOND_SIZE * 2];
- int written = 0;
+ uint8_t *buf;
int ret;
AADemuxContext *c = s->priv_data;
uint64_t pos = avio_tell(s->pb);
@@ -272,7 +267,6 @@ static int aa_read_packet(AVFormatContext *s, AVPacket *pkt)
av_log(s, AV_LOG_DEBUG, "Chapter %d (%" PRId64 " bytes)\n", c->chapter_idx, c->current_chapter_size);
c->chapter_idx = c->chapter_idx + 1;
avio_skip(s->pb, 4); // data start offset
- pos += 8;
c->current_codec_second_size = c->codec_second_size;
}
@@ -281,24 +275,18 @@ static int aa_read_packet(AVFormatContext *s, AVPacket *pkt)
c->current_codec_second_size = c->current_chapter_size % c->current_codec_second_size;
}
+ ret = av_get_packet(s->pb, pkt, c->current_codec_second_size);
+ if (ret != c->current_codec_second_size)
+ return AVERROR_EOF;
+
+ buf = pkt->data;
// decrypt c->current_codec_second_size bytes
+ // trailing bytes are left unencrypted!
blocks = c->current_codec_second_size / TEA_BLOCK_SIZE;
for (i = 0; i < blocks; i++) {
- ret = avio_read(s->pb, src, TEA_BLOCK_SIZE);
- if (ret != TEA_BLOCK_SIZE)
- return (ret < 0) ? ret : AVERROR_EOF;
av_tea_init(c->tea_ctx, c->file_key, 16);
- av_tea_crypt(c->tea_ctx, dst, src, 1, NULL, 1);
- memcpy(buf + written, dst, TEA_BLOCK_SIZE);
- written = written + TEA_BLOCK_SIZE;
- }
- trailing_bytes = c->current_codec_second_size % TEA_BLOCK_SIZE;
- if (trailing_bytes != 0) { // trailing bytes are left unencrypted!
- ret = avio_read(s->pb, src, trailing_bytes);
- if (ret != trailing_bytes)
- return (ret < 0) ? ret : AVERROR_EOF;
- memcpy(buf + written, src, trailing_bytes);
- written = written + trailing_bytes;
+ av_tea_crypt(c->tea_ctx, buf, buf, 1, NULL, 1);
+ buf += TEA_BLOCK_SIZE;
}
// update state
@@ -306,16 +294,12 @@ static int aa_read_packet(AVFormatContext *s, AVPacket *pkt)
if (c->current_chapter_size <= 0)
c->current_chapter_size = 0;
- if (c->seek_offset > written)
+ if (c->seek_offset > c->current_codec_second_size)
c->seek_offset = 0; // ignore wrong estimate
-
- ret = av_new_packet(pkt, written - c->seek_offset);
- if (ret < 0)
- return ret;
- memcpy(pkt->data, buf + c->seek_offset, written - c->seek_offset);
- pkt->pos = pos;
-
+ pkt->data += c->seek_offset;
+ pkt->size -= c->seek_offset;
c->seek_offset = 0;
+
return 0;
}
--
2.32.0
More information about the ffmpeg-devel
mailing list