Attached patch adds Ogg Skeleton 4 support to the ogg demuxer.
For more info on OggIndex and Ogg Skeleton see
https://wiki.xiph.org/Ogg_Skeleton_4
diff --git a/libavformat/oggparseskeleton.c b/libavformat/oggparseskeleton.c
index e318e9e..6d4c8e0 100644
--- a/libavformat/oggparseskeleton.c
+++ b/libavformat/oggparseskeleton.c
@@ -22,15 +22,38 @@
 #include "avformat.h"
 #include "oggdec.h"
 
+static int skeleton_read_vlc (uint8_t ** data, int * size, int64_t * result)
+{
+  int shift = 0;
+  uint8_t byte;
+
+  *result = 0;
+
+  do {
+    if (*size < 1)
+      return 0;
+
+    byte = **data;
+    *result |= ((byte & 0x7f) << shift);
+    shift += 7;
+
+    (*data)++;
+    (*size)--;
+  } while ((byte & 0x80) != 0x80);
+
+  return 1;
+}
+
 static int skeleton_header(AVFormatContext *s, int idx)
 {
     struct ogg *ogg = s->priv_data;
     struct ogg_stream *os = ogg->streams + idx;
-    AVStream *st = s->streams[idx];
-    uint8_t *buf = os->buf + os->pstart;
-    int version_major, version_minor;
-    int64_t start_num, start_den, start_granule;
-    int target_idx, start_time;
+    AVStream *st = s->streams[idx], *target;
+    uint8_t *buf = os->buf + os->pstart, *p;
+    int version_major, version_minor, n_keypoints;
+    int64_t start_num, start_den, start_granule, end_num;
+    int64_t pts, offset, offset_d, timestamp, timestamp_d;
+    int target_idx, start_time, size, i;
 
     strcpy(st->codec->codec_name, "skeleton");
     st->codec->codec_type = AVMEDIA_TYPE_DATA;
@@ -45,7 +68,7 @@ static int skeleton_header(AVFormatContext *s, int idx)
         version_major = AV_RL16(buf+8);
         version_minor = AV_RL16(buf+10);
 
-        if (version_major != 3) {
+        if (version_major != 3 && version_major != 4) {
             av_log(s, AV_LOG_WARNING, "Unknown skeleton version %d.%d\n",
                    version_major, version_minor);
             return -1;
@@ -66,6 +89,53 @@ static int skeleton_header(AVFormatContext *s, int idx)
             os->lastpts =
             st->start_time = start_time;
         }
+    } else if (!strncmp(buf, "index", 6)) {
+        if (os->psize < 42)
+            return -1;
+
+        target_idx = ogg_find_stream(ogg, AV_RL32(buf+6));
+        n_keypoints = AV_RL16(buf+10);
+
+        start_den = AV_RL64(buf+18);
+        start_num = AV_RL64(buf+26);
+        end_num = AV_RL64(buf+34);
+        target = s->streams[target_idx];
+
+        av_log(s, AV_LOG_DEBUG,
+           "stream: %d start: %"PRId64" end: %"PRId64" timebase: %d/%d\n",
+               target_idx,
+               target->time_base.den * start_num / start_den / target->time_base.num,
+               target->time_base.den * end_num / start_den / target->time_base.num,
+               target->time_base.num, target->time_base.den);
+        st->duration = AV_TIME_BASE * (end_num-start_num) / start_den;
+        if (st->duration > s->duration)
+            s->duration = st->duration;
+
+        //read index
+        p = buf + 42;
+        size = os->psize - 42;
+        offset = 0;
+        timestamp = 0;
+        for (i = 0; i < n_keypoints; i++) {
+            /* read deltas */
+            if (!skeleton_read_vlc (&p, &size, &offset_d))
+              break;
+            if (!skeleton_read_vlc (&p, &size, &timestamp_d))
+              break;
+
+            offset += offset_d;
+            timestamp += timestamp_d;
+            pts = target->time_base.den * timestamp / start_den / target->time_base.num;
+            av_log(s, AV_LOG_DEBUG, "index offset %"PRId64",\t pts %"PRId64"\n", offset, pts);
+
+            av_add_index_entry(
+                s->streams[target_idx],
+                offset,
+                pts,
+                0,
+                0,
+                AVINDEX_KEYFRAME);
+        }
     } else if (!strncmp(buf, "fisbone", 8)) {
         if (os->psize < 52)
             return -1;
_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to