⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtsp.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** * rtsp.c: RTSP support for RTP stream output module ***************************************************************************** * Copyright (C) 2003-2004 the VideoLAN team * Copyright © 2007 Rémi Denis-Courmont * * $Id$ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_sout.h>#include <vlc_httpd.h>#include <vlc_url.h>#include <vlc_network.h>#include <vlc_rand.h>#include <assert.h>#include <errno.h>#include <stdlib.h>#include "rtp.h"typedef struct rtsp_session_t rtsp_session_t;struct rtsp_stream_t{    vlc_mutex_t     lock;    sout_stream_t  *owner;    httpd_host_t   *host;    httpd_url_t    *url;    char           *psz_path;    const char     *track_fmt;    unsigned        port;    int             sessionc;    rtsp_session_t **sessionv;};static int  RtspCallback( httpd_callback_sys_t *p_args,                          httpd_client_t *cl, httpd_message_t *answer,                          const httpd_message_t *query );static int  RtspCallbackId( httpd_callback_sys_t *p_args,                            httpd_client_t *cl, httpd_message_t *answer,                            const httpd_message_t *query );static void RtspClientDel( rtsp_stream_t *rtsp, rtsp_session_t *session );rtsp_stream_t *RtspSetup( sout_stream_t *p_stream, const vlc_url_t *url ){    rtsp_stream_t *rtsp = malloc( sizeof( *rtsp ) );    if( rtsp == NULL || ( url->i_port > 99999 ) )    {        free( rtsp );        return NULL;    }    rtsp->owner = p_stream;    rtsp->sessionc = 0;    rtsp->sessionv = NULL;    rtsp->host = NULL;    rtsp->url = NULL;    rtsp->psz_path = NULL;    vlc_mutex_init( &rtsp->lock );    rtsp->port = (url->i_port > 0) ? url->i_port : 554;    rtsp->psz_path = strdup( ( url->psz_path != NULL ) ? url->psz_path : "/" );    if( rtsp->psz_path == NULL )        goto error;    assert( strlen( rtsp->psz_path ) > 0 );    if( rtsp->psz_path[strlen( rtsp->psz_path ) - 1] == '/' )        rtsp->track_fmt = "%strackID=%u";    else        rtsp->track_fmt = "%s/trackID=%u";    msg_Dbg( p_stream, "RTSP stream: host %s port %d at %s",             url->psz_host, rtsp->port, rtsp->psz_path );    rtsp->host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host,                                rtsp->port );    if( rtsp->host == NULL )        goto error;    rtsp->url = httpd_UrlNewUnique( rtsp->host, rtsp->psz_path,                                    NULL, NULL, NULL );    if( rtsp->url == NULL )        goto error;    httpd_UrlCatch( rtsp->url, HTTPD_MSG_DESCRIBE, RtspCallback, (void*)rtsp );    httpd_UrlCatch( rtsp->url, HTTPD_MSG_SETUP,    RtspCallback, (void*)rtsp );    httpd_UrlCatch( rtsp->url, HTTPD_MSG_PLAY,     RtspCallback, (void*)rtsp );    httpd_UrlCatch( rtsp->url, HTTPD_MSG_PAUSE,    RtspCallback, (void*)rtsp );    httpd_UrlCatch( rtsp->url, HTTPD_MSG_GETPARAMETER, RtspCallback,                    (void*)rtsp );    httpd_UrlCatch( rtsp->url, HTTPD_MSG_TEARDOWN, RtspCallback, (void*)rtsp );    return rtsp;error:    RtspUnsetup( rtsp );    return NULL;}void RtspUnsetup( rtsp_stream_t *rtsp ){    while( rtsp->sessionc > 0 )        RtspClientDel( rtsp, rtsp->sessionv[0] );    if( rtsp->url )        httpd_UrlDelete( rtsp->url );    if( rtsp->host )        httpd_HostDelete( rtsp->host );    free( rtsp->psz_path );    vlc_mutex_destroy( &rtsp->lock );    free( rtsp );}struct rtsp_stream_id_t{    rtsp_stream_t    *stream;    sout_stream_id_t *sout_id;    httpd_url_t      *url;    const char       *dst;    int               ttl;    uint32_t          ssrc;    uint16_t          loport, hiport;};typedef struct rtsp_strack_t rtsp_strack_t;/* For unicast streaming */struct rtsp_session_t{    rtsp_stream_t *stream;    uint64_t       id;    /* output (id-access) */    int            trackc;    rtsp_strack_t *trackv;};/* Unicast session track */struct rtsp_strack_t{    sout_stream_id_t  *id;    int                fd;    bool         playing;};rtsp_stream_id_t *RtspAddId( rtsp_stream_t *rtsp, sout_stream_id_t *sid,                             unsigned num, uint32_t ssrc,                             /* Multicast stuff - TODO: cleanup */                             const char *dst, int ttl,                             unsigned loport, unsigned hiport ){    char urlbuf[sizeof( "/trackID=123" ) + strlen( rtsp->psz_path )];    rtsp_stream_id_t *id = malloc( sizeof( *id ) );    httpd_url_t *url;    if( id == NULL )        return NULL;    id->stream = rtsp;    id->sout_id = sid;    id->ssrc = ssrc;    /* TODO: can we assume that this need not be strdup'd? */    id->dst = dst;    if( id->dst != NULL )    {        id->ttl = ttl;        id->loport = loport;        id->hiport = hiport;    }    /* FIXME: num screws up if any ES has been removed and re-added */    snprintf( urlbuf, sizeof( urlbuf ), rtsp->track_fmt, rtsp->psz_path,              num );    msg_Dbg( rtsp->owner, "RTSP: adding %s", urlbuf );    url = id->url = httpd_UrlNewUnique( rtsp->host, urlbuf, NULL, NULL, NULL );    if( url == NULL )    {        free( id );        return NULL;    }    httpd_UrlCatch( url, HTTPD_MSG_DESCRIBE, RtspCallbackId, (void *)id );    httpd_UrlCatch( url, HTTPD_MSG_SETUP,    RtspCallbackId, (void *)id );    httpd_UrlCatch( url, HTTPD_MSG_PLAY,     RtspCallbackId, (void *)id );    httpd_UrlCatch( url, HTTPD_MSG_PAUSE,    RtspCallbackId, (void *)id );    httpd_UrlCatch( url, HTTPD_MSG_GETPARAMETER, RtspCallbackId, (void *)id );    httpd_UrlCatch( url, HTTPD_MSG_TEARDOWN, RtspCallbackId, (void *)id );    return id;}void RtspDelId( rtsp_stream_t *rtsp, rtsp_stream_id_t *id ){    vlc_mutex_lock( &rtsp->lock );    for( int i = 0; i < rtsp->sessionc; i++ )    {        rtsp_session_t *ses = rtsp->sessionv[i];        for( int j = 0; j < ses->trackc; j++ )        {            if( ses->trackv[j].id == id->sout_id )            {                rtsp_strack_t *tr = ses->trackv + j;                net_Close( tr->fd );                REMOVE_ELEM( ses->trackv, ses->trackc, j );            }        }    }    vlc_mutex_unlock( &rtsp->lock );    httpd_UrlDelete( id->url );    free( id );}/** rtsp must be locked */staticrtsp_session_t *RtspClientNew( rtsp_stream_t *rtsp ){    rtsp_session_t *s = malloc( sizeof( *s ) );    if( s == NULL )        return NULL;    s->stream = rtsp;    vlc_rand_bytes (&s->id, sizeof (s->id));    s->trackc = 0;    s->trackv = NULL;    TAB_APPEND( rtsp->sessionc, rtsp->sessionv, s );    return s;}/** rtsp must be locked */staticrtsp_session_t *RtspClientGet( rtsp_stream_t *rtsp, const char *name ){    char *end;    uint64_t id;    int i;    if( name == NULL )        return NULL;    errno = 0;    id = strtoull( name, &end, 0x10 );    if( errno || *end )        return NULL;    /* FIXME: use a hash/dictionary */    for( i = 0; i < rtsp->sessionc; i++ )    {        if( rtsp->sessionv[i]->id == id )            return rtsp->sessionv[i];    }    return NULL;}/** rtsp must be locked */staticvoid RtspClientDel( rtsp_stream_t *rtsp, rtsp_session_t *session ){    int i;    TAB_REMOVE( rtsp->sessionc, rtsp->sessionv, session );    for( i = 0; i < session->trackc; i++ )        rtp_del_sink( session->trackv[i].id, session->trackv[i].fd );    free( session->trackv );    free( session );}/** Finds the next transport choice */static inline const char *transport_next( const char *str ){    /* Looks for comma */    str = strchr( str, ',' );    if( str == NULL )        return NULL; /* No more transport options */    str++; /* skips comma */    while( strchr( "\r\n\t ", *str ) )        str++;    return (*str) ? str : NULL;}/** Finds the next transport parameter */static inline const char *parameter_next( const char *str ){    while( strchr( ",;", *str ) == NULL )        str++;    return (*str == ';') ? (str + 1) : NULL;}/** RTSP requests handler * @param id selected track for non-aggregate URLs, *           NULL for aggregate URLs */static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,                        httpd_client_t *cl,                        httpd_message_t *answer,                        const httpd_message_t *query ){    sout_stream_t *p_stream = rtsp->owner;    char psz_sesbuf[17];    const char *psz_session = NULL, *psz;    char control[sizeof("rtsp://[]:12345") + NI_MAXNUMERICHOST                  + strlen( rtsp->psz_path )];    time_t now;    time (&now);    if( answer == NULL || query == NULL || cl == NULL )        return VLC_SUCCESS;    else    {        /* Build self-referential control URL */        char ip[NI_MAXNUMERICHOST], *ptr;        httpd_ServerIP( cl, ip );        ptr = strchr( ip, '%' );        if( ptr != NULL )            *ptr = '\0';        if( strchr( ip, ':' ) != NULL )            sprintf( control, "rtsp://[%s]:%u%s", ip, rtsp->port,                     rtsp->psz_path );        else            sprintf( control, "rtsp://%s:%u%s", ip, rtsp->port,                     rtsp->psz_path );    }    /* */    answer->i_proto = HTTPD_PROTO_RTSP;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -