Add Ogg Skeleton 4 support to the ogg demuxer. For more info on OggIndex
and Ogg Skeleton see https://wiki.xiph.org/Ogg_Skeleton_4

Addressing Diego's comments.
If the vlc is in libav already it should be used of cause.

---
 libavformat/oggparseskeleton.c |   75
++++++++++++++++++++++++++++++++++++---
 1 files changed, 69 insertions(+), 6 deletions(-)


diff --git a/libavformat/oggparseskeleton.c b/libavformat/oggparseskeleton.c
index ceb7c69..a2a31ba 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,46 @@ 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