#define TEA_BLOCK_SIZE 8
#define CHAPTER_HEADER_SIZE 8
#define TIMEPREC 1000
+#define MP3_FRAME_SIZE 104
typedef struct AADemuxContext {
AVClass *class;
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)
AADemuxContext *c = s->priv_data;
AVIOContext *pb = s->pb;
AVStream *st;
+ int ret;
/* parse .aa header */
avio_skip(pb, 4); // file size
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!
}
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;
ff_update_cur_dts(s, st, 0);
avio_seek(pb, start, SEEK_SET);
c->current_chapter_size = 0;
+ c->seek_offset = 0;
return 0;
}
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;
}
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;