Commit b2bc67df authored by Pierre Ynard's avatar 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.
parent dae49c9e
......@@ -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;
......
......@@ -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,
......
......@@ -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 )
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment