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

📄 mmstu.c

📁 vlc源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************************************************** * mms.c: MMS access plug-in ***************************************************************************** * Copyright (C) 2001, 2002 the VideoLAN team * $Id: 72c817e1a0f1944f56146dcbb9dd9882c589334d $ * * 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_access.h>#include <errno.h>#ifdef HAVE_UNISTD_H#   include <unistd.h>#endif#ifdef HAVE_FCNTL_H#   include <fcntl.h>#endif#ifdef HAVE_SYS_TIME_H#   include <sys/time.h>#endif#ifdef HAVE_SYS_TYPES_H#   include <sys/types.h>#endif#ifdef HAVE_SYS_STAT_H#   include <sys/stat.h>#endif#ifdef HAVE_POLL#   include <poll.h>#endif#include <vlc_network.h>#include "vlc_url.h"#include "asf.h"#include "buffer.h"#include "mms.h"#include "mmstu.h"#undef MMS_DEBUG/**************************************************************************** * NOTES: *  MMSProtocole documentation found at http://get.to/sdp ****************************************************************************//***************************************************************************** * Local prototypes *****************************************************************************/int   MMSTUOpen   ( access_t * );void  MMSTUClose  ( access_t * );static ssize_t Read( access_t *, uint8_t *, size_t );static int Seek( access_t *, int64_t );static int Control( access_t *, int, va_list );static int  MMSOpen ( access_t *, vlc_url_t *, int );static int  MMSStart( access_t *, uint32_t );static int  MMSStop ( access_t * );static void MMSClose( access_t * );static int  mms_CommandRead( access_t *p_access, int i_command1, int i_command2 );static int  mms_CommandSend( access_t *, int, uint32_t, uint32_t, uint8_t *, int );static int  mms_HeaderMediaRead( access_t *, int );static int  mms_ReceivePacket( access_t * );static void* KeepAliveThread( vlc_object_t *p_this );int  MMSTUOpen( access_t *p_access ){    access_sys_t   *p_sys;    int             i_proto;    int             i_status;    /* Set up p_access */    p_access->pf_read = Read;    p_access->pf_block = NULL;    p_access->pf_control = Control;    p_access->pf_seek = Seek;    p_access->info.i_update = 0;    p_access->info.i_size = 0;    p_access->info.i_pos = 0;    p_access->info.b_eof = false;    p_access->info.i_title = 0;    p_access->info.i_seekpoint = 0;    p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) );    if( !p_sys ) return VLC_ENOMEM;    memset( p_sys, 0, sizeof( access_sys_t ) );    p_sys->i_timeout = var_CreateGetInteger( p_access, "mms-timeout" );    vlc_mutex_init( &p_sys->lock_netwrite );    /* *** Parse URL and get server addr/port and path *** */    vlc_UrlParse( &p_sys->url, p_access->psz_path, 0 );    if( p_sys->url.psz_host == NULL || *p_sys->url.psz_host == '\0' )    {        msg_Err( p_access, "invalid server name" );        vlc_UrlClean( &p_sys->url );        vlc_mutex_destroy( &p_sys->lock_netwrite );        free( p_sys );        return VLC_EGENERIC;    }    if( p_sys->url.i_port <= 0 )    {        p_sys->url.i_port = 1755;    }    /* *** connect to this server *** */    /* look at  requested protocol (udp/tcp) */    i_proto = MMS_PROTO_AUTO;    if( *p_access->psz_access )    {        if( !strncmp( p_access->psz_access, "mmsu", 4 ) )        {            i_proto = MMS_PROTO_UDP;        }        else if( !strncmp( p_access->psz_access, "mmst", 4 ) )        {            i_proto = MMS_PROTO_TCP;        }    }    /* connect */    if( i_proto == MMS_PROTO_AUTO )    {   /* first try with TCP and then UDP*/        if( ( i_status = MMSOpen( p_access, &p_sys->url, MMS_PROTO_TCP ) ) )        {            i_status = MMSOpen( p_access, &p_sys->url, MMS_PROTO_UDP );        }    }    else    {        i_status = MMSOpen( p_access, &p_sys->url, i_proto );    }    if( i_status )    {        msg_Err( p_access, "cannot connect to server" );        vlc_UrlClean( &p_sys->url );        vlc_mutex_destroy( &p_sys->lock_netwrite );        free( p_sys );        return VLC_EGENERIC;    }    msg_Dbg( p_access, "connected to %s:%d", p_sys->url.psz_host, p_sys->url.i_port );    /*     * i_flags_broadcast     *  yy xx ?? ??     *  broadcast    yy=0x02, xx= 0x00     *  pre-recorded yy=0x01, xx= 0x80 if video, 0x00 no video     */    if( p_sys->i_packet_count <= 0 && p_sys->asfh.i_data_packets_count > 0 )    {        p_sys->i_packet_count = p_sys->asfh.i_data_packets_count;    }    if( p_sys->i_packet_count <= 0 || ( p_sys->i_flags_broadcast >> 24 ) == 0x02 )    {        p_sys->b_seekable = false;    }    else    {        p_sys->b_seekable = true;        p_access->info.i_size =            (uint64_t)p_sys->i_header +            (uint64_t)p_sys->i_packet_count * (uint64_t)p_sys->i_packet_length;    }    /* *** Start stream *** */    if( MMSStart( p_access, 0xffffffff ) < 0 )    {        msg_Err( p_access, "cannot start stream" );        MMSTUClose ( p_access );        return VLC_EGENERIC;    }    /* Keep the connection alive when paused */    p_sys->p_keepalive_thread = vlc_object_create( p_access, sizeof( mmstu_keepalive_thread_t ) );    p_sys->p_keepalive_thread->p_access = p_access;    p_sys->p_keepalive_thread->b_paused = false;    p_sys->p_keepalive_thread->b_thread_error = false;    if( vlc_thread_create( p_sys->p_keepalive_thread, "mmstu keepalive thread", KeepAliveThread,                           VLC_THREAD_PRIORITY_LOW, false) )        p_sys->p_keepalive_thread->b_thread_error = true;    return VLC_SUCCESS;}/***************************************************************************** * Close: free unused data structures *****************************************************************************/void MMSTUClose( access_t *p_access ){    access_sys_t *p_sys = p_access->p_sys;    if( p_sys->p_keepalive_thread )    {        vlc_object_kill( p_sys->p_keepalive_thread );        if( !p_sys->p_keepalive_thread->b_thread_error )            vlc_thread_join( p_sys->p_keepalive_thread );        vlc_object_release( p_sys->p_keepalive_thread );    }    /* close connection with server */    MMSClose( p_access );    /* free memory */    vlc_UrlClean( &p_sys->url );    vlc_mutex_destroy( &p_sys->lock_netwrite );    free( p_sys );}/***************************************************************************** * Control: *****************************************************************************/static int Control( access_t *p_access, int i_query, va_list args ){    access_sys_t *p_sys = p_access->p_sys;    bool   *pb_bool;    bool    b_bool;    int          *pi_int;    int64_t      *pi_64;    int           i_int;    vlc_value_t  val;    switch( i_query )    {        /* */        case ACCESS_CAN_SEEK:            pb_bool = (bool*)va_arg( args, bool* );            *pb_bool = p_sys->b_seekable;            break;        case ACCESS_CAN_FASTSEEK:            pb_bool = (bool*)va_arg( args, bool* );            *pb_bool = false;            break;        case ACCESS_CAN_PAUSE:            pb_bool = (bool*)va_arg( args, bool* );            *pb_bool = true;            break;        case ACCESS_CAN_CONTROL_PACE:            pb_bool = (bool*)va_arg( args, bool* );#if 0       /* Disable for now until we have a clock synchro algo             * which works with something else than MPEG over UDP */            *pb_bool = false;#endif            *pb_bool = true;            break;        /* */        case ACCESS_GET_MTU:            pi_int = (int*)va_arg( args, int * );            *pi_int = 3 * p_sys->i_packet_length;            break;        case ACCESS_GET_PTS_DELAY:            pi_64 = (int64_t*)va_arg( args, int64_t * );            var_Get( p_access, "mms-caching", &val );            *pi_64 = (int64_t)var_GetInteger( p_access, "mms-caching" ) * INT64_C(1000);            break;        case ACCESS_GET_PRIVATE_ID_STATE:            i_int = (int)va_arg( args, int );            pb_bool = (bool *)va_arg( args, bool * );            if( i_int < 0 || i_int > 127 )                return VLC_EGENERIC;            *pb_bool =  p_sys->asfh.stream[i_int].i_selected ? true : false;            break;        /* */        case ACCESS_SET_PAUSE_STATE:            b_bool = (bool)va_arg( args, int );            if( b_bool )            {                MMSStop( p_access );                vlc_object_lock( p_sys->p_keepalive_thread );                p_sys->p_keepalive_thread->b_paused = true;                vlc_object_unlock( p_sys->p_keepalive_thread );            }            else            {                Seek( p_access, p_access->info.i_pos );                vlc_object_lock( p_sys->p_keepalive_thread );                p_sys->p_keepalive_thread->b_paused = false;                vlc_object_unlock( p_sys->p_keepalive_thread );            }            break;        case ACCESS_GET_TITLE_INFO:        case ACCESS_SET_TITLE:        case ACCESS_SET_SEEKPOINT:        case ACCESS_SET_PRIVATE_ID_STATE:        case ACCESS_GET_CONTENT_TYPE:            return VLC_EGENERIC;        default:            msg_Warn( p_access, "unimplemented query in control" );            return VLC_EGENERIC;    }    return VLC_SUCCESS;}/***************************************************************************** * Seek: try to go at the right place *****************************************************************************/static int Seek( access_t * p_access, int64_t i_pos ){    access_sys_t *p_sys = p_access->p_sys;    uint32_t    i_packet;    uint32_t    i_offset;    var_buffer_t buffer;    if( i_pos < 0 )        return VLC_EGENERIC;    if( i_pos < p_sys->i_header)    {        if( p_access->info.i_pos < p_sys->i_header )        {            /* no need to restart stream, it was already one             * or no stream was yet read */            p_access->info.i_pos = i_pos;            return VLC_SUCCESS;        }        else        {            i_packet = 0xffffffff;            i_offset = 0;        }    }    else    {        i_packet = ( i_pos - p_sys->i_header ) / p_sys->i_packet_length;        i_offset = ( i_pos - p_sys->i_header ) % p_sys->i_packet_length;    }    msg_Dbg( p_access, "seeking to %"PRId64 " (packet:%d)", i_pos, i_packet );    MMSStop( p_access );    msg_Dbg( p_access, "stream stopped (seek)" );    /* *** restart stream *** */    var_buffer_initwrite( &buffer, 0 );    var_buffer_add64( &buffer, 0 ); /* seek point in second */    var_buffer_add32( &buffer, 0xffffffff );    var_buffer_add32( &buffer, i_packet ); // begin from start    var_buffer_add8( &buffer, 0xff ); // stream time limit    var_buffer_add8( &buffer, 0xff ); //  on 3bytes ...    var_buffer_add8( &buffer, 0xff ); //    var_buffer_add8( &buffer, 0x00 ); // don't use limit    var_buffer_add32( &buffer, p_sys->i_media_packet_id_type );    mms_CommandSend( p_access, 0x07, p_sys->i_command_level, 0x0001ffff,                     buffer.p_data, buffer.i_data );    var_buffer_free( &buffer );    while( vlc_object_alive (p_access) )    {        if( mms_HeaderMediaRead( p_access, MMS_PACKET_CMD ) < 0 )        {            p_access->info.b_eof = true;            return VLC_EGENERIC;        }        if( p_sys->i_command == 0x1e )        {            msg_Dbg( p_access, "received 0x1e (seek)" );            break;        }

⌨️ 快捷键说明

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