Signed-off-by: Sasi Inguva <is...@google.com>
---
 libavformat/matroska.h       |  1 +
 libavformat/matroskadec.c    | 21 +++++++++++++-
 libavformat/matroskaenc.c    | 66 ++++++++++++++++++++++++++++++++++++++------
 tests/fate/wavpack.mak       |  4 +--
 tests/ref/acodec/tta         |  4 +--
 tests/ref/fate/binsub-mksenc |  2 +-
 tests/ref/lavf/mkv           |  8 +++---
 tests/ref/seek/lavf-mkv      | 44 ++++++++++++++---------------
 8 files changed, 109 insertions(+), 41 deletions(-)

diff --git a/libavformat/matroska.h b/libavformat/matroska.h
index 344b2c3..e44b001 100644
--- a/libavformat/matroska.h
+++ b/libavformat/matroska.h
@@ -167,6 +167,7 @@
 #define MATROSKA_ID_SIMPLETAG           0x67C8
 #define MATROSKA_ID_TAGNAME             0x45A3
 #define MATROSKA_ID_TAGSTRING           0x4487
+#define MATROSKA_ID_TAGBINARY           0x4485
 #define MATROSKA_ID_TAGLANG             0x447A
 #define MATROSKA_ID_TAGDEFAULT          0x4484
 #define MATROSKA_ID_TAGDEFAULT_BUG      0x44B4
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 1807cae..92698a1 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -221,6 +221,7 @@ typedef struct MatroskaIndex {
 typedef struct MatroskaTag {
     char *name;
     char *string;
+    EbmlBin binary;
     char *lang;
     uint64_t def;
     EbmlList sub;
@@ -528,6 +529,7 @@ static const EbmlSyntax matroska_index[] = {
 static const EbmlSyntax matroska_simpletag[] = {
     { MATROSKA_ID_TAGNAME,        EBML_UTF8, 0,                   
offsetof(MatroskaTag, name) },
     { MATROSKA_ID_TAGSTRING,      EBML_UTF8, 0,                   
offsetof(MatroskaTag, string) },
+    { MATROSKA_ID_TAGBINARY,      EBML_BIN,  0,                   
offsetof(MatroskaTag, binary) },
     { MATROSKA_ID_TAGLANG,        EBML_STR,  0,                   
offsetof(MatroskaTag, lang), { .s = "und" } },
     { MATROSKA_ID_TAGDEFAULT,     EBML_UINT, 0,                   
offsetof(MatroskaTag, def) },
     { MATROSKA_ID_TAGDEFAULT_BUG, EBML_UINT, 0,                   
offsetof(MatroskaTag, def) },
@@ -1375,10 +1377,16 @@ static void matroska_convert_tag(AVFormatContext *s, 
EbmlList *list,
             av_log(s, AV_LOG_WARNING, "Skipping invalid tag with no 
TagName.\n");
             continue;
         }
+
+        if (!tags[i].string) {
+            continue;
+        }
+
         if (prefix)
             snprintf(key, sizeof(key), "%s/%s", prefix, tags[i].name);
         else
             av_strlcpy(key, tags[i].name, sizeof(key));
+
         if (tags[i].def || !lang) {
             av_dict_set(metadata, key, tags[i].string, 0);
             if (tags[i].sub.nb_elem)
@@ -1419,9 +1427,20 @@ static void matroska_convert_tags(AVFormatContext *s)
         } else if (tags[i].target.trackuid) {
             MatroskaTrack *track = matroska->tracks.elem;
             for (j = 0; j < matroska->tracks.nb_elem; j++)
-                if (track[j].uid == tags[i].target.trackuid && track[j].stream)
+                if (track[j].uid == tags[i].target.trackuid && 
track[j].stream) {
+                    MatroskaTag *track_tags = tags[i].tag.elem;
+                    for (int ind = 0; ind < tags[i].tag.nb_elem; ++ind) {
+                        if (track_tags[ind].name &&
+                            !av_strcasecmp(track_tags[ind].name, "duration") &&
+                            track_tags[ind].binary.data &&
+                            track_tags[ind].binary.size == 8) {
+                            track[j].stream->duration = 
AV_RL64(track_tags[ind].binary.data);
+                        }
+                    }
+
                     matroska_convert_tag(s, &tags[i].tag,
                                          &track[j].stream->metadata, NULL);
+                }
         } else {
             matroska_convert_tag(s, &tags[i].tag, &s->metadata,
                                  tags[i].target.type);
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index 2d0d5f6..cb6e24d 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -131,6 +131,9 @@ typedef struct MatroskaMuxContext {
 
     int64_t last_track_timestamp[MAX_TRACKS];
 
+    int64_t* stream_durations;
+    int64_t* stream_duration_offsets;
+
     int allow_raw_vfw;
 } MatroskaMuxContext;
 
@@ -1117,9 +1120,11 @@ static int mkv_write_chapters(AVFormatContext *s)
     return 0;
 }
 
-static int mkv_write_simpletag(AVIOContext *pb, AVDictionaryEntry *t)
+static int mkv_write_simpletag(AVIOContext *pb,
+                               const char* tag_name, const void* data, int 
size,
+                               int write_as_string, int64_t* tag_offset)
 {
-    uint8_t *key = av_strdup(t->key);
+    uint8_t *key = av_strdup(tag_name);
     uint8_t *p   = key;
     const uint8_t *lang = NULL;
     ebml_master tag;
@@ -1144,19 +1149,23 @@ static int mkv_write_simpletag(AVIOContext *pb, 
AVDictionaryEntry *t)
     put_ebml_string(pb, MATROSKA_ID_TAGNAME, key);
     if (lang)
         put_ebml_string(pb, MATROSKA_ID_TAGLANG, lang);
-    put_ebml_string(pb, MATROSKA_ID_TAGSTRING, t->value);
+
+    if (tag_offset)
+        *tag_offset = avio_tell(pb);
+
+    put_ebml_binary(pb, write_as_string == 0 ? MATROSKA_ID_TAGBINARY : 
MATROSKA_ID_TAGSTRING, data, size);
     end_ebml_master(pb, tag);
 
     av_freep(&key);
     return 0;
 }
 
-static int mkv_write_tag(AVFormatContext *s, AVDictionary *m, unsigned int 
elementid,
-                         unsigned int uid, ebml_master *tags)
+static int mkv_write_tag_targets(AVFormatContext *s,
+                                 unsigned int elementid, unsigned int uid,
+                                 ebml_master *tags, ebml_master* tag)
 {
     MatroskaMuxContext *mkv = s->priv_data;
-    ebml_master tag, targets;
-    AVDictionaryEntry *t = NULL;
+    ebml_master targets;
     int ret;
 
     if (!tags->pos) {
@@ -1166,17 +1175,30 @@ static int mkv_write_tag(AVFormatContext *s, 
AVDictionary *m, unsigned int eleme
         *tags = start_ebml_master(s->pb, MATROSKA_ID_TAGS, 0);
     }
 
-    tag     = start_ebml_master(s->pb, MATROSKA_ID_TAG,        0);
+    *tag     = start_ebml_master(s->pb, MATROSKA_ID_TAG,        0);
     targets = start_ebml_master(s->pb, MATROSKA_ID_TAGTARGETS, 0);
     if (elementid)
         put_ebml_uint(s->pb, elementid, uid);
     end_ebml_master(s->pb, targets);
+    return 0;
+}
+
+static int mkv_write_tag(AVFormatContext *s, AVDictionary *m, unsigned int 
elementid,
+                         unsigned int uid, ebml_master *tags)
+{
+    ebml_master tag;
+    int ret;
+    AVDictionaryEntry *t = NULL;
+
+    ret = mkv_write_tag_targets(s, elementid, uid, tags, &tag);
+    if (ret < 0)
+        return ret;
 
     while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) {
         if (av_strcasecmp(t->key, "title") &&
             av_strcasecmp(t->key, "stereo_mode") &&
             av_strcasecmp(t->key, "encoding_tool")) {
-            ret = mkv_write_simpletag(s->pb, t);
+            ret = mkv_write_simpletag(s->pb, t->key, t->value, 
strlen(t->value), 1, NULL);
             if (ret < 0)
                 return ret;
         }
@@ -1220,6 +1242,18 @@ static int mkv_write_tags(AVFormatContext *s)
         if (ret < 0) return ret;
     }
 
+    mkv->stream_durations = av_mallocz(s->nb_streams * sizeof(int64_t));
+    mkv->stream_duration_offsets = av_mallocz(s->nb_streams * sizeof(int64_t));
+
+    for (i = 0; i < s->nb_streams; i++) {
+      ebml_master tag;
+      mkv_write_tag_targets(s, MATROSKA_ID_TAGTARGETS_TRACKUID, i + 1, &tags, 
&tag);
+      mkv_write_simpletag(s->pb, "duration",
+                          mkv->stream_durations + i, sizeof(int64_t),
+                          0, mkv->stream_duration_offsets + i);
+      end_ebml_master(s->pb, tag);
+    }
+
     for (i = 0; i < s->nb_chapters; i++) {
         AVChapter *ch = s->chapters[i];
 
@@ -1801,6 +1835,9 @@ static int mkv_write_packet_internal(AVFormatContext *s, 
AVPacket *pkt, int add_
     }
 
     mkv->duration = FFMAX(mkv->duration, ts + duration);
+    mkv->stream_durations[pkt->stream_index] =
+        FFMAX(mkv->stream_durations[pkt->stream_index], ts + duration);
+
     return 0;
 }
 
@@ -1978,6 +2015,15 @@ static int mkv_write_trailer(AVFormatContext *s)
         avio_seek(pb, mkv->duration_offset, SEEK_SET);
         put_ebml_float(pb, MATROSKA_ID_DURATION, mkv->duration);
 
+        // update stream durations
+        for (int i = 0; i < s->nb_streams; ++i) {
+            av_log(s, AV_LOG_DEBUG, "stream %d end duration = %" PRIu64 "\n", 
i,
+                   mkv->stream_durations[i]);
+            avio_seek(pb, mkv->stream_duration_offsets[i], SEEK_SET);
+            put_ebml_binary(pb, MATROSKA_ID_TAGBINARY, mkv->stream_durations + 
i,
+                            sizeof(int64_t));
+        }
+
         avio_seek(pb, currentpos, SEEK_SET);
     }
 
@@ -1987,6 +2033,8 @@ static int mkv_write_trailer(AVFormatContext *s)
     av_freep(&mkv->tracks);
     av_freep(&mkv->cues->entries);
     av_freep(&mkv->cues);
+    av_freep(&mkv->stream_durations);
+    av_freep(&mkv->stream_duration_offsets);
 
     return 0;
 }
diff --git a/tests/fate/wavpack.mak b/tests/fate/wavpack.mak
index 240f5ea..e3d0edd 100644
--- a/tests/fate/wavpack.mak
+++ b/tests/fate/wavpack.mak
@@ -91,12 +91,12 @@ fate-wavpack-matroskamode: CMD = md5 -i 
$(TARGET_SAMPLES)/wavpack/special/matros
 FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA) += fate-wavpack-matroska_mux-mono
 fate-wavpack-matroska_mux-mono: CMD = md5 -i 
$(TARGET_SAMPLES)/wavpack/num_channels/mono_16bit_int.wv -c copy -fflags 
+bitexact -f matroska
 fate-wavpack-matroska_mux-mono: CMP = oneline
-fate-wavpack-matroska_mux-mono: REF = a2987e2e51e01a35e47e7da13eb47a35
+fate-wavpack-matroska_mux-mono: REF = d0f5cbf0cfdc630ccf19fecd44034b06
 
 FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA) += fate-wavpack-matroska_mux-61
 fate-wavpack-matroska_mux-61: CMD = md5 -i 
$(TARGET_SAMPLES)/wavpack/num_channels/eva_2.22_6.1_16bit-partial.wv -c copy 
-fflags +bitexact -f matroska
 fate-wavpack-matroska_mux-61: CMP = oneline
-fate-wavpack-matroska_mux-61: REF = ffba4ddea1ba71f7a5901d9ed1a267be
+fate-wavpack-matroska_mux-61: REF = 3c6252a863b5cc713c62721c60767367
 
 FATE_SAMPLES_AVCONV += $(FATE_WAVPACK-yes)
 fate-wavpack: $(FATE_WAVPACK-yes)
diff --git a/tests/ref/acodec/tta b/tests/ref/acodec/tta
index b4b9611..ccef17b 100644
--- a/tests/ref/acodec/tta
+++ b/tests/ref/acodec/tta
@@ -1,4 +1,4 @@
-aeeb0f2e75d044dbe2f89b7e70a54c82 *tests/data/fate/acodec-tta.matroska
-331080 tests/data/fate/acodec-tta.matroska
+e271e3ce535ac8c9cb89c9af42e349b8 *tests/data/fate/acodec-tta.matroska
+331136 tests/data/fate/acodec-tta.matroska
 95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-tta.out.wav
 stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  1058400/  1058400
diff --git a/tests/ref/fate/binsub-mksenc b/tests/ref/fate/binsub-mksenc
index c473497..c28580a 100644
--- a/tests/ref/fate/binsub-mksenc
+++ b/tests/ref/fate/binsub-mksenc
@@ -1 +1 @@
-2dad5f63688ec613a04e94c8d4d167db
+e68ea99e034876b82ac957b1a7e30c90
diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv
index edbfe60..46b378a 100644
--- a/tests/ref/lavf/mkv
+++ b/tests/ref/lavf/mkv
@@ -1,6 +1,6 @@
-bab98f5a04a9f7991fb960041c996478 *./tests/data/lavf/lavf.mkv
-472668 ./tests/data/lavf/lavf.mkv
+5200b77dabf4513e028358fe3783d2b1 *./tests/data/lavf/lavf.mkv
+472836 ./tests/data/lavf/lavf.mkv
 ./tests/data/lavf/lavf.mkv CRC=0xec6c3c68
-c93950920d4ee57eb3ff5ba0cf0c8b19 *./tests/data/lavf/lavf.mkv
-320412 ./tests/data/lavf/lavf.mkv
+bb7f2d72e3d455a7ab66315804e599ac *./tests/data/lavf/lavf.mkv
+320524 ./tests/data/lavf/lavf.mkv
 ./tests/data/lavf/lavf.mkv CRC=0xec6c3c68
diff --git a/tests/ref/seek/lavf-mkv b/tests/ref/seek/lavf-mkv
index 11275d6..ed0a2c2 100644
--- a/tests/ref/seek/lavf-mkv
+++ b/tests/ref/seek/lavf-mkv
@@ -1,48 +1,48 @@
-ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    661 size:   
208
+ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    773 size:   
208
 ret: 0         st:-1 flags:0  ts:-1.000000
-ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    877 size: 
27837
+ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    989 size: 
27837
 ret: 0         st:-1 flags:1  ts: 1.894167
-ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291 size: 
27834
+ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292403 size: 
27834
 ret: 0         st: 0 flags:0  ts: 0.788000
-ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291 size: 
27834
+ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292403 size: 
27834
 ret: 0         st: 0 flags:1  ts:-0.317000
-ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    877 size: 
27837
+ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    989 size: 
27837
 ret:-1         st: 1 flags:0  ts: 2.577000
 ret: 0         st: 1 flags:1  ts: 1.471000
-ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320132 size:   
209
+ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320244 size:   
209
 ret: 0         st:-1 flags:0  ts: 0.365002
-ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146844 size: 
27925
+ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146956 size: 
27925
 ret: 0         st:-1 flags:1  ts:-0.740831
-ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    877 size: 
27837
+ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    989 size: 
27837
 ret:-1         st: 0 flags:0  ts: 2.153000
 ret: 0         st: 0 flags:1  ts: 1.048000
-ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291 size: 
27834
+ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292403 size: 
27834
 ret: 0         st: 1 flags:0  ts:-0.058000
-ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    661 size:   
208
+ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    773 size:   
208
 ret: 0         st: 1 flags:1  ts: 2.836000
-ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320132 size:   
209
+ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320244 size:   
209
 ret:-1         st:-1 flags:0  ts: 1.730004
 ret: 0         st:-1 flags:1  ts: 0.624171
-ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146844 size: 
27925
+ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146956 size: 
27925
 ret: 0         st: 0 flags:0  ts:-0.482000
-ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    877 size: 
27837
+ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    989 size: 
27837
 ret: 0         st: 0 flags:1  ts: 2.413000
-ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291 size: 
27834
+ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292403 size: 
27834
 ret:-1         st: 1 flags:0  ts: 1.307000
 ret: 0         st: 1 flags:1  ts: 0.201000
-ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    661 size:   
208
+ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    773 size:   
208
 ret: 0         st:-1 flags:0  ts:-0.904994
-ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    877 size: 
27837
+ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    989 size: 
27837
 ret: 0         st:-1 flags:1  ts: 1.989173
-ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291 size: 
27834
+ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292403 size: 
27834
 ret: 0         st: 0 flags:0  ts: 0.883000
-ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292291 size: 
27834
+ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292403 size: 
27834
 ret: 0         st: 0 flags:1  ts:-0.222000
-ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    877 size: 
27837
+ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    989 size: 
27837
 ret:-1         st: 1 flags:0  ts: 2.672000
 ret: 0         st: 1 flags:1  ts: 1.566000
-ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320132 size:   
209
+ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320244 size:   
209
 ret: 0         st:-1 flags:0  ts: 0.460008
-ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146844 size: 
27925
+ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146956 size: 
27925
 ret: 0         st:-1 flags:1  ts:-0.645825
-ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    877 size: 
27837
+ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:    989 size: 
27837
-- 
2.5.0.rc2.392.g76e840b

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to