[FFmpeg-devel] [PATCH 05/28] support seeking in nuv files
Mans Rullgard
mans
Wed Jun 30 11:09:33 CEST 2010
From: Cory Fields <theuni-nospam- at xbmc.org>
---
libavformat/nuv.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 84 insertions(+), 0 deletions(-)
diff --git a/libavformat/nuv.c b/libavformat/nuv.c
index f0eacd5..2aa0bb4 100644
--- a/libavformat/nuv.c
+++ b/libavformat/nuv.c
@@ -218,12 +218,18 @@ static int nuv_packet(AVFormatContext *s, AVPacket *pkt) {
ret = av_new_packet(pkt, copyhdrsize + size);
if (ret < 0)
return ret;
+
// HACK: we have no idea if it is a keyframe,
// but if we mark none seeking will not work at all.
pkt->flags |= AV_PKT_FLAG_KEY;
pkt->pos = pos;
pkt->pts = AV_RL32(&hdr[4]);
pkt->stream_index = ctx->v_id;
+ if(hdr[2] == 0) {
+ AVStream *st = s->streams[pkt->stream_index];
+ pkt->flags |= PKT_FLAG_KEY;
+ av_add_index_entry(st, pkt->pos, pkt->pts, size + HDRSIZE, 0, AVINDEX_KEYFRAME);
+ }
memcpy(pkt->data, hdr, copyhdrsize);
ret = get_buffer(pb, pkt->data + copyhdrsize, size);
if (ret < 0) {
@@ -257,6 +263,83 @@ static int nuv_packet(AVFormatContext *s, AVPacket *pkt) {
return AVERROR(EIO);
}
+/**
+ * \brief looks for the string RTjjjjjjjjjj in the stream too resync reading
+ * \return TRUE if the syncword is found.
+ */
+static int nuv_resync(AVFormatContext *s, int64_t pos_limit) {
+ ByteIOContext *pb = s->pb;
+ uint32_t tag;
+
+ tag = get_be32(pb);
+ while(!url_feof(pb) && url_ftell(pb) < pos_limit) {
+ if(tag != MKBETAG('R','T','j','j')) {
+ tag = (tag << 8) | get_byte(pb);
+ continue;
+ }
+ tag = get_be32(pb);
+ if(tag != MKBETAG('j','j','j','j'))
+ continue;
+
+ tag = get_be32(pb);
+ if(tag != MKBETAG('j','j','j','j'))
+ continue;
+
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * \brief attempts to read a timestamp from stream at the given stream position
+ * \return timestamp if successfull and AV_NOPTS_VALUE if failure
+ */
+static int64_t nuv_read_dts(AVFormatContext *s, int stream_index,
+ int64_t *ppos, int64_t pos_limit)
+{
+ NUVContext *ctx = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ uint8_t hdr[HDRSIZE];
+ nuv_frametype frametype;
+ int size;
+ int64_t pos, dts;
+
+ if (url_fseek(pb, *ppos, SEEK_SET) < 0)
+ return AV_NOPTS_VALUE;
+
+ if (!nuv_resync(s, pos_limit))
+ return AV_NOPTS_VALUE;
+
+ while (!url_feof(pb) && url_ftell(pb) < pos_limit) {
+ if (get_buffer(pb, hdr, HDRSIZE) <= 0)
+ return AV_NOPTS_VALUE;
+ frametype = hdr[0];
+ size = PKTSIZE(AV_RL32(&hdr[8]));
+ switch (frametype) {
+ case NUV_SEEKP:
+ break;
+ case NUV_AUDIO:
+ case NUV_VIDEO:
+ pos = url_ftell(s->pb) - HDRSIZE;
+ dts = AV_RL32(&hdr[4]);
+ // TODO - add general support in av_gen_search, so it adds positions after reading timestamps
+ av_add_index_entry(s->streams[frametype == NUV_VIDEO ? ctx->v_id : ctx->a_id]
+ , pos, dts, size + HDRSIZE, 0, hdr[2] == 0 ? AVINDEX_KEYFRAME : 0);
+
+ if ((frametype == NUV_VIDEO && stream_index == ctx->v_id) ||
+ (frametype == NUV_AUDIO && stream_index == ctx->a_id)) {
+ *ppos = pos;
+ return dts;
+ }
+ default:
+ url_fskip(pb, size);
+ break;
+ }
+ }
+ return AV_NOPTS_VALUE;
+}
+
+
AVInputFormat nuv_demuxer = {
"nuv",
NULL_IF_CONFIG_SMALL("NuppelVideo format"),
@@ -266,5 +349,6 @@ AVInputFormat nuv_demuxer = {
nuv_packet,
NULL,
NULL,
+ nuv_read_dts,
.flags = AVFMT_GENERIC_INDEX,
};
--
1.7.1.1
More information about the ffmpeg-devel
mailing list