[FFmpeg-devel] [PATCH] matroskaenc: implement CueRelativePosition

Bernie Habermeier bernt at wulfram.com
Tue Jul 23 09:52:08 CEST 2013


This is a minimal change to matroskaenc that implements CueRelativePosition in the output.  Most players will probably ignore this additional information, but it is in the matroska spec, and it'd be nice to be able to make use of it.

Signed-off-by: Bernt Habermeier <bernt at wulfram.com>
---
 libavformat/matroska.h    |  1 +
 libavformat/matroskaenc.c | 20 +++++++++++++-------
 tests/ref/lavf/mkv        |  8 ++++----
 3 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/libavformat/matroska.h b/libavformat/matroska.h
index 886a346..2eb2fe6 100644
--- a/libavformat/matroska.h
+++ b/libavformat/matroska.h
@@ -156,6 +156,7 @@
 /* IDs in the cuetrackposition master */
 #define MATROSKA_ID_CUETRACK   0xF7
 #define MATROSKA_ID_CUECLUSTERPOSITION 0xF1
+#define MATROSKA_ID_CUERELATIVEPOSITION 0xF0
 #define MATROSKA_ID_CUEBLOCKNUMBER 0x5378
 
 /* IDs in the tags master */
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index 8078cc7..fb0fff8 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -67,6 +67,7 @@ typedef struct {
     uint64_t        pts;
     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
 } mkv_cuepoint;
 
 typedef struct {
@@ -113,9 +114,9 @@ typedef struct MatroskaMuxContext {
  * offset, 4 bytes for target EBML ID */
 #define MAX_SEEKENTRY_SIZE 21
 
-/** per-cuepoint-track - 3 1-byte EBML IDs, 3 1-byte EBML sizes, 2
+/** per-cuepoint-track - 4 1-byte EBML IDs, 4 1-byte EBML sizes, 3
  * 8-byte uint max */
-#define MAX_CUETRACKPOS_SIZE 22
+#define MAX_CUETRACKPOS_SIZE 32
 
 /** 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
@@ -372,7 +373,7 @@ 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)
+static int mkv_add_cuepoint(mkv_cues *cues, int stream, int64_t ts, int64_t cluster_pos, int64_t relative_pos)
 {
     mkv_cuepoint *entries = cues->entries;
 
@@ -385,7 +386,8 @@ static int mkv_add_cuepoint(mkv_cues *cues, int stream, int64_t ts, int64_t clus
 
     entries[cues->num_entries  ].pts = ts;
     entries[cues->num_entries  ].tracknum = stream + 1;
-    entries[cues->num_entries++].cluster_pos = cluster_pos - cues->segment_offset;
+    entries[cues->num_entries  ].cluster_pos = cluster_pos - cues->segment_offset;
+    entries[cues->num_entries++].relative_pos = relative_pos;
 
     cues->entries = entries;
     return 0;
@@ -419,8 +421,9 @@ static int64_t mkv_write_cues(AVIOContext *pb, mkv_cues *cues, mkv_track *tracks
                 continue;
             tracks[tracknum].has_cue = 1;
             track_positions = start_ebml_master(pb, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE);
-            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_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);
             end_ebml_master(pb, track_positions);
         }
         i += j - 1;
@@ -1414,6 +1417,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
     int duration = pkt->duration;
     int ret;
     int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts;
+    int64_t relative_packet_pos;
 
     if (ts == AV_NOPTS_VALUE) {
         av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n");
@@ -1437,6 +1441,8 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
         mkv->cluster_pts = FFMAX(0, ts);
     }
 
+    relative_packet_pos = avio_tell(s->pb) - mkv->cluster.pos;
+
     if (codec->codec_type != AVMEDIA_TYPE_SUBTITLE) {
         mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7);
 #if FF_API_ASS_SSA
@@ -1459,7 +1465,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
     }
 
     if (codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe) {
-        ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, ts, mkv->cluster_pos);
+         ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, ts, mkv->cluster_pos, relative_packet_pos);
         if (ret < 0) return ret;
     }
 
diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv
index be474a4..20e8e1c 100644
--- a/tests/ref/lavf/mkv
+++ b/tests/ref/lavf/mkv
@@ -1,6 +1,6 @@
-1748c0b3221977509c62a158236d2492 *./tests/data/lavf/lavf.mkv
-472533 ./tests/data/lavf/lavf.mkv
+b9557a7fa418db7692587b45d20f0d76 *./tests/data/lavf/lavf.mkv
+472542 ./tests/data/lavf/lavf.mkv
 ./tests/data/lavf/lavf.mkv CRC=0x4780846b
-0f78dd9299210a51b18faafc971e71f2 *./tests/data/lavf/lavf.mkv
-320265 ./tests/data/lavf/lavf.mkv
+fd214bc74f0a21dfb36dcf9bb5777b86 *./tests/data/lavf/lavf.mkv
+320274 ./tests/data/lavf/lavf.mkv
 ./tests/data/lavf/lavf.mkv CRC=0x4780846b
-- 
1.8.1.2


More information about the ffmpeg-devel mailing list