summaryrefslogtreecommitdiffstats
path: root/contrib/ffmpeg
diff options
context:
space:
mode:
authorJohn Stebbins <[email protected]>2019-08-04 11:07:02 -0700
committerJohn Stebbins <[email protected]>2019-08-11 15:36:41 -0700
commit57e46db5dfc64db0c5bf5d67357fe3107d4bb8fd (patch)
treed25c5276edba375fd16f3f1a971365b92f4773a1 /contrib/ffmpeg
parent3999c06cb6194d5e537ce2460b80ecf2d2af81af (diff)
ffmpeg: add support to read/write mp4 'titl' track tag
Diffstat (limited to 'contrib/ffmpeg')
-rw-r--r--contrib/ffmpeg/A05-mov-read-name-track-tag-written-by-movenc.patch22
-rw-r--r--contrib/ffmpeg/A06-movenc-write-3gpp-track-titl-tag.patch126
-rw-r--r--contrib/ffmpeg/A07-mov-read-3gpp-udta-tags.patch160
3 files changed, 297 insertions, 11 deletions
diff --git a/contrib/ffmpeg/A05-mov-read-name-track-tag-written-by-movenc.patch b/contrib/ffmpeg/A05-mov-read-name-track-tag-written-by-movenc.patch
index 514aa79d0..67e4d2868 100644
--- a/contrib/ffmpeg/A05-mov-read-name-track-tag-written-by-movenc.patch
+++ b/contrib/ffmpeg/A05-mov-read-name-track-tag-written-by-movenc.patch
@@ -1,14 +1,14 @@
-From b6ce7b6a4ec0429069f05e63edce907c0f80aaea Mon Sep 17 00:00:00 2001
+From 375d09561cb88a7002a833614dbd399446479cd1 Mon Sep 17 00:00:00 2001
From: John Stebbins <[email protected]>
Date: Wed, 31 Jul 2019 15:27:40 -0700
-Subject: [PATCH] mov: read 'name' track tag written by movenc
+Subject: [PATCH 1/3] mov: read 'name' track tag written by movenc
---
libavformat/mov.c | 26 +++++++++++++++++---------
1 file changed, 17 insertions(+), 9 deletions(-)
diff --git a/libavformat/mov.c b/libavformat/mov.c
-index 24de5429d1..fce69129d9 100644
+index 24de5429d1..1f933cccfd 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -306,6 +306,7 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
@@ -19,14 +19,14 @@ index 24de5429d1..fce69129d9 100644
switch (atom.type) {
case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break;
-@@ -384,6 +385,7 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
- case MKTAG(0xa9,'m','a','k'): key = "make"; break;
- case MKTAG(0xa9,'m','o','d'): key = "model"; break;
- case MKTAG(0xa9,'n','a','m'): key = "title"; break;
-+ case MKTAG( 'n','a','m','e'): key = "title"; break;
- case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break;
- case MKTAG(0xa9,'p','r','d'): key = "producer"; break;
- case MKTAG(0xa9,'p','r','f'): key = "performers"; break;
+@@ -338,6 +339,7 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+ return mov_metadata_loci(c, pb, atom.size);
+ case MKTAG( 'm','a','n','u'): key = "make"; break;
+ case MKTAG( 'm','o','d','l'): key = "model"; break;
++ case MKTAG( 'n','a','m','e'): key = "title"; raw = 1; break;
+ case MKTAG( 'p','c','s','t'): key = "podcast";
+ parse = mov_metadata_int8_no_padding; break;
+ case MKTAG( 'p','g','a','p'): key = "gapless_playback";
@@ -514,17 +516,23 @@ retry:
}
str[str_size] = 0;
diff --git a/contrib/ffmpeg/A06-movenc-write-3gpp-track-titl-tag.patch b/contrib/ffmpeg/A06-movenc-write-3gpp-track-titl-tag.patch
new file mode 100644
index 000000000..5c40e66a0
--- /dev/null
+++ b/contrib/ffmpeg/A06-movenc-write-3gpp-track-titl-tag.patch
@@ -0,0 +1,126 @@
+From e9dde141a5fc27df87eb4b3454e34d725b211708 Mon Sep 17 00:00:00 2001
+From: John Stebbins <[email protected]>
+Date: Sun, 4 Aug 2019 10:52:30 -0700
+Subject: [PATCH 2/3] movenc: write 3gpp track 'titl' tag
+
+Apple software used to use 'name' raw tag for track titles. When they
+rewrote everything with AVFoundation, they switched to using 3gpp 'titl'
+tag for track titles and 'name' no longer works.
+---
+ libavformat/movenc.c | 78 +++++++++++++++++++++++---------------------
+ 1 file changed, 40 insertions(+), 38 deletions(-)
+
+diff --git a/libavformat/movenc.c b/libavformat/movenc.c
+index a96139077b..b1b6ef0e4e 100644
+--- a/libavformat/movenc.c
++++ b/libavformat/movenc.c
+@@ -3077,6 +3077,35 @@ static int mov_write_udta_sdp(AVIOContext *pb, MOVTrack *track)
+ return len + 24;
+ }
+
++static uint16_t language_code(const char *str)
++{
++ return (((str[0] - 0x60) & 0x1F) << 10) +
++ (((str[1] - 0x60) & 0x1F) << 5) +
++ (( str[2] - 0x60) & 0x1F);
++}
++
++static int mov_write_3gp_udta_tag(AVIOContext *pb, AVDictionary *metadata,
++ const char *tag, const char *str)
++{
++ int64_t pos = avio_tell(pb);
++ AVDictionaryEntry *t = av_dict_get(metadata, str, NULL, 0);
++ if (!t || !utf8len(t->value))
++ return 0;
++ avio_wb32(pb, 0); /* size */
++ ffio_wfourcc(pb, tag); /* type */
++ avio_wb32(pb, 0); /* version + flags */
++ if (!strcmp(tag, "yrrc"))
++ avio_wb16(pb, atoi(t->value));
++ else {
++ avio_wb16(pb, language_code("eng")); /* language */
++ avio_write(pb, t->value, strlen(t->value) + 1); /* UTF8 string value */
++ if (!strcmp(tag, "albm") &&
++ (t = av_dict_get(metadata, "track", NULL, 0)))
++ avio_w8(pb, atoi(t->value));
++ }
++ return update_size(pb, pos);
++}
++
+ static int mov_write_track_metadata(AVIOContext *pb, AVStream *st,
+ const char *tag, const char *str)
+ {
+@@ -3105,8 +3134,10 @@ static int mov_write_track_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
+ if (ret < 0)
+ return ret;
+
+- if (mov->mode & (MODE_MP4|MODE_MOV))
++ if (mov->mode & (MODE_MP4|MODE_MOV)) {
+ mov_write_track_metadata(pb_buf, st, "name", "title");
++ mov_write_3gp_udta_tag(pb_buf, st->metadata, "titl", "title");
++ }
+
+ if ((size = avio_close_dyn_buf(pb_buf, &buf)) > 0) {
+ avio_wb32(pb, size + 8);
+@@ -3680,35 +3711,6 @@ static int ascii_to_wc(AVIOContext *pb, const uint8_t *b)
+ return 0;
+ }
+
+-static uint16_t language_code(const char *str)
+-{
+- return (((str[0] - 0x60) & 0x1F) << 10) +
+- (((str[1] - 0x60) & 0x1F) << 5) +
+- (( str[2] - 0x60) & 0x1F);
+-}
+-
+-static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s,
+- const char *tag, const char *str)
+-{
+- int64_t pos = avio_tell(pb);
+- AVDictionaryEntry *t = av_dict_get(s->metadata, str, NULL, 0);
+- if (!t || !utf8len(t->value))
+- return 0;
+- avio_wb32(pb, 0); /* size */
+- ffio_wfourcc(pb, tag); /* type */
+- avio_wb32(pb, 0); /* version + flags */
+- if (!strcmp(tag, "yrrc"))
+- avio_wb16(pb, atoi(t->value));
+- else {
+- avio_wb16(pb, language_code("eng")); /* language */
+- avio_write(pb, t->value, strlen(t->value) + 1); /* UTF8 string value */
+- if (!strcmp(tag, "albm") &&
+- (t = av_dict_get(s->metadata, "track", NULL, 0)))
+- avio_w8(pb, atoi(t->value));
+- }
+- return update_size(pb, pos);
+-}
+-
+ static int mov_write_chpl_tag(AVIOContext *pb, AVFormatContext *s)
+ {
+ int64_t pos = avio_tell(pb);
+@@ -3747,14 +3749,14 @@ static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
+ return ret;
+
+ if (mov->mode & MODE_3GP) {
+- mov_write_3gp_udta_tag(pb_buf, s, "perf", "artist");
+- mov_write_3gp_udta_tag(pb_buf, s, "titl", "title");
+- mov_write_3gp_udta_tag(pb_buf, s, "auth", "author");
+- mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre");
+- mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment");
+- mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
+- mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
+- mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
++ mov_write_3gp_udta_tag(pb_buf, s->metadata, "perf", "artist");
++ mov_write_3gp_udta_tag(pb_buf, s->metadata, "titl", "title");
++ mov_write_3gp_udta_tag(pb_buf, s->metadata, "auth", "author");
++ mov_write_3gp_udta_tag(pb_buf, s->metadata, "gnre", "genre");
++ mov_write_3gp_udta_tag(pb_buf, s->metadata, "dscp", "comment");
++ mov_write_3gp_udta_tag(pb_buf, s->metadata, "albm", "album");
++ mov_write_3gp_udta_tag(pb_buf, s->metadata, "cprt", "copyright");
++ mov_write_3gp_udta_tag(pb_buf, s->metadata, "yrrc", "date");
+ mov_write_loci_tag(s, pb_buf);
+ } 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);
+--
+2.21.0
+
diff --git a/contrib/ffmpeg/A07-mov-read-3gpp-udta-tags.patch b/contrib/ffmpeg/A07-mov-read-3gpp-udta-tags.patch
new file mode 100644
index 000000000..6368c7180
--- /dev/null
+++ b/contrib/ffmpeg/A07-mov-read-3gpp-udta-tags.patch
@@ -0,0 +1,160 @@
+From 1b02b0afe201cd14a97d83dc08716bf9cc188cb0 Mon Sep 17 00:00:00 2001
+From: John Stebbins <[email protected]>
+Date: Sun, 4 Aug 2019 10:59:38 -0700
+Subject: [PATCH 3/3] mov: read 3gpp udta tags
+
+---
+ libavformat/mov.c | 110 ++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 107 insertions(+), 3 deletions(-)
+
+diff --git a/libavformat/mov.c b/libavformat/mov.c
+index 1f933cccfd..0c365cde3e 100644
+--- a/libavformat/mov.c
++++ b/libavformat/mov.c
+@@ -50,6 +50,7 @@
+ #include "libavcodec/flac.h"
+ #include "libavcodec/mpegaudiodecheader.h"
+ #include "avformat.h"
++#include "avlanguage.h"
+ #include "internal.h"
+ #include "avio_internal.h"
+ #include "riff.h"
+@@ -295,6 +296,82 @@ static int mov_metadata_hmmt(MOVContext *c, AVIOContext *pb, unsigned len)
+ return 0;
+ }
+
++static int mov_read_3gp_udta_tag(MOVContext *c, AVIOContext *pb, MOVAtom atom)
++{
++ const char *key;
++ AVDictionary *metadata;
++ uint16_t langcode = 0;
++ char key2[32], language[4] = {0};
++ uint32_t str_size, version;
++ char *str;
++
++ if (atom.size < 6)
++ return AVERROR_INVALIDDATA;
++
++ switch (atom.type) {
++ case MKTAG( 'a','l','b','m'): key = "album"; break;
++ case MKTAG( 'a','u','t','h'): key = "author"; break;
++ case MKTAG( 'c','p','r','t'): key = "copyright"; break;
++ case MKTAG( 'd','s','c','p'): key = "comment"; break;
++ case MKTAG( 'g','n','r','e'): key = "genre"; break;
++ case MKTAG( 'p','e','r','f'): key = "artist"; break;
++ case MKTAG( 't','i','t','l'): key = "title"; break;
++ case MKTAG( 'y','r','r','c'): key = "date"; break;
++ default: return 0;
++ }
++
++ version = avio_rb32(pb); // version + flags
++ if (version != 0)
++ return AVERROR_INVALIDDATA;
++
++ if (MKTAG( 'y','r','r','c') == atom.type) {
++ int year;
++ year = avio_rb16(pb);
++ str = av_asprintf("%d", year);
++ if (!str)
++ return AVERROR(ENOMEM);
++ } else {
++ int ret;
++ const char *tmp;
++ langcode = avio_rb16(pb);
++ ff_mov_lang_to_iso639(langcode, language);
++ tmp = ff_convert_lang_to(language, AV_LANG_ISO639_2_BIBL);
++ if (!tmp)
++ return AVERROR_INVALIDDATA;
++
++ str_size = atom.size - 6;
++ if (str_size <= 0 || str_size >= INT_MAX/2)
++ return AVERROR_INVALIDDATA;
++
++ str = av_mallocz(str_size + 1);
++ if (!str)
++ return AVERROR(ENOMEM);
++
++ ret = ffio_read_size(pb, str, str_size);
++ if (ret < 0) {
++ av_free(str);
++ return ret;
++ }
++ str[str_size] = 0;
++ }
++
++ if (c->trak_index < 0) {
++ metadata = c->fc->metadata;
++ c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
++ }
++ else {
++ metadata = c->fc->streams[c->trak_index]->metadata;
++ }
++ av_dict_set(&metadata, key, str, 0);
++ if (*language && strcmp(language, "und")) {
++ snprintf(key2, sizeof(key2), "%s-%s", key, language);
++ av_dict_set(&metadata, key2, str, 0);
++ }
++
++ av_freep(&str);
++ return 0;
++}
++
+ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+ {
+ char tmp_key[5];
+@@ -320,15 +397,33 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+ case MKTAG( 'c','a','t','g'): key = "category"; break;
+ case MKTAG( 'c','p','i','l'): key = "compilation";
+ parse = mov_metadata_int8_no_padding; break;
+- case MKTAG( 'c','p','r','t'): key = "copyright"; break;
++ case MKTAG( 'c','p','r','t'):
++ key = "copyright";
++ if (!c->itunes_metadata) {
++ int64_t pos = avio_tell(pb);
++ int ret = mov_read_3gp_udta_tag(c, pb, atom);
++ if (ret != AVERROR_INVALIDDATA)
++ return ret;
++ avio_seek(pb, pos, SEEK_SET);
++ }
++ break;
+ case MKTAG( 'd','e','s','c'): key = "description"; break;
+ case MKTAG( 'd','i','s','k'): key = "disc";
+ parse = mov_metadata_track_or_disc_number; break;
+ case MKTAG( 'e','g','i','d'): key = "episode_uid";
+ parse = mov_metadata_int8_no_padding; break;
+ case MKTAG( 'F','I','R','M'): key = "firmware"; raw = 1; break;
+- case MKTAG( 'g','n','r','e'): key = "genre";
+- parse = mov_metadata_gnre; break;
++ case MKTAG( 'g','n','r','e'):
++ key = "genre";
++ parse = mov_metadata_gnre;
++ if (!c->itunes_metadata) {
++ int64_t pos = avio_tell(pb);
++ int ret = mov_read_3gp_udta_tag(c, pb, atom);
++ if (ret != AVERROR_INVALIDDATA)
++ return ret;
++ avio_seek(pb, pos, SEEK_SET);
++ }
++ break;
+ case MKTAG( 'h','d','v','d'): key = "hd_video";
+ parse = mov_metadata_int8_no_padding; break;
+ case MKTAG( 'H','M','M','T'):
+@@ -399,6 +494,15 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+ case MKTAG(0xa9,'w','r','n'): key = "warning"; break;
+ case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
+ case MKTAG(0xa9,'x','y','z'): key = "location"; break;
++ case MKTAG( 'a','l','b','m'):
++ case MKTAG( 'a','u','t','h'):
++ case MKTAG( 'd','s','c','p'):
++ case MKTAG( 'p','e','r','f'):
++ case MKTAG( 't','i','t','l'):
++ case MKTAG( 'y','r','r','c'):
++ if (!c->itunes_metadata) {
++ return mov_read_3gp_udta_tag(c, pb, atom);
++ }
+ }
+ retry:
+ if (c->itunes_metadata && atom.size > 8) {
+--
+2.21.0
+