summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorDavid Murmann <david@btf.de>2016-06-22 15:27:07 +0200
committerMichael Niedermayer <michael@niedermayer.cc>2016-06-25 14:38:14 +0200
commit0296b4b8d899ee720a812f8018ff9bba216c8c6d (patch)
tree62fc9da946e45b2a871884796f0b5be625af4143 /libavformat
parentdfd0c0f981c58d913f1a7e355b6bfa49ed1d5f46 (diff)
avformat/movenc: add option to use keys/mdta atoms for metadata
Add -movflags use_metadata_tags to the mov muxer. This will cause the muxer to write all metadata to the file in the keys and mtda atoms. Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/movenc.c81
-rw-r--r--libavformat/movenc.h1
2 files changed, 78 insertions, 4 deletions
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index eb6d82db70..d614933dff 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -70,6 +70,7 @@ static const AVOption options[] = {
{ "global_sidx", "Write a global sidx index at the start of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_GLOBAL_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "write_colr", "Write colr atom (Experimental, may be renamed or changed, do not use from scripts)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_COLR}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "write_gama", "Write deprecated gama atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_GAMA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+ { "use_metadata_tags", "Use mdta atom for metadata.", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_USE_MDTA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
{ "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
{ "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
@@ -3109,7 +3110,71 @@ static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
return update_size(pb, pos);
}
-/* iTunes meta data tag */
+static int mov_write_mdta_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
+ AVFormatContext *s)
+{
+ avio_wb32(pb, 33); /* size */
+ ffio_wfourcc(pb, "hdlr");
+ avio_wb32(pb, 0);
+ avio_wb32(pb, 0);
+ ffio_wfourcc(pb, "mdta");
+ avio_wb32(pb, 0);
+ avio_wb32(pb, 0);
+ avio_wb32(pb, 0);
+ avio_w8(pb, 0);
+ return 33;
+}
+
+static int mov_write_mdta_keys_tag(AVIOContext *pb, MOVMuxContext *mov,
+ AVFormatContext *s)
+{
+ AVDictionaryEntry *t = NULL;
+ int64_t pos = avio_tell(pb);
+ int64_t curpos, entry_pos;
+ int count = 0;
+
+ avio_wb32(pb, 0); /* size */
+ ffio_wfourcc(pb, "keys");
+ avio_wb32(pb, 0);
+ entry_pos = avio_tell(pb);
+ avio_wb32(pb, 0); /* entry count */
+
+ while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
+ avio_wb32(pb, strlen(t->key) + 8);
+ ffio_wfourcc(pb, "mdta");
+ avio_write(pb, t->key, strlen(t->key));
+ count += 1;
+ }
+ curpos = avio_tell(pb);
+ avio_seek(pb, entry_pos, SEEK_SET);
+ avio_wb32(pb, count); // rewrite entry count
+ avio_seek(pb, curpos, SEEK_SET);
+
+ return update_size(pb, pos);
+}
+
+static int mov_write_mdta_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
+ AVFormatContext *s)
+{
+ AVDictionaryEntry *t = NULL;
+ int64_t pos = avio_tell(pb);
+ int count = 1; /* keys are 1-index based */
+
+ avio_wb32(pb, 0); /* size */
+ ffio_wfourcc(pb, "ilst");
+
+ while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
+ int64_t entry_pos = avio_tell(pb);
+ avio_wb32(pb, 0); /* size */
+ avio_wb32(pb, count); /* key */
+ mov_write_string_data_tag(pb, t->value, 0, 1);
+ update_size(pb, entry_pos);
+ count += 1;
+ }
+ return update_size(pb, pos);
+}
+
+/* meta data tags */
static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
AVFormatContext *s)
{
@@ -3118,8 +3183,16 @@ static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
avio_wb32(pb, 0); /* size */
ffio_wfourcc(pb, "meta");
avio_wb32(pb, 0);
- mov_write_itunes_hdlr_tag(pb, mov, s);
- mov_write_ilst_tag(pb, mov, s);
+ if (mov->flags & FF_MOV_FLAG_USE_MDTA) {
+ mov_write_mdta_hdlr_tag(pb, mov, s);
+ mov_write_mdta_keys_tag(pb, mov, s);
+ mov_write_mdta_ilst_tag(pb, mov, s);
+ }
+ else {
+ /* iTunes metadata tag */
+ mov_write_itunes_hdlr_tag(pb, mov, s);
+ mov_write_ilst_tag(pb, mov, s);
+ }
size = update_size(pb, pos);
return size;
}
@@ -3231,7 +3304,7 @@ static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
mov_write_loci_tag(s, pb_buf);
- } else if (mov->mode == MODE_MOV) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
+ } else if (mov->mode == MODE_MOV && !(mov->flags & FF_MOV_FLAG_USE_MDTA)) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
mov_write_string_metadata(s, pb_buf, "\251ART", "artist", 0);
mov_write_string_metadata(s, pb_buf, "\251nam", "title", 0);
mov_write_string_metadata(s, pb_buf, "\251aut", "author", 0);
diff --git a/libavformat/movenc.h b/libavformat/movenc.h
index c4fded89bb..6e9f5ace72 100644
--- a/libavformat/movenc.h
+++ b/libavformat/movenc.h
@@ -234,6 +234,7 @@ typedef struct MOVMuxContext {
#define FF_MOV_FLAG_GLOBAL_SIDX (1 << 14)
#define FF_MOV_FLAG_WRITE_COLR (1 << 15)
#define FF_MOV_FLAG_WRITE_GAMA (1 << 16)
+#define FF_MOV_FLAG_USE_MDTA (1 << 17)
int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt);