+
+ tk = (live_track_t*)malloc( sizeof( live_track_t ) );
+ if( !tk )
+ {
+ delete iter;
+ return VLC_ENOMEM;
+ }
+ tk->p_demux = p_demux;
+ tk->sub = sub;
+ tk->p_es = NULL;
+ tk->b_quicktime = false;
+ tk->b_asf = false;
+ tk->b_muxed = false;
+ tk->p_out_muxed = NULL;
+ tk->waiting = 0;
+ tk->b_rtcp_sync = false;
+ tk->i_pts = 0;
+ tk->i_buffer = 65536;
+ tk->p_buffer = (uint8_t *)malloc( 65536 );
+ if( !tk->p_buffer )
+ {
+ delete iter;
+ return VLC_ENOMEM;
+ }
+
+ /* Value taken from mplayer */
+ if( !strcmp( sub->mediumName(), "audio" ) )
+ {
+ es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC('u','n','d','f') );
+ tk->fmt.audio.i_channels = sub->numChannels();
+ tk->fmt.audio.i_rate = sub->rtpTimestampFrequency();
+
+ if( !strcmp( sub->codecName(), "MPA" ) ||
+ !strcmp( sub->codecName(), "MPA-ROBUST" ) ||
+ !strcmp( sub->codecName(), "X-MP3-DRAFT-00" ) )
+ {
+ tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );
+ tk->fmt.audio.i_rate = 0;
+ }
+ else if( !strcmp( sub->codecName(), "AC3" ) )
+ {
+ tk->fmt.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
+ tk->fmt.audio.i_rate = 0;
+ }
+ else if( !strcmp( sub->codecName(), "L16" ) )
+ {
+ tk->fmt.i_codec = VLC_FOURCC( 't', 'w', 'o', 's' );
+ tk->fmt.audio.i_bitspersample = 16;
+ }
+ else if( !strcmp( sub->codecName(), "L8" ) )
+ {
+ tk->fmt.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );
+ tk->fmt.audio.i_bitspersample = 8;
+ }
+ else if( !strcmp( sub->codecName(), "PCMU" ) )
+ {
+ tk->fmt.i_codec = VLC_FOURCC( 'u', 'l', 'a', 'w' );
+ }
+ else if( !strcmp( sub->codecName(), "PCMA" ) )
+ {
+ tk->fmt.i_codec = VLC_FOURCC( 'a', 'l', 'a', 'w' );
+ }
+ else if( !strncmp( sub->codecName(), "G726", 4 ) )
+ {
+ tk->fmt.i_codec = VLC_FOURCC( 'g', '7', '2', '6' );
+ tk->fmt.audio.i_rate = 8000;
+ tk->fmt.audio.i_channels = 1;
+ if( !strcmp( sub->codecName()+5, "40" ) )
+ tk->fmt.i_bitrate = 40000;
+ else if( !strcmp( sub->codecName()+5, "32" ) )
+ tk->fmt.i_bitrate = 32000;
+ else if( !strcmp( sub->codecName()+5, "24" ) )
+ tk->fmt.i_bitrate = 24000;
+ else if( !strcmp( sub->codecName()+5, "16" ) )
+ tk->fmt.i_bitrate = 16000;
+ }
+ else if( !strcmp( sub->codecName(), "AMR" ) )
+ {
+ tk->fmt.i_codec = VLC_FOURCC( 's', 'a', 'm', 'r' );
+ }
+ else if( !strcmp( sub->codecName(), "AMR-WB" ) )
+ {
+ tk->fmt.i_codec = VLC_FOURCC( 's', 'a', 'w', 'b' );
+ }
+ else if( !strcmp( sub->codecName(), "MP4A-LATM" ) )
+ {
+ unsigned int i_extra;
+ uint8_t *p_extra;
+
+ tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
+
+ if( ( p_extra = parseStreamMuxConfigStr( sub->fmtp_config(),
+ i_extra ) ) )
+ {
+ tk->fmt.i_extra = i_extra;
+ tk->fmt.p_extra = malloc( i_extra );
+ memcpy( tk->fmt.p_extra, p_extra, i_extra );
+ delete[] p_extra;
+ }
+ /* Because the "faad" decoder does not handle the LATM data length field
+ at the start of each returned LATM frame, tell the RTP source to omit it. */
+ ((MPEG4LATMAudioRTPSource*)sub->rtpSource())->omitLATMDataLengthField();
+ }
+ else if( !strcmp( sub->codecName(), "MPEG4-GENERIC" ) )
+ {
+ unsigned int i_extra;
+ uint8_t *p_extra;
+
+ tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
+
+ if( ( p_extra = parseGeneralConfigStr( sub->fmtp_config(),
+ i_extra ) ) )
+ {
+ tk->fmt.i_extra = i_extra;
+ tk->fmt.p_extra = malloc( i_extra );
+ memcpy( tk->fmt.p_extra, p_extra, i_extra );
+ delete[] p_extra;
+ }
+ }
+ else if( !strcmp( sub->codecName(), "X-ASF-PF" ) )
+ {
+ tk->b_asf = true;
+ if( p_sys->p_out_asf == NULL )
+ p_sys->p_out_asf = stream_DemuxNew( p_demux, "asf",
+ p_demux->out );
+ }
+ else if( !strcmp( sub->codecName(), "X-QT" ) ||
+ !strcmp( sub->codecName(), "X-QUICKTIME" ) )
+ {
+ tk->b_quicktime = true;
+ }
+ else if( !strcmp( sub->codecName(), "SPEEX" ) )
+ {
+ tk->fmt.i_codec = VLC_FOURCC( 's', 'p', 'x', 'r' );
+ if ( sub->rtpTimestampFrequency() )
+ tk->fmt.audio.i_rate = sub->rtpTimestampFrequency();
+ else
+ {
+ msg_Warn( p_demux,"Using 8kHz as default sample rate." );
+ tk->fmt.audio.i_rate = 8000;
+ }
+ }
+ }
+ else if( !strcmp( sub->mediumName(), "video" ) )
+ {
+ es_format_Init( &tk->fmt, VIDEO_ES, VLC_FOURCC('u','n','d','f') );
+ if( !strcmp( sub->codecName(), "MPV" ) )
+ {
+ tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' );
+ }
+ else if( !strcmp( sub->codecName(), "H263" ) ||
+ !strcmp( sub->codecName(), "H263-1998" ) ||
+ !strcmp( sub->codecName(), "H263-2000" ) )
+ {
+ tk->fmt.i_codec = VLC_FOURCC( 'H', '2', '6', '3' );
+ }
+ else if( !strcmp( sub->codecName(), "H261" ) )
+ {
+ tk->fmt.i_codec = VLC_FOURCC( 'H', '2', '6', '1' );
+ }
+ else if( !strcmp( sub->codecName(), "H264" ) )
+ {
+ unsigned int i_extra = 0;
+ uint8_t *p_extra = NULL;
+
+ tk->fmt.i_codec = VLC_FOURCC( 'h', '2', '6', '4' );
+ tk->fmt.b_packetized = false;
+
+ if((p_extra=parseH264ConfigStr( sub->fmtp_spropparametersets(),
+ i_extra ) ) )
+ {
+ tk->fmt.i_extra = i_extra;
+ tk->fmt.p_extra = malloc( i_extra );
+ memcpy( tk->fmt.p_extra, p_extra, i_extra );
+
+ delete[] p_extra;
+ }
+ }
+ else if( !strcmp( sub->codecName(), "JPEG" ) )
+ {
+ tk->fmt.i_codec = VLC_FOURCC( 'M', 'J', 'P', 'G' );
+ }
+ else if( !strcmp( sub->codecName(), "MP4V-ES" ) )
+ {
+ unsigned int i_extra;
+ uint8_t *p_extra;
+
+ tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v' );
+
+ if( ( p_extra = parseGeneralConfigStr( sub->fmtp_config(),
+ i_extra ) ) )
+ {
+ tk->fmt.i_extra = i_extra;
+ tk->fmt.p_extra = malloc( i_extra );
+ memcpy( tk->fmt.p_extra, p_extra, i_extra );
+ delete[] p_extra;
+ }
+ }
+ else if( !strcmp( sub->codecName(), "X-QT" ) ||
+ !strcmp( sub->codecName(), "X-QUICKTIME" ) ||
+ !strcmp( sub->codecName(), "X-QDM" ) ||
+ !strcmp( sub->codecName(), "X-SV3V-ES" ) ||
+ !strcmp( sub->codecName(), "X-SORENSONVIDEO" ) )
+ {
+ tk->b_quicktime = true;
+ }
+ else if( !strcmp( sub->codecName(), "MP2T" ) )
+ {
+ tk->b_muxed = true;
+ tk->p_out_muxed = stream_DemuxNew( p_demux, "ts", p_demux->out );
+ }
+ else if( !strcmp( sub->codecName(), "MP2P" ) ||
+ !strcmp( sub->codecName(), "MP1S" ) )
+ {
+ tk->b_muxed = true;
+ tk->p_out_muxed = stream_DemuxNew( p_demux, "ps",
+ p_demux->out );
+ }
+ else if( !strcmp( sub->codecName(), "X-ASF-PF" ) )
+ {
+ tk->b_asf = true;
+ if( p_sys->p_out_asf == NULL )
+ p_sys->p_out_asf = stream_DemuxNew( p_demux, "asf",
+ p_demux->out );;
+ }
+ }
+
+ if( !tk->b_quicktime && !tk->b_muxed && !tk->b_asf )
+ {
+ tk->p_es = es_out_Add( p_demux->out, &tk->fmt );
+ }
+
+ if( sub->rtcpInstance() != NULL )
+ {
+ sub->rtcpInstance()->setByeHandler( StreamClose, tk );
+ }
+
+ if( tk->p_es || tk->b_quicktime || tk->b_muxed || tk->b_asf )
+ {
+ /* Append */
+ p_sys->track = (live_track_t**)realloc( p_sys->track, sizeof( live_track_t ) * ( p_sys->i_track + 1 ) );
+ p_sys->track[p_sys->i_track++] = tk;
+ }
+ else
+ {
+ /* BUG ??? */
+ msg_Err( p_demux, "unusable RTSP track. this should not happen" );
+ es_format_Clean( &tk->fmt );
+ free( tk );
+ }