Browse code

rtpdec: experimental VP9 depacketizer (draft 0)

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Thomas Volkert authored on 2015/02/15 22:46:42
Showing 6 changed files
... ...
@@ -26,6 +26,7 @@ version <next>:
26 26
 - RTP parser for loss tolerant payload format for MP3 audio (RFC 5219)
27 27
 - RTP parser for AC3 payload format (RFC 4184)
28 28
 - palettegen and paletteuse filters
29
+- VP9 RTP payload format (draft 0) experimental depacketizer
29 30
 
30 31
 
31 32
 version 2.5:
... ...
@@ -469,6 +469,7 @@ Muxers/Demuxers:
469 469
   rtpdec_h261.*, rtpenc_h261.*          Thomas Volkert
470 470
   rtpdec_hevc.*, rtpenc_hevc.*          Thomas Volkert
471 471
   rtpdec_asf.*                          Ronald S. Bultje
472
+  rtpdec_vp9.c                          Thomas Volkert
472 473
   rtpenc_mpv.*, rtpenc_aac.*            Martin Storsjo
473 474
   rtsp.c                                Luca Barbato
474 475
   sbgdec.c                              Nicolas George
... ...
@@ -49,6 +49,7 @@ OBJS-$(CONFIG_RTPDEC)                    += rdt.o                       \
49 49
                                             rtpdec_qt.o                 \
50 50
                                             rtpdec_svq3.o               \
51 51
                                             rtpdec_vp8.o                \
52
+                                            rtpdec_vp9.o                \
52 53
                                             rtpdec_xiph.o               \
53 54
                                             srtp.o
54 55
 OBJS-$(CONFIG_RTPENC_CHAIN)              += rtpenc_chain.o rtp.o
... ...
@@ -107,6 +107,7 @@ void ff_register_rtp_dynamic_payload_handlers(void)
107 107
     ff_register_dynamic_payload_handler(&ff_theora_dynamic_handler);
108 108
     ff_register_dynamic_payload_handler(&ff_vorbis_dynamic_handler);
109 109
     ff_register_dynamic_payload_handler(&ff_vp8_dynamic_handler);
110
+    ff_register_dynamic_payload_handler(&ff_vp9_dynamic_handler);
110 111
     ff_register_dynamic_payload_handler(&gsm_dynamic_handler);
111 112
     ff_register_dynamic_payload_handler(&opus_dynamic_handler);
112 113
     ff_register_dynamic_payload_handler(&realmedia_mp3_dynamic_handler);
... ...
@@ -69,5 +69,6 @@ extern RTPDynamicProtocolHandler ff_svq3_dynamic_handler;
69 69
 extern RTPDynamicProtocolHandler ff_theora_dynamic_handler;
70 70
 extern RTPDynamicProtocolHandler ff_vorbis_dynamic_handler;
71 71
 extern RTPDynamicProtocolHandler ff_vp8_dynamic_handler;
72
+extern RTPDynamicProtocolHandler ff_vp9_dynamic_handler;
72 73
 
73 74
 #endif /* AVFORMAT_RTPDEC_FORMATS_H */
74 75
new file mode 100644
... ...
@@ -0,0 +1,317 @@
0
+/*
1
+ * RTP parser for VP9 payload format (draft version 0) - experimental
2
+ * Copyright (c) 2015 Thomas Volkert <thomas@homer-conferencing.com>
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#include "libavcodec/bytestream.h"
23
+
24
+#include "rtpdec_formats.h"
25
+
26
+#define RTP_VP9_DESC_REQUIRED_SIZE 1
27
+
28
+struct PayloadContext {
29
+    AVIOContext *buf;
30
+    uint32_t     timestamp;
31
+};
32
+
33
+static av_cold PayloadContext *vp9_new_context(void)
34
+{
35
+    return av_mallocz(sizeof(PayloadContext));
36
+}
37
+
38
+static void vp9_free_dyn_buffer(AVIOContext **dyn_buf)
39
+{
40
+    uint8_t *ptr_dyn_buffer;
41
+    avio_close_dyn_buf(*dyn_buf, &ptr_dyn_buffer);
42
+    av_free(ptr_dyn_buffer);
43
+    *dyn_buf = NULL;
44
+}
45
+
46
+static av_cold void vp9_free_context(PayloadContext *data)
47
+{
48
+    av_free(data);
49
+}
50
+
51
+static av_cold int vp9_init(AVFormatContext *ctx, int st_index,
52
+                             PayloadContext *data)
53
+{
54
+    av_dlog(ctx, "vp9_init() for stream %d\n", st_index);
55
+    av_log(ctx, AV_LOG_WARNING,
56
+           "RTP/VP9 support is still experimental\n");
57
+
58
+    if (st_index < 0)
59
+        return 0;
60
+
61
+    ctx->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL;
62
+
63
+    return 0;
64
+}
65
+
66
+static int vp9_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_vp9_ctx,
67
+                             AVStream *st, AVPacket *pkt, uint32_t *timestamp,
68
+                             const uint8_t *buf, int len, uint16_t seq,
69
+                             int flags)
70
+{
71
+    int has_pic_id, has_layer_idc, has_ref_idc, has_ss_data, has_su_data;
72
+    av_unused int pic_id = 0, non_key_frame = 0;
73
+    av_unused int layer_temporal = -1, layer_spatial = -1, layer_quality = -1;
74
+    int ref_fields = 0, has_ref_field_ext_pic_id = 0;
75
+    int first_fragment, last_fragment;
76
+    int res = 0;
77
+
78
+    /* drop data of previous packets in case of non-continuous (lossy) packet stream */
79
+    if (rtp_vp9_ctx->buf && rtp_vp9_ctx->timestamp != *timestamp) {
80
+        vp9_free_dyn_buffer(&rtp_vp9_ctx->buf);
81
+    }
82
+
83
+    /* sanity check for size of input packet: 1 byte payload at least */
84
+    if (len < RTP_VP9_DESC_REQUIRED_SIZE + 1) {
85
+        av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet, got %d bytes\n", len);
86
+        return AVERROR_INVALIDDATA;
87
+    }
88
+
89
+    /*
90
+      decode the required VP9 payload descriptor according to section 4.2 of the spec.:
91
+
92
+            0 1 2 3 4 5 6 7
93
+           +-+-+-+-+-+-+-+-+
94
+           |I|L|F|B|E|V|U|-| (REQUIRED)
95
+           +-+-+-+-+-+-+-+-+
96
+
97
+           I: PictureID present
98
+           L: Layer indices present
99
+           F: Reference indices present
100
+           B: Start of VP9 frame
101
+           E: End of picture
102
+           V: Scalability Structure (SS) present
103
+           U: Scalability Structure Update (SU) present
104
+    */
105
+    has_pic_id     = buf[0] & 0x80;
106
+    has_layer_idc  = buf[0] & 0x40;
107
+    has_ref_idc    = buf[0] & 0x20;
108
+    first_fragment = buf[0] & 0x10;
109
+    last_fragment  = buf[0] & 0x08;
110
+    has_ss_data    = buf[0] & 0x04;
111
+    has_su_data    = buf[0] & 0x02;
112
+
113
+    /* sanity check for markers: B should always be equal to the RTP M marker */
114
+    if (last_fragment >> 2 != flags & RTP_FLAG_MARKER) {
115
+        av_log(ctx, AV_LOG_ERROR, "Invalid combination of B and M marker\n");
116
+        return AVERROR_INVALIDDATA;
117
+    }
118
+
119
+    /* pass the extensions field */
120
+    buf += RTP_VP9_DESC_REQUIRED_SIZE;
121
+    len -= RTP_VP9_DESC_REQUIRED_SIZE;
122
+
123
+    /*
124
+      decode the 1-byte/2-byte picture ID:
125
+
126
+            0 1 2 3 4 5 6 7
127
+           +-+-+-+-+-+-+-+-+
128
+   I:      |M|PICTURE ID   | (RECOMMENDED)
129
+           +-+-+-+-+-+-+-+-+
130
+   M:      | EXTENDED PID  | (RECOMMENDED)
131
+           +-+-+-+-+-+-+-+-+
132
+
133
+           M: The most significant bit of the first octet is an extension flag.
134
+           PictureID:  8 or 16 bits including the M bit.
135
+     */
136
+    if (has_pic_id) {
137
+        if (len < 1) {
138
+            av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
139
+            return AVERROR_INVALIDDATA;
140
+        }
141
+
142
+        /* check for 1-byte or 2-byte picture index */
143
+        if (buf[0] & 0x80) {
144
+            if (len < 2) {
145
+                av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
146
+                return AVERROR_INVALIDDATA;
147
+            }
148
+            pic_id = AV_RB16(buf) & 0x7fff;
149
+            buf += 2;
150
+            len -= 2;
151
+        } else {
152
+            pic_id = buf[0] & 0x7f;
153
+            buf++;
154
+            len--;
155
+        }
156
+    }
157
+
158
+    /*
159
+      decode layer indices
160
+
161
+            0 1 2 3 4 5 6 7
162
+           +-+-+-+-+-+-+-+-+
163
+   L:      | T | S | Q | R | (CONDITIONALLY RECOMMENDED)
164
+           +-+-+-+-+-+-+-+-+
165
+
166
+           T, S and Q are 2-bit indices for temporal, spatial, and quality layers.
167
+           If "F" is set in the initial octet, R is 2 bits representing the number
168
+           of reference fields this frame refers to.
169
+     */
170
+    if (has_layer_idc) {
171
+        if (len < 1) {
172
+            av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet");
173
+            return AVERROR_INVALIDDATA;
174
+        }
175
+        layer_temporal = buf[0] & 0xC0;
176
+        layer_spatial  = buf[0] & 0x30;
177
+        layer_quality  = buf[0] & 0x0C;
178
+        if (has_ref_idc) {
179
+            ref_fields = buf[0] & 0x03;
180
+            if (ref_fields)
181
+                non_key_frame = 1;
182
+        }
183
+        buf++;
184
+        len--;
185
+    }
186
+
187
+    /*
188
+      decode the reference fields
189
+
190
+            0 1 2 3 4 5 6 7
191
+           +-+-+-+-+-+-+-+-+              -\
192
+   F:      | PID |X| RS| RQ| (OPTIONAL)    .
193
+           +-+-+-+-+-+-+-+-+               . - R times
194
+   X:      | EXTENDED PID  | (OPTIONAL)    .
195
+           +-+-+-+-+-+-+-+-+              -/
196
+
197
+           PID:  The relative Picture ID referred to by this frame.
198
+           RS and RQ:  The spatial and quality layer IDs.
199
+           X: 1 if this layer index has an extended relative Picture ID.
200
+     */
201
+    if (has_ref_idc) {
202
+        while (ref_fields) {
203
+            if (len < 1) {
204
+                av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
205
+                return AVERROR_INVALIDDATA;
206
+            }
207
+
208
+            has_ref_field_ext_pic_id = buf[0] & 0x10;
209
+
210
+            /* pass ref. field */
211
+            if (has_ref_field_ext_pic_id) {
212
+                if (len < 2) {
213
+                    av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
214
+                    return AVERROR_INVALIDDATA;
215
+                }
216
+
217
+                /* ignore ref. data */
218
+
219
+                buf += 2;
220
+                len -= 2;
221
+            } else {
222
+
223
+                /* ignore ref. data */
224
+
225
+                buf++;
226
+                len--;
227
+            }
228
+            ref_fields--;
229
+        }
230
+    }
231
+
232
+    /*
233
+      decode the scalability structure (SS)
234
+
235
+            0 1 2 3 4 5 6 7
236
+           +-+-+-+-+-+-+-+-+
237
+      V:   | PATTERN LENGTH|
238
+           +-+-+-+-+-+-+-+-+                           -\
239
+           | T | S | Q | R | (OPTIONAL)                 .
240
+           +-+-+-+-+-+-+-+-+              -\            .
241
+           | PID |X| RS| RQ| (OPTIONAL)    .            . - PAT. LEN. times
242
+           +-+-+-+-+-+-+-+-+               . - R times  .
243
+      X:   | EXTENDED PID  | (OPTIONAL)    .            .
244
+           +-+-+-+-+-+-+-+-+              -/           -/
245
+
246
+           PID:  The relative Picture ID referred to by this frame.
247
+           RS and RQ:  The spatial and quality layer IDs.
248
+           X: 1 if this layer index has an extended relative Picture ID.
249
+     */
250
+    if (has_ss_data) {
251
+        avpriv_report_missing_feature(ctx, "VP9 scalability structure data\n");
252
+        return AVERROR_PATCHWELCOME;
253
+    }
254
+
255
+    /*
256
+      decode the scalability update structure (SU)
257
+
258
+        spec. is tbd
259
+     */
260
+    if (has_su_data) {
261
+        avpriv_report_missing_feature(ctx, "VP9 scalability update structure data\n");
262
+        return AVERROR_PATCHWELCOME;
263
+    }
264
+
265
+    /*
266
+      decode the VP9 payload header
267
+
268
+        spec. is tbd
269
+     */
270
+    //XXX: implement when specified
271
+
272
+    /* sanity check: 1 byte payload as minimum */
273
+    if (len < 1) {
274
+        av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
275
+        return AVERROR_INVALIDDATA;
276
+    }
277
+
278
+    /* start frame buffering with new dynamic buffer */
279
+    if (!rtp_vp9_ctx->buf) {
280
+        /* sanity check: a new frame should have started */
281
+        if (first_fragment) {
282
+            res = avio_open_dyn_buf(&rtp_vp9_ctx->buf);
283
+            if (res < 0)
284
+                return res;
285
+            /* update the timestamp in the frame packet with the one from the RTP packet */
286
+            rtp_vp9_ctx->timestamp = *timestamp;
287
+        } else {
288
+            /* frame not started yet, need more packets */
289
+            return AVERROR(EAGAIN);
290
+        }
291
+    }
292
+
293
+    /* write the fragment to the dyn. buffer */
294
+    avio_write(rtp_vp9_ctx->buf, buf, len);
295
+
296
+    /* do we need more fragments? */
297
+    if (!last_fragment)
298
+        return AVERROR(EAGAIN);
299
+
300
+    /* close frame buffering and create resulting A/V packet */
301
+    res = ff_rtp_finalize_packet(pkt, &rtp_vp9_ctx->buf, st->index);
302
+    if (res < 0)
303
+        return res;
304
+
305
+    return 0;
306
+}
307
+
308
+RTPDynamicProtocolHandler ff_vp9_dynamic_handler = {
309
+    .enc_name         = "VP9",
310
+    .codec_type       = AVMEDIA_TYPE_VIDEO,
311
+    .codec_id         = AV_CODEC_ID_VP9,
312
+    .init             = vp9_init,
313
+    .alloc            = vp9_new_context,
314
+    .free             = vp9_free_context,
315
+    .parse_packet     = vp9_handle_packet
316
+};