From a0900a318a60e38ffeb14c322b09f98fcbd97c73 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 5 Dec 2021 20:46:57 +0100 Subject: avformat/aadec: Avoid copying data around Up until now, the packets have been read in blocks of at most eight bytes at a time; then these blocks have been decrypted and copied into a buffer on the stack (that was double the size needed...). From there they have been copied to the dst 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 --- libavformat/aadec.c | 42 +++++++++++++----------------------------- 1 file changed, 13 insertions(+), 29 deletions(-) (limited to 'libavformat') 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; } -- cgit v1.2.3