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, ×tamp_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