diff options
author | Anton Khirnov <anton@khirnov.net> | 2012-02-27 22:08:50 +0100 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2012-02-29 14:26:14 +0100 |
commit | 411225aabce57411d1544a7bbc6f6bee6d8ef638 (patch) | |
tree | f3dcc31c02aaf9507f369239950c7c8349248b07 | |
parent | c19981774880919c7f9417014bdcb1fb63f69231 (diff) | |
download | ffmpeg-411225aabce57411d1544a7bbc6f6bee6d8ef638.tar.gz |
id3v2enc: split ff_id3v2_write().
This will allow writing the tag in several steps, needed for writing
attached pictures.
-rw-r--r-- | libavformat/id3v2.h | 26 | ||||
-rw-r--r-- | libavformat/id3v2enc.c | 64 | ||||
-rw-r--r-- | libavformat/mp3enc.c | 2 | ||||
-rw-r--r-- | libavformat/omaenc.c | 2 |
4 files changed, 68 insertions, 26 deletions
diff --git a/libavformat/id3v2.h b/libavformat/id3v2.h index 5f3ec1b3ca..f47abe9d25 100644 --- a/libavformat/id3v2.h +++ b/libavformat/id3v2.h @@ -46,6 +46,12 @@ enum ID3v2Encoding { ID3v2_ENCODING_UTF8 = 3, }; +typedef struct ID3v2EncContext { + int version; ///< ID3v2 minor version, either 3 or 4 + int64_t size_pos; ///< offset of the tag total size + int len; ///< size of the tag written so far +} ID3v2EncContext; + typedef struct ID3v2ExtraMeta { const char *tag; void *data; @@ -91,12 +97,28 @@ int ff_id3v2_tag_len(const uint8_t *buf); void ff_id3v2_read(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta); /** - * Write an ID3v2 tag. + * Initialize an ID3v2 tag. + */ +void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version, + const char *magic); + +/** + * Convert and write all global metadata from s into an ID3v2 tag. + */ +int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3); + +/** + * Finalize an opened ID3v2 tag. + */ +void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb); + +/** + * Write an ID3v2 tag containing all global metadata from s. * @param id3v2_version Subversion of ID3v2; supported values are 3 and 4 * @param magic magic bytes to identify the header * If in doubt, use ID3v2_DEFAULT_MAGIC. */ -int ff_id3v2_write(struct AVFormatContext *s, int id3v2_version, const char *magic); +int ff_id3v2_write_simple(struct AVFormatContext *s, int id3v2_version, const char *magic); /** * Free memory allocated parsing special (non-text) metadata. diff --git a/libavformat/id3v2enc.c b/libavformat/id3v2enc.c index 3a4d229232..8666818128 100644 --- a/libavformat/id3v2enc.c +++ b/libavformat/id3v2enc.c @@ -97,50 +97,70 @@ static int id3v2_check_write_tag(AVFormatContext *s, AVDictionaryEntry *t, const return -1; } -int ff_id3v2_write(struct AVFormatContext *s, int id3v2_version, - const char *magic) +void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version, + const char *magic) { - int64_t size_pos, cur_pos; - AVDictionaryEntry *t = NULL; - - int totlen = 0, enc = id3v2_version == 3 ? ID3v2_ENCODING_UTF16BOM : - ID3v2_ENCODING_UTF8; + id3->version = id3v2_version; - - avio_wb32(s->pb, MKBETAG(magic[0], magic[1], magic[2], id3v2_version)); - avio_w8(s->pb, 0); - avio_w8(s->pb, 0); /* flags */ + avio_wb32(pb, MKBETAG(magic[0], magic[1], magic[2], id3v2_version)); + avio_w8(pb, 0); + avio_w8(pb, 0); /* flags */ /* reserve space for size */ - size_pos = avio_tell(s->pb); - avio_wb32(s->pb, 0); + id3->size_pos = avio_tell(pb); + avio_wb32(pb, 0); +} + +int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3) +{ + 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 (id3v2_version == 4) + 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(s, t, ff_id3v2_tags, enc)) > 0) { - totlen += ret; + id3->len += ret; continue; } - if ((ret = id3v2_check_write_tag(s, t, id3v2_version == 3 ? + if ((ret = id3v2_check_write_tag(s, t, id3->version == 3 ? ff_id3v2_3_tags : ff_id3v2_4_tags, enc)) > 0) { - totlen += ret; + id3->len += ret; continue; } /* unknown tag, write as TXXX frame */ if ((ret = id3v2_put_ttag(s, t->key, t->value, MKBETAG('T', 'X', 'X', 'X'), enc)) < 0) return ret; - totlen += ret; + id3->len += ret; } - cur_pos = avio_tell(s->pb); - avio_seek(s->pb, size_pos, SEEK_SET); - id3v2_put_size(s->pb, totlen); - avio_seek(s->pb, cur_pos, SEEK_SET); + return 0; +} + +void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb) +{ + int64_t cur_pos = avio_tell(pb); + avio_seek(pb, id3->size_pos, SEEK_SET); + id3v2_put_size(pb, id3->len); + avio_seek(pb, cur_pos, SEEK_SET); +} + +int ff_id3v2_write_simple(struct AVFormatContext *s, int id3v2_version, + const char *magic) +{ + ID3v2EncContext id3 = { 0 }; + int ret; + + ff_id3v2_start(&id3, s->pb, id3v2_version, magic); + if ((ret = ff_id3v2_write_metadata(s, &id3)) < 0) + return ret; + ff_id3v2_finish(&id3, s->pb); + return 0; } diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index ce547ead38..ab20c299fe 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -187,7 +187,7 @@ static int mp3_write_header(struct AVFormatContext *s) MP3Context *mp3 = s->priv_data; int ret; - ret = ff_id3v2_write(s, mp3->id3v2_version, ID3v2_DEFAULT_MAGIC); + ret = ff_id3v2_write_simple(s, mp3->id3v2_version, ID3v2_DEFAULT_MAGIC); if (ret < 0) return ret; diff --git a/libavformat/omaenc.c b/libavformat/omaenc.c index e932b4bbc1..c3ee0e8de1 100644 --- a/libavformat/omaenc.c +++ b/libavformat/omaenc.c @@ -49,7 +49,7 @@ static av_cold int oma_write_header(AVFormatContext *s) } /* Metadata; OpenMG does not support ID3v2.4 */ - ff_id3v2_write(s, 3, ID3v2_EA3_MAGIC); + ff_id3v2_write_simple(s, 3, ID3v2_EA3_MAGIC); ffio_wfourcc(s->pb, "EA3\0"); avio_w8(s->pb, EA3_HEADER_SIZE >> 7); |