mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-13 21:28:01 +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);
|
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;
|
AVDictionaryEntry *t = NULL;
|
||||||
int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM :
|
int ret;
|
||||||
ID3v2_ENCODING_UTF8;
|
|
||||||
|
|
||||||
ff_metadata_conv(&s->metadata, ff_id3v2_34_metadata_conv, NULL);
|
ff_metadata_conv(metadata, ff_id3v2_34_metadata_conv, NULL);
|
||||||
if (id3->version == 3)
|
if (id3->version == 3)
|
||||||
id3v2_3_metadata_split_date(&s->metadata);
|
id3v2_3_metadata_split_date(metadata);
|
||||||
else if (id3->version == 4)
|
else if (id3->version == 4)
|
||||||
ff_metadata_conv(&s->metadata, ff_id3v2_4_metadata_conv, NULL);
|
ff_metadata_conv(metadata, ff_id3v2_4_metadata_conv, NULL);
|
||||||
|
|
||||||
while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
|
while ((t = av_dict_get(*metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
|
||||||
int ret;
|
if ((ret = id3v2_check_write_tag(id3, pb, t, ff_id3v2_tags, enc)) > 0) {
|
||||||
|
|
||||||
if ((ret = id3v2_check_write_tag(id3, s->pb, t, ff_id3v2_tags, enc)) > 0) {
|
|
||||||
id3->len += ret;
|
id3->len += ret;
|
||||||
continue;
|
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) {
|
ff_id3v2_3_tags : ff_id3v2_4_tags, enc)) > 0) {
|
||||||
id3->len += ret;
|
id3->len += ret;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unknown tag, write as TXXX frame */
|
/* 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;
|
return ret;
|
||||||
id3->len += ret;
|
id3->len += ret;
|
||||||
}
|
}
|
||||||
@ -196,6 +194,64 @@ int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3)
|
|||||||
return 0;
|
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)
|
int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt)
|
||||||
{
|
{
|
||||||
AVStream *st = s->streams[pkt->stream_index];
|
AVStream *st = s->streams[pkt->stream_index];
|
||||||
|
Loading…
Reference in New Issue
Block a user