[vlc-commits] commit: rtp sout: send in-band vorbis/theora configuration packets ( Pierre Ynard )

git at videolan.org git at videolan.org
Fri Dec 3 02:25:09 CET 2010


vlc | branch: master | Pierre Ynard <linkfanel at yahoo.fr> | Fri Dec  3 02:20:05 2010 +0100| [b2bc67df36f7234f18f757c7719827ccd698e266] | committer: Pierre Ynard 

rtp sout: send in-band vorbis/theora configuration packets

This is an alternative to SDP to convey the codec configuration
necessary to decode the stream. The configuration is sent only once at
the beginning of the stream; at least you won't be tempted to waste
bandwidth with retransmissions. This is a ad-hoc hack, but it's not too
bad or pervasive.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=b2bc67df36f7234f18f757c7719827ccd698e266
---

 modules/stream_out/rtp.c    |    9 +++++
 modules/stream_out/rtp.h    |    3 ++
 modules/stream_out/rtpfmt.c |   84 +++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 93 insertions(+), 3 deletions(-)

diff --git a/modules/stream_out/rtp.c b/modules/stream_out/rtp.c
index ebb3330..6e2e8a9 100644
--- a/modules/stream_out/rtp.c
+++ b/modules/stream_out/rtp.c
@@ -1261,6 +1261,15 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
     while( p_buffer != NULL )
     {
         p_next = p_buffer->p_next;
+
+        /* Send a Vorbis/Theora Packed Configuration packet (RFC 5215 §3.1)
+         * as the first packet of the stream */
+        if (id->i_sequence == id->i_seq_sent_next
+            && (!strcmp(id->rtp_fmt.ptname, "vorbis")
+                || !strcmp(id->rtp_fmt.ptname, "theora")))
+                rtp_packetize_xiph_config(id, id->rtp_fmt.fmtp,
+                                          p_buffer->i_pts);
+
         if( id->rtp_fmt.pf_packetize( id, p_buffer ) )
             break;
 
diff --git a/modules/stream_out/rtp.h b/modules/stream_out/rtp.h
index a391577..e9c1655 100644
--- a/modules/stream_out/rtp.h
+++ b/modules/stream_out/rtp.h
@@ -59,6 +59,9 @@ void rtp_packetize_common (sout_stream_id_t *id, block_t *out,
 void rtp_packetize_send (sout_stream_id_t *id, block_t *out);
 size_t rtp_mtu (const sout_stream_id_t *id);
 
+int rtp_packetize_xiph_config( sout_stream_id_t *id, const char *fmtp,
+                               int64_t i_pts );
+
 /* RTCP */
 typedef struct rtcp_sender_t rtcp_sender_t;
 rtcp_sender_t *OpenRTCP (vlc_object_t *obj, int rtp_fd, int proto,
diff --git a/modules/stream_out/rtpfmt.c b/modules/stream_out/rtpfmt.c
index 1907bb6..05417ba 100644
--- a/modules/stream_out/rtpfmt.c
+++ b/modules/stream_out/rtpfmt.c
@@ -494,9 +494,10 @@ int rtp_get_fmt( vlc_object_t *obj, es_format_t *p_fmt, const char *mux,
 
                 if( asprintf( &rtp_fmt->fmtp,
                               "sampling=YCbCr-4:%d:%d; width=%d; height=%d; "
-                              "delivery-method=inline; configuration=%s;",
-                              c1, c2, p_fmt->video.i_width,
-                              p_fmt->video.i_height, config ) == -1 )
+                              "delivery-method=inline; configuration=%s; "
+                              "delivery-method=in_band;", c1, c2,
+                              p_fmt->video.i_width, p_fmt->video.i_height,
+                              config ) == -1 )
                     rtp_fmt->fmtp = NULL;
                 free(config);
             }
@@ -522,6 +523,83 @@ rtp_packetize_h264_nal( sout_stream_id_t *id,
                         const uint8_t *p_data, int i_data, int64_t i_pts,
                         int64_t i_dts, bool b_last, int64_t i_length );
 
+int rtp_packetize_xiph_config( sout_stream_id_t *id, const char *fmtp,
+                               int64_t i_pts )
+{
+    if (fmtp == NULL)
+        return VLC_EGENERIC;
+
+    /* extract base64 configuration from fmtp */
+    char *start = strstr(fmtp, "configuration=");
+    assert(start != NULL);
+    start += sizeof("configuration=") - 1;
+    char *end = strchr(start, ';');
+    assert(end != NULL);
+    size_t len = end - start;
+    char b64[len + 1];
+    memcpy(b64, start, len);
+    b64[len] = '\0';
+
+    int     i_max   = rtp_mtu (id) - 6; /* payload max in one packet */
+
+    uint8_t *p_orig, *p_data;
+    int i_data;
+
+    i_data = vlc_b64_decode_binary(&p_orig, b64);
+    if (i_data == 0)
+        return VLC_EGENERIC;
+    assert(i_data > 9);
+    p_data = p_orig + 9;
+    i_data -= 9;
+
+    int i_count = ( i_data + i_max - 1 ) / i_max;
+
+    for( int i = 0; i < i_count; i++ )
+    {
+        int           i_payload = __MIN( i_max, i_data );
+        block_t *out = block_Alloc( 18 + i_payload );
+
+        unsigned fragtype, numpkts;
+        if (i_count == 1)
+        {
+            fragtype = 0;
+            numpkts = 1;
+        }
+        else
+        {
+            numpkts = 0;
+            if (i == 0)
+                fragtype = 1;
+            else if (i == i_count - 1)
+                fragtype = 3;
+            else
+                fragtype = 2;
+        }
+        /* Ident:24, Fragment type:2, Vorbis/Theora Data Type:2, # of pkts:4 */
+        uint32_t header = ((XIPH_IDENT & 0xffffff) << 8) |
+                          (fragtype << 6) | (1 << 4) | numpkts;
+
+        /* rtp common header */
+        rtp_packetize_common( id, out, 0, i_pts );
+
+        SetDWBE( out->p_buffer + 12, header);
+        SetWBE( out->p_buffer + 16, i_payload);
+        memcpy( &out->p_buffer[18], p_data, i_payload );
+
+        out->i_buffer   = 18 + i_payload;
+        out->i_dts    = i_pts;
+
+        rtp_packetize_send( id, out );
+
+        p_data += i_payload;
+        i_data -= i_payload;
+    }
+
+    free(p_orig);
+
+    return VLC_SUCCESS;
+}
+
 /* rfc5215 */
 static int rtp_packetize_xiph( sout_stream_id_t *id, block_t *in )
 {



More information about the vlc-commits mailing list