[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