vlc 调用live555的源码分析--vlc v2.1.1版本

33 篇文章 10 订阅
9 篇文章 0 订阅
VLC调用Live555源码解析
 以前在看live555的源码和例子的时,发现live555的例子都是回调,这样我们根本无法判断命令是否发送成功,也无法判断发送是否超时;网上搜索,也没有看到有用的资料;于是就分析了VLC的live555.cpp文件,对该问题恍然大悟,于是记下vlc live555的Rtsp连接建立过程,供大家参考,我们可以从vlc怎么调用live555.cpp中看到vlc 是如何结合live555的,这样对我们调用live555写客户端等等有很大的帮助!

 

源码见:

http://blog.csdn.net/smilestone_322/article/details/17504909

1)  连接RTSP服务器
/*****************************************************************************
 * Connect: connects to the RTSP server to setup the session DESCRIBE
 *****************************************************************************/
static int Connect( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    Authenticator authenticator;
    char *psz_user    = NULL;
    char *psz_pwd     = NULL;
    char *psz_url     = NULL;
    int  i_http_port  = 0;
int  i_ret        = VLC_SUCCESS;
 
//获取超时的时间
    const int i_timeout = var_InheritInteger( p_demux, "ipv4-timeout" );
 
/* Get the user name and password */
//获取RTSP的URL的用户名和密码;
    if( p_sys->url.psz_username || p_sys->url.psz_password )
    {
        /* Create the URL by stripping away the username/password part */
        if( p_sys->url.i_port == 0 )
            p_sys->url.i_port = 554;
        if( asprintf( &psz_url, "rtsp://%s:%d%s",
                      strempty( p_sys->url.psz_host ),
                      p_sys->url.i_port,
                      strempty( p_sys->url.psz_path ) ) == -1 )
            return VLC_ENOMEM;
 
        psz_user = strdup( strempty( p_sys->url.psz_username ) );
        psz_pwd  = strdup( strempty( p_sys->url.psz_password ) );
    }
    else
    {
        if( asprintf( &psz_url, "rtsp://%s", p_sys->psz_path ) == -1 )
            return VLC_ENOMEM;
 
        psz_user = var_InheritString( p_demux, "rtsp-user" );
        psz_pwd  = var_InheritString( p_demux, "rtsp-pwd" );
    }
 
createnew:
    if( !vlc_object_alive (p_demux) )
    {
        i_ret = VLC_EGENERIC;
        goto bailout;
    }
       //判断是否走http隧道
    if( var_CreateGetBool( p_demux, "rtsp-http" ) )
        i_http_port = var_InheritInteger( p_demux, "rtsp-http-port" );
 
//创建一个RTSPClient客户端, RTSPClientVlc继承自live555的RTSPClient
    p_sys->rtsp = new RTSPClientVlc( *p_sys->env, psz_url,
                                     var_InheritInteger( p_demux, "verbose" ) > 1 ? 1 : 0,
                                     "LibVLC/"VERSION, i_http_port, p_sys );
    if( !p_sys->rtsp )
    {
        msg_Err( p_demux, "RTSPClient::createNew failed (%s)",
                 p_sys->env->getResultMsg() );
        i_ret = VLC_EGENERIC;
        goto bailout;
    }
 
    /* Kasenna enables KeepAlive by analysing the User-Agent string.
     * Appending _KA to the string should be enough to enable this feature,
     * however, there is a bug where the _KA doesn't get parsed from the
     * default User-Agent as created by VLC/Live555 code. This is probably due
     * to spaces in the string or the string being too long. Here we override
     * the default string with a more compact version.
     */
    if( var_InheritBool( p_demux, "rtsp-kasenna" ))
    {
        p_sys->rtsp->setUserAgentString( "VLC_MEDIA_PLAYER_KA" );
    }
 
describe:
    authenticator.setUsernameAndPassword( psz_user, psz_pwd );
      
       //往服务器发送sendOptionsCommand请求,continueAfterOPTIONS和live555的例子一样,是一个回调,在发送完sendOptionsCommand请求,收到它的应答后调用该回调函数,在continueAfterOPTIONS函数中发送Describe请求;
    p_sys->rtsp->sendOptionsCommand( &continueAfterOPTIONS, &authenticator );
      
       // wait_Live555_response 用来判断发送命令是否超时,相当重要,Live555给的例子中都没有这个,这样我们是不好判断我们发送的命令是否失败,比如发送命令超时了,程序就没有响应了,都不能给个提示,VLC使用该函数解决了Live555的这个问题;
    if( !wait_Live555_response( p_demux, i_timeout ) )
    {
        int i_code = p_sys->i_live555_ret;
        if( i_code == 401 )
        {
            msg_Dbg( p_demux, "authentication failed" );
 
            free( psz_user );
            free( psz_pwd );
            dialog_Login( p_demux, &psz_user, &psz_pwd,
                          _("RTSP authentication"), "%s",
                        _("Please enter a valid login name and a password.") );
            if( psz_user != NULL && psz_pwd != NULL )
            {
                            //鉴权失败,转到describe再次发送Opinion请求
                msg_Dbg( p_demux, "retrying with user=%s", psz_user );
                goto describe;
            }
        }
        else if( i_code > 0 && i_code != 404 && !var_GetBool( p_demux, "rtsp-http" ) )
        {
            /* Perhaps a firewall is being annoying. Try HTTP tunneling mode */
                     //失败,转http 隧道模式
            msg_Dbg( p_demux, "we will now try HTTP tunneling mode" );
            var_SetBool( p_demux, "rtsp-http", true );
            if( p_sys->rtsp ) RTSPClient::close( p_sys->rtsp );
            p_sys->rtsp = NULL;
            goto createnew;
        }
        else
        {
                     // i_code=0表示连接超时
            if( i_code == 0 )
                msg_Dbg( p_demux, "connection timeout" );
            else
            {
                            //连接失败
                msg_Dbg( p_demux, "connection error %d", i_code );
                if( i_code == 403 )
                    dialog_Fatal( p_demux, _("RTSP connection failed"),
                                  _("Access to the stream is denied by the server configuration.") );
            }
            if( p_sys->rtsp ) RTSPClient::close( p_sys->rtsp );
            p_sys->rtsp = NULL;
        }
        i_ret = VLC_EGENERIC;
    }
 
bailout:
    /* malloc-ated copy */
    free( psz_url );
    free( psz_user );
    free( psz_pwd );
 
    return i_ret;
}
 
其中:
static void continueAfterOPTIONS( RTSPClient* client, int result_code,
                                  char* result_string )
{
    RTSPClientVlc *client_vlc = static_cast<RTSPClientVlc *> (client);
    demux_sys_t *p_sys = client_vlc->p_sys;
    p_sys->b_get_param =
      // If OPTIONS fails, assume GET_PARAMETER is not supported but
      // still continue on with the stream.  Some servers (foscam)
      // return 501/not implemented for OPTIONS.
      result_code == 0
      && result_string != NULL
      && strstr( result_string, "GET_PARAMETER" ) != NULL;
    client->sendDescribeCommand( continueAfterDESCRIBE );
    delete[] result_string;
}
 
在continueAfterOPTIONS函数中,调用sendDescribeCommand函数发送Describe命令;continueAfterDESCRIBE为sendDescribeCommand命令发送后调用的回调函数;
 
continueAfterDESCRIBE函数如下:
static void continueAfterDESCRIBE( RTSPClient* client, int result_code,
                                   char* result_string )
{
    RTSPClientVlc *client_vlc = static_cast<RTSPClientVlc *> ( client );
    demux_sys_t *p_sys = client_vlc->p_sys;
    p_sys->i_live555_ret = result_code;
    if ( result_code == 0 )
    {
        char* sdpDescription = result_string;
        free( p_sys->p_sdp );
        p_sys->p_sdp = NULL;
        if( sdpDescription )
        {
            p_sys->p_sdp = strdup( sdpDescription );
            p_sys->b_error = false;
        }
    }
    else
        p_sys->b_error = true;
    delete[] result_string;
    p_sys->event_rtsp = 1;
}
 
回调函数中的result_code和result_string还是挺重要的,可以从其中判断发送的命令是否错误;
 
判断超时的函数如下:
/* return true if the RTSP command succeeded */
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_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,
                                                      TaskInterruptRTSP,
                                                      p_demux );
    }
    p_sys->event_rtsp = 0;
    p_sys->b_error = true;
p_sys->i_live555_ret = 0;
//
    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 )
    {
        /* remove the task */
        p_sys->scheduler->unscheduleDelayedTask( task );
    }
    return !p_sys->b_error;
}
 
如果超时:那么调用TaskInterruptRTSP函数;当超时时,在TaskInterruptRTSP将event_rtsp置为非0;这样doEventLoop里面的while循环会顺利退出;如果没有超时,在continueAfterDESCRIBE函数中也将event_rtsp置为非0;DoEventLoop的线程也会顺利退出,这样在根据p_sys->b_error;判断是否成功还是失败;
 
*****************************************************************************/
static void TaskInterruptRTSP( void *p_private )
{
    demux_t *p_demux = (demux_t*)p_private;
 
    /* Avoid lock */
    p_demux->p_sys->event_rtsp = 0xff;
}
 
2)  发送Setup建立会话;
 
/*****************************************************************************
 * SessionsSetup: prepares the subsessions and does the SETUP
 *****************************************************************************/
static int SessionsSetup( demux_t *p_demux )
{
    demux_sys_t             *p_sys  = p_demux->p_sys;
    MediaSubsessionIterator *iter   = NULL;
    MediaSubsession         *sub    = NULL;
 
    bool           b_rtsp_tcp;
    int            i_client_port;
    int            i_return = VLC_SUCCESS;
    unsigned int   i_receive_buffer = 0;
    int            i_frame_buffer = DEFAULT_FRAME_BUFFER_SIZE;
    unsigned const thresh = 200000; /* RTP reorder threshold .2 second (default .1) */
 
    b_rtsp_tcp    = var_CreateGetBool( p_demux, "rtsp-tcp" ) ||
                    var_GetBool( p_demux, "rtsp-http" );
    i_client_port = var_InheritInteger( p_demux, "rtp-client-port" );
 
 
    /* Create the session from the SDP */
    if( !( p_sys->ms = MediaSession::createNew( *p_sys->env, p_sys->p_sdp ) ) )
    {
        msg_Err( p_demux, "Could not create the RTSP Session: %s",
            p_sys->env->getResultMsg() );
        return VLC_EGENERIC;
    }
 
    /* Initialise each media subsession */
    iter = new MediaSubsessionIterator( *p_sys->ms );
    while( ( sub = iter->next() ) != NULL )
    {
        Boolean bInit;
        live_track_t *tk;
 
        if( !vlc_object_alive (p_demux) )
        {
            delete iter;
            return VLC_EGENERIC;
        }
 
        /* Value taken from mplayer */
        if( !strcmp( sub->mediumName(), "audio" ) )
            i_receive_buffer = 100000;
        else if( !strcmp( sub->mediumName(), "video" ) )
        {
            int i_var_buf_size = var_InheritInteger( p_demux, "rtsp-frame-buffer-size" );
            if( i_var_buf_size > 0 )
                i_frame_buffer = i_var_buf_size;
            i_receive_buffer = 2000000;
        }
        else if( !strcmp( sub->mediumName(), "text" ) )
            ;
        else continue;
 
        if( i_client_port != -1 )
        {
            sub->setClientPortNum( i_client_port );
            i_client_port += 2;
        }
 
        if( strcasestr( sub->codecName(), "REAL" ) )
        {
            msg_Info( p_demux, "real codec detected, using real-RTSP instead" );
            p_sys->b_real = true; /* This is a problem, we'll handle it later */
            continue;
        }
 
        if( !strcmp( sub->codecName(), "X-ASF-PF" ) )
            bInit = sub->initiate( 0 );
        else
            bInit = sub->initiate();
 
        if( !bInit )
        {
            msg_Warn( p_demux, "RTP subsession '%s/%s' failed (%s)",
                      sub->mediumName(), sub->codecName(),
                      p_sys->env->getResultMsg() );
        }
        else
        {
            if( sub->rtpSource() != NULL )
            {
                int fd = sub->rtpSource()->RTPgs()->socketNum();
 
                /* Increase the buffer size */
                if( i_receive_buffer > 0 )
                    increaseReceiveBufferTo( *p_sys->env, fd, i_receive_buffer );
 
                /* Increase the RTP reorder timebuffer just a bit */
                sub->rtpSource()->setPacketReorderingThresholdTime(thresh);
            }
            msg_Dbg( p_demux, "RTP subsession '%s/%s'", sub->mediumName(),
                     sub->codecName() );
 
            /* Issue the SETUP */
            if( p_sys->rtsp )
            {
       //发送Setup命令,建立会话;default_live555_callback为sendSetupCommand函数的回调函数;其主要作用是判断SetUp命令是否发送成功,置为DoEvent的线程标志,使得线程顺利退出,从而wait_Live555_response函数能够顺利退出;
                p_sys->rtsp->sendSetupCommand( *sub, default_live555_callback, False,
                                               toBool( b_rtsp_tcp ),
                                               toBool( p_sys->b_force_mcast && !b_rtsp_tcp ) );
//判断Setup命令是否发送成功
                if( !wait_Live555_response( p_demux ) )
                {
                    /* if we get an unsupported transport error, toggle TCP
                     * 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 );
                    if( p_sys->i_live555_ret != 461 || !wait_Live555_response( p_demux ) )
                    {
                        msg_Err( p_demux, "SETUP of'%s/%s' failed %s",
                                 sub->mediumName(), sub->codecName(),
                                 p_sys->env->getResultMsg() );
                        continue;
                    }
                    else
                    {
                        var_SetBool( p_demux, "rtsp-tcp", true );
                        b_rtsp_tcp = true;
                    }
                }
            }
 
            /* Check if we will receive data from this subsession for
             * this track */
            if( sub->readSource() == NULL ) continue;
            if( !p_sys->b_multicast )
            {
                /* We need different rollover behaviour for multicast */
                p_sys->b_multicast = IsMulticastAddress( sub->connectionEndpointAddress() );
            }
 
            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->p_asf_block = NULL;
            tk->b_muxed     = false;
            tk->b_discard_trunc = false;
            tk->p_out_muxed = NULL;
            tk->waiting     = 0;
            tk->b_rtcp_sync = false;
            tk->i_pts       = VLC_TS_INVALID;
            tk->f_npt       = 0.;
            tk->b_selected  = true;
            tk->i_buffer    = i_frame_buffer;
            tk->p_buffer    = (uint8_t *)malloc( i_frame_buffer );
 
            if( !tk->p_buffer )
            {
                free( tk );
                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_CODEC_MPGA;
                    tk->fmt.audio.i_rate = 0;
                }
                else if( !strcmp( sub->codecName(), "AC3" ) )
                {
                    tk->fmt.i_codec = VLC_CODEC_A52;
                    tk->fmt.audio.i_rate = 0;
                }
                else if( !strcmp( sub->codecName(), "L16" ) )
                {
                    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;
                    tk->fmt.audio.i_bitspersample = 24;
                }
                else if( !strcmp( sub->codecName(), "L8" ) )
                {
                    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;
                    tk->fmt.audio.i_bitspersample = 8;
                }
                else if( !strcmp( sub->codecName(), "PCMA" ) )
                {
                    tk->fmt.i_codec = VLC_CODEC_ALAW;
                    tk->fmt.audio.i_bitspersample = 8;
                }
                else if( !strncmp( sub->codecName(), "G726", 4 ) )
                {
                    tk->fmt.i_codec = VLC_CODEC_ADPCM_G726;
                    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_CODEC_AMR_NB;
                }
                else if( !strcmp( sub->codecName(), "AMR-WB" ) )
                {
                    tk->fmt.i_codec = VLC_CODEC_AMR_WB;
                }
                else if( !strcmp( sub->codecName(), "MP4A-LATM" ) )
                {
                    unsigned int i_extra;
                    uint8_t      *p_extra;
 
                    tk->fmt.i_codec = VLC_CODEC_MP4A;
 
                    if( ( p_extra = parseStreamMuxConfigStr( sub->fmtp_config(),
                                                             i_extra ) ) )
                    {
                        tk->fmt.i_extra = i_extra;
                        tk->fmt.p_extra = xmalloc( 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. */
                    ((MPEG4LATMAudioRTPSource*)sub->rtpSource())->omitLATMDataLengthField();
                }
                else if( !strcmp( sub->codecName(), "MPEG4-GENERIC" ) )
                {
                    unsigned int i_extra;
                    uint8_t      *p_extra;
 
                    tk->fmt.i_codec = VLC_CODEC_MP4A;
 
                    if( ( p_extra = parseGeneralConfigStr( sub->fmtp_config(),
                                                           i_extra ) ) )
                    {
                        tk->fmt.i_extra = i_extra;
                        tk->fmt.p_extra = xmalloc( 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 ( tk->fmt.audio.i_rate == 0 )
                    {
                        msg_Warn( p_demux,"Using 8kHz as default sample rate." );
                        tk->fmt.audio.i_rate = 8000;
                    }
                }
                else if( !strcmp( sub->codecName(), "VORBIS" ) )
                {
                    tk->fmt.i_codec = VLC_CODEC_VORBIS;
                    unsigned int i_extra;
                    unsigned char *p_extra;
                    if( ( p_extra=parseVorbisConfigStr( sub->fmtp_config(),
                                                        i_extra ) ) )
                    {
                        tk->fmt.i_extra = i_extra;
                        tk->fmt.p_extra = p_extra;
                    }
                    else
                        msg_Warn( p_demux,"Missing or unsupported vorbis header." );
                }
            }
            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_CODEC_MPGV;
                    tk->fmt.b_packetized = false;
                }
                else if( !strcmp( sub->codecName(), "H263" ) ||
                         !strcmp( sub->codecName(), "H263-1998" ) ||
                         !strcmp( sub->codecName(), "H263-2000" ) )
                {
                    tk->fmt.i_codec = VLC_CODEC_H263;
                }
                else if( !strcmp( sub->codecName(), "H261" ) )
                {
                    tk->fmt.i_codec = VLC_CODEC_H261;
                }
                else if( !strcmp( sub->codecName(), "H264" ) )
                {
                    unsigned int i_extra = 0;
                    uint8_t      *p_extra = NULL;
 
                    tk->fmt.i_codec = VLC_CODEC_H264;
                    tk->fmt.b_packetized = false;
 
                    if((p_extra=parseH264ConfigStr( sub->fmtp_spropparametersets(),
                                                    i_extra ) ) )
                    {
                        tk->fmt.i_extra = i_extra;
                        tk->fmt.p_extra = xmalloc( 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_CODEC_MJPG;
                }
                else if( !strcmp( sub->codecName(), "MP4V-ES" ) )
                {
                    unsigned int i_extra;
                    uint8_t      *p_extra;
 
                    tk->fmt.i_codec = VLC_CODEC_MP4V;
 
                    if( ( p_extra = parseGeneralConfigStr( sub->fmtp_config(),
                                                           i_extra ) ) )
                    {
                        tk->fmt.i_extra = i_extra;
                        tk->fmt.p_extra = xmalloc( 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 );;
                }
                else if( !strcmp( sub->codecName(), "DV" ) )
                {
                    tk->b_muxed = true;
                    tk->b_discard_trunc = true;
                    tk->p_out_muxed = stream_DemuxNew( p_demux, "rawdv",
                                                       p_demux->out );
                }
                else if( !strcmp( sub->codecName(), "VP8" ) )
                {
                    tk->fmt.i_codec = VLC_CODEC_VP8;
                }
            }
            else if( !strcmp( sub->mediumName(), "text" ) )
            {
                es_format_Init( &tk->fmt, SPU_ES, VLC_FOURCC('u','n','d','f') );
 
                if( !strcmp( sub->codecName(), "T140" ) )
                {
                    tk->fmt.i_codec = VLC_CODEC_ITU_T140;
                }
            }
 
            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->p_out_muxed ) ||
                ( tk->b_asf && p_sys->p_out_asf ) )
            {
                TAB_APPEND_CAST( (live_track_t **), p_sys->i_track, p_sys->track, tk );
            }
            else
            {
                /* BUG ??? */
                msg_Err( p_demux, "unusable RTSP track. this should not happen" );
                es_format_Clean( &tk->fmt );
                free( tk );
            }
        }
    }
    delete iter;
    if( p_sys->i_track <= 0 ) i_return = VLC_EGENERIC;
 
    /* Retrieve the starttime if possible */
    p_sys->f_npt_start = p_sys->ms->playStartTime();
 
    /* Retrieve the duration if possible */
    p_sys->f_npt_length = p_sys->ms->playEndTime();
 
    /* */
    msg_Dbg( p_demux, "setup start: %f stop:%f", p_sys->f_npt_start, p_sys->f_npt_length );
 
    /* */
    p_sys->b_no_data = true;
    p_sys->i_no_data_ti = 0;
 
    return i_return;
}
 
其中default_live555_callback函数定义如下,该函数也是挺重要的:
 
static void default_live555_callback( RTSPClient* client, int result_code, char* result_string )
{
    RTSPClientVlc *client_vlc = static_cast<RTSPClientVlc *> ( client );
    demux_sys_t *p_sys = client_vlc->p_sys;
    delete []result_string;
    p_sys->i_live555_ret = result_code;
    p_sys->b_error = p_sys->i_live555_ret != 0;
    p_sys->event_rtsp = 1;
}
 
3)  发送Play请求;
 
static int Play( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
 
    if( p_sys->rtsp )
    {
        /* The PLAY */
              //发送sendPlayCommand命令,default_live555_callback为其回调函数
        p_sys->rtsp->sendPlayCommand( *p_sys->ms, default_live555_callback, p_sys->f_npt_start, -1, 1 );
 
              //判断Play命令是否发送超时
        if( !wait_Live555_response(p_demux) )
        {
            msg_Err( p_demux, "RTSP PLAY failed %s", p_sys->env->getResultMsg() );
            return VLC_EGENERIC;
        }
 
        /* Retrieve the timeout value and set up a timeout prevention thread */
        p_sys->i_timeout = p_sys->rtsp->sessionTimeoutParameter();
        if( p_sys->i_timeout <= 0 )
            p_sys->i_timeout = 60; /* default value from RFC2326 */
 
        /* start timeout-thread only if GET_PARAMETER is supported by the server */
        /* or start it if wmserver dialect, since they don't report that GET_PARAMETER is supported correctly */
        if( !p_sys->p_timeout && ( p_sys->b_get_param || var_InheritBool( p_demux, "rtsp-wmserver" ) ) )
        {
            msg_Dbg( p_demux, "We have a timeout of %d seconds",  p_sys->i_timeout );
            p_sys->p_timeout = (timeout_thread_t *)malloc( sizeof(timeout_thread_t) );
            if( p_sys->p_timeout )
            {
                memset( p_sys->p_timeout, 0, sizeof(timeout_thread_t) );
                p_sys->p_timeout->p_sys = p_demux->p_sys; /* lol, object recursion :D */
                if( vlc_clone( &p_sys->p_timeout->handle,  TimeoutPrevention,
                               p_sys->p_timeout, VLC_THREAD_PRIORITY_LOW ) )
                {
                    msg_Err( p_demux, "cannot spawn liveMedia timeout thread" );
                    free( p_sys->p_timeout );
                    p_sys->p_timeout = NULL;
                }
                else
                    msg_Dbg( p_demux, "spawned timeout thread" );
            }
            else
                msg_Err( p_demux, "cannot spawn liveMedia timeout thread" );
        }
    }
    p_sys->i_pcr = 0;
 
    /* Retrieve the starttime if possible */
    p_sys->f_npt_start = p_sys->ms->playStartTime();
    if( p_sys->ms->playEndTime() > 0 )
        p_sys->f_npt_length = p_sys->ms->playEndTime();
 
    msg_Dbg( p_demux, "play start: %f stop:%f", p_sys->f_npt_start, p_sys->f_npt_length );
    return VLC_SUCCESS;
}
 
 
 
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值