aboutsummaryrefslogtreecommitdiff
path: root/lib/ffmpeg/patches/0005-support-seeking-in-nuv-files.patch
blob: 0771ad654271181acc499bf197b6471a14144903 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
From 51d5bcf7d7504adec97841c93c88ebe4a9729cbf Mon Sep 17 00:00:00 2001
From: Cory Fields <theuni-nospam-@xbmc.org>
Date: Mon, 28 Jun 2010 01:36:50 -0400
Subject: [PATCH 05/32] support seeking in nuv files

---
 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.0