X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Flive555.cpp;h=2ccef2facc22f4f41aa28a311091ce52421de347;hb=ef466bbdae537748a588bac3eb55bbaa6a989a88;hp=9e908ac2fc1a8beed70f3441d45c10c271e57786;hpb=7ec013e0c9be7ff431e9823e745c2329a01db64d;p=vlc diff --git a/modules/demux/live555.cpp b/modules/demux/live555.cpp index 9e908ac2fc..2ccef2facc 100644 --- a/modules/demux/live555.cpp +++ b/modules/demux/live555.cpp @@ -47,7 +47,6 @@ #include #include -#include #include #include @@ -60,6 +59,7 @@ #include #include #include +#include extern "C" { #include "../access/mms/asf.h" /* Who said ugly ? */ @@ -73,18 +73,13 @@ using namespace std; static int Open ( vlc_object_t * ); static void Close( vlc_object_t * ); -#define CACHING_TEXT N_("Caching value (ms)") -#define CACHING_LONGTEXT N_( \ - "Allows you to modify the default caching value for RTSP streams. This " \ - "value should be set in millisecond units." ) - #define KASENNA_TEXT N_( "Kasenna RTSP dialect") #define KASENNA_LONGTEXT N_( "Kasenna servers use an old and nonstandard " \ "dialect of RTSP. With this parameter VLC will try this dialect, but "\ "then it cannot connect to normal RTSP servers." ) #define WMSERVER_TEXT N_("WMServer RTSP dialect") -#define WMSERVER_LONGTEXT N_("WMServer uses an unstandard dialect " \ +#define WMSERVER_LONGTEXT N_("WMServer uses a nonstandard dialect " \ "of RTSP. Selecting this parameter will tell VLC to assume some " \ "options contrary to RFC 2326 guidelines.") @@ -128,9 +123,6 @@ vlc_module_begin () N_("HTTP tunnel port"), N_("Port to use for tunneling the RTSP/RTP over HTTP."), true ) - add_integer("rtsp-caching", 4 * DEFAULT_PTS_DELAY / 1000, - CACHING_TEXT, CACHING_LONGTEXT, true ) - change_safe() add_bool( "rtsp-kasenna", false, KASENNA_TEXT, KASENNA_LONGTEXT, true ) change_safe() @@ -173,6 +165,8 @@ typedef struct int64_t i_pts; float i_npt; + bool b_selected; + } live_track_t; struct timeout_thread_t @@ -197,7 +191,7 @@ struct demux_sys_t /* */ int i_track; - live_track_t **track; /* XXX mallocated */ + live_track_t **track; /* Weird formats */ asf_header_t asfh; @@ -221,7 +215,8 @@ struct demux_sys_t bool b_no_data; /* if we never received any data */ int i_no_data_ti; /* consecutive number of TaskInterrupt */ - char event; + char event_rtsp; + char event_data; bool b_get_param; /* Does the server support GET_PARAMETER */ bool b_paused; /* Are we paused? */ @@ -258,7 +253,8 @@ static int RollOverTcp ( demux_t * ); static void StreamRead ( void *, unsigned int, unsigned int, struct timeval, unsigned int ); static void StreamClose ( void * ); -static void TaskInterrupt( void * ); +static void TaskInterruptData( void * ); +static void TaskInterruptRTSP( void * ); static void* TimeoutPrevention( void * ); @@ -290,20 +286,20 @@ static int Open ( vlc_object_t *p_this ) return VLC_EGENERIC; } } - var_Create( p_demux, "rtsp-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT ); p_demux->pf_demux = Demux; p_demux->pf_control= Control; p_demux->p_sys = p_sys = (demux_sys_t*)malloc( sizeof( demux_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; + msg_Dbg( p_demux, "version "LIVEMEDIA_LIBRARY_VERSION_STRING ); + p_sys->p_sdp = NULL; p_sys->scheduler = NULL; p_sys->env = NULL; p_sys->ms = NULL; p_sys->rtsp = NULL; - p_sys->i_track = 0; - p_sys->track = NULL; + TAB_INIT( p_sys->i_track, p_sys->track ); p_sys->i_pcr = 0; p_sys->i_npt = 0.; p_sys->i_npt_start = 0.; @@ -458,8 +454,7 @@ static void Close( vlc_object_t *p_this ) free( tk->p_buffer ); free( tk ); } - - if( p_sys->i_track ) free( p_sys->track ); + TAB_CLEAN( p_sys->i_track, p_sys->track ); if( p_sys->p_out_asf ) stream_Delete( p_sys->p_out_asf ); delete p_sys->scheduler; free( p_sys->p_sdp ); @@ -480,7 +475,7 @@ static void default_live555_callback( RTSPClient* client, int result_code, char* delete []result_string; p_sys->i_live555_ret = result_code; p_sys->b_error = p_sys->i_live555_ret != 0; - p_sys->event = 1; + p_sys->event_rtsp = 1; } /* return true if the RTSP command succeeded */ @@ -488,17 +483,18 @@ static bool wait_Live555_response( demux_t *p_demux, int i_timeout = 0 /* ms */ { TaskToken task; demux_sys_t * p_sys = p_demux->p_sys; - p_sys->event = 0; + p_sys->event_rtsp = 0; if( i_timeout > 0 ) { /* Create a task that will be called if we wait more than timeout ms */ - task = p_sys->scheduler->scheduleDelayedTask( i_timeout*1000, TaskInterrupt, + task = p_sys->scheduler->scheduleDelayedTask( i_timeout*1000, + TaskInterruptRTSP, p_demux ); } - p_sys->event = 0; + p_sys->event_rtsp = 0; p_sys->b_error = true; p_sys->i_live555_ret = 0; - p_sys->scheduler->doEventLoop( &p_sys->event ); + p_sys->scheduler->doEventLoop( &p_sys->event_rtsp ); //here, if b_error is true and i_live555_ret = 0 we didn't receive a response if( i_timeout > 0 ) { @@ -528,7 +524,7 @@ static void continueAfterDESCRIBE( RTSPClient* client, int result_code, else p_sys->b_error = true; delete[] result_string; - p_sys->event = 1; + p_sys->event_rtsp = 1; } static void continueAfterOPTIONS( RTSPClient* client, int result_code, @@ -540,11 +536,11 @@ static void continueAfterOPTIONS( RTSPClient* client, int result_code, if ( result_code != 0 ) { p_sys->b_error = true; - p_sys->event = 1; + p_sys->event_rtsp = 1; } else { - p_sys->b_get_param = (bool)strstr( result_string, "GET_PARAMETER" ); + p_sys->b_get_param = result_string != NULL && strstr( result_string, "GET_PARAMETER" ) != NULL; client->sendDescribeCommand( continueAfterDESCRIBE ); } delete[] result_string; @@ -560,8 +556,6 @@ static int Connect( demux_t *p_demux ) char *psz_user = NULL; char *psz_pwd = NULL; char *psz_url = NULL; - char *psz_options = NULL; - char *p_sdp = NULL; int i_http_port = 0; int i_ret = VLC_SUCCESS; const int i_timeout = var_InheritInteger( p_demux, "ipv4-timeout" ); @@ -685,13 +679,13 @@ static int SessionsSetup( demux_t *p_demux ) MediaSubsessionIterator *iter = NULL; MediaSubsession *sub = NULL; - bool b_rtsp_tcp = false; + bool b_rtsp_tcp; int i_client_port; int i_return = VLC_SUCCESS; unsigned int i_buffer = 0; unsigned const thresh = 200000; /* RTP reorder threshold .2 second (default .1) */ - b_rtsp_tcp = var_InheritBool( p_demux, "rtsp-tcp" ) || + b_rtsp_tcp = var_CreateGetBool( p_demux, "rtsp-tcp" ) || var_InheritBool( p_demux, "rtsp-http" ); i_client_port = var_InheritInteger( p_demux, "rtp-client-port" ); @@ -777,7 +771,7 @@ static int SessionsSetup( demux_t *p_demux ) * use and try again */ if( p_sys->i_live555_ret == 461 ) p_sys->rtsp->sendSetupCommand( *sub, default_live555_callback, False, - toBool( b_rtsp_tcp ), False ); + !toBool( b_rtsp_tcp ), False ); if( p_sys->i_live555_ret != 461 || !wait_Live555_response( p_demux ) ) { msg_Err( p_demux, "SETUP of'%s/%s' failed %s", @@ -785,6 +779,11 @@ static int SessionsSetup( demux_t *p_demux ) p_sys->env->getResultMsg() ); continue; } + else + { + var_SetBool( p_demux, "rtsp-tcp", true ); + b_rtsp_tcp = true; + } } } @@ -816,6 +815,7 @@ static int SessionsSetup( demux_t *p_demux ) tk->b_rtcp_sync = false; tk->i_pts = VLC_TS_INVALID; tk->i_npt = 0.; + tk->b_selected = true; tk->i_buffer = 65536; tk->p_buffer = (uint8_t *)malloc( 65536 ); if( !tk->p_buffer ) @@ -849,6 +849,11 @@ static int SessionsSetup( demux_t *p_demux ) tk->fmt.i_codec = VLC_CODEC_S16B; tk->fmt.audio.i_bitspersample = 16; } + else if( !strcmp( sub->codecName(), "L20" ) ) + { + tk->fmt.i_codec = VLC_CODEC_S20B; + tk->fmt.audio.i_bitspersample = 20; + } else if( !strcmp( sub->codecName(), "L24" ) ) { tk->fmt.i_codec = VLC_CODEC_S24B; @@ -859,6 +864,11 @@ static int SessionsSetup( demux_t *p_demux ) tk->fmt.i_codec = VLC_CODEC_U8; tk->fmt.audio.i_bitspersample = 8; } + else if( !strcmp( sub->codecName(), "DAT12" ) ) + { + tk->fmt.i_codec = VLC_CODEC_DAT12; + tk->fmt.audio.i_bitspersample = 12; + } else if( !strcmp( sub->codecName(), "PCMU" ) ) { tk->fmt.i_codec = VLC_CODEC_MULAW; @@ -1062,12 +1072,10 @@ static int SessionsSetup( demux_t *p_demux ) sub->rtcpInstance()->setByeHandler( StreamClose, tk ); } - if( tk->p_es || tk->b_quicktime || tk->b_muxed || tk->b_asf ) + if( tk->p_es || tk->b_quicktime || ( tk->b_muxed && tk->p_out_muxed ) || + ( tk->b_asf && p_sys->p_out_asf ) ) { - /* Append */ - p_sys->track = (live_track_t**)xrealloc( p_sys->track, - sizeof( live_track_t ) * ( p_sys->i_track + 1 ) ); - p_sys->track[p_sys->i_track++] = tk; + TAB_APPEND_CAST( (live_track_t **), p_sys->i_track, p_sys->track, tk ); } else { @@ -1179,6 +1187,44 @@ static int Demux( demux_t *p_demux ) { live_track_t *tk = p_sys->track[i]; + if( tk->p_es ) + { + bool b; + es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b ); + if( !b && tk->b_selected ) + { + tk->b_selected = false; + p_sys->rtsp->sendTeardownCommand( *tk->sub, NULL ); + } + else if( b && !tk->b_selected) + { + bool b_rtsp_tcp = var_GetBool( p_demux, "rtsp-tcp" ) || + var_GetBool( p_demux, "rtsp-http" ); + p_sys->rtsp->sendSetupCommand( *tk->sub, default_live555_callback, False, + toBool( b_rtsp_tcp ), + toBool( p_sys->b_force_mcast && !b_rtsp_tcp ) ); + if( !wait_Live555_response( p_demux ) ) + { + msg_Err( p_demux, "SETUP of'%s/%s' failed %s", + tk->sub->mediumName(), tk->sub->codecName(), + p_sys->env->getResultMsg() ); + } + else + { + p_sys->rtsp->sendPlayCommand( *tk->sub, default_live555_callback, -1, -1, p_sys->ms->scale() ); + if( !wait_Live555_response(p_demux) ) + { + msg_Err( p_demux, "RTSP PLAY failed %s", p_sys->env->getResultMsg() ); + p_sys->rtsp->sendTeardownCommand( *tk->sub, NULL ); + } + else + tk->b_selected = true; + } + if( !tk->b_selected ) + es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, tk->p_es, false ); + } + } + if( tk->b_asf || tk->b_muxed ) b_send_pcr = false; #if 0 @@ -1199,7 +1245,7 @@ static int Demux( demux_t *p_demux ) } /* First warn we want to read data */ - p_sys->event = 0; + p_sys->event_data = 0; for( i = 0; i < p_sys->i_track; i++ ) { live_track_t *tk = p_sys->track[i]; @@ -1212,10 +1258,10 @@ static int Demux( demux_t *p_demux ) } } /* Create a task that will be called if we wait more than 300ms */ - task = p_sys->scheduler->scheduleDelayedTask( 300000, TaskInterrupt, p_demux ); + task = p_sys->scheduler->scheduleDelayedTask( 300000, TaskInterruptData, p_demux ); /* Do the read */ - p_sys->scheduler->doEventLoop( &p_sys->event ); + p_sys->scheduler->doEventLoop( &p_sys->event_data ); /* remove the task */ p_sys->scheduler->unscheduleDelayedTask( task ); @@ -1538,7 +1584,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) case DEMUX_GET_PTS_DELAY: pi64 = (int64_t*)va_arg( args, int64_t * ); - *pi64 = var_GetInteger( p_demux, "rtsp-caching" ) * 1000; + *pi64 = INT64_C(1000) + * var_GetInteger( p_demux, "network-caching" ); return VLC_SUCCESS; default: @@ -1559,6 +1606,10 @@ static int RollOverTcp( demux_t *p_demux ) var_SetBool( p_demux, "rtsp-tcp", true ); /* We close the old RTSP session */ + p_sys->rtsp->sendTeardownCommand( *p_sys->ms, NULL ); + Medium::close( p_sys->ms ); + RTSPClient::close( p_sys->rtsp ); + for( i = 0; i < p_sys->i_track; i++ ) { live_track_t *tk = p_sys->track[i]; @@ -1570,17 +1621,11 @@ static int RollOverTcp( demux_t *p_demux ) free( tk->p_buffer ); free( tk ); } - if( p_sys->i_track ) free( p_sys->track ); + TAB_CLEAN( p_sys->i_track, p_sys->track ); if( p_sys->p_out_asf ) stream_Delete( p_sys->p_out_asf ); - p_sys->rtsp->sendTeardownCommand( *p_sys->ms, NULL ); - Medium::close( p_sys->ms ); - RTSPClient::close( p_sys->rtsp ); - p_sys->ms = NULL; p_sys->rtsp = NULL; - p_sys->track = NULL; - p_sys->i_track = 0; p_sys->b_no_data = true; p_sys->i_no_data_ti = 0; p_sys->p_out_asf = NULL; @@ -1631,7 +1676,6 @@ static block_t *StreamParseAsf( demux_t *p_demux, live_track_t *tk, unsigned i_length_offset = (p_data[1] << 16) | (p_data[2] << 8) | (p_data[3] ); - bool b_key = i_flags & 0x80; bool b_length = i_flags & 0x40; bool b_relative_ts = i_flags & 0x20; bool b_duration = i_flags & 0x10; @@ -1707,6 +1751,8 @@ static void StreamRead( void *p_private, unsigned int i_size, unsigned int i_truncated_bytes, struct timeval pts, unsigned int duration ) { + VLC_UNUSED( duration ); + live_track_t *tk = (live_track_t*)p_private; demux_t *p_demux = tk->p_demux; demux_sys_t *p_sys = p_demux->p_sys; @@ -1734,7 +1780,7 @@ static void StreamRead( void *p_private, unsigned int i_size, if( qtState.sdAtomSize < 16 + 32 ) { /* invalid */ - p_sys->event = 0xff; + p_sys->event_data = 0xff; tk->waiting = 0; return; } @@ -1773,7 +1819,7 @@ static void StreamRead( void *p_private, unsigned int i_size, if( qtState.sdAtomSize < 4 ) { /* invalid */ - p_sys->event = 0xff; + p_sys->event_data = 0xff; tk->waiting = 0; return; } @@ -1811,7 +1857,7 @@ static void StreamRead( void *p_private, unsigned int i_size, if( tk->b_discard_trunc ) { - p_sys->event = 0xff; + p_sys->event_data = 0xff; tk->waiting = 0; return; } @@ -1870,7 +1916,8 @@ static void StreamRead( void *p_private, unsigned int i_size, } /* Update our global npt value */ - if( tk->i_npt > 0 && tk->i_npt > p_sys->i_npt && tk->i_npt < p_sys->i_npt_length) + if( tk->i_npt > 0 && tk->i_npt > p_sys->i_npt && + ( tk->i_npt < p_sys->i_npt_length || p_sys->i_npt_length <= 0 ) ) p_sys->i_npt = tk->i_npt; if( p_block ) @@ -1892,7 +1939,7 @@ static void StreamRead( void *p_private, unsigned int i_size, } /* warn that's ok */ - p_sys->event = 0xff; + p_sys->event_data = 0xff; /* we have read data */ tk->waiting = 0; @@ -1913,30 +1960,49 @@ static void StreamClose( void *p_private ) live_track_t *tk = (live_track_t*)p_private; demux_t *p_demux = tk->p_demux; demux_sys_t *p_sys = p_demux->p_sys; + tk->b_selected = false; + p_sys->event_rtsp = 0xff; + p_sys->event_data = 0xff; - msg_Dbg( p_demux, "StreamClose" ); + es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, tk->p_es, false ); - p_sys->event = 0xff; - p_sys->b_error = true; + int nb_tracks = 0; + for( int i = 0; i < p_sys->i_track; i++ ) + { + if( p_sys->track[i]->b_selected ) + nb_tracks++; + } + msg_Dbg( p_demux, "RTSP track Close, %d track remaining", nb_tracks ); + if( !nb_tracks ) + p_sys->b_error = true; } /***************************************************************************** * *****************************************************************************/ -static void TaskInterrupt( void *p_private ) +static void TaskInterruptRTSP( void *p_private ) +{ + demux_t *p_demux = (demux_t*)p_private; + + /* Avoid lock */ + p_demux->p_sys->event_rtsp = 0xff; +} + +static void TaskInterruptData( void *p_private ) { demux_t *p_demux = (demux_t*)p_private; p_demux->p_sys->i_no_data_ti++; /* Avoid lock */ - p_demux->p_sys->event = 0xff; + p_demux->p_sys->event_data = 0xff; } /***************************************************************************** * *****************************************************************************/ +VLC_NORETURN static void* TimeoutPrevention( void *p_data ) { timeout_thread_t *p_timeout = (timeout_thread_t *)p_data;