[FFmpeg-devel] [PATCH] matroska: Add the CueDuration element

James Almer jamrial at gmail.com
Sat Sep 21 03:15:49 CEST 2013


Use it only on subtitle CuePoints.
With proper demuxer/splitter support this should improve the display
of subtitles right after seeking to a given point in the stream.

Signed-off-by: James Almer <jamrial at gmail.com>
---
 libavformat/matroska.h    |  1 +
 libavformat/matroskadec.c |  1 +
 libavformat/matroskaenc.c | 16 +++++++++++-----
 tests/ref/lavf/mkv        |  4 ++--
 4 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/libavformat/matroska.h b/libavformat/matroska.h
index 0c3dc29..3bb5aee 100644
--- a/libavformat/matroska.h
+++ b/libavformat/matroska.h
@@ -159,6 +159,7 @@
 #define MATROSKA_ID_CUETRACK   0xF7
 #define MATROSKA_ID_CUECLUSTERPOSITION 0xF1
 #define MATROSKA_ID_CUERELATIVEPOSITION 0xF0
+#define MATROSKA_ID_CUEDURATION 0xB2
 #define MATROSKA_ID_CUEBLOCKNUMBER 0x5378
 
 /* IDs in the tags master */
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 2482c6d..a1b7f56 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -476,6 +476,7 @@ static EbmlSyntax matroska_index_pos[] = {
     { MATROSKA_ID_CUETRACK,           EBML_UINT, 0, offsetof(MatroskaIndexPos,track) },
     { MATROSKA_ID_CUECLUSTERPOSITION, EBML_UINT, 0, offsetof(MatroskaIndexPos,pos)   },
     { MATROSKA_ID_CUERELATIVEPOSITION,EBML_NONE },
+    { MATROSKA_ID_CUEDURATION,        EBML_NONE },
     { MATROSKA_ID_CUEBLOCKNUMBER,     EBML_NONE },
     { 0 }
 };
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index c1e7f1f..b9848b6 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -70,6 +70,7 @@ typedef struct {
     int             tracknum;
     int64_t         cluster_pos;        ///< file offset of the cluster containing the block
     int64_t         relative_pos;       ///< relative offset from the position of the cluster containing the block
+    int64_t         duration;           ///< duration of the block according to time base
 } mkv_cuepoint;
 
 typedef struct {
@@ -119,9 +120,9 @@ typedef struct MatroskaMuxContext {
  * offset, 4 bytes for target EBML ID */
 #define MAX_SEEKENTRY_SIZE 21
 
-/** per-cuepoint-track - 4 1-byte EBML IDs, 4 1-byte EBML sizes, 3
+/** per-cuepoint-track - 5 1-byte EBML IDs, 5 1-byte EBML sizes, 4
  * 8-byte uint max */
-#define MAX_CUETRACKPOS_SIZE 32
+#define MAX_CUETRACKPOS_SIZE 42
 
 /** per-cuepoint - 2 1-byte EBML IDs, 2 1-byte EBML sizes, 8-byte uint max */
 #define MAX_CUEPOINT_SIZE(num_tracks) 12 + MAX_CUETRACKPOS_SIZE*num_tracks
@@ -381,7 +382,8 @@ static mkv_cues * mkv_start_cues(int64_t segment_offset)
     return cues;
 }
 
-static int mkv_add_cuepoint(mkv_cues *cues, int stream, int64_t ts, int64_t cluster_pos, int64_t relative_pos)
+static int mkv_add_cuepoint(mkv_cues *cues, int stream, int64_t ts, int64_t cluster_pos, int64_t relative_pos,
+                            int64_t duration)
 {
     mkv_cuepoint *entries = cues->entries;
 
@@ -396,7 +398,8 @@ static int mkv_add_cuepoint(mkv_cues *cues, int stream, int64_t ts, int64_t clus
     cues->entries[cues->num_entries].pts           = ts;
     cues->entries[cues->num_entries].tracknum      = stream + 1;
     cues->entries[cues->num_entries].cluster_pos   = cluster_pos - cues->segment_offset;
-    cues->entries[cues->num_entries++].relative_pos= relative_pos;
+    cues->entries[cues->num_entries].relative_pos  = relative_pos;
+    cues->entries[cues->num_entries++].duration    = duration;
 
     return 0;
 }
@@ -432,6 +435,8 @@ static int64_t mkv_write_cues(AVIOContext *pb, mkv_cues *cues, mkv_track *tracks
             put_ebml_uint(pb, MATROSKA_ID_CUETRACK           , entry[j].tracknum   );
             put_ebml_uint(pb, MATROSKA_ID_CUECLUSTERPOSITION , entry[j].cluster_pos);
             put_ebml_uint(pb, MATROSKA_ID_CUERELATIVEPOSITION, entry[j].relative_pos);
+            if (entry[j].duration != -1)
+                put_ebml_uint(pb, MATROSKA_ID_CUEDURATION    , entry[j].duration);
             end_ebml_master(pb, track_positions);
         }
         i += j - 1;
@@ -1521,7 +1526,8 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
     }
 
     if ((codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe) || codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
-        ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, ts, mkv->cluster_pos, relative_packet_pos);
+        ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, ts, mkv->cluster_pos, relative_packet_pos,
+                               codec->codec_type == AVMEDIA_TYPE_SUBTITLE ? duration : -1);
         if (ret < 0) return ret;
     }
 
diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv
index 72e20b7..51fd2e7 100644
--- a/tests/ref/lavf/mkv
+++ b/tests/ref/lavf/mkv
@@ -1,5 +1,5 @@
-9e68abfecce533f200d9409bf7a38122 *./tests/data/lavf/lavf.mkv
-472556 ./tests/data/lavf/lavf.mkv
+5e3e58192b11644477474a25bef2e022 *./tests/data/lavf/lavf.mkv
+472559 ./tests/data/lavf/lavf.mkv
 ./tests/data/lavf/lavf.mkv CRC=0xec6c3c68
 6aac0de39634046f23a3447b08380efe *./tests/data/lavf/lavf.mkv
 320288 ./tests/data/lavf/lavf.mkv
-- 
1.8.1.5



More information about the ffmpeg-devel mailing list