1 /*****************************************************************************
2 * live.cpp : live.com support.
3 *****************************************************************************
4 * Copyright (C) 2003 VideoLAN
5 * $Id: livedotcom.cpp,v 1.8 2003/11/20 22:10:55 fenrir Exp $
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <stdlib.h> /* malloc(), free() */
30 #include <vlc/input.h>
32 #include <codecs.h> /* BITMAPINFOHEADER, WAVEFORMATEX */
36 # include <winsock2.h>
39 #include "BasicUsageEnvironment.hh"
40 #include "GroupsockHelper.hh"
41 #include "liveMedia.hh"
45 /*****************************************************************************
47 *****************************************************************************/
48 static int DemuxOpen ( vlc_object_t * );
49 static void DemuxClose( vlc_object_t * );
51 static int AccessOpen ( vlc_object_t * );
52 static void AccessClose( vlc_object_t * );
54 #define CACHING_TEXT N_("Caching value in ms")
55 #define CACHING_LONGTEXT N_( \
56 "Allows you to modify the default caching value for rtsp streams. This " \
57 "value should be set in miliseconds units." )
60 set_description( _("live.com (RTSP/RTP/SDP) demuxer" ) );
61 set_capability( "demux", 50 );
62 set_callbacks( DemuxOpen, DemuxClose );
63 add_shortcut( "live" );
66 set_description( _("RTSP/RTP describe") );
67 add_shortcut( "rtsp" );
68 set_capability( "access", 0 );
69 set_callbacks( AccessOpen, AccessClose );
70 add_category_hint( N_("RTSP"), NULL, VLC_TRUE );
71 add_bool( "rtsp-tcp", 0, NULL,
72 "Use rtp over rtsp(tcp)",
73 "Use rtp over rtsp(tcp)", VLC_TRUE );
74 add_integer( "rtsp-caching", 4 * DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
78 * - Support PS/TS (need to rework the TS/PS demuxer a lot).
79 * - Support X-QT/X-QUICKTIME generic codec for audio.
81 * - Check memory leak, delete/free -> still one when using rtsp-tcp but I'm
82 * not sure if it comes from me.
86 /*****************************************************************************
88 *****************************************************************************/
99 input_thread_t *p_input;
101 vlc_bool_t b_quicktime;
106 RTPSource *rtpSource;
107 FramedSource *readSource;
109 uint8_t buffer[65536];
118 char *p_sdp; /* XXX mallocated */
121 TaskScheduler *scheduler;
122 UsageEnvironment *env ;
126 live_track_t **track; /* XXX mallocated */
136 static ssize_t Read ( input_thread_t *, byte_t *, size_t );
138 static int Demux ( input_thread_t * );
139 static int Control( input_thread_t *, int, va_list );
143 /*****************************************************************************
145 *****************************************************************************/
146 static int AccessOpen( vlc_object_t *p_this )
148 input_thread_t *p_input = (input_thread_t *)p_this;
151 TaskScheduler *scheduler = NULL;
152 UsageEnvironment *env = NULL;
153 RTSPClient *rtsp = NULL;
158 if( p_input->psz_access == NULL || strcasecmp( p_input->psz_access, "rtsp" ) )
160 msg_Warn( p_input, "RTSP access discarded" );
163 if( ( scheduler = BasicTaskScheduler::createNew() ) == NULL )
165 msg_Err( p_input, "BasicTaskScheduler::createNew failed" );
168 if( ( env = BasicUsageEnvironment::createNew(*scheduler) ) == NULL )
171 msg_Err( p_input, "BasicUsageEnvironment::createNew failed" );
174 if( ( rtsp = RTSPClient::createNew(*env, 1/*verbose*/, "VLC Media Player" ) ) == NULL )
178 msg_Err( p_input, "RTSPClient::createNew failed" );
182 psz_url = (char*)malloc( strlen( p_input->psz_name ) + 8 );
183 sprintf( psz_url, "rtsp://%s", p_input->psz_name );
185 p_sys = (access_sys_t*)malloc( sizeof( access_sys_t ) );
186 p_sys->p_sdp = rtsp->describeURL( psz_url );
188 if( p_sys->p_sdp == NULL )
190 msg_Err( p_input, "describeURL failed (%s)", env->getResultMsg() );
199 p_sys->i_sdp = strlen( p_sys->p_sdp );
202 //fprintf( stderr, "sdp=%s\n", p_sys->p_sdp );
207 var_Create( p_input, "rtsp-tcp", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
208 var_Get( p_input, "rtsp-tcp", &val );
210 p_input->p_access_data = p_sys;
213 /* Set exported functions */
214 p_input->pf_read = Read;
215 p_input->pf_seek = NULL;
216 p_input->pf_set_program = input_SetProgram;
217 p_input->pf_set_area = NULL;
218 p_input->p_private = NULL;
220 p_input->psz_demux = "live";
222 /* Finished to set some variable */
223 vlc_mutex_lock( &p_input->stream.stream_lock );
224 /* FIXME that's not true but eg over tcp, server send data too fast */
225 p_input->stream.b_pace_control = val.b_bool;
226 p_input->stream.p_selected_area->i_tell = 0;
227 p_input->stream.b_seekable = 1; /* Hack to display time */
228 p_input->stream.p_selected_area->i_size = 0;
229 p_input->stream.i_method = INPUT_METHOD_NETWORK;
230 vlc_mutex_unlock( &p_input->stream.stream_lock );
232 /* Update default_pts to a suitable value for RTSP access */
233 var_Create( p_input, "rtsp-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
234 var_Get( p_input, "rtsp-caching", &val );
235 p_input->i_pts_delay = val.i_int * 1000;
240 /*****************************************************************************
242 *****************************************************************************/
243 static void AccessClose( vlc_object_t *p_this )
245 input_thread_t *p_input = (input_thread_t *)p_this;
246 access_sys_t *p_sys = p_input->p_access_data;
248 delete[] p_sys->p_sdp;
252 /*****************************************************************************
254 *****************************************************************************/
255 static ssize_t Read ( input_thread_t *p_input, byte_t *p_buffer, size_t i_len )
257 access_sys_t *p_sys = p_input->p_access_data;
258 int i_copy = __MIN( (int)i_len, p_sys->i_sdp - p_sys->i_pos );
262 memcpy( p_buffer, &p_sys->p_sdp[p_sys->i_pos], i_copy );
263 p_sys->i_pos += i_copy;
269 /*****************************************************************************
271 *****************************************************************************/
272 static int DemuxOpen ( vlc_object_t *p_this )
274 input_thread_t *p_input = (input_thread_t *)p_this;
277 MediaSubsessionIterator *iter;
278 MediaSubsession *sub;
288 /* See if it looks like a SDP
289 v, o, s fields are mandatory and in this order */
290 if( stream_Peek( p_input->s, &p_peek, 7 ) < 7 )
292 msg_Err( p_input, "cannot peek" );
295 if( strncmp( (char*)p_peek, "v=0\r\n", 5 ) && strncmp( (char*)p_peek, "v=0\n", 4 ) &&
296 ( p_input->psz_access == NULL || strcasecmp( p_input->psz_access, "rtsp" ) ||
297 p_peek[0] < 'a' || p_peek[0] > 'z' || p_peek[1] != '=' ) )
299 msg_Warn( p_input, "SDP module discarded" );
303 p_input->pf_demux = Demux;
304 p_input->pf_demux_control = Control;
305 p_input->p_demux_data = p_sys = (demux_sys_t*)malloc( sizeof( demux_sys_t ) );
307 p_sys->scheduler = NULL;
314 p_sys->i_pcr_start = 0;
318 /* Gather the complete sdp file */
321 p_sdp = (uint8_t*)malloc( i_sdp_max );
324 int i_read = stream_Read( p_input->s, &p_sdp[i_sdp], i_sdp_max - i_sdp - 1 );
328 msg_Err( p_input, "failed to read SDP" );
335 if( i_read < i_sdp_max - i_sdp - 1 )
342 p_sdp = (uint8_t*)realloc( p_sdp, i_sdp_max );
344 p_sys->p_sdp = (char*)p_sdp;
346 fprintf( stderr, "sdp=%s\n", p_sys->p_sdp );
348 if( ( p_sys->scheduler = BasicTaskScheduler::createNew() ) == NULL )
350 msg_Err( p_input, "BasicTaskScheduler::createNew failed" );
353 if( ( p_sys->env = BasicUsageEnvironment::createNew(*p_sys->scheduler) ) == NULL )
355 msg_Err( p_input, "BasicUsageEnvironment::createNew failed" );
358 if( p_input->psz_access != NULL && !strcasecmp( p_input->psz_access, "rtsp" ) )
363 if( ( p_sys->rtsp = RTSPClient::createNew(*p_sys->env, 1/*verbose*/, "VLC Media Player" ) ) == NULL )
365 msg_Err( p_input, "RTSPClient::createNew failed (%s)", p_sys->env->getResultMsg() );
368 psz_url = (char*)malloc( strlen( p_input->psz_name ) + 8 );
369 sprintf( psz_url, "rtsp://%s", p_input->psz_name );
371 psz_options = p_sys->rtsp->sendOptionsCmd( psz_url );
372 /* FIXME psz_options -> delete or free */
375 if( ( p_sys->ms = MediaSession::createNew(*p_sys->env, p_sys->p_sdp ) ) == NULL )
377 msg_Err( p_input, "MediaSession::createNew failed" );
381 var_Create( p_input, "rtsp-tcp", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
382 var_Get( p_input, "rtsp-tcp", &val );
384 /* Initialise each media subsession */
385 iter = new MediaSubsessionIterator( *p_sys->ms );
386 while( ( sub = iter->next() ) != NULL )
388 unsigned int i_buffer = 0;
390 /* Value taken from mplayer */
391 if( !strcmp( sub->mediumName(), "audio" ) )
395 else if( !strcmp( sub->mediumName(), "video" ) )
404 if( !sub->initiate() )
406 msg_Warn( p_input, "RTP subsession '%s/%s' failed(%s)", sub->mediumName(), sub->codecName(), p_sys->env->getResultMsg() );
410 int fd = sub->rtpSource()->RTPgs()->socketNum();
412 msg_Dbg( p_input, "RTP subsession '%s/%s'", sub->mediumName(), sub->codecName() );
414 /* Increase the buffer size */
415 increaseReceiveBufferTo( *p_sys->env, fd, i_buffer );
416 /* Issue the SETUP */
419 p_sys->rtsp->setupMediaSubsession( *sub, False, val.b_bool ? True : False );
427 if( !p_sys->rtsp->playMediaSession( *p_sys->ms ) )
429 msg_Err( p_input, "PLAY failed %s", p_sys->env->getResultMsg() );
434 /* Create all es struct */
436 while( ( sub = iter->next() ) != NULL )
440 if( sub->readSource() == NULL )
445 tk = (live_track_t*)malloc( sizeof( live_track_t ) );
446 tk->p_input = p_input;
449 tk->b_quicktime = VLC_FALSE;
451 /* Value taken from mplayer */
452 if( !strcmp( sub->mediumName(), "audio" ) )
454 es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC( 'u', 'n', 'd', 'f' ) );
455 tk->fmt.audio.i_channels = sub->numChannels();
456 tk->fmt.audio.i_rate = sub->rtpSource()->timestampFrequency();
458 if( !strcmp( sub->codecName(), "MPA" ) ||
459 !strcmp( sub->codecName(), "MPA-ROBUST" ) ||
460 !strcmp( sub->codecName(), "X-MP3-DRAFT-00" ) )
462 tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );
463 tk->fmt.audio.i_rate = 0;
465 else if( !strcmp( sub->codecName(), "AC3" ) )
467 tk->fmt.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
468 tk->fmt.audio.i_rate = 0;
470 else if( !strcmp( sub->codecName(), "L16" ) )
472 tk->fmt.i_codec = VLC_FOURCC( 't', 'w', 'o', 's' );
473 tk->fmt.audio.i_bitspersample = 16;
475 else if( !strcmp( sub->codecName(), "L8" ) )
477 tk->fmt.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );
478 tk->fmt.audio.i_bitspersample = 8;
480 else if( !strcmp( sub->codecName(), "PCMU" ) )
482 tk->fmt.i_codec = VLC_FOURCC( 'u', 'l', 'a', 'w' );
484 else if( !strcmp( sub->codecName(), "PCMA" ) )
486 tk->fmt.i_codec = VLC_FOURCC( 'a', 'l', 'a', 'w' );
488 else if( !strcmp( sub->codecName(), "MP4A-LATM" ) )
490 unsigned int i_extra;
493 tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
495 if( ( p_extra = parseStreamMuxConfigStr( sub->fmtp_config(), i_extra ) ) )
497 tk->fmt.i_extra = i_extra;
498 tk->fmt.p_extra = malloc( sizeof( i_extra ) );
499 memcpy( tk->fmt.p_extra, p_extra, i_extra );
503 else if( !strcmp( sub->codecName(), "MPEG4-GENERIC" ) )
505 unsigned int i_extra;
508 tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
510 if( ( p_extra = parseGeneralConfigStr( sub->fmtp_config(), i_extra ) ) )
512 tk->fmt.i_extra = i_extra;
513 tk->fmt.p_extra = malloc( i_extra );
514 memcpy( tk->fmt.p_extra, p_extra, i_extra );
519 else if( !strcmp( sub->mediumName(), "video" ) )
521 es_format_Init( &tk->fmt, VIDEO_ES, VLC_FOURCC( 'u', 'n', 'd', 'f' ) );
522 if( !strcmp( sub->codecName(), "MPV" ) )
524 tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' );
526 else if( !strcmp( sub->codecName(), "H263" ) ||
527 !strcmp( sub->codecName(), "H263-1998" ) )
529 tk->fmt.i_codec = VLC_FOURCC( 'h', '2', '6', '3' );
531 else if( !strcmp( sub->codecName(), "H261" ) )
533 tk->fmt.i_codec = VLC_FOURCC( 'h', '2', '6', '1' );
535 else if( !strcmp( sub->codecName(), "JPEG" ) )
537 tk->fmt.i_codec = VLC_FOURCC( 'M', 'J', 'P', 'G' );
539 else if( !strcmp( sub->codecName(), "MP4V-ES" ) )
541 unsigned int i_extra;
544 tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v' );
546 if( ( p_extra = parseGeneralConfigStr( sub->fmtp_config(), i_extra ) ) )
548 tk->fmt.i_extra = i_extra;
549 tk->fmt.p_extra = malloc( i_extra );
550 memcpy( tk->fmt.p_extra, p_extra, i_extra );
554 else if( !strcmp( sub->codecName(), "X-QT" ) || !strcmp( sub->codecName(), "X-QUICKTIME" ) )
556 tk->b_quicktime = VLC_TRUE;
560 if( tk->fmt.i_codec != VLC_FOURCC( 'u', 'n', 'd', 'f' ) )
562 tk->p_es = es_out_Add( p_input->p_es_out, &tk->fmt );
569 if( tk->p_es || tk->b_quicktime )
571 TAB_APPEND( p_sys->i_track, (void**)p_sys->track, (void*)tk );
572 tk->readSource = sub->readSource();
573 tk->rtpSource = sub->rtpSource();
583 p_sys->i_length = (mtime_t)(p_sys->ms->playEndTime() * 1000000.0);
584 if( p_sys->i_length < 0 )
588 else if( p_sys->i_length > 0 )
590 p_input->stream.p_selected_area->i_size = 1000; /* needed for now */
593 if( p_sys->i_track <= 0 )
595 msg_Err( p_input, "No codec supported, aborting" );
604 Medium::close( p_sys->ms );
608 Medium::close( p_sys->rtsp );
614 if( p_sys->scheduler )
616 delete p_sys->scheduler;
620 free( p_sys->p_sdp );
628 /*****************************************************************************
630 *****************************************************************************/
631 static void DemuxClose( vlc_object_t *p_this )
633 input_thread_t *p_input = (input_thread_t *)p_this;
634 demux_sys_t *p_sys = p_input->p_demux_data;
637 for( i = 0; i < p_sys->i_track; i++ )
639 live_track_t *tk = p_sys->track[i];
645 free( p_sys->track );
648 if( p_sys->rtsp && p_sys->ms )
651 p_sys->rtsp->teardownMediaSession( *p_sys->ms );
653 Medium::close( p_sys->ms );
656 Medium::close( p_sys->rtsp );
663 if( p_sys->scheduler )
665 delete p_sys->scheduler;
669 free( p_sys->p_sdp );
675 static void StreamRead( void *p_private, unsigned int i_size, struct timeval pts );
676 static void StreamClose( void *p_private );
677 static void TaskInterrupt( void *p_private );
679 /*****************************************************************************
681 *****************************************************************************/
682 static int Demux ( input_thread_t *p_input )
684 demux_sys_t *p_sys = p_input->p_demux_data;
690 for( i = 0; i < p_sys->i_track; i++ )
692 live_track_t *tk = p_sys->track[i];
698 else if( tk->i_pts != 0 && i_pcr > tk->i_pts )
703 if( i_pcr != p_sys->i_pcr && i_pcr > 0 )
705 input_ClockManageRef( p_input,
706 p_input->stream.p_selected_program,
708 p_sys->i_pcr = i_pcr;
709 if( p_sys->i_pcr_start <= 0 || p_sys->i_pcr_start > i_pcr )
711 p_sys->i_pcr_start = i_pcr;
715 /* First warm we want to read data */
717 for( i = 0; i < p_sys->i_track; i++ )
719 live_track_t *tk = p_sys->track[i];
721 if( tk->waiting == 0 )
724 tk->readSource->getNextFrame( tk->buffer, 65536,
729 /* Create a task that will be called if we wait more than 300ms */
730 task = p_sys->scheduler->scheduleDelayedTask( 300000, TaskInterrupt, p_input );
733 p_sys->scheduler->doEventLoop( &p_sys->event );
735 /* remove the task */
736 p_sys->scheduler->unscheduleDelayedTask( task );
738 return p_input->b_error ? 0 : 1;
741 static int Control( input_thread_t *p_input, int i_query, va_list args )
743 demux_sys_t *p_sys = p_input->p_demux_data;
750 pi64 = (int64_t*)va_arg( args, int64_t * );
751 *pi64 = p_sys->i_pcr - p_sys->i_pcr_start + p_sys->i_start;
754 case DEMUX_GET_LENGTH:
755 pi64 = (int64_t*)va_arg( args, int64_t * );
756 *pi64 = p_sys->i_length;
759 case DEMUX_GET_POSITION:
760 pf = (double*)va_arg( args, double* );
761 if( p_sys->i_length > 0 )
763 *pf = (double)( p_sys->i_pcr - p_sys->i_pcr_start + p_sys->i_start)/
764 (double)(p_sys->i_length);
772 case DEMUX_SET_POSITION:
776 f = (double)va_arg( args, double );
777 time = f * (double)p_sys->i_length / 1000000.0; /* in second */
779 if( p_sys->rtsp && p_sys->i_length > 0 )
781 MediaSubsessionIterator *iter = new MediaSubsessionIterator( *p_sys->ms );
782 MediaSubsession *sub;
785 while( ( sub = iter->next() ) != NULL )
787 p_sys->rtsp->playMediaSubsession( *sub, time );
790 p_sys->i_start = (mtime_t)(f * (double)p_sys->i_length);
791 p_sys->i_pcr_start = 0;
793 for( i = 0; i < p_sys->i_track; i++ )
795 p_sys->track[i]->i_pts = 0;
803 return demux_vaControlDefault( p_input, i_query, args );
807 /*****************************************************************************
809 *****************************************************************************/
810 static void StreamRead( void *p_private, unsigned int i_size, struct timeval pts )
812 live_track_t *tk = (live_track_t*)p_private;
813 input_thread_t *p_input = tk->p_input;
814 demux_sys_t *p_sys = p_input->p_demux_data;
816 data_packet_t *p_data;
818 mtime_t i_pts = (mtime_t)pts.tv_sec * 1000000LL + (mtime_t)pts.tv_usec;
820 if( tk->b_quicktime && tk->p_es == NULL )
822 QuickTimeGenericRTPSource *qtRTPSource = (QuickTimeGenericRTPSource*)tk->rtpSource;
823 QuickTimeGenericRTPSource::QTState &qtState = qtRTPSource->qtState;
824 uint8_t *sdAtom = (uint8_t*)&qtState.sdAtom[4];
826 if( qtState.sdAtomSize < 16 + 32 )
833 tk->fmt.i_codec = VLC_FOURCC( sdAtom[0], sdAtom[1], sdAtom[2], sdAtom[3] );
834 tk->fmt.video.i_width = (sdAtom[28] << 8) | sdAtom[29];
835 tk->fmt.video.i_height = (sdAtom[30] << 8) | sdAtom[31];
837 tk->fmt.i_extra = qtState.sdAtomSize - 16;
838 tk->fmt.p_extra = malloc( tk->fmt.i_extra );
839 memcpy( tk->fmt.p_extra, &sdAtom[12], tk->fmt.i_extra );
841 tk->p_es = es_out_Add( p_input->p_es_out, &tk->fmt );
845 fprintf( stderr, "StreamRead size=%d pts=%lld\n",
847 pts.tv_sec * 1000000LL + pts.tv_usec );
850 if( ( p_pes = input_NewPES( p_input->p_method_data ) ) == NULL )
856 msg_Warn( p_input, "buffer overflow" );
858 /* FIXME could i_size be > buffer size ? */
859 p_data = input_NewPacket( p_input->p_method_data, i_size );
861 memcpy( p_data->p_payload_start, tk->buffer, i_size );
862 p_data->p_payload_end = p_data->p_payload_start + i_size;
864 p_pes->p_first = p_pes->p_last = p_data;
865 p_pes->i_nb_data = 1;
866 p_pes->i_pes_size = i_size;
867 p_pes->i_rate = p_input->stream.control.i_rate;
869 if( i_pts != tk->i_pts )
872 p_pes->i_pts = input_ClockGetTS( p_input,
873 p_input->stream.p_selected_program,
881 //fprintf( stderr, "tk -> dpts=%lld\n", i_pts - tk->i_pts );
883 es_out_Send( p_input->p_es_out, tk->p_es, p_pes );
888 /* we have read data */
897 /*****************************************************************************
899 *****************************************************************************/
900 static void StreamClose( void *p_private )
902 live_track_t *tk = (live_track_t*)p_private;
903 input_thread_t *p_input = tk->p_input;
904 demux_sys_t *p_sys = p_input->p_demux_data;
906 fprintf( stderr, "StreamClose\n" );
909 p_input->b_error = VLC_TRUE;
913 /*****************************************************************************
915 *****************************************************************************/
916 static void TaskInterrupt( void *p_private )
918 input_thread_t *p_input = (input_thread_t*)p_private;
920 fprintf( stderr, "TaskInterrupt\n" );
923 p_input->p_demux_data->event = 0xff;