movenc: add track title to tracks
authorJohn Stebbins <stebbins@jetheaddev.com>
Thu, 31 Jul 2014 17:00:05 +0000 (10:00 -0700)
committerJohn Stebbins <stebbins@jetheaddev.com>
Wed, 6 Aug 2014 20:27:17 +0000 (13:27 -0700)
libavformat/movenc.c
libavformat/movenc.h

index a2d4739..c9b0f6e 100644 (file)
@@ -78,6 +78,17 @@ static const AVClass flavor ## _muxer_class = {\
     .version    = LIBAVUTIL_VERSION_INT,\
 };
 
+static int utf8len(const uint8_t *b)
+{
+    int len = 0;
+    int val;
+    while (*b) {
+        GET_UTF8(val, *b++, return -1;)
+        len++;
+    }
+    return len;
+}
+
 //FIXME support 64 bit variant with wide placeholders
 static int64_t update_size(AVIOContext *pb, int64_t pos)
 {
@@ -1353,6 +1364,15 @@ static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track)
                    "Unknown hldr_type for %s / 0x%04X, writing dummy values\n",
                    tag_buf, track->enc->codec_tag);
         }
+        if (track->st) {
+            // hdlr.name is used by some players to identify the content title
+            // of the track. So if an alternate handler description is
+            // specified, use it.
+            AVDictionaryEntry *t;
+            t = av_dict_get(track->st->metadata, "handler", NULL, 0);
+            if (t && utf8len(t->value))
+                descr = t->value;
+        }
     }
 
     avio_wb32(pb, 0); /* size */
@@ -1672,6 +1692,47 @@ static int mov_write_udta_sdp(AVIOContext *pb, MOVTrack *track)
     return len + 24;
 }
 
+static int mov_write_track_metadata(AVIOContext *pb, AVStream *st,
+                                    const char *tag, const char *str)
+{
+    int64_t pos = avio_tell(pb);
+    AVDictionaryEntry *t = av_dict_get(st->metadata, str, NULL, 0);
+    if (!t || !utf8len(t->value))
+        return 0;
+
+    avio_wb32(pb, 0);   /* size */
+    ffio_wfourcc(pb, tag); /* type */
+    avio_write(pb, t->value, strlen(t->value)); /* UTF8 string value */
+    return update_size(pb, pos);
+}
+
+static int mov_write_track_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
+                                    AVStream *st)
+{
+    AVIOContext *pb_buf;
+    int ret, size;
+    uint8_t *buf;
+
+    if (st == NULL || mov->fc->flags & AVFMT_FLAG_BITEXACT)
+        return 0;
+
+    ret = avio_open_dyn_buf(&pb_buf);
+    if (ret < 0)
+        return ret;
+
+    if (mov->mode & MODE_MP4)
+        mov_write_track_metadata(pb_buf, st, "name", "title");
+
+    if ((size = avio_close_dyn_buf(pb_buf, &buf)) > 0) {
+        avio_wb32(pb, size + 8);
+        ffio_wfourcc(pb, "udta");
+        avio_write(pb, buf, size);
+    }
+    av_free(buf);
+
+    return 0;
+}
+
 static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov,
                               MOVTrack *track, AVStream *st)
 {
@@ -1703,6 +1764,7 @@ static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov,
             mov_write_tapt_tag(pb, track);
         }
     }
+    mov_write_track_udta_tag(pb, mov, st);
     return update_size(pb, pos);
 }
 
@@ -1960,17 +2022,6 @@ static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
     return size;
 }
 
-static int utf8len(const uint8_t *b)
-{
-    int len = 0;
-    int val;
-    while (*b) {
-        GET_UTF8(val, *b++, return -1;)
-        len++;
-    }
-    return len;
-}
-
 static int ascii_to_wc(AVIOContext *pb, const uint8_t *b)
 {
     int val;
@@ -3308,6 +3359,8 @@ static int mov_write_header(AVFormatContext *s)
     AVDictionaryEntry *t;
     int i, hint_track = 0;
 
+    mov->fc = s;
+
     /* Default mode == MP4 */
     mov->mode = MODE_MP4;
 
index 0d3eb34..2f2c09c 100644 (file)
@@ -164,6 +164,7 @@ typedef struct MOVMuxContext {
     char *major_brand;
 
     int per_stream_grouping;
+    AVFormatContext *fc;
 } MOVMuxContext;
 
 #define FF_MOV_FLAG_RTP_HINT 1