summaryrefslogtreecommitdiff
path: root/libavformat/id3v2.c
diff options
context:
space:
mode:
authorRichard Shaffer <rshaffer@tunein.com>2018-01-23 09:39:53 -0800
committerwm4 <nfxjfg@googlemail.com>2018-01-24 04:01:01 +0100
commit8a4cc0a2567fa8418709f75af5539cdf76fefb99 (patch)
tree8b4f3db2013b830a884249f4aced89149eab48fc /libavformat/id3v2.c
parentf0320afab977edc7b73317c8ef36ff1d60296401 (diff)
avformat: add option to parse/store ID3 PRIV tags in metadata.
Enables getting access to ID3 PRIV tags from the command-line or metadata API when demuxing. The PRIV owner is stored as the metadata key prepended with "id3v2_priv.", and the data is stored as the metadata value. As PRIV tags may contain arbitrary data, non-printable characters, including NULL bytes, are escaped as \xXX. Similarly, any metadata tags that begin with "id3v2_priv." are inserted as ID3 PRIV tags into the output (assuming the format supports ID3). \xXX sequences in the value are un-escaped to their byte value. Signed-off-by: wm4 <nfxjfg@googlemail.com>
Diffstat (limited to 'libavformat/id3v2.c')
-rw-r--r--libavformat/id3v2.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index 6c216ba7a2..b80178d67a 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -33,6 +33,7 @@
#endif
#include "libavutil/avstring.h"
+#include "libavutil/bprint.h"
#include "libavutil/dict.h"
#include "libavutil/intreadwrite.h"
#include "avio_internal.h"
@@ -1224,3 +1225,50 @@ end:
av_freep(&chapters);
return ret;
}
+
+int ff_id3v2_parse_priv_dict(AVDictionary **metadata, ID3v2ExtraMeta **extra_meta)
+{
+ ID3v2ExtraMeta *cur;
+ int dict_flags = AV_DICT_DONT_OVERWRITE | AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL;
+
+ for (cur = *extra_meta; cur; cur = cur->next) {
+ if (!strcmp(cur->tag, "PRIV")) {
+ ID3v2ExtraMetaPRIV *priv = cur->data;
+ AVBPrint bprint;
+ char *escaped, *key;
+ int i, ret;
+
+ if ((key = av_asprintf(ID3v2_PRIV_METADATA_PREFIX "%s", priv->owner)) == NULL) {
+ return AVERROR(ENOMEM);
+ }
+
+ av_bprint_init(&bprint, priv->datasize + 1, AV_BPRINT_SIZE_UNLIMITED);
+
+ for (i = 0; i < priv->datasize; i++) {
+ if (priv->data[i] < 32 || priv->data[i] > 126 || priv->data[i] == '\\') {
+ av_bprintf(&bprint, "\\x%02x", priv->data[i]);
+ } else {
+ av_bprint_chars(&bprint, priv->data[i], 1);
+ }
+ }
+
+ if ((ret = av_bprint_finalize(&bprint, &escaped)) < 0) {
+ av_free(key);
+ return ret;
+ }
+
+ if ((ret = av_dict_set(metadata, key, escaped, dict_flags)) < 0) {
+ av_free(key);
+ av_free(escaped);
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int ff_id3v2_parse_priv(AVFormatContext *s, ID3v2ExtraMeta **extra_meta)
+{
+ return ff_id3v2_parse_priv_dict(&s->metadata, extra_meta);
+}