X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fvorbiscomment.c;h=a929634cc0459e2a0709f1e47fd4933868b8661e;hb=4de2b035a736ca8b5b7abbee323327031a50873a;hp=575dd133287d9dbf37d67c75a8d4e86c596996a9;hpb=f4cf6ba8c9646814af842a99335c6ee312ded299;p=ffmpeg diff --git a/libavformat/vorbiscomment.c b/libavformat/vorbiscomment.c index 575dd133287..a929634cc04 100644 --- a/libavformat/vorbiscomment.c +++ b/libavformat/vorbiscomment.c @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "avio.h" #include "avformat.h" #include "metadata.h" #include "vorbiscomment.h" -#include "libavcodec/bytestream.h" #include "libavutil/dict.h" /** @@ -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(const 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))) { @@ -51,26 +62,69 @@ int64_t ff_vorbiscomment_length(AVDictionary *m, const char *vendor_string) return len; } -int ff_vorbiscomment_write(uint8_t **p, AVDictionary **m, - const char *vendor_string) +int ff_vorbiscomment_write(AVIOContext *pb, const AVDictionary *m, + const char *vendor_string, + AVChapter **chapters, unsigned int nb_chapters) { - bytestream_put_le32(p, strlen(vendor_string)); - bytestream_put_buffer(p, vendor_string, strlen(vendor_string)); - if (*m) { - int count = av_dict_count(*m); + int cm_count = 0; + avio_wl32(pb, strlen(vendor_string)); + avio_write(pb, 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) + cm_count; AVDictionaryEntry *tag = NULL; - bytestream_put_le32(p, count); - while ((tag = av_dict_get(*m, "", tag, AV_DICT_IGNORE_SUFFIX))) { + avio_wl32(pb, count); + while ((tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) { int64_t len1 = strlen(tag->key); int64_t len2 = strlen(tag->value); if (len1+1+len2 > UINT32_MAX) return AVERROR(EINVAL); - bytestream_put_le32(p, len1+1+len2); - bytestream_put_buffer(p, tag->key, len1); - bytestream_put_byte(p, '='); - bytestream_put_buffer(p, tag->value, len2); + avio_wl32(pb, len1 + 1 + len2); + avio_write(pb, tag->key, len1); + avio_w8(pb, '='); + avio_write(pb, 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); + avio_wl32(pb, 10 + 1 + 12); + avio_write(pb, "CHAPTER", 7); + avio_write(pb, chapter_number, 3); + avio_w8(pb, '='); + avio_write(pb, 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); + avio_wl32(pb, 10 + len1 + 1 + len2); + avio_write(pb, "CHAPTER", 7); + avio_write(pb, chapter_number, 3); + if (!strcmp(tag->key, "title")) + avio_write(pb, "NAME", 4); + else + avio_write(pb, tag->key, len1); + avio_w8(pb, '='); + avio_write(pb, tag->value, len2); + } } } else - bytestream_put_le32(p, 0); + avio_wl32(pb, 0); return 0; }