X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fstream_out%2Frtpfmt.c;h=7b71588545b3bafd0e558e4455fd887ce3ae843e;hb=56d4e908e1b71fc6161622701d1cf0db64e57aa6;hp=20ae5672145e914e1d72e58993dd0e1576d1a704;hpb=152fee0cd5a879df625ae1c23ad2193081161648;p=vlc diff --git a/modules/stream_out/rtpfmt.c b/modules/stream_out/rtpfmt.c index 20ae567214..7b71588545 100644 --- a/modules/stream_out/rtpfmt.c +++ b/modules/stream_out/rtpfmt.c @@ -52,12 +52,15 @@ static int rtp_packetize_g726_16 (sout_stream_id_t *, block_t *); static int rtp_packetize_g726_24 (sout_stream_id_t *, block_t *); static int rtp_packetize_g726_32 (sout_stream_id_t *, block_t *); static int rtp_packetize_g726_40 (sout_stream_id_t *, block_t *); -static int rtp_packetize_vorbis (sout_stream_id_t *, block_t *); +static int rtp_packetize_xiph (sout_stream_id_t *, block_t *); -#define VORBIS_IDENT (0) +#define XIPH_IDENT (0) -static int rtp_vorbis_pack_headers(size_t room, void *p_extra, size_t i_extra, - uint8_t **p_buffer, size_t *i_buffer) +/* Helpers common to xiph codecs (vorbis and theora) */ + +static int rtp_xiph_pack_headers(size_t room, void *p_extra, size_t i_extra, + uint8_t **p_buffer, size_t *i_buffer, + uint8_t *theora_pixel_fmt) { unsigned packet_size[XIPH_MAX_HEADER_COUNT]; void *packet[XIPH_MAX_HEADER_COUNT]; @@ -67,7 +70,20 @@ static int rtp_vorbis_pack_headers(size_t room, void *p_extra, size_t i_extra, if (val != VLC_SUCCESS) return val; if (packet_count < 3) - return VLC_EGENERIC; + { + val = VLC_EGENERIC; + goto free; + } + + if (theora_pixel_fmt != NULL) + { + if (packet_size[0] < 42) + { + val = VLC_EGENERIC; + goto free; + } + *theora_pixel_fmt = (((uint8_t *)packet[0])[41] >> 3) & 0x03; + } unsigned length_size[2] = { 0, 0 }; for (int i = 0; i < 2; i++) @@ -84,7 +100,10 @@ static int rtp_vorbis_pack_headers(size_t room, void *p_extra, size_t i_extra, + packet_size[0] + packet_size[1] + packet_size[2]; *p_buffer = malloc(*i_buffer); if (*p_buffer == NULL) - return VLC_ENOMEM; + { + val = VLC_ENOMEM; + goto free; + } uint8_t *p = *p_buffer + room; /* Number of headers */ @@ -104,11 +123,38 @@ static int rtp_vorbis_pack_headers(size_t room, void *p_extra, size_t i_extra, for (int i = 0; i < 3; i++) { memcpy(p, packet[i], packet_size[i]); - free(packet[i]); p += packet_size[i]; } - return VLC_SUCCESS; + val = VLC_SUCCESS; +free: + for (unsigned i = 0; i < packet_count; i++) + free(packet[i]); + + return val; +} + +static char *rtp_xiph_b64_oob_config(void *p_extra, size_t i_extra, + uint8_t *theora_pixel_fmt) +{ + uint8_t *p_buffer; + size_t i_buffer; + if (rtp_xiph_pack_headers(9, p_extra, i_extra, &p_buffer, &i_buffer, + theora_pixel_fmt) != VLC_SUCCESS) + return NULL; + + /* Number of packed headers */ + SetDWBE(p_buffer, 1); + /* Ident */ + uint32_t ident = XIPH_IDENT; + SetWBE(p_buffer + 4, ident >> 8); + p_buffer[6] = ident & 0xff; + /* Length field */ + SetWBE(p_buffer + 7, i_buffer); + + char *config = vlc_b64_encode_binary(p_buffer, i_buffer); + free(p_buffer); + return config; } static void sprintf_hexa( char *s, uint8_t *p_data, int i_data ) @@ -192,6 +238,10 @@ int rtp_get_fmt( vlc_object_t *obj, es_format_t *p_fmt, const char *mux, rtp_fmt->ptname = "L8"; rtp_fmt->pf_packetize = rtp_packetize_split; break; + case VLC_CODEC_S24B: + rtp_fmt->ptname = "L24"; + rtp_fmt->pf_packetize = rtp_packetize_split; + break; case VLC_CODEC_MPGA: rtp_fmt->payload_type = 14; rtp_fmt->ptname = "MPA"; @@ -397,27 +447,12 @@ int rtp_get_fmt( vlc_object_t *obj, es_format_t *p_fmt, const char *mux, break; case VLC_CODEC_VORBIS: rtp_fmt->ptname = "vorbis"; - rtp_fmt->pf_packetize = rtp_packetize_vorbis; + rtp_fmt->pf_packetize = rtp_packetize_xiph; if( p_fmt->i_extra > 0 ) { rtp_fmt->fmtp = NULL; - uint8_t *p_buffer; - size_t i_buffer; - if (rtp_vorbis_pack_headers(9, p_fmt->p_extra, p_fmt->i_extra, - &p_buffer, &i_buffer) != VLC_SUCCESS) - break; - - /* Number of packed headers */ - SetDWBE(p_buffer, 1); - /* Ident */ - uint32_t ident = VORBIS_IDENT; - SetWBE(p_buffer + 4, ident >> 8); - p_buffer[6] = ident & 0xff; - /* Length field */ - SetWBE(p_buffer + 7, i_buffer); - - char *config = vlc_b64_encode_binary(p_buffer, i_buffer); - free(p_buffer); + char *config = rtp_xiph_b64_oob_config(p_fmt->p_extra, + p_fmt->i_extra, NULL); if (config == NULL) break; if( asprintf( &rtp_fmt->fmtp, @@ -426,6 +461,51 @@ int rtp_get_fmt( vlc_object_t *obj, es_format_t *p_fmt, const char *mux, free(config); } break; + case VLC_CODEC_THEORA: + rtp_fmt->ptname = "theora"; + rtp_fmt->pf_packetize = rtp_packetize_xiph; + if( p_fmt->i_extra > 0 ) + { + rtp_fmt->fmtp = NULL; + uint8_t pixel_fmt, c1, c2; + char *config = rtp_xiph_b64_oob_config(p_fmt->p_extra, + p_fmt->i_extra, + &pixel_fmt); + if (config == NULL) + break; + + if (pixel_fmt == 1) + { + /* reserved */ + free(config); + break; + } + switch (pixel_fmt) + { + case 0: + c1 = 2; + c2 = 0; + break; + case 2: + c1 = c2 = 2; + break; + case 3: + c1 = c2 = 4; + break; + default: + assert(0); + } + + if( asprintf( &rtp_fmt->fmtp, + "sampling=YCbCr-4:%d:%d; width=%d; height=%d; " + "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); + } + break; case VLC_CODEC_ITU_T140: rtp_fmt->ptname = "t140" ; rtp_fmt->clock_rate = 1000; @@ -447,8 +527,85 @@ 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_vorbis( sout_stream_id_t *id, block_t *in ) +static int rtp_packetize_xiph( sout_stream_id_t *id, block_t *in ) { int i_max = rtp_mtu (id) - 6; /* payload max in one packet */ int i_count = ( in->i_buffer + i_max - 1 ) / i_max; @@ -479,8 +636,8 @@ static int rtp_packetize_vorbis( sout_stream_id_t *id, block_t *in ) else fragtype = 2; } - /* Ident:24, Fragment type:2, Vorbis Data Type:2, # of packets:4 */ - uint32_t header = ((VORBIS_IDENT & 0xffffff) << 8) | + /* Ident:24, Fragment type:2, Vorbis/Theora Data Type:2, # of pkts:4 */ + uint32_t header = ((XIPH_IDENT & 0xffffff) << 8) | (fragtype << 6) | (0 << 4) | numpkts; /* rtp common header */ @@ -1075,7 +1232,7 @@ static int rtp_packetize_t140( sout_stream_id_t *id, block_t *in ) memcpy( out->p_buffer + 12, p_data, i_payload ); out->i_buffer = 12 + i_payload; - out->i_dts = out->i_pts; + out->i_dts = in->i_pts; out->i_length = 0; rtp_packetize_send( id, out ); @@ -1174,7 +1331,7 @@ static int rtp_packetize_g726( sout_stream_id_t *id, block_t *in, int i_pad ) while( i_data > 0 ) { int i_payload = __MIN( i_max, i_data ); - block_t *out = block_New( p_stream, 12 + i_payload ); + block_t *out = block_Alloc( 12 + i_payload ); /* rtp common header */ rtp_packetize_common( id, out, 0,