summaryrefslogtreecommitdiff
path: root/libavformat/wavdec.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2020-08-31 14:18:37 +0200
committerPaul B Mahol <onemda@gmail.com>2020-09-01 14:19:19 +0200
commit2a14d55a7c41ba8665cfd17b82d96e669ecd0e4c (patch)
treee15bfa238b2fd9186263b213660c275bb612eeb3 /libavformat/wavdec.c
parent97c73ba56505e180f6ab8f49b7b5642e0c09fa09 (diff)
avformat/wavdec: add support for chapters
Support parsing 'cue ' and 'adtl' chunks.
Diffstat (limited to 'libavformat/wavdec.c')
-rw-r--r--libavformat/wavdec.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c
index 4be0ed7b31..d6ab0dde35 100644
--- a/libavformat/wavdec.c
+++ b/libavformat/wavdec.c
@@ -500,6 +500,7 @@ static int wav_read_header(AVFormatContext *s)
wav->smv_cur_pt = 0;
goto break_loop;
case MKTAG('L', 'I', 'S', 'T'):
+ case MKTAG('l', 'i', 's', 't'):
if (size < 4) {
av_log(s, AV_LOG_ERROR, "too short LIST tag\n");
return AVERROR_INVALIDDATA;
@@ -507,6 +508,33 @@ static int wav_read_header(AVFormatContext *s)
switch (avio_rl32(pb)) {
case MKTAG('I', 'N', 'F', 'O'):
ff_read_riff_info(s, size - 4);
+ break;
+ case MKTAG('a', 'd', 't', 'l'):
+ if (s->nb_chapters > 0) {
+ while (avio_tell(pb) < next_tag_ofs &&
+ !avio_feof(pb)) {
+ char cue_label[512];
+ unsigned id, sub_size;
+
+ if (avio_rl32(pb) != MKTAG('l', 'a', 'b', 'l'))
+ break;
+
+ sub_size = avio_rl32(pb);
+ if (sub_size < 5)
+ break;
+ id = avio_rl32(pb);
+ avio_get_str(pb, sub_size - 4, cue_label, sizeof(cue_label));
+ avio_skip(pb, avio_tell(pb) & 1);
+
+ for (int i = 0; i < s->nb_chapters; i++) {
+ if (s->chapters[i]->id == id) {
+ av_dict_set(&s->chapters[i]->metadata, "title", cue_label, 0);
+ break;
+ }
+ }
+ }
+ }
+ break;
}
break;
case MKTAG('I', 'D', '3', ' '):
@@ -521,6 +549,24 @@ static int wav_read_header(AVFormatContext *s)
ff_id3v2_free_extra_meta(&id3v2_extra_meta);
}
break;
+ case MKTAG('c', 'u', 'e', ' '):
+ if (size >= 4 && got_fmt && st->codecpar->sample_rate > 0) {
+ AVRational tb = {1, st->codecpar->sample_rate};
+ unsigned nb_cues = avio_rl32(pb);
+
+ if (size >= nb_cues * 24LL + 4LL) {
+ for (int i = 0; i < nb_cues; i++) {
+ unsigned offset, id = avio_rl32(pb);
+
+ avio_skip(pb, 16);
+ offset = avio_rl32(pb);
+
+ if (!avpriv_new_chapter(s, id, tb, offset, AV_NOPTS_VALUE, NULL))
+ return AVERROR(ENOMEM);
+ }
+ }
+ }
+ break;
}
/* seek to next tag unless we know that we'll run into EOF */