summaryrefslogtreecommitdiff
path: root/libavformat/vorbiscomment.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2018-12-16 21:50:08 +0100
committerPaul B Mahol <onemda@gmail.com>2018-12-18 19:45:59 +0100
commitc0fb6f963fd7ee555ba2fdc254444e208bb0bc46 (patch)
tree20cf209d035ef7039bfed1acc4ee97610248b5ac /libavformat/vorbiscomment.c
parentd283ee085f9aac44b5de1b09e3cab62920fa4a9a (diff)
avformat/vorbiscomment: add support for writing chapters
Fixes #7532.
Diffstat (limited to 'libavformat/vorbiscomment.c')
-rw-r--r--libavformat/vorbiscomment.c60
1 files changed, 57 insertions, 3 deletions
diff --git a/libavformat/vorbiscomment.c b/libavformat/vorbiscomment.c
index 575dd13328..fb5c655a23 100644
--- a/libavformat/vorbiscomment.c
+++ b/libavformat/vorbiscomment.c
@@ -38,10 +38,21 @@ const AVMetadataConv ff_vorbiscomment_metadata_conv[] = {
{ 0 }
};
-int64_t ff_vorbiscomment_length(AVDictionary *m, const char *vendor_string)
+int64_t ff_vorbiscomment_length(AVDictionary *m, const char *vendor_string,
+ AVChapter **chapters, unsigned int nb_chapters)
{
int64_t len = 8;
len += strlen(vendor_string);
+ if (chapters && nb_chapters) {
+ for (int i = 0; i < nb_chapters; i++) {
+ AVDictionaryEntry *tag = NULL;
+ len += 4 + 12 + 1 + 10;
+ while ((tag = av_dict_get(chapters[i]->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
+ int64_t len1 = !strcmp(tag->key, "title") ? 4 : strlen(tag->key);
+ len += 4 + 10 + len1 + 1 + strlen(tag->value);
+ }
+ }
+ }
if (m) {
AVDictionaryEntry *tag = NULL;
while ((tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) {
@@ -52,12 +63,19 @@ int64_t ff_vorbiscomment_length(AVDictionary *m, const char *vendor_string)
}
int ff_vorbiscomment_write(uint8_t **p, AVDictionary **m,
- const char *vendor_string)
+ const char *vendor_string,
+ AVChapter **chapters, unsigned int nb_chapters)
{
+ int cm_count = 0;
bytestream_put_le32(p, strlen(vendor_string));
bytestream_put_buffer(p, vendor_string, strlen(vendor_string));
+ if (chapters && nb_chapters) {
+ for (int i = 0; i < nb_chapters; i++) {
+ cm_count += av_dict_count(chapters[i]->metadata) + 1;
+ }
+ }
if (*m) {
- int count = av_dict_count(*m);
+ int count = av_dict_count(*m) + cm_count;
AVDictionaryEntry *tag = NULL;
bytestream_put_le32(p, count);
while ((tag = av_dict_get(*m, "", tag, AV_DICT_IGNORE_SUFFIX))) {
@@ -70,6 +88,42 @@ int ff_vorbiscomment_write(uint8_t **p, AVDictionary **m,
bytestream_put_byte(p, '=');
bytestream_put_buffer(p, tag->value, len2);
}
+ for (int i = 0; i < nb_chapters; i++) {
+ AVChapter *chp = chapters[i];
+ char chapter_time[13];
+ char chapter_number[4];
+ int h, m, s, ms;
+
+ s = av_rescale(chp->start, chp->time_base.num, chp->time_base.den);
+ h = s / 3600;
+ m = (s / 60) % 60;
+ ms = av_rescale_q(chp->start, chp->time_base, av_make_q( 1, 1000)) % 1000;
+ s = s % 60;
+ snprintf(chapter_number, sizeof(chapter_number), "%03d", i);
+ snprintf(chapter_time, sizeof(chapter_time), "%02d:%02d:%02d.%03d", h, m, s, ms);
+ bytestream_put_le32(p, 10+1+12);
+ bytestream_put_buffer(p, "CHAPTER", 7);
+ bytestream_put_buffer(p, chapter_number, 3);
+ bytestream_put_byte(p, '=');
+ bytestream_put_buffer(p, chapter_time, 12);
+
+ tag = NULL;
+ while ((tag = av_dict_get(chapters[i]->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
+ int64_t len1 = !strcmp(tag->key, "title") ? 4 : strlen(tag->key);
+ int64_t len2 = strlen(tag->value);
+ if (len1+1+len2+10 > UINT32_MAX)
+ return AVERROR(EINVAL);
+ bytestream_put_le32(p, 10+len1+1+len2);
+ bytestream_put_buffer(p, "CHAPTER", 7);
+ bytestream_put_buffer(p, chapter_number, 3);
+ if (!strcmp(tag->key, "title"))
+ bytestream_put_buffer(p, "NAME", 4);
+ else
+ bytestream_put_buffer(p, tag->key, len1);
+ bytestream_put_byte(p, '=');
+ bytestream_put_buffer(p, tag->value, len2);
+ }
+ }
} else
bytestream_put_le32(p, 0);
return 0;