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 <vlc_codecs.h>
39 #include "../../demux/xiph.h"
44 * vorbis: Xiph Vorbis audio (draft-ietf-avt-rtp-vorbis-09, RFC FIXME)
46 typedef struct rtp_vorbis_t
53 static void *vorbis_init (demux_t *demux)
55 rtp_vorbis_t *self = malloc (sizeof (*self));
62 self->ident = 0xffffffff; /* impossible value on the wire */
67 static void vorbis_destroy (demux_t *demux, void *data)
69 rtp_vorbis_t *self = data;
75 self->block->i_flags |= BLOCK_FLAG_CORRUPTED;
76 codec_decode (demux, self->id, self->block);
78 codec_destroy (demux, self->id);
82 /* Convert configuration from RTP to VLC format */
83 static ssize_t vorbis_header (void **pextra, const uint8_t *buf, size_t len)
87 return -1; /* Invalid */
88 unsigned hcount = 1 + *buf++;
91 return -1; /* Invalid */
94 uint16_t idlen = 0, cmtlen = 0, setuplen = 0;
99 idlen = (idlen << 7) | (*buf & 0x7f);
102 while (*buf++ & 0x80);
107 cmtlen = (cmtlen << 7) | (*buf & 0x7f);
110 while (*buf++ & 0x80);
111 if (len < idlen + cmtlen)
113 setuplen = len - (idlen + cmtlen);
115 /* Create the VLC extra format header */
116 unsigned sizes[3] = {
117 idlen, cmtlen, setuplen
119 void *payloads[3] = {
126 if (xiph_PackHeaders (&extra_size, &extra, sizes, payloads, 3))
133 static void vorbis_decode (demux_t *demux, void *data, block_t *block)
135 rtp_vorbis_t *self = data;
137 if (!data || block->i_buffer < 4)
140 /* 32-bits Vorbis RTP header (§2.2) */
141 uint32_t ident = GetDWBE (block->p_buffer);
142 block->i_buffer -= 4;
143 block->p_buffer += 4;
145 unsigned fragtype = (ident >> 6) & 3;
146 unsigned datatype = (ident >> 4) & 3;
147 unsigned pkts = (ident) & 15;
150 /* Vorbis RTP defragmentation */
151 if (self->block && (block->i_flags & BLOCK_FLAG_DISCONTINUITY))
152 { /* Screwed! discontinuity within a fragmented packet */
153 msg_Warn (demux, "discontinuity in fragmented Vorbis packet");
154 block_Release (self->block);
160 if (self->block) /* Invalid first fragment */
162 block_Release (self->block);
169 goto drop; /* Invalid non-first fragment */
174 if (pkts > 0 || block->i_buffer < 2)
177 size_t fraglen = GetWBE (block->p_buffer);
178 if (block->i_buffer < (fraglen + 2))
179 goto drop; /* Invalid payload length */
180 block->i_buffer = fraglen;
181 if (fragtype == 1)/* Keep first fragment */
183 block->i_buffer += 2;
187 { /* Append non-first fragment */
188 size_t len = self->block->i_buffer;
189 self->block = block_Realloc (self->block, 0, len + fraglen);
192 block_Release (block);
195 memcpy (self->block->p_buffer + len, block->p_buffer + 2,
197 block_Release (block);
200 return; /* Non-last fragment */
202 /* Last fragment reached, process it */
205 SetWBE (block->p_buffer, block->i_buffer - 2);
209 /* Vorbis RTP payload packets processing */
212 if (block->i_buffer < 2)
215 size_t len = GetWBE (block->p_buffer);
216 block->i_buffer -= 2;
217 block->p_buffer += 2;
218 if (block->i_buffer < len)
223 case 0: /* Raw audio frame */
225 if (self->ident != ident)
226 break; /* Ignore raw without configuration */
227 block_t *raw = block_Alloc (len);
228 memcpy (raw->p_buffer, block->p_buffer, len);
229 raw->i_pts = block->i_pts; /* FIXME: what about pkts > 1 */
230 codec_decode (demux, self->id, raw);
234 case 1: /* Packed configuration frame (§3.1.1) */
236 if (self->ident == ident)
237 break; /* Ignore config retransmission */
240 ssize_t extc = vorbis_header (&extv, block->p_buffer, len);
245 es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_VORBIS);
248 codec_destroy (demux, self->id);
249 msg_Dbg (demux, "Vorbis packed configuration received "
250 "(%06"PRIx32")", ident);
252 self->id = codec_init (demux, &fmt);
257 block->i_buffer -= len;
258 block->p_buffer += len;
263 block_Release (block);