]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/aadec.c
hwcontext_vulkan: only convert image layout for transfers if necessary
[ffmpeg] / libavformat / aadec.c
index 17ad20686b5bc07abf2ac33f901bef49c52cdbbb..b9dd51ebfc3da00eac322f95a081872f35365e90 100644 (file)
@@ -37,6 +37,7 @@
 #define TEA_BLOCK_SIZE 8
 #define CHAPTER_HEADER_SIZE 8
 #define TIMEPREC 1000
+#define MP3_FRAME_SIZE 104
 
 typedef struct AADemuxContext {
     AVClass *class;
@@ -50,6 +51,7 @@ typedef struct AADemuxContext {
     int64_t current_chapter_size;
     int64_t content_start;
     int64_t content_end;
+    int seek_offset;
 } AADemuxContext;
 
 static int get_second_size(char *codec_name)
@@ -83,6 +85,7 @@ static int aa_read_header(AVFormatContext *s)
     AADemuxContext *c = s->priv_data;
     AVIOContext *pb = s->pb;
     AVStream *st;
+    int ret;
 
     /* parse .aa header */
     avio_skip(pb, 4); // file size
@@ -116,8 +119,12 @@ static int aa_read_header(AVFormatContext *s)
             header_seed = atoi(val);
         } else if (!strcmp(key, "HeaderKey")) { // this looks like "1234567890 1234567890 1234567890 1234567890"
             av_log(s, AV_LOG_DEBUG, "HeaderKey is <%s>\n", val);
-            sscanf(val, "%"SCNu32"%"SCNu32"%"SCNu32"%"SCNu32,
+
+            ret = sscanf(val, "%"SCNu32"%"SCNu32"%"SCNu32"%"SCNu32,
                    &header_key_part[0], &header_key_part[1], &header_key_part[2], &header_key_part[3]);
+            if (ret != 4)
+                return AVERROR_INVALIDDATA;
+
             for (idx = 0; idx < 4; idx++) {
                 AV_WB32(&header_key[idx * 4], header_key_part[idx]); // convert each part to BE!
             }
@@ -177,6 +184,7 @@ static int aa_read_header(AVFormatContext *s)
         st->codecpar->sample_rate = 22050;
         st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
         avpriv_set_pts_info(st, 64, 8, 32000 * TIMEPREC);
+        // encoded audio frame is MP3_FRAME_SIZE bytes (+1 with padding, unlikely)
     } else if (!strcmp(codec_name, "acelp85")) {
         st->codecpar->codec_id = AV_CODEC_ID_SIPR;
         st->codecpar->block_align = 19;
@@ -228,6 +236,7 @@ static int aa_read_header(AVFormatContext *s)
     ff_update_cur_dts(s, st, 0);
     avio_seek(pb, start, SEEK_SET);
     c->current_chapter_size = 0;
+    c->seek_offset = 0;
 
     return 0;
 }
@@ -293,12 +302,16 @@ static int aa_read_packet(AVFormatContext *s, AVPacket *pkt)
     if (c->current_chapter_size <= 0)
         c->current_chapter_size = 0;
 
-    ret = av_new_packet(pkt, written);
+    if (c->seek_offset > written)
+        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, written);
+    memcpy(pkt->data, buf + c->seek_offset, written - c->seek_offset);
     pkt->pos = pos;
 
+    c->seek_offset = 0;
     return 0;
 }
 
@@ -342,12 +355,17 @@ static int aa_read_seek(AVFormatContext *s,
     c->current_chapter_size = chapter_size - chapter_pos;
     c->chapter_idx = 1 + chapter_idx;
 
-    ff_update_cur_dts(s, s->streams[0], ch->start + chapter_pos * TIMEPREC);
+    // for unaligned frames, estimate offset of first frame in block (assume no padding)
+    if (s->streams[0]->codecpar->codec_id == AV_CODEC_ID_MP3) {
+        c->seek_offset = (MP3_FRAME_SIZE - chapter_pos % MP3_FRAME_SIZE) % MP3_FRAME_SIZE;
+    }
+
+    ff_update_cur_dts(s, s->streams[0], ch->start + (chapter_pos + c->seek_offset) * TIMEPREC);
 
     return 1;
 }
 
-static int aa_probe(AVProbeData *p)
+static int aa_probe(const AVProbeData *p)
 {
     uint8_t *buf = p->buf;