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>
31 #include <vlc_network.h>
35 #include <vlc_plugin.h>
37 #include "../../demux/xiph.h"
41 typedef struct rtp_xiph_t
49 static void *xiph_init (bool vorbis)
51 rtp_xiph_t *self = malloc (sizeof (*self));
58 self->ident = 0xffffffff; /* impossible value on the wire */
59 self->vorbis = vorbis;
65 * vorbis: Xiph Vorbis audio (RFC 5215)
67 static void *vorbis_init (demux_t *demux)
70 return xiph_init (true);
75 * vorbis: Xiph Theora video
77 void *theora_init (demux_t *demux)
80 return xiph_init (false);
83 void xiph_destroy (demux_t *demux, void *data)
85 rtp_xiph_t *self = data;
91 self->block->i_flags |= BLOCK_FLAG_CORRUPTED;
92 codec_decode (demux, self->id, self->block);
94 codec_destroy (demux, self->id);
98 /* Convert configuration from RTP to VLC format */
99 static ssize_t xiph_header (void **pextra, const uint8_t *buf, size_t len)
103 return -1; /* Invalid */
104 unsigned hcount = 1 + *buf++;
107 return -1; /* Invalid */
110 uint16_t idlen = 0, cmtlen = 0, setuplen = 0;
115 idlen = (idlen << 7) | (*buf & 0x7f);
118 while (*buf++ & 0x80);
123 cmtlen = (cmtlen << 7) | (*buf & 0x7f);
126 while (*buf++ & 0x80);
127 if (len < idlen + cmtlen)
129 setuplen = len - (idlen + cmtlen);
131 /* Create the VLC extra format header */
132 unsigned sizes[3] = {
133 idlen, cmtlen, setuplen
135 const void *payloads[3] = {
142 if (xiph_PackHeaders (&extra_size, &extra, sizes, payloads, 3))
149 void xiph_decode (demux_t *demux, void *data, block_t *block)
151 rtp_xiph_t *self = data;
153 if (!data || block->i_buffer < 4)
156 /* 32-bits RTP header (§2.2) */
157 uint32_t ident = GetDWBE (block->p_buffer);
158 block->i_buffer -= 4;
159 block->p_buffer += 4;
161 unsigned fragtype = (ident >> 6) & 3;
162 unsigned datatype = (ident >> 4) & 3;
163 unsigned pkts = (ident) & 15;
166 /* RTP defragmentation */
167 if (self->block && (block->i_flags & BLOCK_FLAG_DISCONTINUITY))
168 { /* Screwed! discontinuity within a fragmented packet */
169 msg_Warn (demux, self->vorbis ?
170 "discontinuity in fragmented Vorbis packet" :
171 "discontinuity in fragmented Theora packet");
172 block_Release (self->block);
178 if (self->block) /* Invalid first fragment */
180 block_Release (self->block);
187 goto drop; /* Invalid non-first fragment */
192 if (pkts > 0 || block->i_buffer < 2)
195 size_t fraglen = GetWBE (block->p_buffer);
196 if (block->i_buffer < (fraglen + 2))
197 goto drop; /* Invalid payload length */
198 block->i_buffer = fraglen;
199 if (fragtype == 1)/* Keep first fragment */
201 block->i_buffer += 2;
205 { /* Append non-first fragment */
206 size_t len = self->block->i_buffer;
207 self->block = block_Realloc (self->block, 0, len + fraglen);
210 block_Release (block);
213 memcpy (self->block->p_buffer + len, block->p_buffer + 2,
215 block_Release (block);
218 return; /* Non-last fragment */
220 /* Last fragment reached, process it */
223 SetWBE (block->p_buffer, block->i_buffer - 2);
227 /* RTP payload packets processing */
230 if (block->i_buffer < 2)
233 size_t len = GetWBE (block->p_buffer);
234 block->i_buffer -= 2;
235 block->p_buffer += 2;
236 if (block->i_buffer < len)
241 case 0: /* Raw payload */
243 if (self->ident != ident)
245 msg_Warn (demux, self->vorbis ?
246 "ignoring raw Vorbis payload without configuration" :
247 "ignoring raw Theora payload without configuration");
250 block_t *raw = block_Alloc (len);
251 memcpy (raw->p_buffer, block->p_buffer, len);
252 raw->i_pts = block->i_pts; /* FIXME: what about pkts > 1 */
253 codec_decode (demux, self->id, raw);
257 case 1: /* Packed configuration frame (§3.1.1) */
259 if (self->ident == ident)
260 break; /* Ignore config retransmission */
263 ssize_t extc = xiph_header (&extv, block->p_buffer, len);
268 es_format_Init (&fmt, self->vorbis ? AUDIO_ES : VIDEO_ES,
269 self->vorbis ? VLC_CODEC_VORBIS
273 codec_destroy (demux, self->id);
274 msg_Dbg (demux, self->vorbis ?
275 "Vorbis packed configuration received (%06"PRIx32")" :
276 "Theora packed configuration received (%06"PRIx32")",
279 self->id = codec_init (demux, &fmt);
284 block->i_buffer -= len;
285 block->p_buffer += len;
290 block_Release (block);