[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