3 * @brief Real-Time Protocol (RTP) Xiph payloads receival
5 /*****************************************************************************
6 * Copyright © 2008 Rémi Denis-Courmont
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 ****************************************************************************/
29 #include <vlc_common.h>
30 #include <vlc_demux.h>
32 #include <vlc_network.h>
36 #include <vlc_plugin.h>
38 #include "../../demux/xiph.h"
42 typedef struct rtp_xiph_t
50 static void *xiph_init (bool vorbis)
52 rtp_xiph_t *self = malloc (sizeof (*self));
59 self->ident = 0xffffffff; /* impossible value on the wire */
60 self->vorbis = vorbis;
66 * vorbis: Xiph Vorbis audio (RFC 5215)
68 static void *vorbis_init (demux_t *demux)
71 return xiph_init (true);
76 * vorbis: Xiph Theora video
78 void *theora_init (demux_t *demux)
81 return xiph_init (false);
84 void xiph_destroy (demux_t *demux, void *data)
86 rtp_xiph_t *self = data;
92 self->block->i_flags |= BLOCK_FLAG_CORRUPTED;
93 codec_decode (demux, self->id, self->block);
95 codec_destroy (demux, self->id);
99 /* Convert configuration from RTP to VLC format */
100 static ssize_t xiph_header (void **pextra, const uint8_t *buf, size_t len)
104 return -1; /* Invalid */
105 unsigned hcount = 1 + *buf++;
108 return -1; /* Invalid */
111 uint16_t idlen = 0, cmtlen = 0, setuplen = 0;
116 idlen = (idlen << 7) | (*buf & 0x7f);
119 while (*buf++ & 0x80);
124 cmtlen = (cmtlen << 7) | (*buf & 0x7f);
127 while (*buf++ & 0x80);
128 if (len < idlen + cmtlen)
130 setuplen = len - (idlen + cmtlen);
132 /* Create the VLC extra format header */
133 unsigned sizes[3] = {
134 idlen, cmtlen, setuplen
136 const void *payloads[3] = {
143 if (xiph_PackHeaders (&extra_size, &extra, sizes, payloads, 3))
150 void xiph_decode (demux_t *demux, void *data, block_t *block)
152 rtp_xiph_t *self = data;
154 if (!data || block->i_buffer < 4)
157 /* 32-bits RTP header (§2.2) */
158 uint32_t ident = GetDWBE (block->p_buffer);
159 block->i_buffer -= 4;
160 block->p_buffer += 4;
162 unsigned fragtype = (ident >> 6) & 3;
163 unsigned datatype = (ident >> 4) & 3;
164 unsigned pkts = (ident) & 15;
167 /* RTP defragmentation */
168 if (self->block && (block->i_flags & BLOCK_FLAG_DISCONTINUITY))
169 { /* Screwed! discontinuity within a fragmented packet */
170 msg_Warn (demux, self->vorbis ?
171 "discontinuity in fragmented Vorbis packet" :
172 "discontinuity in fragmented Theora packet");
173 block_Release (self->block);
179 if (self->block) /* Invalid first fragment */
181 block_Release (self->block);
188 goto drop; /* Invalid non-first fragment */
193 if (pkts > 0 || block->i_buffer < 2)
196 size_t fraglen = GetWBE (block->p_buffer);
197 if (block->i_buffer < (fraglen + 2))
198 goto drop; /* Invalid payload length */
199 block->i_buffer = fraglen;
200 if (fragtype == 1)/* Keep first fragment */
202 block->i_buffer += 2;
206 { /* Append non-first fragment */
207 size_t len = self->block->i_buffer;
208 self->block = block_Realloc (self->block, 0, len + fraglen);
211 block_Release (block);
214 memcpy (self->block->p_buffer + len, block->p_buffer + 2,
216 block_Release (block);
219 return; /* Non-last fragment */
221 /* Last fragment reached, process it */
224 SetWBE (block->p_buffer, block->i_buffer - 2);
228 /* RTP payload packets processing */
231 if (block->i_buffer < 2)
234 size_t len = GetWBE (block->p_buffer);
235 block->i_buffer -= 2;
236 block->p_buffer += 2;
237 if (block->i_buffer < len)
242 case 0: /* Raw payload */
244 if (self->ident != ident)
246 msg_Warn (demux, self->vorbis ?
247 "ignoring raw Vorbis payload without configuration" :
248 "ignoring raw Theora payload without configuration");
251 block_t *raw = block_Alloc (len);
252 memcpy (raw->p_buffer, block->p_buffer, len);
253 raw->i_pts = block->i_pts; /* FIXME: what about pkts > 1 */
254 codec_decode (demux, self->id, raw);
258 case 1: /* Packed configuration frame (§3.1.1) */
260 if (self->ident == ident)
261 break; /* Ignore config retransmission */
264 ssize_t extc = xiph_header (&extv, block->p_buffer, len);
269 es_format_Init (&fmt, self->vorbis ? AUDIO_ES : VIDEO_ES,
270 self->vorbis ? VLC_CODEC_VORBIS
274 codec_destroy (demux, self->id);
275 msg_Dbg (demux, self->vorbis ?
276 "Vorbis packed configuration received (%06"PRIx32")" :
277 "Theora packed configuration received (%06"PRIx32")",
280 self->id = codec_init (demux, &fmt);
285 block->i_buffer -= len;
286 block->p_buffer += len;
291 block_Release (block);