]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/vorbiscomment.c
Merge commit '8629149816930a43bf5a66b11c6224446cabd044'
[ffmpeg] / libavformat / vorbiscomment.c
index 575dd133287d9dbf37d67c75a8d4e86c596996a9..fb5c655a23f504fcb20c4675a5050f0c189b4236 100644 (file)
@@ -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;