📄 mmstu.c
字号:
/***************************************************************************** * mms.c: MMS access plug-in ***************************************************************************** * Copyright (C) 2001, 2002 the VideoLAN team * $Id: mmstu.c 15016 2006-03-31 23:07:01Z xtophe $ * * 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 *****************************************************************************/#include <stdlib.h>#include <vlc/vlc.h>#include <string.h>#include <vlc/input.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#include "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 E_( MMSTUOpen ) ( access_t * );void E_( MMSTUClose ) ( access_t * );static int Read( access_t *, uint8_t *, int );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 * );/* * XXX DON'T FREE MY MEMORY !!! XXX * non mais :P *//* * Ok, ok, j'le ferai plus... *//* * Merci :)) *//* * Vous pourriez signer vos commentaires (m�e si on voit bien qui peut * �rire ce genre de trucs :p), et �rire en anglais, bordel de * merde :p. *//* * Alors la ouai �est fou les gens qui �rivent des commentaires sans les * signer. Ca m�iterait un coup de pied dans le cul � :) */int E_(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 = VLC_FALSE; p_access->info.i_title = 0; p_access->info.i_seekpoint = 0; p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) ); memset( p_sys, 0, sizeof( access_sys_t ) ); /* *** 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 ); 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 ); 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 = VLC_FALSE; } else { p_sys->b_seekable = VLC_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" ); MMSClose( p_access ); vlc_UrlClean( &p_sys->url ); return VLC_EGENERIC; } return VLC_SUCCESS;}/***************************************************************************** * Close: free unused data structures *****************************************************************************/void E_(MMSTUClose)( access_t *p_access ){ access_sys_t *p_sys = p_access->p_sys; /* close connection with server */ MMSClose( p_access ); /* free memory */ vlc_UrlClean( &p_sys->url ); 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; vlc_bool_t *pb_bool; int *pi_int; int64_t *pi_64; int i_int; vlc_value_t val; switch( i_query ) { /* */ case ACCESS_CAN_SEEK: pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* ); *pb_bool = p_sys->b_seekable; break; case ACCESS_CAN_FASTSEEK: case ACCESS_CAN_PAUSE: pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* ); *pb_bool = VLC_FALSE; break; case ACCESS_CAN_CONTROL_PACE: pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );#if 0 /* Disable for now until we have a clock synchro algo * which works with something else than MPEG over UDP */ *pb_bool = VLC_FALSE;#endif *pb_bool = VLC_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" ) * I64C(1000); break; case ACCESS_GET_PRIVATE_ID_STATE: i_int = (int)va_arg( args, int ); pb_bool = (vlc_bool_t *)va_arg( args, vlc_bool_t * ); if( i_int < 0 || i_int > 127 ) return VLC_EGENERIC; *pb_bool = p_sys->asfh.stream[i_int].i_selected ? VLC_TRUE : VLC_FALSE; break; /* */ case ACCESS_SET_PAUSE_STATE: case ACCESS_GET_TITLE_INFO: case ACCESS_SET_TITLE: case ACCESS_SET_SEEKPOINT: case ACCESS_SET_PRIVATE_ID_STATE: 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 "I64Fd " (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( !p_access->b_die ) { mms_HeaderMediaRead( p_access, MMS_PACKET_CMD ); if( p_sys->i_command == 0x1e ) { msg_Dbg( p_access, "received 0x1e (seek)" ); break; } } while( !p_access->b_die ) { mms_HeaderMediaRead( p_access, MMS_PACKET_CMD ); if( p_sys->i_command == 0x05 ) { msg_Dbg( p_access, "received 0x05 (seek)" ); break; } } /* get a packet */ mms_HeaderMediaRead( p_access, MMS_PACKET_MEDIA ); msg_Dbg( p_access, "Streaming restarted" ); p_sys->i_media_used += i_offset; p_access->info.i_pos = i_pos; p_access->info.b_eof = VLC_FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -