[vlc-commits] [Git][videolan/vlc][master] 21 commits: rtp: remove stray comment
Rémi Denis-Courmont (@Courmisch)
gitlab at videolan.org
Tue Nov 9 20:36:30 UTC 2021
Rémi Denis-Courmont pushed to branch master at VideoLAN / VLC
Commits:
30b1e43c by Rémi Denis-Courmont at 2021-11-09T20:40:29+02:00
rtp: remove stray comment
The SAP plugin no longer cares about payload formats.
- - - - -
fb3fbcb7 by Rémi Denis-Courmont at 2021-11-09T20:40:29+02:00
rtp: remove no-op
Block flags are not meaningful on the stream/demux interface.
- - - - -
28a7f2dd by Rémi Denis-Courmont at 2021-11-09T20:40:29+02:00
rtp: remove no-op callback
- - - - -
c71d5786 by Rémi Denis-Courmont at 2021-11-09T20:40:29+02:00
rtp: assert the PT init callback
The init callback can not be NULL. That would be completely useless.
- - - - -
e94e45e4 by Rémi Denis-Courmont at 2021-11-09T20:40:29+02:00
rtp: pass pointer to "self"
Some payload type initialisation callbacks will be needing access to a
context soon enough.
- - - - -
311ed8e2 by Rémi Denis-Courmont at 2021-11-09T20:40:29+02:00
rtp: use informed frequency for G.711 and PCM
According to RFC 3551 §4.5, those audio encodings have variable
sampling rates.
- - - - -
8b066cdc by Rémi Denis-Courmont at 2021-11-09T20:40:29+02:00
rtp: assert the PT decode callback
This is always non-NULL.
- - - - -
f50bfe33 by Rémi Denis-Courmont at 2021-11-09T20:40:29+02:00
rtp: simplify copying payload type
...and prepare for callback structure separation.
- - - - -
90582881 by Rémi Denis-Courmont at 2021-11-09T20:40:29+02:00
rtp: add helpers for payload type callbacks
- - - - -
648356b6 by Rémi Denis-Courmont at 2021-11-09T20:40:29+02:00
rtp: use the PT helpers
- - - - -
35dd3ded by Rémi Denis-Courmont at 2021-11-09T20:40:29+02:00
rtp: use separate structure for PT callbacks
- - - - -
44ac686e by Rémi Denis-Courmont at 2021-11-09T20:40:29+02:00
rtp: add channel count to PT
- - - - -
e131da95 by Rémi Denis-Courmont at 2021-11-09T20:40:29+02:00
rtp: use channel count to merge L16 payload types
- - - - -
d346bbab by Rémi Denis-Courmont at 2021-11-09T20:40:29+02:00
rtp: add parser for m= PT list and a=rtpmap
- - - - -
905ace56 by Rémi Denis-Courmont at 2021-11-09T20:41:10+02:00
rtp: fix parsing payload types from SDP
- - - - -
099d5a87 by Rémi Denis-Courmont at 2021-11-09T20:41:12+02:00
rtp: remove obsolete rtp-dynamic-pt option
- - - - -
0247129d by Rémi Denis-Courmont at 2021-11-09T20:41:12+02:00
rtp: deduplicate static payload formats
- - - - -
69323242 by Rémi Denis-Courmont at 2021-11-09T20:41:12+02:00
rtp: expose vlc_rtp_pt_release()
- - - - -
989d40a4 by Rémi Denis-Courmont at 2021-11-09T20:41:12+02:00
rtp: track payload types by reference
(instead of copying them)
- - - - -
847c7a90 by Rémi Denis-Courmont at 2021-11-09T20:41:12+02:00
rtp: remove useless parameter
- - - - -
084c5979 by Rémi Denis-Courmont at 2021-11-09T20:41:12+02:00
rtp: lower demux_t requirement to vlc_object_t
- - - - -
6 changed files:
- modules/access/rtp/input.c
- modules/access/rtp/rtp.c
- modules/access/rtp/rtp.h
- modules/access/rtp/rtpfmt.c
- modules/access/rtp/session.c
- modules/access/rtp/xiph.c
Changes:
=====================================
modules/access/rtp/input.c
=====================================
@@ -77,7 +77,7 @@ static void rtp_process (demux_t *demux, block_t *block)
/* TODO: use SDP and get rid of this hack */
if (unlikely(sys->autodetect))
{ /* Autodetect payload type, _before_ rtp_queue() */
- rtp_autodetect (demux, sys->session, block);
+ rtp_autodetect(VLC_OBJECT(demux), sys->session, block);
sys->autodetect = false;
}
=====================================
modules/access/rtp/rtp.c
=====================================
@@ -32,6 +32,7 @@
#include <vlc_network.h>
#include <vlc_plugin.h>
#include <vlc_dtls.h>
+#include <vlc_modules.h> /* module_exists() */
#include "rtp.h"
#ifdef HAVE_SRTP
@@ -44,7 +45,6 @@
/*
* 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 stream_filter in case of chained demux (MPEG-TS)
*/
@@ -199,13 +199,6 @@ static int OpenSDP(vlc_object_t *obj)
goto error;
}
- /* Check payload type (FIXME: handle multiple, match w/ a=rtpmap) */
- unsigned char pt = atoi(media->format);
- if (pt >= 64 || !(UINT64_C(0x300005d09) & (UINT64_C(1) << pt))) {
- msg_Dbg(obj, "unsupported payload format(s) %s", media->format);
- goto error;
- }
-
if (vlc_sdp_media_attr_value(media, "control") != NULL
|| vlc_sdp_attr_value(sdp, "control") != NULL) {
msg_Dbg(obj, "RTSP not supported");
@@ -294,15 +287,12 @@ static int OpenSDP(vlc_object_t *obj)
}
}
- vlc_sdp_free(sdp);
- sdp = NULL;
-
sys->chained_demux = NULL;
sys->max_src = var_InheritInteger(obj, "rtp-max-src");
sys->timeout = vlc_tick_from_sec(var_InheritInteger(obj, "rtp-timeout"));
sys->max_dropout = var_InheritInteger(obj, "rtp-max-dropout");
sys->max_misorder = -var_InheritInteger(obj, "rtp-max-misorder");
- sys->autodetect = true;
+ sys->autodetect = false;
demux->pf_demux = NULL;
demux->pf_control = Control;
@@ -312,11 +302,22 @@ static int OpenSDP(vlc_object_t *obj)
if (sys->session == NULL)
goto error;
+ /* Parse payload types */
+ int err = vlc_rtp_add_media_types(obj, sys->session, media);
+ if (err < 0) {
+ msg_Err(obj, "SDP description parse error");
+ goto error;
+ }
+ if (err > 0 && module_exists("live555")) /* Bail out to live555 */
+ goto error;
+
if (vlc_clone(&sys->thread, rtp_dgram_thread, demux,
VLC_THREAD_PRIORITY_INPUT)) {
rtp_session_destroy(demux, sys->session);
goto error;
}
+
+ vlc_sdp_free(sdp);
return VLC_SUCCESS;
error:
@@ -324,8 +325,7 @@ error:
vlc_dtls_Close(sys->rtcp_sock);
if (sys->rtp_sock != NULL)
vlc_dtls_Close(sys->rtp_sock);
- if (sdp != NULL)
- vlc_sdp_free(sdp);
+ vlc_sdp_free(sdp);
return VLC_EGENERIC;
}
@@ -532,16 +532,6 @@ error:
"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." )
-#define RTP_DYNAMIC_PT_TEXT N_("RTP payload format assumed for dynamic " \
- "payloads")
-#define RTP_DYNAMIC_PT_LONGTEXT N_( \
- "This payload format will be assumed for dynamic payload types " \
- "(between 96 and 127) if it can't be determined otherwise with " \
- "out-of-band mappings (SDP)" )
-
-static const char *const dynamic_pt_list[] = { "", "theora" };
-static const char *const dynamic_pt_list_text[] = { N_( "Unset" ), N_( "Theora Encoded Video" ) };
-
/*
* Module descriptor
*/
@@ -580,9 +570,7 @@ vlc_module_begin()
add_integer("rtp-max-misorder", 100, RTP_MAX_MISORDER_TEXT,
RTP_MAX_MISORDER_LONGTEXT)
change_integer_range (0, 32767)
- add_string("rtp-dynamic-pt", "", RTP_DYNAMIC_PT_TEXT,
- RTP_DYNAMIC_PT_LONGTEXT)
- change_string_list(dynamic_pt_list, dynamic_pt_list_text)
+ add_obsolete_string("rtp-dynamic-pt") /* since 4.0.0 */
/*add_shortcut ("sctp")*/
add_shortcut("dccp", "rtp", "udplite")
=====================================
modules/access/rtp/rtp.h
=====================================
@@ -20,22 +20,90 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
-typedef struct rtp_pt_t rtp_pt_t;
+typedef struct vlc_rtp_pt rtp_pt_t;
typedef struct rtp_session_t rtp_session_t;
struct vlc_demux_chained_t;
+struct vlc_sdp_media;
/** @section RTP payload format */
-struct rtp_pt_t
+
+struct vlc_sdp_pt {
+ const struct vlc_sdp_media *media;
+ char name[16];
+ unsigned int clock_rate;
+ unsigned char channel_count;
+ const char *parameters;
+};
+
+struct vlc_rtp_pt_operations {
+ void *(*init)(struct vlc_rtp_pt *, demux_t *);
+ void (*destroy)(demux_t *, void *);
+ void (*decode)(demux_t *, void *, block_t *);
+};
+
+struct vlc_rtp_pt
{
- void *(*init) (demux_t *);
- void (*destroy) (demux_t *, void *);
- void (*header) (demux_t *, void *, block_t *);
- void (*decode) (demux_t *, void *, block_t *);
+ const struct vlc_rtp_pt_operations *ops;
uint32_t frequency; /* RTP clock rate (Hz) */
uint8_t number;
+ uint8_t channel_count;
};
-void rtp_autodetect (demux_t *, rtp_session_t *, const block_t *);
+
+/**
+ * Destroys a payload type parameter set.
+ */
+void vlc_rtp_pt_release(struct vlc_rtp_pt *pt);
+
+/**
+ * Instantiates a payload type from a set of parameters.
+ *
+ * A given SDP media can have multiple alternative payload types, each with
+ * their set of parameters. The RTP session can then have multiple concurrent
+ * RTP sources (SSRC). This function creates an instance of a given payload
+ * type for use by an unique RTP source.
+ *
+ * @param pt RTP payload type to instantiate
+ * @param demux demux object for output
+ * @return private data for the instance
+ */
+static inline void *vlc_rtp_pt_begin(struct vlc_rtp_pt *pt, demux_t *demux)
+{
+ assert(pt->ops->init != NULL);
+ return pt->ops->init(pt, demux);
+}
+
+/**
+ * Deinstantiates a payload type.
+ *
+ * This destroys an instance of a payload type created by vlc_rtp_pt_begin().
+ *
+ * @param pt RTP payload type to deinstantiate
+ * @param demux demux object that was used by the instance
+ * @param data instance private data as returned by vlc_rtp_pt_begin()
+ */
+static inline void vlc_rtp_pt_end(struct vlc_rtp_pt *pt, demux_t *demux,
+ void *data)
+{
+ if (pt->ops->destroy != NULL)
+ pt->ops->destroy(demux, data);
+}
+
+/**
+ * Processes an payload packet.
+ *
+ * This passes a data payload of an RTP packet to the instance of the
+ * payload type specified in the packet (PT and SSRC fields).
+ */
+static inline void vlc_rtp_pt_decode(const struct vlc_rtp_pt *pt,
+ demux_t *demux,
+ void *data, block_t *pkt)
+{
+ assert(pt->ops->decode != NULL);
+ pt->ops->decode(demux, data, pkt);
+}
+
+void rtp_autodetect(vlc_object_t *, rtp_session_t *, const block_t *);
static inline uint8_t rtp_ptype (const block_t *block)
{
@@ -46,16 +114,16 @@ void *codec_init (demux_t *demux, es_format_t *fmt);
void codec_destroy (demux_t *demux, void *data);
void codec_decode (demux_t *demux, void *data, block_t *block);
-void *theora_init (demux_t *demux);
-void xiph_destroy (demux_t *demux, void *data);
-void xiph_decode (demux_t *demux, void *data, block_t *block);
+extern const struct vlc_rtp_pt_operations rtp_video_theora;
/** @section RTP session */
rtp_session_t *rtp_session_create (demux_t *);
void rtp_session_destroy (demux_t *, rtp_session_t *);
void rtp_queue (demux_t *, rtp_session_t *, block_t *);
bool rtp_dequeue (demux_t *, const rtp_session_t *, vlc_tick_t *);
-int rtp_add_type (demux_t *demux, rtp_session_t *ses, const rtp_pt_t *pt);
+int rtp_add_type(rtp_session_t *ses, rtp_pt_t *pt);
+int vlc_rtp_add_media_types(vlc_object_t *obj, rtp_session_t *ses,
+ const struct vlc_sdp_media *media);
void *rtp_dgram_thread (void *data);
=====================================
modules/access/rtp/rtpfmt.c
=====================================
@@ -25,6 +25,7 @@
#endif
#include <stdlib.h>
+#include <errno.h>
#include <vlc_common.h>
#include <vlc_demux.h>
@@ -32,6 +33,7 @@
#include <vlc_aout.h> /* aout_FormatPrepare() */
#include "rtp.h"
+#include "sdp.h"
/*
* Generic packet handlers
@@ -85,16 +87,6 @@ static void stream_destroy (demux_t *demux, void *data)
}
}
-static void stream_header (demux_t *demux, void *data, block_t *block)
-{
- VLC_UNUSED(demux);
- VLC_UNUSED(data);
- if(block->p_buffer[1] & 0x80) /* TS M-bit == discontinuity (RFC 2250, 2.1) */
- {
- block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
- }
-}
-
/* Send a packet to a chained demuxer */
static void stream_decode (demux_t *demux, void *data, block_t *block)
{
@@ -112,88 +104,101 @@ static void stream_decode (demux_t *demux, void *data, block_t *block)
/* PT=0
* PCMU: G.711 µ-law (RFC3551)
*/
-static void *pcmu_init (demux_t *demux)
+static void *pcmu_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_MULAW);
- fmt.audio.i_rate = 8000;
+ fmt.audio.i_rate = pt->frequency;
fmt.audio.i_physical_channels = AOUT_CHAN_CENTER;
return codec_init (demux, &fmt);
}
+static const struct vlc_rtp_pt_operations rtp_audio_pcmu = {
+ pcmu_init, codec_destroy, codec_decode,
+};
+
/* PT=3
* GSM
*/
-static void *gsm_init (demux_t *demux)
+static void *gsm_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_GSM);
fmt.audio.i_rate = 8000;
fmt.audio.i_physical_channels = AOUT_CHAN_CENTER;
+ (void) pt;
return codec_init (demux, &fmt);
}
+static const struct vlc_rtp_pt_operations rtp_audio_gsm = {
+ gsm_init, codec_destroy, codec_decode,
+};
+
/* PT=8
* PCMA: G.711 A-law (RFC3551)
*/
-static void *pcma_init (demux_t *demux)
+static void *pcma_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_ALAW);
- fmt.audio.i_rate = 8000;
+ fmt.audio.i_rate = pt->frequency;
fmt.audio.i_physical_channels = AOUT_CHAN_CENTER;
return codec_init (demux, &fmt);
}
+static const struct vlc_rtp_pt_operations rtp_audio_pcma = {
+ pcma_init, codec_destroy, codec_decode,
+};
+
/* PT=10,11
* L16: 16-bits (network byte order) PCM
*/
-static void *l16s_init (demux_t *demux)
+static void *l16_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_S16B);
- fmt.audio.i_rate = 44100;
- fmt.audio.i_physical_channels = AOUT_CHANS_STEREO;
+ fmt.audio.i_rate = pt->frequency;
+ fmt.audio.i_channels = pt->channel_count ? pt->channel_count : 1;
return codec_init (demux, &fmt);
}
-static void *l16m_init (demux_t *demux)
-{
- es_format_t fmt;
-
- es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_S16B);
- fmt.audio.i_rate = 44100;
- fmt.audio.i_physical_channels = AOUT_CHAN_CENTER;
- return codec_init (demux, &fmt);
-}
+static const struct vlc_rtp_pt_operations rtp_audio_l16 = {
+ l16_init, codec_destroy, codec_decode,
+};
/* PT=12
* QCELP
*/
-static void *qcelp_init (demux_t *demux)
+static void *qcelp_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_QCELP);
fmt.audio.i_rate = 8000;
fmt.audio.i_physical_channels = AOUT_CHAN_CENTER;
+ (void) pt;
return codec_init (demux, &fmt);
}
+static const struct vlc_rtp_pt_operations rtp_audio_qcelp = {
+ qcelp_init, codec_destroy, codec_decode,
+};
+
/* PT=14
* MPA: MPEG Audio (RFC2250, §3.4)
*/
-static void *mpa_init (demux_t *demux)
+static void *mpa_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_MPGA);
fmt.audio.i_physical_channels = AOUT_CHANS_STEREO;
fmt.b_packetized = false;
+ (void) pt;
return codec_init (demux, &fmt);
}
@@ -211,16 +216,20 @@ static void mpa_decode (demux_t *demux, void *data, block_t *block)
codec_decode (demux, data, block);
}
+static const struct vlc_rtp_pt_operations rtp_audio_mpa = {
+ mpa_init, codec_destroy, mpa_decode,
+};
/* PT=32
* MPV: MPEG Video (RFC2250, §3.5)
*/
-static void *mpv_init (demux_t *demux)
+static void *mpv_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, VIDEO_ES, VLC_CODEC_MPGV);
fmt.b_packetized = false;
+ (void) pt;
return codec_init (demux, &fmt);
}
@@ -244,128 +253,254 @@ static void mpv_decode (demux_t *demux, void *data, block_t *block)
codec_decode (demux, data, block);
}
+static const struct vlc_rtp_pt_operations rtp_video_mpv = {
+ mpv_init, codec_destroy, mpv_decode,
+};
/* PT=33
* MP2: MPEG TS (RFC2250, §2)
*/
-static void *ts_init (demux_t *demux)
+static void *ts_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
+ (void) pt;
return stream_init (demux, "ts");
}
+static const struct vlc_rtp_pt_operations rtp_av_ts = {
+ ts_init, stream_destroy, stream_decode,
+};
/* Not using SDP, we need to guess the payload format used */
/* see http://www.iana.org/assignments/rtp-parameters */
-void rtp_autodetect (demux_t *demux, rtp_session_t *session,
- const block_t *block)
+void rtp_autodetect(vlc_object_t *obj, rtp_session_t *session,
+ const block_t *block)
{
uint8_t ptype = rtp_ptype (block);
- rtp_pt_t pt = {
- .init = NULL,
- .destroy = codec_destroy,
- .header = NULL,
- .decode = codec_decode,
- .frequency = 0,
- .number = ptype,
+ char type[6], proto[] = "RTP/AVP", numstr[4];
+ struct vlc_sdp_media media = {
+ .type = type, .port_count = 1, .proto = proto, .format = numstr
};
- /* Remember to keep this in sync with modules/services_discovery/sap.c */
- switch (ptype)
- {
- case 0:
- msg_Dbg (demux, "detected G.711 mu-law");
- pt.init = pcmu_init;
- pt.frequency = 8000;
- break;
-
- case 3:
- msg_Dbg (demux, "detected GSM");
- pt.init = gsm_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 12:
- msg_Dbg (demux, "detected QCELP");
- pt.init = qcelp_init;
- pt.frequency = 8000;
- 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.header = stream_header;
- pt.decode = stream_decode;
- pt.frequency = 90000;
- break;
-
- default:
- if (ptype >= 96)
- {
- char *dynamic = var_InheritString(demux, "rtp-dynamic-pt");
- if (dynamic == NULL)
- ;
- else if (!strcmp(dynamic, "theora"))
- {
- msg_Dbg (demux, "assuming Theora Encoded Video");
- pt.init = theora_init;
- pt.destroy = xiph_destroy;
- pt.decode = xiph_decode;
- pt.frequency = 90000;
-
- free (dynamic);
- break;
- }
- else
- msg_Err (demux, "unknown dynamic payload format `%s' "
- "specified", dynamic);
- free (dynamic);
- }
+ /* We only support static audio subtypes except MPV (PT=32).
+ * MP2T (PT=33) can be treated as either audio or video. */
+ memcpy(type, (ptype == 32) ? "video" : "audio", 6);
+ snprintf(numstr, sizeof (numstr), "%hhu", ptype);
- msg_Err (demux, "unspecified payload format (type %"PRIu8")", ptype);
- msg_Info (demux, "A valid SDP is needed to parse this RTP stream.");
- vlc_dialog_display_error (demux, N_("SDP required"),
+ if (vlc_rtp_add_media_types(obj, session, &media)) {
+ msg_Err(obj, "unspecified payload format (type %"PRIu8")", ptype);
+ msg_Info(obj, "A valid SDP is needed to parse this RTP stream.");
+ vlc_dialog_display_error(obj, N_("SDP required"),
N_("A description in SDP format is required to receive the RTP "
"stream. Note that rtp:// URIs cannot work with dynamic "
"RTP payload format (%"PRIu8")."), ptype);
- return;
}
- rtp_add_type (demux, session, &pt);
}
/*
* Dynamic payload type handlers
- * Hmm, none implemented yet apart from Xiph ones.
*/
+
+static struct vlc_rtp_pt *vlc_rtp_pt_create(vlc_object_t *obj,
+ const struct vlc_sdp_pt *desc)
+{
+ if (desc->clock_rate == 0) {
+ /* Dynamic payload type not defined in the SDP */
+ errno = EINVAL;
+ return NULL;
+ }
+
+ struct vlc_rtp_pt *pt = malloc(sizeof (*pt));
+ if (unlikely(pt == NULL))
+ return NULL;
+
+ pt->frequency = desc->clock_rate;
+ pt->channel_count = desc->channel_count;
+ pt->ops = NULL;
+
+ /* TODO: introduce module (capabilities) for payload types */
+ if (strcmp(desc->media->type, "audio") == 0) {
+ if (strcmp(desc->name, "PCMU") == 0)
+ pt->ops = &rtp_audio_pcmu;
+ else if (strcmp(desc->name, "GSM") == 0)
+ pt->ops = &rtp_audio_gsm;
+ else if (strcmp(desc->name, "PCMA") == 0)
+ pt->ops = &rtp_audio_pcma;
+ else if (strcmp(desc->name, "L16") == 0)
+ pt->ops = &rtp_audio_l16;
+ else if (strcmp(desc->name, "QCLEP") == 0)
+ pt->ops = &rtp_audio_qcelp;
+ else if (strcmp(desc->name, "MPA") == 0)
+ pt->ops = &rtp_audio_mpa;
+ } else if (strcmp(desc->media->type, "video") == 0) {
+ if (strcmp(desc->name, "MPV") == 0)
+ pt->ops = &rtp_video_mpv;
+ }
+
+ if (strcmp(desc->name, "MP2T") == 0)
+ pt->ops = &rtp_av_ts;
+
+ if (pt->ops == NULL) {
+ msg_Err(obj, "unsupported media type %s/%s", desc->media->type,
+ desc->name);
+ free(pt);
+ errno = ENOTSUP;
+ pt = NULL;
+ }
+
+ return pt;
+}
+
+void vlc_rtp_pt_release(struct vlc_rtp_pt *pt)
+{
+ free(pt);
+}
+
+struct vlc_sdp_pt_default {
+ unsigned char number;
+ char subtype[6];
+ unsigned char channel_count;
+ unsigned int clock_rate;
+};
+
+/**
+ * Sets the static payload types.
+ */
+static void vlc_rtp_set_default_types(struct vlc_sdp_pt *restrict types,
+ const struct vlc_sdp_media *media)
+{
+ /* Implicit payload type mappings (RFC3551 section 6) */
+ static const struct vlc_sdp_pt_default audio_defaults[] = {
+ { 0, "PCMU", 1, 8000, },
+ { 3, "GSM", 1, 8000, },
+ { 4, "G723", 1, 8000, },
+ { 5, "DIV4", 1, 8000, },
+ { 6, "DIV4", 1, 16000, },
+ { 7, "LPC", 1, 8000, },
+ { 8, "PCMA", 1, 8000, },
+ { 9, "G722", 1, 8000, },
+ { 10, "L16", 2, 44100, },
+ { 11, "L16", 1, 44100, },
+ { 12, "QCELP", 1, 8000, },
+ { 13, "CN", 1, 8000, },
+ { 14, "MPA", 0, 90000 },
+ { 15, "G728", 1, 8000, },
+ { 16, "DIV4", 1, 11025, },
+ { 17, "DIV4", 1, 22050, },
+ { 18, "G729", 1, 8000, },
+ { 33, "MP2T", 0, 90000, },
+ };
+ static const struct vlc_sdp_pt_default video_defaults[] = {
+ { 25, "CelB", 0, 90000, },
+ { 26, "JPEG", 0, 90000, },
+ { 28, "nv", 0, 90000, },
+ { 31, "H261", 0, 90000, },
+ { 32, "MPV", 0, 90000, },
+ { 33, "MP2T", 0, 90000, },
+ { 34, "H263", 0, 90000, },
+ };
+ const struct vlc_sdp_pt_default *defs = NULL;
+ size_t def_size = 0;
+
+ if (strcmp(media->type, "audio") == 0) {
+ defs = audio_defaults;
+ def_size = ARRAY_SIZE(audio_defaults);
+ } else if (strcmp(media->type, "video") == 0) {
+ defs = video_defaults;
+ def_size = ARRAY_SIZE(video_defaults);
+ }
+
+ for (size_t i = 0; i < def_size; i++) {
+ const struct vlc_sdp_pt_default *def = defs + i;
+ struct vlc_sdp_pt *pt = types + def->number;
+
+ pt->media = media;
+ strcpy(pt->name, def->subtype);
+ pt->clock_rate = def->clock_rate;
+ pt->channel_count = def->channel_count;
+ }
+}
+
+/**
+ * Registers all payload types declared in an SDP media.
+ */
+int vlc_rtp_add_media_types(vlc_object_t *obj, rtp_session_t *session,
+ const struct vlc_sdp_media *media)
+{
+ struct vlc_sdp_pt types[128] = { };
+
+ vlc_rtp_set_default_types(types, media);
+
+ /* Parse the a=rtpmap and extract a=fmtp lines */
+ for (const struct vlc_sdp_attr *a = media->attrs; a != NULL; a = a->next) {
+ if (strcmp(a->name, "rtpmap") == 0) {
+ unsigned char number, channels;
+ char name[16];
+ unsigned int frequency;
+
+ switch (sscanf(a->value, "%hhu %15[^/]/%u/%hhu", &number, name,
+ &frequency, &channels)) {
+ case 3:
+ channels = 0;
+ /* fall through */
+ case 4:
+ if (number < ARRAY_SIZE(types)) {
+ strcpy(types[number].name, name);
+ types[number].clock_rate = frequency;
+ types[number].channel_count = channels;
+ }
+ break;
+ }
+
+ } else if (strcmp(a->name, "fmtp") == 0) {
+ unsigned char number;
+ int offset;
+
+ if (sscanf(a->value, "%hhu %n", &number, &offset) == 1
+ && number < ARRAY_SIZE(types))
+ types[number].parameters = a->value + offset;
+ }
+ }
+
+ const char *numbers = media->format; /* space-separated list of PTs */
+ char *end;
+ int errors = 0;
+
+ for (;;) {
+ unsigned long number = strtoul(numbers, &end, 10);
+
+ if (end == numbers) {
+ if (*end != '\0')
+ return -EINVAL;
+ break; /* garbage or end of the line */
+ }
+
+ numbers = end + strspn(end, " "); /* next PT number */
+
+ if (number >= ARRAY_SIZE(types))
+ continue;
+
+ struct vlc_sdp_pt *const type = types + number;
+
+ if (type->media == NULL) /* not defined or already used */
+ continue;
+
+ msg_Dbg(obj, "payload type %lu: %s/%s, %u Hz", number,
+ media->type, type->name, type->clock_rate);
+ if (type->channel_count > 0)
+ msg_Dbg(obj, " - %hhu channel(s)", type->channel_count);
+ if (type->parameters != NULL)
+ msg_Dbg(obj, " - parameters: %s", type->parameters);
+
+ struct vlc_rtp_pt *pt = vlc_rtp_pt_create(obj, type);
+ if (pt != NULL) {
+ pt->number = number;
+ if (rtp_add_type(session, pt))
+ vlc_rtp_pt_release(pt);
+ } else
+ errors++;
+
+ type->media = NULL; /* Prevent duplicate PT numbers. */
+ }
+
+ return errors;
+}
=====================================
modules/access/rtp/session.c
=====================================
@@ -41,7 +41,7 @@ struct rtp_session_t
rtp_source_t **srcv;
unsigned srcc;
uint8_t ptc;
- rtp_pt_t *ptv;
+ rtp_pt_t **ptv;
};
static rtp_source_t *
@@ -79,58 +79,31 @@ 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]);
+ for (uint_fast8_t i = 0; i < session->ptc; i++)
+ vlc_rtp_pt_release(session->ptv[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)
+int rtp_add_type(rtp_session_t *ses, rtp_pt_t *pt)
{
+ assert(pt->frequency > 0); /* SIGFPE! */
+
if (ses->srcc > 0)
- {
- msg_Err (demux, "cannot change RTP payload formats during session");
- return EINVAL;
- }
+ return EBUSY;
- rtp_pt_t *ppt = realloc (ses->ptv, (ses->ptc + 1) * sizeof (rtp_pt_t));
+ rtp_pt_t **ppt = realloc(ses->ptv, (ses->ptc + 1) * sizeof (pt));
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->header = NULL;
- 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;
+ ses->ptv[ses->ptc++] = pt;
return 0;
}
@@ -176,7 +149,7 @@ rtp_source_create (demux_t *demux, const rtp_session_t *session,
/* Initializes all payload */
for (unsigned i = 0; i < session->ptc; i++)
- source->opaque[i] = session->ptv[i].init (demux);
+ source->opaque[i] = vlc_rtp_pt_begin(session->ptv[i], demux);
msg_Dbg (demux, "added RTP source (%08x)", ssrc);
return source;
@@ -193,7 +166,7 @@ rtp_source_destroy (demux_t *demux, const rtp_session_t *session,
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]);
+ vlc_rtp_pt_end(session->ptv[i], demux, source->opaque[i]);
block_ChainRelease (source->blocks);
free (source);
}
@@ -210,7 +183,7 @@ static inline uint32_t rtp_timestamp (const block_t *block)
return GetDWBE (block->p_buffer + 4);
}
-static const struct rtp_pt_t *
+static const struct vlc_rtp_pt *
rtp_find_ptype (const rtp_session_t *session, rtp_source_t *source,
const block_t *block, void **pt_data)
{
@@ -218,11 +191,13 @@ rtp_find_ptype (const rtp_session_t *session, rtp_source_t *source,
for (unsigned i = 0; i < session->ptc; i++)
{
- if (session->ptv[i].number == ptype)
+ struct vlc_rtp_pt *pt = session->ptv[i];
+
+ if (pt->number == ptype)
{
if (pt_data != NULL)
*pt_data = source->opaque[i];
- return &session->ptv[i];
+ return pt;
}
}
return NULL;
@@ -502,9 +477,6 @@ rtp_decode (demux_t *demux, const rtp_session_t *session, rtp_source_t *src)
goto drop;
}
- if(pt->header)
- pt->header(demux, pt_data, block);
-
/* 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.
@@ -540,7 +512,7 @@ rtp_decode (demux_t *demux, const rtp_session_t *session, rtp_source_t *src)
block->p_buffer += skip;
block->i_buffer -= skip;
- pt->decode (demux, pt_data, block);
+ vlc_rtp_pt_decode(pt, demux, pt_data, block);
return;
drop:
=====================================
modules/access/rtp/xiph.c
=====================================
@@ -71,13 +71,13 @@ static void *vorbis_init (demux_t *demux)
/* PT=dynamic
* vorbis: Xiph Theora video
*/
-void *theora_init (demux_t *demux)
+static void *theora_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
- (void)demux;
+ (void) pt; (void) demux;
return xiph_init (false);
}
-void xiph_destroy (demux_t *demux, void *data)
+static void xiph_destroy(demux_t *demux, void *data)
{
rtp_xiph_t *self = data;
@@ -142,8 +142,7 @@ static ssize_t xiph_header (void **pextra, const uint8_t *buf, size_t len)
return extra_size;
}
-
-void xiph_decode (demux_t *demux, void *data, block_t *block)
+static void xiph_decode(demux_t *demux, void *data, block_t *block)
{
rtp_xiph_t *self = data;
@@ -286,3 +285,7 @@ void xiph_decode (demux_t *demux, void *data, block_t *block)
drop:
block_Release (block);
}
+
+const struct vlc_rtp_pt_operations rtp_video_theora = {
+ theora_init, xiph_destroy, xiph_decode,
+};
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/a8613e9b92db9a29b87ca81ef2ec12d8ec1f345a...084c59793a50fba3eb84a82ca741d512250211dc
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/a8613e9b92db9a29b87ca81ef2ec12d8ec1f345a...084c59793a50fba3eb84a82ca741d512250211dc
You're receiving this email because of your account on code.videolan.org.
More information about the vlc-commits
mailing list