mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
id3v2enc: chapter support
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
parent
d26f637b02
commit
47ac344970
@ -162,33 +162,31 @@ void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version,
|
||||
avio_wb32(pb, 0);
|
||||
}
|
||||
|
||||
int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3)
|
||||
static int write_metadata(AVIOContext *pb, AVDictionary **metadata,
|
||||
ID3v2EncContext *id3, int enc)
|
||||
{
|
||||
AVDictionaryEntry *t = NULL;
|
||||
int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM :
|
||||
ID3v2_ENCODING_UTF8;
|
||||
|
||||
ff_metadata_conv(&s->metadata, ff_id3v2_34_metadata_conv, NULL);
|
||||
if (id3->version == 3)
|
||||
id3v2_3_metadata_split_date(&s->metadata);
|
||||
else if (id3->version == 4)
|
||||
ff_metadata_conv(&s->metadata, ff_id3v2_4_metadata_conv, NULL);
|
||||
|
||||
while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
|
||||
int ret;
|
||||
|
||||
if ((ret = id3v2_check_write_tag(id3, s->pb, t, ff_id3v2_tags, enc)) > 0) {
|
||||
ff_metadata_conv(metadata, ff_id3v2_34_metadata_conv, NULL);
|
||||
if (id3->version == 3)
|
||||
id3v2_3_metadata_split_date(metadata);
|
||||
else if (id3->version == 4)
|
||||
ff_metadata_conv(metadata, ff_id3v2_4_metadata_conv, NULL);
|
||||
|
||||
while ((t = av_dict_get(*metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
|
||||
if ((ret = id3v2_check_write_tag(id3, pb, t, ff_id3v2_tags, enc)) > 0) {
|
||||
id3->len += ret;
|
||||
continue;
|
||||
}
|
||||
if ((ret = id3v2_check_write_tag(id3, s->pb, t, id3->version == 3 ?
|
||||
if ((ret = id3v2_check_write_tag(id3, pb, t, id3->version == 3 ?
|
||||
ff_id3v2_3_tags : ff_id3v2_4_tags, enc)) > 0) {
|
||||
id3->len += ret;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* unknown tag, write as TXXX frame */
|
||||
if ((ret = id3v2_put_ttag(id3, s->pb, t->key, t->value, MKBETAG('T', 'X', 'X', 'X'), enc)) < 0)
|
||||
if ((ret = id3v2_put_ttag(id3, pb, t->key, t->value, MKBETAG('T', 'X', 'X', 'X'), enc)) < 0)
|
||||
return ret;
|
||||
id3->len += ret;
|
||||
}
|
||||
@ -196,6 +194,64 @@ int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3)
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
char name[123];
|
||||
int len, start, end, ret;
|
||||
|
||||
if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0)
|
||||
goto fail;
|
||||
|
||||
start = av_rescale_q(ch->start, ch->time_base, time_base);
|
||||
end = av_rescale_q(ch->end, ch->time_base, time_base);
|
||||
|
||||
snprintf(name, 122, "ch%d", id);
|
||||
id3->len += avio_put_str(dyn_bc, name);
|
||||
avio_wb32(dyn_bc, start);
|
||||
avio_wb32(dyn_bc, end);
|
||||
avio_wb32(dyn_bc, 0xFFFFFFFFu);
|
||||
avio_wb32(dyn_bc, 0xFFFFFFFFu);
|
||||
|
||||
if ((ret = write_metadata(dyn_bc, &ch->metadata, id3, enc)) < 0)
|
||||
goto fail;
|
||||
|
||||
len = avio_close_dyn_buf(dyn_bc, &dyn_buf);
|
||||
id3->len += 16 + ID3v2_HEADER_SIZE;
|
||||
|
||||
avio_wb32(s->pb, MKBETAG('C', 'H', 'A', 'P'));
|
||||
avio_wb32(s->pb, len);
|
||||
avio_wb16(s->pb, 0);
|
||||
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);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3)
|
||||
{
|
||||
int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM :
|
||||
ID3v2_ENCODING_UTF8;
|
||||
int i, ret;
|
||||
|
||||
if ((ret = write_metadata(s->pb, &s->metadata, id3, enc)) < 0)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < s->nb_chapters; i++) {
|
||||
if ((ret = write_chapter(s, id3, i, enc)) < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt)
|
||||
{
|
||||
AVStream *st = s->streams[pkt->stream_index];
|
||||
|
Loading…
Reference in New Issue
Block a user