X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fid3v2enc.c;h=5d821ea4db247754c5fe90c47e9c3b3ea0169b7e;hb=337f777f378cfcc0d6f0d01fb7125905e8b0da55;hp=ffe358f0198659c7a41c9793d8106c312f0db182;hpb=e427ba5c68a522b26a45bf7c61016d9349fab43d;p=ffmpeg diff --git a/libavformat/id3v2enc.c b/libavformat/id3v2enc.c index ffe358f0198..5d821ea4db2 100644 --- a/libavformat/id3v2enc.c +++ b/libavformat/id3v2enc.c @@ -65,11 +65,11 @@ static void id3v2_encode_string(AVIOContext *pb, const uint8_t *str, static int id3v2_put_ttag(ID3v2EncContext *id3, AVIOContext *avioc, const char *str1, const char *str2, uint32_t tag, enum ID3v2Encoding enc) { - int len; + int len, ret; uint8_t *pb; AVIOContext *dyn_buf; - if (avio_open_dyn_buf(&dyn_buf) < 0) - return AVERROR(ENOMEM); + if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0) + return ret; /* check if the strings are ASCII-only and use UTF16 only if * they're not */ @@ -81,7 +81,7 @@ static int id3v2_put_ttag(ID3v2EncContext *id3, AVIOContext *avioc, const char * id3v2_encode_string(dyn_buf, str1, enc); if (str2) id3v2_encode_string(dyn_buf, str2, enc); - len = avio_close_dyn_buf(dyn_buf, &pb); + len = avio_get_dyn_buf(dyn_buf, &pb); avio_wb32(avioc, tag); /* ID3v2.3 frame size is not sync-safe */ @@ -92,7 +92,7 @@ static int id3v2_put_ttag(ID3v2EncContext *id3, AVIOContext *avioc, const char * avio_wb16(avioc, 0); avio_write(avioc, pb, len); - av_freep(&pb); + ffio_free_dyn_buf(&dyn_buf); return len + ID3v2_HEADER_SIZE; } @@ -103,7 +103,7 @@ static int id3v2_put_ttag(ID3v2EncContext *id3, AVIOContext *avioc, const char * */ static int id3v2_put_priv(ID3v2EncContext *id3, AVIOContext *avioc, const char *key, const char *data) { - int len; + int len, ret; uint8_t *pb; AVIOContext *dyn_buf; @@ -111,8 +111,8 @@ static int id3v2_put_priv(ID3v2EncContext *id3, AVIOContext *avioc, const char * return 0; } - if (avio_open_dyn_buf(&dyn_buf) < 0) - return AVERROR(ENOMEM); + if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0) + return ret; // owner + null byte. avio_write(dyn_buf, key, strlen(key) + 1); @@ -134,7 +134,7 @@ static int id3v2_put_priv(ID3v2EncContext *id3, AVIOContext *avioc, const char * } } - len = avio_close_dyn_buf(dyn_buf, &pb); + len = avio_get_dyn_buf(dyn_buf, &pb); avio_wb32(avioc, MKBETAG('P', 'R', 'I', 'V')); if (id3->version == 3) @@ -144,7 +144,7 @@ static int id3v2_put_priv(ID3v2EncContext *id3, AVIOContext *avioc, const char * avio_wb16(avioc, 0); avio_write(avioc, pb, len); - av_free(pb); + ffio_free_dyn_buf(&dyn_buf); return len + ID3v2_HEADER_SIZE; } @@ -255,17 +255,50 @@ static int write_metadata(AVIOContext *pb, AVDictionary **metadata, return 0; } +static int write_ctoc(AVFormatContext *s, ID3v2EncContext *id3, int enc) +{ + uint8_t *dyn_buf; + AVIOContext *dyn_bc; + char name[123]; + int len, ret; + + if (s->nb_chapters == 0) + return 0; + + if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0) + return ret; + + avio_put_str(dyn_bc, "toc"); + avio_w8(dyn_bc, 0x03); + avio_w8(dyn_bc, s->nb_chapters); + for (int i = 0; i < s->nb_chapters; i++) { + snprintf(name, 122, "ch%d", i); + avio_put_str(dyn_bc, name); + } + len = avio_get_dyn_buf(dyn_bc, &dyn_buf); + id3->len += len + ID3v2_HEADER_SIZE; + + avio_wb32(s->pb, MKBETAG('C', 'T', 'O', 'C')); + avio_wb32(s->pb, len); + avio_wb16(s->pb, 0); + avio_write(s->pb, dyn_buf, len); + + ffio_free_dyn_buf(&dyn_bc); + + return ret; +} + static int write_chapter(AVFormatContext *s, ID3v2EncContext *id3, int id, int enc) { const AVRational time_base = {1, 1000}; AVChapter *ch = s->chapters[id]; - uint8_t *dyn_buf = NULL; - AVIOContext *dyn_bc = NULL; + uint8_t *dyn_buf; + AVIOContext *dyn_bc; char name[123]; int len, start, end, ret; if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0) - goto fail; + return ret; start = av_rescale_q(ch->start, ch->time_base, time_base); end = av_rescale_q(ch->end, ch->time_base, time_base); @@ -280,7 +313,7 @@ static int write_chapter(AVFormatContext *s, ID3v2EncContext *id3, int id, int e if ((ret = write_metadata(dyn_bc, &ch->metadata, id3, enc)) < 0) goto fail; - len = avio_close_dyn_buf(dyn_bc, &dyn_buf); + len = avio_get_dyn_buf(dyn_bc, &dyn_buf); id3->len += 16 + ID3v2_HEADER_SIZE; avio_wb32(s->pb, MKBETAG('C', 'H', 'A', 'P')); @@ -289,9 +322,7 @@ static int write_chapter(AVFormatContext *s, ID3v2EncContext *id3, int id, int e avio_write(s->pb, dyn_buf, len); fail: - if (dyn_bc && !dyn_buf) - avio_close_dyn_buf(dyn_bc, &dyn_buf); - av_freep(&dyn_buf); + ffio_free_dyn_buf(&dyn_bc); return ret; } @@ -306,6 +337,9 @@ int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3) if ((ret = write_metadata(s->pb, &s->metadata, id3, enc)) < 0) return ret; + if ((ret = write_ctoc(s, id3, enc)) < 0) + return ret; + for (i = 0; i < s->nb_chapters; i++) { if ((ret = write_chapter(s, id3, i, enc)) < 0) return ret; @@ -325,7 +359,7 @@ int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt) const char *mimetype = NULL, *desc = ""; int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM : ID3v2_ENCODING_UTF8; - int i, len, type = 0; + int i, len, type = 0, ret; /* get the mimetype*/ while (mime->id != AV_CODEC_ID_NONE) { @@ -359,15 +393,15 @@ int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt) enc = ID3v2_ENCODING_ISO8859; /* start writing */ - if (avio_open_dyn_buf(&dyn_buf) < 0) - return AVERROR(ENOMEM); + if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0) + return ret; avio_w8(dyn_buf, enc); avio_put_str(dyn_buf, mimetype); avio_w8(dyn_buf, type); id3v2_encode_string(dyn_buf, desc, enc); avio_write(dyn_buf, pkt->data, pkt->size); - len = avio_close_dyn_buf(dyn_buf, &buf); + len = avio_get_dyn_buf(dyn_buf, &buf); avio_wb32(s->pb, MKBETAG('A', 'P', 'I', 'C')); if (id3->version == 3) @@ -376,7 +410,7 @@ int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt) id3v2_put_size(s->pb, len); avio_wb16(s->pb, 0); avio_write(s->pb, buf, len); - av_freep(&buf); + ffio_free_dyn_buf(&dyn_buf); id3->len += len + ID3v2_HEADER_SIZE;