apetag: add support for writing APE tags

This will be useful in the WavPack muxer.
This commit is contained in:
Anton Khirnov 2013-05-28 17:43:22 +02:00
parent 01656fd476
commit 88de0c7901
2 changed files with 61 additions and 0 deletions

View File

@ -23,12 +23,14 @@
#include "libavutil/intreadwrite.h" #include "libavutil/intreadwrite.h"
#include "libavutil/dict.h" #include "libavutil/dict.h"
#include "avformat.h" #include "avformat.h"
#include "avio_internal.h"
#include "apetag.h" #include "apetag.h"
#include "internal.h" #include "internal.h"
#define APE_TAG_VERSION 2000 #define APE_TAG_VERSION 2000
#define APE_TAG_FOOTER_BYTES 32 #define APE_TAG_FOOTER_BYTES 32
#define APE_TAG_FLAG_CONTAINS_HEADER (1 << 31) #define APE_TAG_FLAG_CONTAINS_HEADER (1 << 31)
#define APE_TAG_FLAG_CONTAINS_FOOTER (1 << 30)
#define APE_TAG_FLAG_IS_HEADER (1 << 29) #define APE_TAG_FLAG_IS_HEADER (1 << 29)
#define APE_TAG_FLAG_IS_BINARY (1 << 1) #define APE_TAG_FLAG_IS_BINARY (1 << 1)
@ -169,3 +171,57 @@ int64_t ff_ape_parse_tag(AVFormatContext *s)
return tag_start; return tag_start;
} }
int ff_ape_write_tag(AVFormatContext *s)
{
AVDictionaryEntry *e = NULL;
int64_t start, end;
int size, count = 0;
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
// flags
avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER |
APE_TAG_FLAG_IS_HEADER);
ffio_fill(s->pb, 0, 8); // reserved
while ((e = av_dict_get(s->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) {
int 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
count++;
}
size = avio_tell(s->pb) - start;
// footer
avio_write(s->pb, "APETAGEX", 8); // id
avio_wl32 (s->pb, APE_TAG_VERSION); // version
avio_wl32(s->pb, size); // size
avio_wl32(s->pb, count); // tag count
// flags
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);
return 0;
}

View File

@ -32,4 +32,9 @@
*/ */
int64_t ff_ape_parse_tag(AVFormatContext *s); int64_t ff_ape_parse_tag(AVFormatContext *s);
/**
* Write an APE tag into a file.
*/
int ff_ape_write_tag(AVFormatContext *s);
#endif /* AVFORMAT_APETAG_H */ #endif /* AVFORMAT_APETAG_H */