diff options
author | Paul B Mahol <onemda@gmail.com> | 2013-06-06 13:35:49 +0000 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2013-06-14 17:07:36 +0000 |
commit | a75d2a6505bf85c947a2428bd2f18f0bb6d0fcd1 (patch) | |
tree | d5363c07a562cd082d98377e03ae189f0765b9cf | |
parent | 7fff3df6b277d4f1ebc504e950c9de56cdc14ddd (diff) | |
download | ffmpeg-a75d2a6505bf85c947a2428bd2f18f0bb6d0fcd1.tar.gz |
apetag: do not require seekable output
Also don't write empty tags.
Signed-off-by: Paul B Mahol <onemda@gmail.com>
-rw-r--r-- | libavformat/apetag.c | 58 |
1 files changed, 31 insertions, 27 deletions
diff --git a/libavformat/apetag.c b/libavformat/apetag.c index e0b56be7c8..ab93736718 100644 --- a/libavformat/apetag.c +++ b/libavformat/apetag.c @@ -179,24 +179,17 @@ static int string_is_ascii(const uint8_t *str) int ff_ape_write_tag(AVFormatContext *s) { AVDictionaryEntry *e = NULL; - int64_t start, end; - int size, count = 0; + int size, ret, count = 0; + AVIOContext *dyn_bc = NULL; + uint8_t *dyn_buf = NULL; - if (!s->pb->seekable) - return 0; - - start = avio_tell(s->pb); - - // header - avio_write(s->pb, "APETAGEX", 8); // id - avio_wl32 (s->pb, APE_TAG_VERSION); // version - avio_wl32(s->pb, 0); // reserve space for size - avio_wl32(s->pb, 0); // reserve space for tag count + if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0) + goto end; // flags - avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER | + avio_wl32(dyn_bc, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER | APE_TAG_FLAG_IS_HEADER); - ffio_fill(s->pb, 0, 8); // reserved + ffio_fill(dyn_bc, 0, 8); // reserved while ((e = av_dict_get(s->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) { int val_len; @@ -207,18 +200,31 @@ int ff_ape_write_tag(AVFormatContext *s) } val_len = strlen(e->value); - avio_wl32(s->pb, val_len); // value length - avio_wl32(s->pb, 0); // item flags - avio_put_str(s->pb, e->key); // key - avio_write(s->pb, e->value, val_len); // value + avio_wl32(dyn_bc, val_len); // value length + avio_wl32(dyn_bc, 0); // item flags + avio_put_str(dyn_bc, e->key); // key + avio_write(dyn_bc, e->value, val_len); // value count++; } + if (!count) + goto end; - size = avio_tell(s->pb) - start; + size = avio_close_dyn_buf(dyn_bc, &dyn_buf); + if (size <= 0) + goto end; + size += 20; + + // header + avio_write(s->pb, "APETAGEX", 8); // id + avio_wl32(s->pb, APE_TAG_VERSION); // version + avio_wl32(s->pb, size); + avio_wl32(s->pb, count); + + avio_write(s->pb, dyn_buf, size - 20); // footer avio_write(s->pb, "APETAGEX", 8); // id - avio_wl32 (s->pb, APE_TAG_VERSION); // version + avio_wl32(s->pb, APE_TAG_VERSION); // version avio_wl32(s->pb, size); // size avio_wl32(s->pb, count); // tag count @@ -226,12 +232,10 @@ int ff_ape_write_tag(AVFormatContext *s) avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER); ffio_fill(s->pb, 0, 8); // reserved - // update values in the header - end = avio_tell(s->pb); - avio_seek(s->pb, start + 12, SEEK_SET); - avio_wl32(s->pb, size); - avio_wl32(s->pb, count); - avio_seek(s->pb, end, SEEK_SET); +end: + if (dyn_bc && !dyn_buf) + avio_close_dyn_buf(dyn_bc, &dyn_buf); + av_freep(&dyn_buf); - return 0; + return ret; } |