Move RTP to access/rtp
authorRémi Denis-Courmont <rdenis@simphalempin.com>
Sun, 9 Nov 2008 12:41:07 +0000 (14:41 +0200)
committerRémi Denis-Courmont <rdenis@simphalempin.com>
Sun, 9 Nov 2008 12:41:07 +0000 (14:41 +0200)
12 files changed:
configure.ac
modules/access/Modules.am
modules/access/rtp/Modules.am [new file with mode: 0644]
modules/access/rtp/rtp.c [new file with mode: 0644]
modules/access/rtp/rtp.h [new file with mode: 0644]
modules/access/rtp/session.c [new file with mode: 0644]
modules/access/rtp/xiph.c [new file with mode: 0644]
modules/demux/Modules.am
modules/demux/rtp.c [deleted file]
modules/demux/rtp.h [deleted file]
modules/demux/rtpsession.c [deleted file]
modules/demux/rtpxiph.c [deleted file]

index 7445925..36ad414 100644 (file)
@@ -5759,6 +5759,7 @@ AC_CONFIG_FILES([
   modules/access/dvb/Makefile
   modules/access/mms/Makefile
   modules/access/cdda/Makefile
+  modules/access/rtp/Makefile
   modules/access/rtsp/Makefile
   modules/access/rtmp/Makefile
   modules/access/v4l2/Makefile
index c91bfd0..c52e499 100644 (file)
@@ -3,7 +3,7 @@
 # obviously does not. Here is a fix for that.
 LIBTOOL=@LIBTOOL@ --tag=CC
 
-BASE_SUBDIRS = dvb mms cdda rtsp rtmp v4l2 vcd vcdx screen
+BASE_SUBDIRS = dvb mms cdda rtp rtsp rtmp v4l2 vcd vcdx screen
 EXTRA_SUBDIRS = bda dshow
 SUBDIRS = $(BASE_SUBDIRS)
 DIST_SUBDIRS = $(BASE_SUBDIRS) $(EXTRA_SUBDIRS)
diff --git a/modules/access/rtp/Modules.am b/modules/access/rtp/Modules.am
new file mode 100644 (file)
index 0000000..e8150b7
--- /dev/null
@@ -0,0 +1,12 @@
+if HAVE_LIBGCRYPT
+# RTP plugin
+libvlc_LTLIBRARIES += \
+       librtp_plugin.la
+librtp_plugin_la_SOURCES = \
+       rtp.c rtp.h session.c
+librtp_plugin_la_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/libs/srtp
+librtp_plugin_la_LIBADD = $(AM_LIBADD) \
+       $(top_builddir)/libs/srtp/libvlc_srtp.la
+librtp_plugin_la_DEPENDENCIES = \
+       $(top_builddir)/libs/srtp/libvlc_srtp.la
+endif
diff --git a/modules/access/rtp/rtp.c b/modules/access/rtp/rtp.c
new file mode 100644 (file)
index 0000000..86d3d96
--- /dev/null
@@ -0,0 +1,724 @@
+/**
+ * @file rtp.c
+ * @brief Real-Time Protocol (RTP) demux module for VLC media player
+ */
+/*****************************************************************************
+ * Copyright (C) 2001-2005 the VideoLAN team
+ * Copyright © 2007-2008 Rémi Denis-Courmont
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2.0
+ * of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdarg.h>
+#include <assert.h>
+
+#include <vlc_common.h>
+#include <vlc_demux.h>
+#include <vlc_aout.h>
+#include <vlc_network.h>
+#ifdef HAVE_POLL
+# include <poll.h>
+#endif
+#include <vlc_plugin.h>
+
+#include <vlc_codecs.h>
+
+#include "rtp.h"
+#include <srtp.h>
+
+#define RTP_CACHING_TEXT N_("RTP de-jitter buffer length (msec)")
+#define RTP_CACHING_LONGTEXT N_( \
+    "How long to wait for late RTP packets (and delay the performance)." )
+
+#define SRTP_KEY_TEXT N_("SRTP key (hexadecimal)")
+#define SRTP_KEY_LONGTEXT N_( \
+    "RTP packets will be authenticated and deciphered "\
+    "with this Secure RTP master shared secret key.")
+
+#define SRTP_SALT_TEXT N_("SRTP salt (hexadecimal)")
+#define SRTP_SALT_LONGTEXT N_( \
+    "Secure RTP requires a (non-secret) master salt value.")
+
+#define RTP_MAX_SRC_TEXT N_("Maximum RTP sources")
+#define RTP_MAX_SRC_LONGTEXT N_( \
+    "How many distinct active RTP sources are allowed at a time." )
+
+#define RTP_TIMEOUT_TEXT N_("RTP source timeout (sec)")
+#define RTP_TIMEOUT_LONGTEXT N_( \
+    "How long to wait for any packet before a source is expired.")
+
+#define RTP_MAX_DROPOUT_TEXT N_("Maximum RTP sequence number dropout")
+#define RTP_MAX_DROPOUT_LONGTEXT N_( \
+    "RTP packets will be discarded if they are too much ahead (i.e. in the " \
+    "future) by this many packets from the last received packet." )
+
+#define RTP_MAX_MISORDER_TEXT N_("Maximum RTP sequence number misordering")
+#define RTP_MAX_MISORDER_LONGTEXT N_( \
+    "RTP packets will be discarded if they are too far behind (i.e. in the " \
+    "past) by this many packets from the last received packet." )
+
+static int  Open (vlc_object_t *);
+static void Close (vlc_object_t *);
+
+/*
+ * Module descriptor
+ */
+vlc_module_begin ()
+    set_shortname (_("RTP"))
+    set_description (_("(Experimental) Real-Time Protocol demuxer"))
+    set_category (CAT_INPUT)
+    set_subcategory (SUBCAT_INPUT_DEMUX)
+    set_capability ("access_demux", 0)
+    set_callbacks (Open, Close)
+
+    add_integer ("rtp-caching", 1000, NULL, RTP_CACHING_TEXT,
+                 RTP_CACHING_LONGTEXT, true);
+        change_integer_range (0, 65535)
+    add_string ("srtp-key", "", NULL,
+                SRTP_KEY_TEXT, SRTP_KEY_LONGTEXT, false);
+    add_string ("srtp-salt", "", NULL,
+                SRTP_SALT_TEXT, SRTP_SALT_LONGTEXT, false);
+    add_integer ("rtp-max-src", 1, NULL, RTP_MAX_SRC_TEXT,
+                 RTP_MAX_SRC_LONGTEXT, true);
+        change_integer_range (1, 255)
+    add_integer ("rtp-timeout", 5, NULL, RTP_TIMEOUT_TEXT,
+                 RTP_TIMEOUT_LONGTEXT, true);
+    add_integer ("rtp-max-dropout", 3000, NULL, RTP_MAX_DROPOUT_TEXT,
+                 RTP_MAX_DROPOUT_LONGTEXT, true);
+        change_integer_range (0, 32767)
+    add_integer ("rtp-max-misorder", 100, NULL, RTP_MAX_MISORDER_TEXT,
+                 RTP_MAX_MISORDER_LONGTEXT, true);
+        change_integer_range (0, 32767)
+
+    add_shortcut ("dccp")
+    /*add_shortcut ("sctp")*/
+    add_shortcut ("rtptcp") /* "tcp" is already taken :( */
+    add_shortcut ("rtp")
+    add_shortcut ("udplite")
+vlc_module_end ()
+
+/*
+ * TODO: so much stuff
+ * - send RTCP-RR and RTCP-BYE
+ * - dynamic payload types (need SDP parser)
+ * - multiple medias (need SDP parser, and RTCP-SR parser for lip-sync)
+ * - support for access_filter in case of stream_Demux (MPEG-TS)
+ */
+
+#ifndef IPPROTO_DCCP
+# define IPPROTO_DCCP 33 /* IANA */
+#endif
+
+#ifndef IPPROTO_UDPLITE
+# define IPPROTO_UDPLITE 136 /* from IANA */
+#endif
+
+
+/*
+ * Local prototypes
+ */
+static int Demux (demux_t *);
+static int Control (demux_t *, int i_query, va_list args);
+static int extract_port (char **phost);
+
+/**
+ * Probes and initializes.
+ */
+static int Open (vlc_object_t *obj)
+{
+    demux_t *demux = (demux_t *)obj;
+    int tp; /* transport protocol */
+
+    if (!strcmp (demux->psz_access, "dccp"))
+        tp = IPPROTO_DCCP;
+    else
+    if (!strcmp (demux->psz_access, "rtptcp"))
+        tp = IPPROTO_TCP;
+    else
+    if (!strcmp (demux->psz_access, "rtp"))
+        tp = IPPROTO_UDP;
+    else
+    if (!strcmp (demux->psz_access, "udplite"))
+        tp = IPPROTO_UDPLITE;
+    else
+        return VLC_EGENERIC;
+
+    char *tmp = strdup (demux->psz_path);
+    char *shost = tmp;
+    if (shost == NULL)
+        return VLC_ENOMEM;
+
+    char *dhost = strchr (shost, '@');
+    if (dhost)
+        *dhost++ = '\0';
+
+    /* Parses the port numbers */
+    int sport = 0, dport = 0;
+    sport = extract_port (&shost);
+    if (dhost != NULL)
+        dport = extract_port (&dhost);
+    if (dport == 0)
+        dport = 5004; /* avt-profile-1 port */
+
+    /* Try to connect */
+    int fd = -1, rtcp_fd = -1;
+
+    switch (tp)
+    {
+        case IPPROTO_UDP:
+        case IPPROTO_UDPLITE:
+            fd = net_OpenDgram (obj, dhost, (dport + 1) & ~1,
+                                shost, (sport + 1) & ~1, AF_UNSPEC, tp);
+            if (fd == -1)
+                break;
+            rtcp_fd = net_OpenDgram (obj, dhost, dport | 1, shost,
+                                     sport ? (sport | 1) : 0, AF_UNSPEC, tp);
+            break;
+
+         case IPPROTO_DCCP:
+#ifndef SOCK_DCCP /* provisional API (FIXME) */
+# ifdef __linux__
+#  define SOCK_DCCP 6
+# endif
+#endif
+#ifdef SOCK_DCCP
+            var_Create (obj, "dccp-service", VLC_VAR_STRING);
+            var_SetString (obj, "dccp-service", "RTPV"); /* FIXME: RTPA? */
+            fd = net_Connect (obj, shost, (sport + 1) & ~1, SOCK_DCCP, tp);
+#else
+            msg_Err (obj, "DCCP support not included");
+#endif
+            break;
+
+        case IPPROTO_TCP:
+            fd = net_Connect (obj, shost, (sport + 1) & ~1, SOCK_STREAM, tp);
+            break;
+    }
+
+    free (tmp);
+    if (fd == -1)
+        return VLC_EGENERIC;
+    net_SetCSCov (fd, -1, 12);
+
+    /* Initializes demux */
+    demux_sys_t *p_sys = malloc (sizeof (*p_sys));
+    if (p_sys == NULL)
+    {
+        net_Close (fd);
+        if (rtcp_fd != -1)
+            net_Close (rtcp_fd);
+        return VLC_EGENERIC;
+    }
+
+    p_sys->srtp         = NULL;
+    p_sys->fd           = fd;
+    p_sys->rtcp_fd      = rtcp_fd;
+    p_sys->caching      = var_CreateGetInteger (obj, "rtp-caching");
+    p_sys->max_src      = var_CreateGetInteger (obj, "rtp-max-src");
+    p_sys->timeout      = var_CreateGetInteger (obj, "rtp-timeout");
+    p_sys->max_dropout  = var_CreateGetInteger (obj, "rtp-max-dropout");
+    p_sys->max_misorder = var_CreateGetInteger (obj, "rtp-max-misorder");
+    p_sys->autodetect   = true;
+    p_sys->framed_rtp   = (tp == IPPROTO_TCP);
+
+    demux->pf_demux   = Demux;
+    demux->pf_control = Control;
+    demux->p_sys      = p_sys;
+
+    p_sys->session = rtp_session_create (demux);
+    if (p_sys->session == NULL)
+        goto error;
+
+    char *key = var_CreateGetNonEmptyString (demux, "srtp-key");
+    if (key)
+    {
+        p_sys->srtp = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 10,
+                                   SRTP_PRF_AES_CM, SRTP_RCC_MODE1);
+        if (p_sys->srtp == NULL)
+        {
+            free (key);
+            goto error;
+        }
+
+        char *salt = var_CreateGetNonEmptyString (demux, "srtp-salt");
+        errno = srtp_setkeystring (p_sys->srtp, key, salt ? salt : "");
+        free (salt);
+        free (key);
+        if (errno)
+        {
+            msg_Err (obj, "bad SRTP key/salt combination (%m)");
+            goto error;
+        }
+    }
+
+    return VLC_SUCCESS;
+
+error:
+    Close (obj);
+    return VLC_EGENERIC;
+}
+
+
+/**
+ * Releases resources
+ */
+static void Close (vlc_object_t *obj)
+{
+    demux_t *demux = (demux_t *)obj;
+    demux_sys_t *p_sys = demux->p_sys;
+
+    if (p_sys->srtp)
+        srtp_destroy (p_sys->srtp);
+    if (p_sys->session)
+        rtp_session_destroy (demux, p_sys->session);
+    if (p_sys->rtcp_fd != -1)
+        net_Close (p_sys->rtcp_fd);
+    net_Close (p_sys->fd);
+    free (p_sys);
+}
+
+
+/**
+ * Extracts port number from "[host]:port" or "host:port" strings,
+ * and remove brackets from the host name.
+ * @param phost pointer to the string upon entry,
+ * pointer to the hostname upon return.
+ * @return port number, 0 if missing.
+ */
+static int extract_port (char **phost)
+{
+    char *host = *phost, *port;
+
+    if (host[0] == '[')
+    {
+        host = ++*phost; /* skip '[' */
+        port = strchr (host, ']');
+        if (port)
+            *port++ = '\0'; /* skip ']' */
+    }
+    else
+        port = strchr (host, ':');
+
+    if (port == NULL)
+        return 0;
+    *port++ = '\0'; /* skip ':' */
+    return atoi (port);
+}
+
+
+/**
+ * Control callback
+ */
+static int Control (demux_t *demux, int i_query, va_list args)
+{
+    demux_sys_t *p_sys = demux->p_sys;
+
+    switch (i_query)
+    {
+        case DEMUX_GET_POSITION:
+        {
+            float *v = va_arg (args, float *);
+            *v = 0.;
+            return VLC_SUCCESS;
+        }
+
+        case DEMUX_GET_LENGTH:
+        case DEMUX_GET_TIME:
+        {
+            int64_t *v = va_arg (args, int64_t *);
+            *v = 0;
+            return VLC_SUCCESS;
+        }
+
+        case DEMUX_GET_PTS_DELAY:
+        {
+            int64_t *v = va_arg (args, int64_t *);
+            *v = p_sys->caching * 1000;
+            return VLC_SUCCESS;
+        }
+
+        case DEMUX_CAN_PAUSE:
+        case DEMUX_CAN_SEEK:
+        case DEMUX_CAN_CONTROL_PACE:
+        {
+            bool *v = (bool*)va_arg( args, bool * );
+            *v = false;
+            return VLC_SUCCESS;
+        }
+    }
+
+    return VLC_EGENERIC;
+}
+
+
+/**
+ * Checks if a file descriptor is hung up.
+ */
+static bool fd_dead (int fd)
+{
+    struct pollfd ufd = { .fd = fd, };
+
+    return (poll (&ufd, 1, 0) == 1) && (ufd.revents & POLLHUP);
+}
+
+
+/**
+ * Gets a datagram from the network, or NULL in case of fatal error.
+ */
+static block_t *rtp_dgram_recv (demux_t *demux, int fd)
+{
+    block_t *block = block_Alloc (0xffff);
+    ssize_t len;
+
+    do
+    {
+        len = net_Read (VLC_OBJECT (demux), fd, NULL,
+                                block->p_buffer, block->i_buffer, false);
+        if (((len <= 0) && fd_dead (fd))
+         || !vlc_object_alive (demux))
+        {
+            block_Release (block);
+            return NULL;
+        }
+    }
+    while (len == -1);
+
+    return block_Realloc (block, 0, len);
+}
+
+/**
+ * Gets a framed RTP packet, or NULL in case of fatal error.
+ */
+static block_t *rtp_stream_recv (demux_t *demux, int fd)
+{
+    ssize_t len = 0;
+    uint8_t hdr[2]; /* frame header */
+
+    /* Receives the RTP frame header */
+    do
+    {
+        ssize_t val = net_Read (VLC_OBJECT (demux), fd, NULL,
+                                hdr + len, 2 - len, false);
+        if (val <= 0)
+            return NULL;
+        len += val;
+    }
+    while (len < 2);
+
+    block_t *block = block_Alloc (GetWBE (hdr));
+
+    /* Receives the RTP packet */
+    for (ssize_t i = 0; i < len;)
+    {
+        ssize_t val;
+
+        val = net_Read (VLC_OBJECT (demux), fd, NULL,
+                        block->p_buffer + i, block->i_buffer - i, false);
+        if (val <= 0)
+        {
+            block_Release (block);
+            return NULL;
+        }
+        i += val;
+    }
+
+    return block;
+}
+
+
+/*
+ * Generic packet handlers
+ */
+
+static void *codec_init (demux_t *demux, es_format_t *fmt)
+{
+    return es_out_Add (demux->out, fmt);
+}
+
+static void codec_destroy (demux_t *demux, void *data)
+{
+    if (data)
+        es_out_Del (demux->out, (es_out_id_t *)data);
+}
+
+/* Send a packet to decoder */
+static void codec_decode (demux_t *demux, void *data, block_t *block)
+{
+    if (data)
+    {
+        block->i_dts = 0; /* RTP does not specify this */
+        es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts );
+        es_out_Send (demux->out, (es_out_id_t *)data, block);
+    }
+    else
+        block_Release (block);
+}
+
+
+static void *stream_init (demux_t *demux, const char *name)
+{
+    return stream_DemuxNew (demux, name, demux->out);
+}
+
+static void stream_destroy (demux_t *demux, void *data)
+{
+    if (data)
+        stream_DemuxDelete ((stream_t *)data);
+    (void)demux;
+}
+
+/* Send a packet to a chained demuxer */
+static void stream_decode (demux_t *demux, void *data, block_t *block)
+{
+    if (data)
+        stream_DemuxSend ((stream_t *)data, block);
+    else
+        block_Release (block);
+    (void)demux;
+}
+
+/*
+ * Static payload types handler
+ */
+
+/* PT=0
+ * PCMU: G.711 µ-law (RFC3551)
+ */
+static void *pcmu_init (demux_t *demux)
+{
+    es_format_t fmt;
+
+    es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('u', 'l', 'a', 'w'));
+    fmt.audio.i_rate = 8000;
+    fmt.audio.i_channels = 1;
+    return codec_init (demux, &fmt);
+}
+
+/* PT=8
+ * PCMA: G.711 A-law (RFC3551)
+ */
+static void *pcma_init (demux_t *demux)
+{
+    es_format_t fmt;
+
+    es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('a', 'l', 'a', 'w'));
+    fmt.audio.i_rate = 8000;
+    fmt.audio.i_channels = 1;
+    return codec_init (demux, &fmt);
+}
+
+/* PT=10,11
+ * L16: 16-bits (network byte order) PCM
+ */
+static void *l16s_init (demux_t *demux)
+{
+    es_format_t fmt;
+
+    es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('s', '1', '6', 'b'));
+    fmt.audio.i_rate = 44100;
+    fmt.audio.i_channels = 2;
+    return codec_init (demux, &fmt);
+}
+
+static void *l16m_init (demux_t *demux)
+{
+    es_format_t fmt;
+
+    es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('s', '1', '6', 'b'));
+    fmt.audio.i_rate = 44100;
+    fmt.audio.i_channels = 1;
+    return codec_init (demux, &fmt);
+}
+
+/* PT=14
+ * MPA: MPEG Audio (RFC2250, §3.4)
+ */
+static void *mpa_init (demux_t *demux)
+{
+    es_format_t fmt;
+
+    es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('m', 'p', 'g', 'a'));
+    fmt.audio.i_channels = 2;
+    return codec_init (demux, &fmt);
+}
+
+static void mpa_decode (demux_t *demux, void *data, block_t *block)
+{
+    if (block->i_buffer < 4)
+    {
+        block_Release (block);
+        return;
+    }
+
+    block->i_buffer -= 4; /* 32-bits RTP/MPA header */
+    block->p_buffer += 4;
+
+    codec_decode (demux, data, block);
+}
+
+
+/* PT=32
+ * MPV: MPEG Video (RFC2250, §3.5)
+ */
+static void *mpv_init (demux_t *demux)
+{
+    es_format_t fmt;
+
+    es_format_Init (&fmt, VIDEO_ES, VLC_FOURCC ('m', 'p', 'g', 'v'));
+    return codec_init (demux, &fmt);
+}
+
+static void mpv_decode (demux_t *demux, void *data, block_t *block)
+{
+    if (block->i_buffer < 4)
+    {
+        block_Release (block);
+        return;
+    }
+
+    block->i_buffer -= 4; /* 32-bits RTP/MPV header */
+    block->p_buffer += 4;
+#if 0
+    if (block->p_buffer[-3] & 0x4)
+    {
+        /* MPEG2 Video extension header */
+        /* TODO: shouldn't we skip this too ? */
+    }
+#endif
+    codec_decode (demux, data, block);
+}
+
+
+/* PT=33
+ * MP2: MPEG TS (RFC2250, §2)
+ */
+static void *ts_init (demux_t *demux)
+{
+    return stream_init (demux, *demux->psz_demux ? demux->psz_demux : "ts");
+}
+
+
+/*
+ * Dynamic payload type handlers
+ * Hmm, none implemented yet.
+ */
+
+/**
+ * Processing callback
+ */
+static int Demux (demux_t *demux)
+{
+    demux_sys_t *p_sys = demux->p_sys;
+    block_t     *block;
+
+    block = p_sys->framed_rtp
+        ? rtp_stream_recv (demux, p_sys->fd)
+        : rtp_dgram_recv (demux, p_sys->fd);
+    if (!block)
+        return 0;
+
+    if (block->i_buffer < 2)
+        goto drop;
+
+    const uint8_t ptype = block->p_buffer[1] & 0x7F;
+    if (ptype >= 72 && ptype <= 76)
+        goto drop; /* Muxed RTCP, ignore for now */
+
+    if (p_sys->srtp)
+    {
+        size_t len = block->i_buffer;
+        if (srtp_recv (p_sys->srtp, block->p_buffer, &len))
+        {
+            msg_Dbg (demux, "SRTP authentication/decryption failed");
+            goto drop;
+        }
+        block->i_buffer = len;
+    }
+
+    /* Not using SDP, we need to guess the payload format used */
+    /* see http://www.iana.org/assignments/rtp-parameters */
+    if (p_sys->autodetect)
+    {
+        rtp_pt_t pt = {
+            .init = NULL,
+            .destroy = codec_destroy,
+            .decode = codec_decode,
+            .frequency = 0,
+            .number = ptype,
+        };
+        switch (ptype)
+        {
+          case 0:
+            msg_Dbg (demux, "detected G.711 mu-law");
+            pt.init = pcmu_init;
+            pt.frequency = 8000;
+            break;
+
+          case 8:
+            msg_Dbg (demux, "detected G.711 A-law");
+            pt.init = pcma_init;
+            pt.frequency = 8000;
+            break;
+
+          case 10:
+            msg_Dbg (demux, "detected stereo PCM");
+            pt.init = l16s_init;
+            pt.frequency = 44100;
+            break;
+
+          case 11:
+            msg_Dbg (demux, "detected mono PCM");
+            pt.init = l16m_init;
+            pt.frequency = 44100;
+            break;
+
+          case 14:
+            msg_Dbg (demux, "detected MPEG Audio");
+            pt.init = mpa_init;
+            pt.decode = mpa_decode;
+            pt.frequency = 90000;
+            break;
+
+          case 32:
+            msg_Dbg (demux, "detected MPEG Video");
+            pt.init = mpv_init;
+            pt.decode = mpv_decode;
+            pt.frequency = 90000;
+            break;
+
+          case 33:
+            msg_Dbg (demux, "detected MPEG2 TS");
+            pt.init = ts_init;
+            pt.destroy = stream_destroy;
+            pt.decode = stream_decode;
+            pt.frequency = 90000;
+            break;
+
+          default:
+            goto drop;
+        }
+        rtp_add_type (demux, p_sys->session, &pt);
+        p_sys->autodetect = false;
+    }
+    rtp_receive (demux, p_sys->session, block);
+
+    return 1;
+drop:
+    block_Release (block);
+    return 1;
+}
diff --git a/modules/access/rtp/rtp.h b/modules/access/rtp/rtp.h
new file mode 100644 (file)
index 0000000..c8daa66
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+ * @file rtp.h
+ * @brief RTP demux module shared declarations
+ */
+/*****************************************************************************
+ * Copyright © 2008 Rémi Denis-Courmont
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2.0
+ * of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ ****************************************************************************/
+
+/* RTP payload format */
+typedef struct rtp_pt_t rtp_pt_t;
+struct rtp_pt_t
+{
+    void   *(*init) (demux_t *);
+    void    (*destroy) (demux_t *, void *);
+    void    (*decode) (demux_t *, void *, block_t *);
+    uint32_t  frequency; /* RTP clock rate (Hz) */
+    uint8_t   number;
+};
+
+/* RTP session */
+typedef struct rtp_session_t rtp_session_t;
+rtp_session_t *rtp_session_create (demux_t *);
+void rtp_session_destroy (demux_t *, rtp_session_t *);
+void rtp_receive (demux_t *, rtp_session_t *, block_t *);
+int rtp_add_type (demux_t *demux, rtp_session_t *ses, const rtp_pt_t *pt);
+
+
+/* Global data */
+struct demux_sys_t
+{
+    rtp_session_t *session;
+    struct srtp_session_t *srtp;
+    int           fd;
+    int           rtcp_fd;
+
+    unsigned      caching;
+    unsigned      timeout;
+    uint8_t       max_src;
+    uint16_t      max_dropout;
+    uint16_t      max_misorder;
+    bool          autodetect;
+    bool          framed_rtp;
+};
+
diff --git a/modules/access/rtp/session.c b/modules/access/rtp/session.c
new file mode 100644 (file)
index 0000000..dd8eaff
--- /dev/null
@@ -0,0 +1,439 @@
+/**
+ * @file session.c
+ * @brief RTP session handling
+ */
+/*****************************************************************************
+ * Copyright © 2008 Rémi Denis-Courmont
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2.0
+ * of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <vlc/vlc.h>
+#include <vlc_demux.h>
+
+#include "rtp.h"
+
+typedef struct rtp_source_t rtp_source_t;
+
+/** State for a RTP session: */
+struct rtp_session_t
+{
+    rtp_source_t **srcv;
+    unsigned       srcc;
+    uint8_t        ptc;
+    rtp_pt_t      *ptv;
+};
+
+static rtp_source_t *
+rtp_source_create (demux_t *, const rtp_session_t *, uint32_t, uint16_t);
+static void
+rtp_source_destroy (demux_t *, const rtp_session_t *, rtp_source_t *);
+
+static void rtp_decode (demux_t *, const rtp_session_t *, rtp_source_t *);
+
+/**
+ * Creates a new RTP session.
+ */
+rtp_session_t *
+rtp_session_create (demux_t *demux)
+{
+    rtp_session_t *session = malloc (sizeof (*session));
+    if (session == NULL)
+        return NULL;
+
+    session->srcv = NULL;
+    session->srcc = 0;
+    session->ptc = 0;
+    session->ptv = NULL;
+
+    (void)demux;
+    return session;
+}
+
+
+/**
+ * Destroys an RTP session.
+ */
+void rtp_session_destroy (demux_t *demux, rtp_session_t *session)
+{
+    for (unsigned i = 0; i < session->srcc; i++)
+        rtp_source_destroy (demux, session, session->srcv[i]);
+
+    free (session->srcv);
+    free (session->ptv);
+    free (session);
+    (void)demux;
+}
+
+static void *no_init (demux_t *demux)
+{
+    (void)demux;
+    return NULL;
+}
+
+static void no_destroy (demux_t *demux, void *opaque)
+{
+    (void)demux; (void)opaque;
+}
+
+static void no_decode (demux_t *demux, void *opaque, block_t *block)
+{
+    (void)demux; (void)opaque;
+    block_Release (block);
+}
+
+/**
+ * Adds a payload type to an RTP session.
+ */
+int rtp_add_type (demux_t *demux, rtp_session_t *ses, const rtp_pt_t *pt)
+{
+    if (ses->srcc > 0)
+    {
+        msg_Err (demux, "cannot change RTP payload formats during session");
+        return EINVAL;
+    }
+
+    rtp_pt_t *ppt = realloc (ses->ptv, (ses->ptc + 1) * sizeof (rtp_pt_t));
+    if (ppt == NULL)
+        return ENOMEM;
+
+    ses->ptv = ppt;
+    ppt += ses->ptc++;
+
+    ppt->init = pt->init ? pt->init : no_init;
+    ppt->destroy = pt->destroy ? pt->destroy : no_destroy;
+    ppt->decode = pt->decode ? pt->decode : no_decode;
+    ppt->frequency = pt->frequency;
+    ppt->number = pt->number;
+    msg_Dbg (demux, "added payload type %"PRIu8" (f = %"PRIu32" Hz)",
+             ppt->number, ppt->frequency);
+
+    assert (ppt->frequency > 0); /* SIGFPE! */
+    (void)demux;
+    return 0;
+}
+
+/** State for an RTP source */
+struct rtp_source_t
+{
+    uint32_t ssrc;
+    uint32_t jitter;  /* interarrival delay jitter estimate */
+    mtime_t  last_rx; /* last received packet local timestamp */
+    uint32_t last_ts; /* last received packet RTP timestamp */
+
+    uint16_t bad_seq; /* tentatively next expected sequence for resync */
+    uint16_t max_seq; /* next expected sequence */
+
+    uint16_t last_seq; /* sequence of the last dequeued packet */
+    block_t *blocks; /* re-ordered blocks queue */
+    void    *opaque[0]; /* Per-source private payload data */
+};
+
+/**
+ * Initializes a new RTP source within an RTP session.
+ */
+static rtp_source_t *
+rtp_source_create (demux_t *demux, const rtp_session_t *session,
+                   uint32_t ssrc, uint16_t init_seq)
+{
+    rtp_source_t *source;
+
+    source = malloc (sizeof (*source) + (sizeof (void *) * session->ptc));
+    if (source == NULL)
+        return NULL;
+
+    source->ssrc = ssrc;
+    source->jitter = 0;
+    source->max_seq = source->bad_seq = init_seq;
+    source->last_seq = init_seq - 1;
+    source->blocks = NULL;
+
+    /* Initializes all payload */
+    for (unsigned i = 0; i < session->ptc; i++)
+        source->opaque[i] = session->ptv[i].init (demux);
+
+    msg_Dbg (demux, "added RTP source (%08x)", ssrc);
+    return source;
+}
+
+
+/**
+ * Destroys an RTP source and its associated streams.
+ */
+static void
+rtp_source_destroy (demux_t *demux, const rtp_session_t *session,
+                    rtp_source_t *source)
+{
+    msg_Dbg (demux, "removing RTP source (%08x)", source->ssrc);
+
+    for (unsigned i = 0; i < session->ptc; i++)
+        session->ptv[i].destroy (demux, source->opaque[i]);
+    block_ChainRelease (source->blocks);
+    free (source);
+}
+
+static inline uint8_t rtp_ptype (const block_t *block)
+{
+    return block->p_buffer[1] & 0x7F;
+}
+
+static inline uint16_t rtp_seq (const block_t *block)
+{
+    assert (block->i_buffer >= 4);
+    return GetWBE (block->p_buffer + 2);
+}
+
+static inline uint32_t rtp_timestamp (const block_t *block)
+{
+    assert (block->i_buffer >= 12);
+    return GetDWBE (block->p_buffer + 4);
+}
+
+static const struct rtp_pt_t *
+rtp_find_ptype (const rtp_session_t *session, rtp_source_t *source,
+                const block_t *block, void **pt_data)
+{
+    uint8_t ptype = rtp_ptype (block);
+
+    for (unsigned i = 0; i < session->ptc; i++)
+    {
+        if (session->ptv[i].number == ptype)
+        {
+            if (pt_data != NULL)
+                *pt_data = source->opaque[i];
+            return &session->ptv[i];
+        }
+    }
+    return NULL;
+}
+
+/**
+ * Receives an RTP packet and queues it.
+ * @param demux VLC demux object
+ * @param session RTP session receiving the packet
+ * @param block RTP packet including the RTP header
+ */
+void
+rtp_receive (demux_t *demux, rtp_session_t *session, block_t *block)
+{
+    demux_sys_t *p_sys = demux->p_sys;
+
+    /* RTP header sanity checks (see RFC 3550) */
+    if (block->i_buffer < 12)
+        goto drop;
+    if ((block->p_buffer[0] >> 6 ) != 2) /* RTP version number */
+        goto drop;
+
+    /* Remove padding if present */
+    if (block->p_buffer[0] & 0x20)
+    {
+        uint8_t padding = block->p_buffer[block->i_buffer - 1];
+        if ((padding == 0) || (block->i_buffer < (12u + padding)))
+            goto drop; /* illegal value */
+
+        block->i_buffer -= padding;
+    }
+
+    mtime_t        now = mdate ();
+    rtp_source_t  *src  = NULL;
+    const uint16_t seq  = GetWBE (block->p_buffer + 2);
+    const uint32_t ssrc = GetDWBE (block->p_buffer + 8);
+
+    /* In most case, we know this source already */
+    for (unsigned i = 0, max = session->srcc; i < max; i++)
+    {
+        rtp_source_t *tmp = session->srcv[i];
+        if (tmp->ssrc == ssrc)
+        {
+            src = tmp;
+            break;
+        }
+
+        /* RTP source garbage collection */
+        if ((tmp->last_rx + (p_sys->timeout * CLOCK_FREQ)) < now)
+        {
+            rtp_source_destroy (demux, session, tmp);
+            if (--session->srcc > 0)
+                session->srcv[i] = session->srcv[session->srcc - 1];
+        }
+    }
+
+    if (src == NULL)
+    {
+        /* New source */
+        if (session->srcc >= p_sys->max_src)
+        {
+            msg_Warn (demux, "too many RTP sessions");
+            goto drop;
+        }
+
+        rtp_source_t **tab;
+        tab = realloc (session->srcv, (session->srcc + 1) * sizeof (*tab));
+        if (tab == NULL)
+            goto drop;
+        session->srcv = tab;
+
+        src = rtp_source_create (demux, session, ssrc, seq);
+        if (src == NULL)
+            goto drop;
+
+        tab[session->srcc++] = src;
+        /* Cannot compute jitter yet */
+    }
+    else
+    {
+        const rtp_pt_t *pt = rtp_find_ptype (session, src, block, NULL);
+
+        if (pt != NULL)
+        {
+            /* Recompute jitter estimate.
+             * That is computed from the RTP timestamps and the system clock.
+             * It is independent of RTP sequence. */
+            uint32_t freq = pt->frequency;
+            uint32_t ts = rtp_timestamp (block);
+            int64_t d = ((now - src->last_rx) * freq) / CLOCK_FREQ;
+            d        -=    ts - src->last_ts;
+            if (d < 0) d = -d;
+            src->jitter += ((d - src->jitter) + 8) >> 4;
+        }
+    }
+    src->last_rx = now;
+    src->last_ts = rtp_timestamp (block);
+
+    /* Be optimistic for the first packet. Certain codec, such as Vorbis
+     * do not like loosing the first packet(s), so we cannot just wait
+     * for proper sequence synchronization. And we don't want to assume that
+     * the sender starts at seq=0 either. */
+    if (src->blocks == NULL)
+        src->max_seq = seq - p_sys->max_dropout;
+
+    /* Check sequence number */
+    /* NOTE: the sequence number is per-source,
+     * but is independent from the payload type. */
+    uint16_t delta_seq = seq - (src->max_seq + 1);
+    if ((delta_seq < 0x8000) ? (delta_seq > p_sys->max_dropout)
+                             : ((65535 - delta_seq) > p_sys->max_misorder))
+    {
+        msg_Dbg (demux, "sequence discontinuity (got: %u, expected: %u)",
+                 seq, (src->max_seq + 1) & 0xffff);
+        if (seq == ((src->bad_seq + 1) & 0xffff))
+        {
+            src->max_seq = src->bad_seq = seq;
+            msg_Warn (demux, "sequence resynchronized");
+            block_ChainRelease (src->blocks);
+            src->blocks = NULL;
+        }
+        else
+        {
+            src->bad_seq = seq;
+            goto drop;
+        }
+    }
+    else
+    if (delta_seq < 0x8000)
+        src->max_seq = seq;
+
+    /* Queues the block in sequence order,
+     * hence there is a single queue for all payload types. */
+    block_t **pp = &src->blocks;
+    for (block_t *prev = *pp; prev != NULL; prev = *pp)
+    {
+        int16_t delta_seq = seq - rtp_seq (prev);
+        if (delta_seq < 0)
+            break;
+        if (delta_seq == 0)
+            goto drop; /* duplicate */
+        pp = &prev->p_next;
+    }
+    block->p_next = *pp;
+    *pp = block;
+
+    rtp_decode (demux, session, src);
+    return;
+
+drop:
+    block_Release (block);
+}
+
+
+static void
+rtp_decode (demux_t *demux, const rtp_session_t *session, rtp_source_t *src)
+{
+    block_t *block = src->blocks;
+
+    /* Buffer underflow? */
+    if (!block || !block->p_next || !block->p_next->p_next)
+        return;
+    /* TODO: use time rather than packet counts for buffer measurement */
+    src->blocks = block->p_next;
+    block->p_next = NULL;
+
+    /* Discontinuity detection */
+    if (((src->last_seq + 1) & 0xffff) != rtp_seq (block))
+        block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
+    src->last_seq = rtp_seq (block);
+
+    /* Match the payload type */
+    void *pt_data;
+    const rtp_pt_t *pt = rtp_find_ptype (session, src, block, &pt_data);
+    if (pt == NULL)
+    {
+        msg_Dbg (demux, "ignoring unknown payload (%"PRIu8")",
+                 rtp_ptype (block));
+        goto drop;
+    }
+
+    /* Computes the PTS from the RTP timestamp and payload RTP frequency.
+     * DTS is unknown. Also, while the clock frequency depends on the payload
+     * format, a single source MUST only use payloads of a chosen frequency.
+     * Otherwise it would be impossible to compute consistent timestamps. */
+    /* FIXME: handle timestamp wrap properly */
+    /* TODO: sync multiple sources sanely... */
+    const uint32_t timestamp = rtp_timestamp (block);
+    block->i_pts = UINT64_C(1) * CLOCK_FREQ * timestamp / pt->frequency;
+
+    /* CSRC count */
+    size_t skip = 12u + (block->p_buffer[0] & 0x0F) * 4;
+
+    /* Extension header (ignored for now) */
+    if (block->p_buffer[0] & 0x10)
+    {
+        skip += 4;
+        if (block->i_buffer < skip)
+            goto drop;
+
+        skip += 4 * GetWBE (block->p_buffer + skip - 2);
+    }
+
+    if (block->i_buffer < skip)
+        goto drop;
+
+    block->p_buffer += skip;
+    block->i_buffer -= skip;
+
+    pt->decode (demux, pt_data, block);
+    return;
+
+drop:
+    block_Release (block);
+}
diff --git a/modules/access/rtp/xiph.c b/modules/access/rtp/xiph.c
new file mode 100644 (file)
index 0000000..7f6492e
--- /dev/null
@@ -0,0 +1,272 @@
+/**
+ * @file rtpxiph.c
+ * @brief Real-Time Protocol (RTP) Xiph payloads receival
+ */
+/*****************************************************************************
+ * Copyright © 2008 Rémi Denis-Courmont
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2.0
+ * of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdarg.h>
+#include <assert.h>
+
+#include <vlc_common.h>
+#include <vlc_demux.h>
+#include <vlc_aout.h>
+#include <vlc_network.h>
+#ifdef HAVE_POLL
+# include <poll.h>
+#endif
+#include <vlc_plugin.h>
+
+#include <vlc_codecs.h>
+
+#include "rtp.h"
+#include <srtp.h>
+
+/* PT=dynamic
+ * vorbis: Xiph Vorbis audio (draft-ietf-avt-rtp-vorbis-09, RFC FIXME)
+ */
+typedef struct rtp_vorbis_t
+{
+    es_out_id_t *id;
+    block_t     *block;
+    uint32_t     ident;
+} rtp_vorbis_t;
+
+static void *vorbis_init (demux_t *demux)
+{
+    rtp_vorbis_t *self = malloc (sizeof (*self));
+
+    if (self == NULL)
+        return NULL;
+
+    self->id = NULL;
+    self->block = NULL;
+    self->ident = 0xffffffff; /* impossible value on the wire */
+    (void)demux;
+    return self;
+}
+
+static void vorbis_destroy (demux_t *demux, void *data)
+{
+    rtp_vorbis_t *self = data;
+
+    if (!data)
+        return;
+    if (self->block)
+    {
+        self->block->i_flags |= BLOCK_FLAG_CORRUPTED;
+        codec_decode (demux, self->id, self->block);
+    }
+    codec_destroy (demux, self->id);
+    free (self);
+}
+
+/* Convert configuration from RTP to VLC format */
+static ssize_t vorbis_header (void **pextra, const uint8_t *buf, size_t len)
+{
+    /* Headers number */
+    if (len == 0)
+          return -1; /* Invalid */
+    unsigned hcount = 1 + *buf++;
+    len--;
+    if (hcount != 3)
+          return -1; /* Invalid */
+
+    /* Header lengths */
+    uint16_t idlen = 0, cmtlen = 0, setuplen = 0;
+    do
+    {
+        if (len == 0)
+            return -1;
+        idlen = (idlen << 7) | (*buf & 0x7f);
+        len--;
+    }
+    while (*buf++ & 0x80);
+    do
+    {
+        if (len == 0)
+            return -1;
+        cmtlen = (cmtlen << 7) | (*buf & 0x7f);
+        len--;
+    }
+    while (*buf++ & 0x80);
+    if (len < idlen + cmtlen)
+        return -1;
+    setuplen = len - (idlen + cmtlen);
+
+    /* Create the VLC extra format header */
+    uint8_t *extra = malloc ((size_t)6 + idlen + cmtlen + setuplen);
+    if (extra == NULL)
+        return -1;
+    uint8_t *ptr = *pextra = extra;
+    /* Identification header */
+    *ptr++ = idlen >> 8;
+    *ptr++ = idlen & 0xff;
+    memcpy (ptr, buf, idlen);
+    buf += idlen;
+    ptr += idlen;
+    /* Comments header */
+    *ptr++ = cmtlen >> 8;
+    *ptr++ = cmtlen & 0xff;
+    memcpy (ptr, buf, cmtlen);
+    buf += cmtlen;
+    ptr += cmtlen;
+    /* Setup header */
+    *ptr++ = setuplen >> 8;
+    *ptr++ = setuplen & 0xff;
+    memcpy (ptr, buf, setuplen);
+    ptr += setuplen;
+    return ptr - extra;
+}
+
+
+static void vorbis_decode (demux_t *demux, void *data, block_t *block)
+{
+    rtp_vorbis_t *self = data;
+
+    if (!data || block->i_buffer < 4)
+        goto drop;
+
+    /* 32-bits Vorbis RTP header (§2.2) */
+    uint32_t ident = GetDWBE (block->p_buffer);
+    block->i_buffer -= 4;
+    block->p_buffer += 4;
+
+    unsigned fragtype = (ident >> 6) & 3;
+    unsigned datatype = (ident >> 4) & 3;
+    unsigned pkts = (ident) & 15;
+    ident >>= 8;
+
+    /* Vorbis RTP defragmentation */
+    if (self->block && (block->i_flags & BLOCK_FLAG_DISCONTINUITY))
+    {   /* Screwed! discontinuity within a fragmented packet */
+        msg_Warn (demux, "discontinuity in fragmented Vorbis packet");
+        block_Release (self->block);
+        self->block = NULL;
+    }
+
+    if (fragtype <= 1)
+    {
+        if (self->block) /* Invalid first fragment */
+        {
+            block_Release (self->block);
+            self->block = NULL;
+        }
+    }
+    else
+    {
+        if (!self->block)
+            goto drop; /* Invalid non-first fragment */
+    }
+
+    if (fragtype > 0)
+    {   /* Fragment */
+        if (pkts > 0 || block->i_buffer < 2)
+            goto drop;
+
+        size_t fraglen = GetWBE (block->p_buffer);
+        if (block->i_buffer < (fraglen + 2))
+            goto drop; /* Invalid payload length */
+        block->i_buffer = fraglen;
+        if (fragtype == 1)/* Keep first fragment */
+        {
+            block->i_buffer += 2;
+            self->block = block;
+        }
+        else
+        {   /* Append non-first fragment */
+            size_t len = self->block->i_buffer;
+            self->block = block_Realloc (self->block, 0, len + fraglen);
+            if (!self->block)
+            {
+                block_Release (block);
+                return;
+            }
+            memcpy (self->block->p_buffer + len, block->p_buffer + 2,
+                    fraglen);
+            block_Release (block);
+        }
+        if (fragtype < 3)
+            return; /* Non-last fragment */
+
+        /* Last fragment reached, process it */
+        block = self->block;
+        self->block = NULL;
+        SetWBE (block->p_buffer, block->i_buffer - 2);
+        pkts = 1;
+    }
+
+    /* Vorbis RTP payload packets processing */
+    while (pkts > 0)
+    {
+        if (block->i_buffer < 2)
+            goto drop;
+
+        size_t len = GetWBE (block->p_buffer);
+        block->i_buffer -= 2;
+        block->p_buffer += 2;
+        if (block->i_buffer < len)
+            goto drop;
+
+        switch (datatype)
+        {
+            case 0: /* Raw audio frame */
+            {
+                if (self->ident != ident)
+                    break; /* Ignore raw without configuration */
+                block_t *raw = block_Alloc (len);
+                memcpy (raw->p_buffer, block->p_buffer, len);
+                raw->i_pts = block->i_pts; /* FIXME: what about pkts > 1 */
+                codec_decode (demux, self->id, raw);
+                break;
+            }
+
+            case 1: /* Packed configuration frame (§3.1.1) */
+            {
+                if (self->ident == ident)
+                    break; /* Ignore config retransmission */
+
+                void *extv;
+                ssize_t extc = vorbis_header (&extv, block->p_buffer, len);
+                if (extc < 0)
+                    break;
+
+                es_format_t fmt;
+                es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('v','o','r','b'));
+                fmt.p_extra = extv;
+                fmt.i_extra = extc;
+                codec_destroy (demux, self->id);
+                msg_Dbg (demux, "Vorbis packed configuration received "
+                         "(%06"PRIx32")", ident);
+                self->ident = ident;
+                self->id = codec_init (demux, &fmt);
+                break;
+            }
+        }
+
+        block->i_buffer -= len;
+        block->p_buffer += len;
+        pkts--;
+    }
+
+drop:
+    block_Release (block);
+}
index 72f51fb..6a81ab1 100644 (file)
@@ -56,16 +56,3 @@ libvlc_LTLIBRARIES += \
        libwav_plugin.la \
        libxa_plugin.la \
        $(NULL)
-
-if HAVE_LIBGCRYPT
-# RTP plugin
-libvlc_LTLIBRARIES += \
-       librtp_plugin.la
-librtp_plugin_la_SOURCES = \
-       rtp.c rtp.h rtpsession.c
-librtp_plugin_la_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/libs/srtp
-librtp_plugin_la_LIBADD = $(AM_LIBADD) \
-       $(top_builddir)/libs/srtp/libvlc_srtp.la
-librtp_plugin_la_DEPENDENCIES = \
-       $(top_builddir)/libs/srtp/libvlc_srtp.la
-endif
diff --git a/modules/demux/rtp.c b/modules/demux/rtp.c
deleted file mode 100644 (file)
index 86d3d96..0000000
+++ /dev/null
@@ -1,724 +0,0 @@
-/**
- * @file rtp.c
- * @brief Real-Time Protocol (RTP) demux module for VLC media player
- */
-/*****************************************************************************
- * Copyright (C) 2001-2005 the VideoLAN team
- * Copyright © 2007-2008 Rémi Denis-Courmont
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2.0
- * of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- ****************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <stdarg.h>
-#include <assert.h>
-
-#include <vlc_common.h>
-#include <vlc_demux.h>
-#include <vlc_aout.h>
-#include <vlc_network.h>
-#ifdef HAVE_POLL
-# include <poll.h>
-#endif
-#include <vlc_plugin.h>
-
-#include <vlc_codecs.h>
-
-#include "rtp.h"
-#include <srtp.h>
-
-#define RTP_CACHING_TEXT N_("RTP de-jitter buffer length (msec)")
-#define RTP_CACHING_LONGTEXT N_( \
-    "How long to wait for late RTP packets (and delay the performance)." )
-
-#define SRTP_KEY_TEXT N_("SRTP key (hexadecimal)")
-#define SRTP_KEY_LONGTEXT N_( \
-    "RTP packets will be authenticated and deciphered "\
-    "with this Secure RTP master shared secret key.")
-
-#define SRTP_SALT_TEXT N_("SRTP salt (hexadecimal)")
-#define SRTP_SALT_LONGTEXT N_( \
-    "Secure RTP requires a (non-secret) master salt value.")
-
-#define RTP_MAX_SRC_TEXT N_("Maximum RTP sources")
-#define RTP_MAX_SRC_LONGTEXT N_( \
-    "How many distinct active RTP sources are allowed at a time." )
-
-#define RTP_TIMEOUT_TEXT N_("RTP source timeout (sec)")
-#define RTP_TIMEOUT_LONGTEXT N_( \
-    "How long to wait for any packet before a source is expired.")
-
-#define RTP_MAX_DROPOUT_TEXT N_("Maximum RTP sequence number dropout")
-#define RTP_MAX_DROPOUT_LONGTEXT N_( \
-    "RTP packets will be discarded if they are too much ahead (i.e. in the " \
-    "future) by this many packets from the last received packet." )
-
-#define RTP_MAX_MISORDER_TEXT N_("Maximum RTP sequence number misordering")
-#define RTP_MAX_MISORDER_LONGTEXT N_( \
-    "RTP packets will be discarded if they are too far behind (i.e. in the " \
-    "past) by this many packets from the last received packet." )
-
-static int  Open (vlc_object_t *);
-static void Close (vlc_object_t *);
-
-/*
- * Module descriptor
- */
-vlc_module_begin ()
-    set_shortname (_("RTP"))
-    set_description (_("(Experimental) Real-Time Protocol demuxer"))
-    set_category (CAT_INPUT)
-    set_subcategory (SUBCAT_INPUT_DEMUX)
-    set_capability ("access_demux", 0)
-    set_callbacks (Open, Close)
-
-    add_integer ("rtp-caching", 1000, NULL, RTP_CACHING_TEXT,
-                 RTP_CACHING_LONGTEXT, true);
-        change_integer_range (0, 65535)
-    add_string ("srtp-key", "", NULL,
-                SRTP_KEY_TEXT, SRTP_KEY_LONGTEXT, false);
-    add_string ("srtp-salt", "", NULL,
-                SRTP_SALT_TEXT, SRTP_SALT_LONGTEXT, false);
-    add_integer ("rtp-max-src", 1, NULL, RTP_MAX_SRC_TEXT,
-                 RTP_MAX_SRC_LONGTEXT, true);
-        change_integer_range (1, 255)
-    add_integer ("rtp-timeout", 5, NULL, RTP_TIMEOUT_TEXT,
-                 RTP_TIMEOUT_LONGTEXT, true);
-    add_integer ("rtp-max-dropout", 3000, NULL, RTP_MAX_DROPOUT_TEXT,
-                 RTP_MAX_DROPOUT_LONGTEXT, true);
-        change_integer_range (0, 32767)
-    add_integer ("rtp-max-misorder", 100, NULL, RTP_MAX_MISORDER_TEXT,
-                 RTP_MAX_MISORDER_LONGTEXT, true);
-        change_integer_range (0, 32767)
-
-    add_shortcut ("dccp")
-    /*add_shortcut ("sctp")*/
-    add_shortcut ("rtptcp") /* "tcp" is already taken :( */
-    add_shortcut ("rtp")
-    add_shortcut ("udplite")
-vlc_module_end ()
-
-/*
- * TODO: so much stuff
- * - send RTCP-RR and RTCP-BYE
- * - dynamic payload types (need SDP parser)
- * - multiple medias (need SDP parser, and RTCP-SR parser for lip-sync)
- * - support for access_filter in case of stream_Demux (MPEG-TS)
- */
-
-#ifndef IPPROTO_DCCP
-# define IPPROTO_DCCP 33 /* IANA */
-#endif
-
-#ifndef IPPROTO_UDPLITE
-# define IPPROTO_UDPLITE 136 /* from IANA */
-#endif
-
-
-/*
- * Local prototypes
- */
-static int Demux (demux_t *);
-static int Control (demux_t *, int i_query, va_list args);
-static int extract_port (char **phost);
-
-/**
- * Probes and initializes.
- */
-static int Open (vlc_object_t *obj)
-{
-    demux_t *demux = (demux_t *)obj;
-    int tp; /* transport protocol */
-
-    if (!strcmp (demux->psz_access, "dccp"))
-        tp = IPPROTO_DCCP;
-    else
-    if (!strcmp (demux->psz_access, "rtptcp"))
-        tp = IPPROTO_TCP;
-    else
-    if (!strcmp (demux->psz_access, "rtp"))
-        tp = IPPROTO_UDP;
-    else
-    if (!strcmp (demux->psz_access, "udplite"))
-        tp = IPPROTO_UDPLITE;
-    else
-        return VLC_EGENERIC;
-
-    char *tmp = strdup (demux->psz_path);
-    char *shost = tmp;
-    if (shost == NULL)
-        return VLC_ENOMEM;
-
-    char *dhost = strchr (shost, '@');
-    if (dhost)
-        *dhost++ = '\0';
-
-    /* Parses the port numbers */
-    int sport = 0, dport = 0;
-    sport = extract_port (&shost);
-    if (dhost != NULL)
-        dport = extract_port (&dhost);
-    if (dport == 0)
-        dport = 5004; /* avt-profile-1 port */
-
-    /* Try to connect */
-    int fd = -1, rtcp_fd = -1;
-
-    switch (tp)
-    {
-        case IPPROTO_UDP:
-        case IPPROTO_UDPLITE:
-            fd = net_OpenDgram (obj, dhost, (dport + 1) & ~1,
-                                shost, (sport + 1) & ~1, AF_UNSPEC, tp);
-            if (fd == -1)
-                break;
-            rtcp_fd = net_OpenDgram (obj, dhost, dport | 1, shost,
-                                     sport ? (sport | 1) : 0, AF_UNSPEC, tp);
-            break;
-
-         case IPPROTO_DCCP:
-#ifndef SOCK_DCCP /* provisional API (FIXME) */
-# ifdef __linux__
-#  define SOCK_DCCP 6
-# endif
-#endif
-#ifdef SOCK_DCCP
-            var_Create (obj, "dccp-service", VLC_VAR_STRING);
-            var_SetString (obj, "dccp-service", "RTPV"); /* FIXME: RTPA? */
-            fd = net_Connect (obj, shost, (sport + 1) & ~1, SOCK_DCCP, tp);
-#else
-            msg_Err (obj, "DCCP support not included");
-#endif
-            break;
-
-        case IPPROTO_TCP:
-            fd = net_Connect (obj, shost, (sport + 1) & ~1, SOCK_STREAM, tp);
-            break;
-    }
-
-    free (tmp);
-    if (fd == -1)
-        return VLC_EGENERIC;
-    net_SetCSCov (fd, -1, 12);
-
-    /* Initializes demux */
-    demux_sys_t *p_sys = malloc (sizeof (*p_sys));
-    if (p_sys == NULL)
-    {
-        net_Close (fd);
-        if (rtcp_fd != -1)
-            net_Close (rtcp_fd);
-        return VLC_EGENERIC;
-    }
-
-    p_sys->srtp         = NULL;
-    p_sys->fd           = fd;
-    p_sys->rtcp_fd      = rtcp_fd;
-    p_sys->caching      = var_CreateGetInteger (obj, "rtp-caching");
-    p_sys->max_src      = var_CreateGetInteger (obj, "rtp-max-src");
-    p_sys->timeout      = var_CreateGetInteger (obj, "rtp-timeout");
-    p_sys->max_dropout  = var_CreateGetInteger (obj, "rtp-max-dropout");
-    p_sys->max_misorder = var_CreateGetInteger (obj, "rtp-max-misorder");
-    p_sys->autodetect   = true;
-    p_sys->framed_rtp   = (tp == IPPROTO_TCP);
-
-    demux->pf_demux   = Demux;
-    demux->pf_control = Control;
-    demux->p_sys      = p_sys;
-
-    p_sys->session = rtp_session_create (demux);
-    if (p_sys->session == NULL)
-        goto error;
-
-    char *key = var_CreateGetNonEmptyString (demux, "srtp-key");
-    if (key)
-    {
-        p_sys->srtp = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 10,
-                                   SRTP_PRF_AES_CM, SRTP_RCC_MODE1);
-        if (p_sys->srtp == NULL)
-        {
-            free (key);
-            goto error;
-        }
-
-        char *salt = var_CreateGetNonEmptyString (demux, "srtp-salt");
-        errno = srtp_setkeystring (p_sys->srtp, key, salt ? salt : "");
-        free (salt);
-        free (key);
-        if (errno)
-        {
-            msg_Err (obj, "bad SRTP key/salt combination (%m)");
-            goto error;
-        }
-    }
-
-    return VLC_SUCCESS;
-
-error:
-    Close (obj);
-    return VLC_EGENERIC;
-}
-
-
-/**
- * Releases resources
- */
-static void Close (vlc_object_t *obj)
-{
-    demux_t *demux = (demux_t *)obj;
-    demux_sys_t *p_sys = demux->p_sys;
-
-    if (p_sys->srtp)
-        srtp_destroy (p_sys->srtp);
-    if (p_sys->session)
-        rtp_session_destroy (demux, p_sys->session);
-    if (p_sys->rtcp_fd != -1)
-        net_Close (p_sys->rtcp_fd);
-    net_Close (p_sys->fd);
-    free (p_sys);
-}
-
-
-/**
- * Extracts port number from "[host]:port" or "host:port" strings,
- * and remove brackets from the host name.
- * @param phost pointer to the string upon entry,
- * pointer to the hostname upon return.
- * @return port number, 0 if missing.
- */
-static int extract_port (char **phost)
-{
-    char *host = *phost, *port;
-
-    if (host[0] == '[')
-    {
-        host = ++*phost; /* skip '[' */
-        port = strchr (host, ']');
-        if (port)
-            *port++ = '\0'; /* skip ']' */
-    }
-    else
-        port = strchr (host, ':');
-
-    if (port == NULL)
-        return 0;
-    *port++ = '\0'; /* skip ':' */
-    return atoi (port);
-}
-
-
-/**
- * Control callback
- */
-static int Control (demux_t *demux, int i_query, va_list args)
-{
-    demux_sys_t *p_sys = demux->p_sys;
-
-    switch (i_query)
-    {
-        case DEMUX_GET_POSITION:
-        {
-            float *v = va_arg (args, float *);
-            *v = 0.;
-            return VLC_SUCCESS;
-        }
-
-        case DEMUX_GET_LENGTH:
-        case DEMUX_GET_TIME:
-        {
-            int64_t *v = va_arg (args, int64_t *);
-            *v = 0;
-            return VLC_SUCCESS;
-        }
-
-        case DEMUX_GET_PTS_DELAY:
-        {
-            int64_t *v = va_arg (args, int64_t *);
-            *v = p_sys->caching * 1000;
-            return VLC_SUCCESS;
-        }
-
-        case DEMUX_CAN_PAUSE:
-        case DEMUX_CAN_SEEK:
-        case DEMUX_CAN_CONTROL_PACE:
-        {
-            bool *v = (bool*)va_arg( args, bool * );
-            *v = false;
-            return VLC_SUCCESS;
-        }
-    }
-
-    return VLC_EGENERIC;
-}
-
-
-/**
- * Checks if a file descriptor is hung up.
- */
-static bool fd_dead (int fd)
-{
-    struct pollfd ufd = { .fd = fd, };
-
-    return (poll (&ufd, 1, 0) == 1) && (ufd.revents & POLLHUP);
-}
-
-
-/**
- * Gets a datagram from the network, or NULL in case of fatal error.
- */
-static block_t *rtp_dgram_recv (demux_t *demux, int fd)
-{
-    block_t *block = block_Alloc (0xffff);
-    ssize_t len;
-
-    do
-    {
-        len = net_Read (VLC_OBJECT (demux), fd, NULL,
-                                block->p_buffer, block->i_buffer, false);
-        if (((len <= 0) && fd_dead (fd))
-         || !vlc_object_alive (demux))
-        {
-            block_Release (block);
-            return NULL;
-        }
-    }
-    while (len == -1);
-
-    return block_Realloc (block, 0, len);
-}
-
-/**
- * Gets a framed RTP packet, or NULL in case of fatal error.
- */
-static block_t *rtp_stream_recv (demux_t *demux, int fd)
-{
-    ssize_t len = 0;
-    uint8_t hdr[2]; /* frame header */
-
-    /* Receives the RTP frame header */
-    do
-    {
-        ssize_t val = net_Read (VLC_OBJECT (demux), fd, NULL,
-                                hdr + len, 2 - len, false);
-        if (val <= 0)
-            return NULL;
-        len += val;
-    }
-    while (len < 2);
-
-    block_t *block = block_Alloc (GetWBE (hdr));
-
-    /* Receives the RTP packet */
-    for (ssize_t i = 0; i < len;)
-    {
-        ssize_t val;
-
-        val = net_Read (VLC_OBJECT (demux), fd, NULL,
-                        block->p_buffer + i, block->i_buffer - i, false);
-        if (val <= 0)
-        {
-            block_Release (block);
-            return NULL;
-        }
-        i += val;
-    }
-
-    return block;
-}
-
-
-/*
- * Generic packet handlers
- */
-
-static void *codec_init (demux_t *demux, es_format_t *fmt)
-{
-    return es_out_Add (demux->out, fmt);
-}
-
-static void codec_destroy (demux_t *demux, void *data)
-{
-    if (data)
-        es_out_Del (demux->out, (es_out_id_t *)data);
-}
-
-/* Send a packet to decoder */
-static void codec_decode (demux_t *demux, void *data, block_t *block)
-{
-    if (data)
-    {
-        block->i_dts = 0; /* RTP does not specify this */
-        es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts );
-        es_out_Send (demux->out, (es_out_id_t *)data, block);
-    }
-    else
-        block_Release (block);
-}
-
-
-static void *stream_init (demux_t *demux, const char *name)
-{
-    return stream_DemuxNew (demux, name, demux->out);
-}
-
-static void stream_destroy (demux_t *demux, void *data)
-{
-    if (data)
-        stream_DemuxDelete ((stream_t *)data);
-    (void)demux;
-}
-
-/* Send a packet to a chained demuxer */
-static void stream_decode (demux_t *demux, void *data, block_t *block)
-{
-    if (data)
-        stream_DemuxSend ((stream_t *)data, block);
-    else
-        block_Release (block);
-    (void)demux;
-}
-
-/*
- * Static payload types handler
- */
-
-/* PT=0
- * PCMU: G.711 µ-law (RFC3551)
- */
-static void *pcmu_init (demux_t *demux)
-{
-    es_format_t fmt;
-
-    es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('u', 'l', 'a', 'w'));
-    fmt.audio.i_rate = 8000;
-    fmt.audio.i_channels = 1;
-    return codec_init (demux, &fmt);
-}
-
-/* PT=8
- * PCMA: G.711 A-law (RFC3551)
- */
-static void *pcma_init (demux_t *demux)
-{
-    es_format_t fmt;
-
-    es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('a', 'l', 'a', 'w'));
-    fmt.audio.i_rate = 8000;
-    fmt.audio.i_channels = 1;
-    return codec_init (demux, &fmt);
-}
-
-/* PT=10,11
- * L16: 16-bits (network byte order) PCM
- */
-static void *l16s_init (demux_t *demux)
-{
-    es_format_t fmt;
-
-    es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('s', '1', '6', 'b'));
-    fmt.audio.i_rate = 44100;
-    fmt.audio.i_channels = 2;
-    return codec_init (demux, &fmt);
-}
-
-static void *l16m_init (demux_t *demux)
-{
-    es_format_t fmt;
-
-    es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('s', '1', '6', 'b'));
-    fmt.audio.i_rate = 44100;
-    fmt.audio.i_channels = 1;
-    return codec_init (demux, &fmt);
-}
-
-/* PT=14
- * MPA: MPEG Audio (RFC2250, §3.4)
- */
-static void *mpa_init (demux_t *demux)
-{
-    es_format_t fmt;
-
-    es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('m', 'p', 'g', 'a'));
-    fmt.audio.i_channels = 2;
-    return codec_init (demux, &fmt);
-}
-
-static void mpa_decode (demux_t *demux, void *data, block_t *block)
-{
-    if (block->i_buffer < 4)
-    {
-        block_Release (block);
-        return;
-    }
-
-    block->i_buffer -= 4; /* 32-bits RTP/MPA header */
-    block->p_buffer += 4;
-
-    codec_decode (demux, data, block);
-}
-
-
-/* PT=32
- * MPV: MPEG Video (RFC2250, §3.5)
- */
-static void *mpv_init (demux_t *demux)
-{
-    es_format_t fmt;
-
-    es_format_Init (&fmt, VIDEO_ES, VLC_FOURCC ('m', 'p', 'g', 'v'));
-    return codec_init (demux, &fmt);
-}
-
-static void mpv_decode (demux_t *demux, void *data, block_t *block)
-{
-    if (block->i_buffer < 4)
-    {
-        block_Release (block);
-        return;
-    }
-
-    block->i_buffer -= 4; /* 32-bits RTP/MPV header */
-    block->p_buffer += 4;
-#if 0
-    if (block->p_buffer[-3] & 0x4)
-    {
-        /* MPEG2 Video extension header */
-        /* TODO: shouldn't we skip this too ? */
-    }
-#endif
-    codec_decode (demux, data, block);
-}
-
-
-/* PT=33
- * MP2: MPEG TS (RFC2250, §2)
- */
-static void *ts_init (demux_t *demux)
-{
-    return stream_init (demux, *demux->psz_demux ? demux->psz_demux : "ts");
-}
-
-
-/*
- * Dynamic payload type handlers
- * Hmm, none implemented yet.
- */
-
-/**
- * Processing callback
- */
-static int Demux (demux_t *demux)
-{
-    demux_sys_t *p_sys = demux->p_sys;
-    block_t     *block;
-
-    block = p_sys->framed_rtp
-        ? rtp_stream_recv (demux, p_sys->fd)
-        : rtp_dgram_recv (demux, p_sys->fd);
-    if (!block)
-        return 0;
-
-    if (block->i_buffer < 2)
-        goto drop;
-
-    const uint8_t ptype = block->p_buffer[1] & 0x7F;
-    if (ptype >= 72 && ptype <= 76)
-        goto drop; /* Muxed RTCP, ignore for now */
-
-    if (p_sys->srtp)
-    {
-        size_t len = block->i_buffer;
-        if (srtp_recv (p_sys->srtp, block->p_buffer, &len))
-        {
-            msg_Dbg (demux, "SRTP authentication/decryption failed");
-            goto drop;
-        }
-        block->i_buffer = len;
-    }
-
-    /* Not using SDP, we need to guess the payload format used */
-    /* see http://www.iana.org/assignments/rtp-parameters */
-    if (p_sys->autodetect)
-    {
-        rtp_pt_t pt = {
-            .init = NULL,
-            .destroy = codec_destroy,
-            .decode = codec_decode,
-            .frequency = 0,
-            .number = ptype,
-        };
-        switch (ptype)
-        {
-          case 0:
-            msg_Dbg (demux, "detected G.711 mu-law");
-            pt.init = pcmu_init;
-            pt.frequency = 8000;
-            break;
-
-          case 8:
-            msg_Dbg (demux, "detected G.711 A-law");
-            pt.init = pcma_init;
-            pt.frequency = 8000;
-            break;
-
-          case 10:
-            msg_Dbg (demux, "detected stereo PCM");
-            pt.init = l16s_init;
-            pt.frequency = 44100;
-            break;
-
-          case 11:
-            msg_Dbg (demux, "detected mono PCM");
-            pt.init = l16m_init;
-            pt.frequency = 44100;
-            break;
-
-          case 14:
-            msg_Dbg (demux, "detected MPEG Audio");
-            pt.init = mpa_init;
-            pt.decode = mpa_decode;
-            pt.frequency = 90000;
-            break;
-
-          case 32:
-            msg_Dbg (demux, "detected MPEG Video");
-            pt.init = mpv_init;
-            pt.decode = mpv_decode;
-            pt.frequency = 90000;
-            break;
-
-          case 33:
-            msg_Dbg (demux, "detected MPEG2 TS");
-            pt.init = ts_init;
-            pt.destroy = stream_destroy;
-            pt.decode = stream_decode;
-            pt.frequency = 90000;
-            break;
-
-          default:
-            goto drop;
-        }
-        rtp_add_type (demux, p_sys->session, &pt);
-        p_sys->autodetect = false;
-    }
-    rtp_receive (demux, p_sys->session, block);
-
-    return 1;
-drop:
-    block_Release (block);
-    return 1;
-}
diff --git a/modules/demux/rtp.h b/modules/demux/rtp.h
deleted file mode 100644 (file)
index c8daa66..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * @file rtp.h
- * @brief RTP demux module shared declarations
- */
-/*****************************************************************************
- * Copyright © 2008 Rémi Denis-Courmont
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2.0
- * of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- ****************************************************************************/
-
-/* RTP payload format */
-typedef struct rtp_pt_t rtp_pt_t;
-struct rtp_pt_t
-{
-    void   *(*init) (demux_t *);
-    void    (*destroy) (demux_t *, void *);
-    void    (*decode) (demux_t *, void *, block_t *);
-    uint32_t  frequency; /* RTP clock rate (Hz) */
-    uint8_t   number;
-};
-
-/* RTP session */
-typedef struct rtp_session_t rtp_session_t;
-rtp_session_t *rtp_session_create (demux_t *);
-void rtp_session_destroy (demux_t *, rtp_session_t *);
-void rtp_receive (demux_t *, rtp_session_t *, block_t *);
-int rtp_add_type (demux_t *demux, rtp_session_t *ses, const rtp_pt_t *pt);
-
-
-/* Global data */
-struct demux_sys_t
-{
-    rtp_session_t *session;
-    struct srtp_session_t *srtp;
-    int           fd;
-    int           rtcp_fd;
-
-    unsigned      caching;
-    unsigned      timeout;
-    uint8_t       max_src;
-    uint16_t      max_dropout;
-    uint16_t      max_misorder;
-    bool          autodetect;
-    bool          framed_rtp;
-};
-
diff --git a/modules/demux/rtpsession.c b/modules/demux/rtpsession.c
deleted file mode 100644 (file)
index dd8eaff..0000000
+++ /dev/null
@@ -1,439 +0,0 @@
-/**
- * @file session.c
- * @brief RTP session handling
- */
-/*****************************************************************************
- * Copyright © 2008 Rémi Denis-Courmont
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2.0
- * of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- ****************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <vlc/vlc.h>
-#include <vlc_demux.h>
-
-#include "rtp.h"
-
-typedef struct rtp_source_t rtp_source_t;
-
-/** State for a RTP session: */
-struct rtp_session_t
-{
-    rtp_source_t **srcv;
-    unsigned       srcc;
-    uint8_t        ptc;
-    rtp_pt_t      *ptv;
-};
-
-static rtp_source_t *
-rtp_source_create (demux_t *, const rtp_session_t *, uint32_t, uint16_t);
-static void
-rtp_source_destroy (demux_t *, const rtp_session_t *, rtp_source_t *);
-
-static void rtp_decode (demux_t *, const rtp_session_t *, rtp_source_t *);
-
-/**
- * Creates a new RTP session.
- */
-rtp_session_t *
-rtp_session_create (demux_t *demux)
-{
-    rtp_session_t *session = malloc (sizeof (*session));
-    if (session == NULL)
-        return NULL;
-
-    session->srcv = NULL;
-    session->srcc = 0;
-    session->ptc = 0;
-    session->ptv = NULL;
-
-    (void)demux;
-    return session;
-}
-
-
-/**
- * Destroys an RTP session.
- */
-void rtp_session_destroy (demux_t *demux, rtp_session_t *session)
-{
-    for (unsigned i = 0; i < session->srcc; i++)
-        rtp_source_destroy (demux, session, session->srcv[i]);
-
-    free (session->srcv);
-    free (session->ptv);
-    free (session);
-    (void)demux;
-}
-
-static void *no_init (demux_t *demux)
-{
-    (void)demux;
-    return NULL;
-}
-
-static void no_destroy (demux_t *demux, void *opaque)
-{
-    (void)demux; (void)opaque;
-}
-
-static void no_decode (demux_t *demux, void *opaque, block_t *block)
-{
-    (void)demux; (void)opaque;
-    block_Release (block);
-}
-
-/**
- * Adds a payload type to an RTP session.
- */
-int rtp_add_type (demux_t *demux, rtp_session_t *ses, const rtp_pt_t *pt)
-{
-    if (ses->srcc > 0)
-    {
-        msg_Err (demux, "cannot change RTP payload formats during session");
-        return EINVAL;
-    }
-
-    rtp_pt_t *ppt = realloc (ses->ptv, (ses->ptc + 1) * sizeof (rtp_pt_t));
-    if (ppt == NULL)
-        return ENOMEM;
-
-    ses->ptv = ppt;
-    ppt += ses->ptc++;
-
-    ppt->init = pt->init ? pt->init : no_init;
-    ppt->destroy = pt->destroy ? pt->destroy : no_destroy;
-    ppt->decode = pt->decode ? pt->decode : no_decode;
-    ppt->frequency = pt->frequency;
-    ppt->number = pt->number;
-    msg_Dbg (demux, "added payload type %"PRIu8" (f = %"PRIu32" Hz)",
-             ppt->number, ppt->frequency);
-
-    assert (ppt->frequency > 0); /* SIGFPE! */
-    (void)demux;
-    return 0;
-}
-
-/** State for an RTP source */
-struct rtp_source_t
-{
-    uint32_t ssrc;
-    uint32_t jitter;  /* interarrival delay jitter estimate */
-    mtime_t  last_rx; /* last received packet local timestamp */
-    uint32_t last_ts; /* last received packet RTP timestamp */
-
-    uint16_t bad_seq; /* tentatively next expected sequence for resync */
-    uint16_t max_seq; /* next expected sequence */
-
-    uint16_t last_seq; /* sequence of the last dequeued packet */
-    block_t *blocks; /* re-ordered blocks queue */
-    void    *opaque[0]; /* Per-source private payload data */
-};
-
-/**
- * Initializes a new RTP source within an RTP session.
- */
-static rtp_source_t *
-rtp_source_create (demux_t *demux, const rtp_session_t *session,
-                   uint32_t ssrc, uint16_t init_seq)
-{
-    rtp_source_t *source;
-
-    source = malloc (sizeof (*source) + (sizeof (void *) * session->ptc));
-    if (source == NULL)
-        return NULL;
-
-    source->ssrc = ssrc;
-    source->jitter = 0;
-    source->max_seq = source->bad_seq = init_seq;
-    source->last_seq = init_seq - 1;
-    source->blocks = NULL;
-
-    /* Initializes all payload */
-    for (unsigned i = 0; i < session->ptc; i++)
-        source->opaque[i] = session->ptv[i].init (demux);
-
-    msg_Dbg (demux, "added RTP source (%08x)", ssrc);
-    return source;
-}
-
-
-/**
- * Destroys an RTP source and its associated streams.
- */
-static void
-rtp_source_destroy (demux_t *demux, const rtp_session_t *session,
-                    rtp_source_t *source)
-{
-    msg_Dbg (demux, "removing RTP source (%08x)", source->ssrc);
-
-    for (unsigned i = 0; i < session->ptc; i++)
-        session->ptv[i].destroy (demux, source->opaque[i]);
-    block_ChainRelease (source->blocks);
-    free (source);
-}
-
-static inline uint8_t rtp_ptype (const block_t *block)
-{
-    return block->p_buffer[1] & 0x7F;
-}
-
-static inline uint16_t rtp_seq (const block_t *block)
-{
-    assert (block->i_buffer >= 4);
-    return GetWBE (block->p_buffer + 2);
-}
-
-static inline uint32_t rtp_timestamp (const block_t *block)
-{
-    assert (block->i_buffer >= 12);
-    return GetDWBE (block->p_buffer + 4);
-}
-
-static const struct rtp_pt_t *
-rtp_find_ptype (const rtp_session_t *session, rtp_source_t *source,
-                const block_t *block, void **pt_data)
-{
-    uint8_t ptype = rtp_ptype (block);
-
-    for (unsigned i = 0; i < session->ptc; i++)
-    {
-        if (session->ptv[i].number == ptype)
-        {
-            if (pt_data != NULL)
-                *pt_data = source->opaque[i];
-            return &session->ptv[i];
-        }
-    }
-    return NULL;
-}
-
-/**
- * Receives an RTP packet and queues it.
- * @param demux VLC demux object
- * @param session RTP session receiving the packet
- * @param block RTP packet including the RTP header
- */
-void
-rtp_receive (demux_t *demux, rtp_session_t *session, block_t *block)
-{
-    demux_sys_t *p_sys = demux->p_sys;
-
-    /* RTP header sanity checks (see RFC 3550) */
-    if (block->i_buffer < 12)
-        goto drop;
-    if ((block->p_buffer[0] >> 6 ) != 2) /* RTP version number */
-        goto drop;
-
-    /* Remove padding if present */
-    if (block->p_buffer[0] & 0x20)
-    {
-        uint8_t padding = block->p_buffer[block->i_buffer - 1];
-        if ((padding == 0) || (block->i_buffer < (12u + padding)))
-            goto drop; /* illegal value */
-
-        block->i_buffer -= padding;
-    }
-
-    mtime_t        now = mdate ();
-    rtp_source_t  *src  = NULL;
-    const uint16_t seq  = GetWBE (block->p_buffer + 2);
-    const uint32_t ssrc = GetDWBE (block->p_buffer + 8);
-
-    /* In most case, we know this source already */
-    for (unsigned i = 0, max = session->srcc; i < max; i++)
-    {
-        rtp_source_t *tmp = session->srcv[i];
-        if (tmp->ssrc == ssrc)
-        {
-            src = tmp;
-            break;
-        }
-
-        /* RTP source garbage collection */
-        if ((tmp->last_rx + (p_sys->timeout * CLOCK_FREQ)) < now)
-        {
-            rtp_source_destroy (demux, session, tmp);
-            if (--session->srcc > 0)
-                session->srcv[i] = session->srcv[session->srcc - 1];
-        }
-    }
-
-    if (src == NULL)
-    {
-        /* New source */
-        if (session->srcc >= p_sys->max_src)
-        {
-            msg_Warn (demux, "too many RTP sessions");
-            goto drop;
-        }
-
-        rtp_source_t **tab;
-        tab = realloc (session->srcv, (session->srcc + 1) * sizeof (*tab));
-        if (tab == NULL)
-            goto drop;
-        session->srcv = tab;
-
-        src = rtp_source_create (demux, session, ssrc, seq);
-        if (src == NULL)
-            goto drop;
-
-        tab[session->srcc++] = src;
-        /* Cannot compute jitter yet */
-    }
-    else
-    {
-        const rtp_pt_t *pt = rtp_find_ptype (session, src, block, NULL);
-
-        if (pt != NULL)
-        {
-            /* Recompute jitter estimate.
-             * That is computed from the RTP timestamps and the system clock.
-             * It is independent of RTP sequence. */
-            uint32_t freq = pt->frequency;
-            uint32_t ts = rtp_timestamp (block);
-            int64_t d = ((now - src->last_rx) * freq) / CLOCK_FREQ;
-            d        -=    ts - src->last_ts;
-            if (d < 0) d = -d;
-            src->jitter += ((d - src->jitter) + 8) >> 4;
-        }
-    }
-    src->last_rx = now;
-    src->last_ts = rtp_timestamp (block);
-
-    /* Be optimistic for the first packet. Certain codec, such as Vorbis
-     * do not like loosing the first packet(s), so we cannot just wait
-     * for proper sequence synchronization. And we don't want to assume that
-     * the sender starts at seq=0 either. */
-    if (src->blocks == NULL)
-        src->max_seq = seq - p_sys->max_dropout;
-
-    /* Check sequence number */
-    /* NOTE: the sequence number is per-source,
-     * but is independent from the payload type. */
-    uint16_t delta_seq = seq - (src->max_seq + 1);
-    if ((delta_seq < 0x8000) ? (delta_seq > p_sys->max_dropout)
-                             : ((65535 - delta_seq) > p_sys->max_misorder))
-    {
-        msg_Dbg (demux, "sequence discontinuity (got: %u, expected: %u)",
-                 seq, (src->max_seq + 1) & 0xffff);
-        if (seq == ((src->bad_seq + 1) & 0xffff))
-        {
-            src->max_seq = src->bad_seq = seq;
-            msg_Warn (demux, "sequence resynchronized");
-            block_ChainRelease (src->blocks);
-            src->blocks = NULL;
-        }
-        else
-        {
-            src->bad_seq = seq;
-            goto drop;
-        }
-    }
-    else
-    if (delta_seq < 0x8000)
-        src->max_seq = seq;
-
-    /* Queues the block in sequence order,
-     * hence there is a single queue for all payload types. */
-    block_t **pp = &src->blocks;
-    for (block_t *prev = *pp; prev != NULL; prev = *pp)
-    {
-        int16_t delta_seq = seq - rtp_seq (prev);
-        if (delta_seq < 0)
-            break;
-        if (delta_seq == 0)
-            goto drop; /* duplicate */
-        pp = &prev->p_next;
-    }
-    block->p_next = *pp;
-    *pp = block;
-
-    rtp_decode (demux, session, src);
-    return;
-
-drop:
-    block_Release (block);
-}
-
-
-static void
-rtp_decode (demux_t *demux, const rtp_session_t *session, rtp_source_t *src)
-{
-    block_t *block = src->blocks;
-
-    /* Buffer underflow? */
-    if (!block || !block->p_next || !block->p_next->p_next)
-        return;
-    /* TODO: use time rather than packet counts for buffer measurement */
-    src->blocks = block->p_next;
-    block->p_next = NULL;
-
-    /* Discontinuity detection */
-    if (((src->last_seq + 1) & 0xffff) != rtp_seq (block))
-        block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
-    src->last_seq = rtp_seq (block);
-
-    /* Match the payload type */
-    void *pt_data;
-    const rtp_pt_t *pt = rtp_find_ptype (session, src, block, &pt_data);
-    if (pt == NULL)
-    {
-        msg_Dbg (demux, "ignoring unknown payload (%"PRIu8")",
-                 rtp_ptype (block));
-        goto drop;
-    }
-
-    /* Computes the PTS from the RTP timestamp and payload RTP frequency.
-     * DTS is unknown. Also, while the clock frequency depends on the payload
-     * format, a single source MUST only use payloads of a chosen frequency.
-     * Otherwise it would be impossible to compute consistent timestamps. */
-    /* FIXME: handle timestamp wrap properly */
-    /* TODO: sync multiple sources sanely... */
-    const uint32_t timestamp = rtp_timestamp (block);
-    block->i_pts = UINT64_C(1) * CLOCK_FREQ * timestamp / pt->frequency;
-
-    /* CSRC count */
-    size_t skip = 12u + (block->p_buffer[0] & 0x0F) * 4;
-
-    /* Extension header (ignored for now) */
-    if (block->p_buffer[0] & 0x10)
-    {
-        skip += 4;
-        if (block->i_buffer < skip)
-            goto drop;
-
-        skip += 4 * GetWBE (block->p_buffer + skip - 2);
-    }
-
-    if (block->i_buffer < skip)
-        goto drop;
-
-    block->p_buffer += skip;
-    block->i_buffer -= skip;
-
-    pt->decode (demux, pt_data, block);
-    return;
-
-drop:
-    block_Release (block);
-}
diff --git a/modules/demux/rtpxiph.c b/modules/demux/rtpxiph.c
deleted file mode 100644 (file)
index 7f6492e..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-/**
- * @file rtpxiph.c
- * @brief Real-Time Protocol (RTP) Xiph payloads receival
- */
-/*****************************************************************************
- * Copyright © 2008 Rémi Denis-Courmont
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2.0
- * of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- ****************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <stdarg.h>
-#include <assert.h>
-
-#include <vlc_common.h>
-#include <vlc_demux.h>
-#include <vlc_aout.h>
-#include <vlc_network.h>
-#ifdef HAVE_POLL
-# include <poll.h>
-#endif
-#include <vlc_plugin.h>
-
-#include <vlc_codecs.h>
-
-#include "rtp.h"
-#include <srtp.h>
-
-/* PT=dynamic
- * vorbis: Xiph Vorbis audio (draft-ietf-avt-rtp-vorbis-09, RFC FIXME)
- */
-typedef struct rtp_vorbis_t
-{
-    es_out_id_t *id;
-    block_t     *block;
-    uint32_t     ident;
-} rtp_vorbis_t;
-
-static void *vorbis_init (demux_t *demux)
-{
-    rtp_vorbis_t *self = malloc (sizeof (*self));
-
-    if (self == NULL)
-        return NULL;
-
-    self->id = NULL;
-    self->block = NULL;
-    self->ident = 0xffffffff; /* impossible value on the wire */
-    (void)demux;
-    return self;
-}
-
-static void vorbis_destroy (demux_t *demux, void *data)
-{
-    rtp_vorbis_t *self = data;
-
-    if (!data)
-        return;
-    if (self->block)
-    {
-        self->block->i_flags |= BLOCK_FLAG_CORRUPTED;
-        codec_decode (demux, self->id, self->block);
-    }
-    codec_destroy (demux, self->id);
-    free (self);
-}
-
-/* Convert configuration from RTP to VLC format */
-static ssize_t vorbis_header (void **pextra, const uint8_t *buf, size_t len)
-{
-    /* Headers number */
-    if (len == 0)
-          return -1; /* Invalid */
-    unsigned hcount = 1 + *buf++;
-    len--;
-    if (hcount != 3)
-          return -1; /* Invalid */
-
-    /* Header lengths */
-    uint16_t idlen = 0, cmtlen = 0, setuplen = 0;
-    do
-    {
-        if (len == 0)
-            return -1;
-        idlen = (idlen << 7) | (*buf & 0x7f);
-        len--;
-    }
-    while (*buf++ & 0x80);
-    do
-    {
-        if (len == 0)
-            return -1;
-        cmtlen = (cmtlen << 7) | (*buf & 0x7f);
-        len--;
-    }
-    while (*buf++ & 0x80);
-    if (len < idlen + cmtlen)
-        return -1;
-    setuplen = len - (idlen + cmtlen);
-
-    /* Create the VLC extra format header */
-    uint8_t *extra = malloc ((size_t)6 + idlen + cmtlen + setuplen);
-    if (extra == NULL)
-        return -1;
-    uint8_t *ptr = *pextra = extra;
-    /* Identification header */
-    *ptr++ = idlen >> 8;
-    *ptr++ = idlen & 0xff;
-    memcpy (ptr, buf, idlen);
-    buf += idlen;
-    ptr += idlen;
-    /* Comments header */
-    *ptr++ = cmtlen >> 8;
-    *ptr++ = cmtlen & 0xff;
-    memcpy (ptr, buf, cmtlen);
-    buf += cmtlen;
-    ptr += cmtlen;
-    /* Setup header */
-    *ptr++ = setuplen >> 8;
-    *ptr++ = setuplen & 0xff;
-    memcpy (ptr, buf, setuplen);
-    ptr += setuplen;
-    return ptr - extra;
-}
-
-
-static void vorbis_decode (demux_t *demux, void *data, block_t *block)
-{
-    rtp_vorbis_t *self = data;
-
-    if (!data || block->i_buffer < 4)
-        goto drop;
-
-    /* 32-bits Vorbis RTP header (§2.2) */
-    uint32_t ident = GetDWBE (block->p_buffer);
-    block->i_buffer -= 4;
-    block->p_buffer += 4;
-
-    unsigned fragtype = (ident >> 6) & 3;
-    unsigned datatype = (ident >> 4) & 3;
-    unsigned pkts = (ident) & 15;
-    ident >>= 8;
-
-    /* Vorbis RTP defragmentation */
-    if (self->block && (block->i_flags & BLOCK_FLAG_DISCONTINUITY))
-    {   /* Screwed! discontinuity within a fragmented packet */
-        msg_Warn (demux, "discontinuity in fragmented Vorbis packet");
-        block_Release (self->block);
-        self->block = NULL;
-    }
-
-    if (fragtype <= 1)
-    {
-        if (self->block) /* Invalid first fragment */
-        {
-            block_Release (self->block);
-            self->block = NULL;
-        }
-    }
-    else
-    {
-        if (!self->block)
-            goto drop; /* Invalid non-first fragment */
-    }
-
-    if (fragtype > 0)
-    {   /* Fragment */
-        if (pkts > 0 || block->i_buffer < 2)
-            goto drop;
-
-        size_t fraglen = GetWBE (block->p_buffer);
-        if (block->i_buffer < (fraglen + 2))
-            goto drop; /* Invalid payload length */
-        block->i_buffer = fraglen;
-        if (fragtype == 1)/* Keep first fragment */
-        {
-            block->i_buffer += 2;
-            self->block = block;
-        }
-        else
-        {   /* Append non-first fragment */
-            size_t len = self->block->i_buffer;
-            self->block = block_Realloc (self->block, 0, len + fraglen);
-            if (!self->block)
-            {
-                block_Release (block);
-                return;
-            }
-            memcpy (self->block->p_buffer + len, block->p_buffer + 2,
-                    fraglen);
-            block_Release (block);
-        }
-        if (fragtype < 3)
-            return; /* Non-last fragment */
-
-        /* Last fragment reached, process it */
-        block = self->block;
-        self->block = NULL;
-        SetWBE (block->p_buffer, block->i_buffer - 2);
-        pkts = 1;
-    }
-
-    /* Vorbis RTP payload packets processing */
-    while (pkts > 0)
-    {
-        if (block->i_buffer < 2)
-            goto drop;
-
-        size_t len = GetWBE (block->p_buffer);
-        block->i_buffer -= 2;
-        block->p_buffer += 2;
-        if (block->i_buffer < len)
-            goto drop;
-
-        switch (datatype)
-        {
-            case 0: /* Raw audio frame */
-            {
-                if (self->ident != ident)
-                    break; /* Ignore raw without configuration */
-                block_t *raw = block_Alloc (len);
-                memcpy (raw->p_buffer, block->p_buffer, len);
-                raw->i_pts = block->i_pts; /* FIXME: what about pkts > 1 */
-                codec_decode (demux, self->id, raw);
-                break;
-            }
-
-            case 1: /* Packed configuration frame (§3.1.1) */
-            {
-                if (self->ident == ident)
-                    break; /* Ignore config retransmission */
-
-                void *extv;
-                ssize_t extc = vorbis_header (&extv, block->p_buffer, len);
-                if (extc < 0)
-                    break;
-
-                es_format_t fmt;
-                es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('v','o','r','b'));
-                fmt.p_extra = extv;
-                fmt.i_extra = extc;
-                codec_destroy (demux, self->id);
-                msg_Dbg (demux, "Vorbis packed configuration received "
-                         "(%06"PRIx32")", ident);
-                self->ident = ident;
-                self->id = codec_init (demux, &fmt);
-                break;
-            }
-        }
-
-        block->i_buffer -= len;
-        block->p_buffer += len;
-        pkts--;
-    }
-
-drop:
-    block_Release (block);
-}