From e9dde141a5fc27df87eb4b3454e34d725b211708 Mon Sep 17 00:00:00 2001
From: John Stebbins <jstebbins@jetheaddev.com>
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

