X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fvorbiscomment.c;h=fb5c655a23f504fcb20c4675a5050f0c189b4236;hb=44085b9951b06df1cab4105dcda004213988d84f;hp=575dd133287d9dbf37d67c75a8d4e86c596996a9;hpb=22219a3ac46ac18f797c94e4619a34728556786c;p=ffmpeg diff --git a/libavformat/vorbiscomment.c b/libavformat/vorbiscomment.c index 575dd133287..fb5c655a23f 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;