mmstu.c
来自「VLC媒体播放程序」· C语言 代码 · 共 1,527 行 · 第 1/3 页
C
1,527 行
return VLC_EGENERIC; } i_server_version = GetDWLE( p_sys->p_cmd + MMS_CMD_HEADERSIZE + 32 ); i_tool_version = GetDWLE( p_sys->p_cmd + MMS_CMD_HEADERSIZE + 36 ); i_update_player_url = GetDWLE( p_sys->p_cmd + MMS_CMD_HEADERSIZE + 40 ); i_encryption_type = GetDWLE( p_sys->p_cmd + MMS_CMD_HEADERSIZE + 44 ); p = (uint16_t*)( p_sys->p_cmd + MMS_CMD_HEADERSIZE + 48 );#define GETUTF16( psz, size ) \ { \ int i; \ psz = malloc( size + 1); \ for( i = 0; i < size; i++ ) \ { \ psz[i] = p[i]; \ } \ psz[size] = '\0'; \ p += 2 * ( size ); \ } GETUTF16( p_sys->psz_server_version, i_server_version ); GETUTF16( p_sys->psz_tool_version, i_tool_version ); GETUTF16( p_sys->psz_update_player_url, i_update_player_url ); GETUTF16( p_sys->psz_encryption_type, i_encryption_type );#undef GETUTF16 msg_Dbg( p_input, "0x01 --> server_version:\"%s\" tool_version:\"%s\" update_player_url:\"%s\" encryption_type:\"%s\"", p_sys->psz_server_version, p_sys->psz_tool_version, p_sys->psz_update_player_url, p_sys->psz_encryption_type ); /* *** should make an 18 command to make data timing *** */ /* *** send command 2 : transport protocol selection *** */ var_buffer_reinitwrite( &buffer, 0 ); var_buffer_add32( &buffer, 0x00000000 ); var_buffer_add32( &buffer, 0x000a0000 ); var_buffer_add32( &buffer, 0x00000002 ); if( b_udp ) { sprintf( tmp, "\\\\%s\\UDP\\%d", p_sys->psz_bind_addr, 7000 ); // FIXME } else { sprintf( tmp, "\\\\192.168.0.1\\TCP\\1242" ); } var_buffer_addUTF16( &buffer, tmp ); var_buffer_add16( &buffer, '0' ); mms_CommandSend( p_input, 0x02, /* connexion request */ 0x00000000, /* flags, FIXME */ 0xffffffff, /* ???? */ buffer.p_data, buffer.i_data ); /* *** response from server, should be 0x02 or 0x03 *** */ mms_CommandRead( p_input, 0x02, 0x03 ); if( p_sys->i_command == 0x03 ) { msg_Err( p_input, "%s protocol selection failed", b_udp ? "UDP" : "TCP" ); var_buffer_free( &buffer ); MMSClose( p_input ); return VLC_EGENERIC; } else if( p_sys->i_command != 0x02 ) { msg_Warn( p_input, "received command isn't 0x02 in reponse to 0x02" ); } /* *** send command 5 : media file name/path requested *** */ var_buffer_reinitwrite( &buffer, 0 ); var_buffer_add64( &buffer, 0 ); var_buffer_addUTF16( &buffer, p_url->psz_path ); mms_CommandSend( p_input, 0x05, p_sys->i_command_level, 0xffffffff, buffer.p_data, buffer.i_data ); /* *** wait for reponse *** */ mms_CommandRead( p_input, 0x1a, 0x06 ); /* test if server send 0x1A answer */ if( p_sys->i_command == 0x1A ) { msg_Err( p_input, "id/password requested (not yet supported)" ); /* FIXME */ var_buffer_free( &buffer ); MMSClose( p_input ); return VLC_EGENERIC; } if( p_sys->i_command != 0x06 ) { msg_Err( p_input, "unknown answer (0x%x instead of 0x06)", p_sys->i_command ); var_buffer_free( &buffer ); MMSClose( p_input ); return( -1 ); } /* 1 for file ok, 2 for authen ok */ switch( GetDWLE( p_sys->p_cmd + MMS_CMD_HEADERSIZE ) ) { case 0x0001: msg_Dbg( p_input, "Media file name/path accepted" ); break; case 0x0002: msg_Dbg( p_input, "Authentication accepted" ); break; case -1: default: msg_Err( p_input, "error while asking for file %d", GetDWLE( p_sys->p_cmd + MMS_CMD_HEADERSIZE ) ); var_buffer_free( &buffer ); MMSClose( p_input ); return VLC_EGENERIC; } p_sys->i_flags_broadcast = GetDWLE( p_sys->p_cmd + MMS_CMD_HEADERSIZE + 12 ); p_sys->i_media_length = GetDWLE( p_sys->p_cmd + MMS_CMD_HEADERSIZE + 24 ); p_sys->i_packet_length = GetDWLE( p_sys->p_cmd + MMS_CMD_HEADERSIZE + 44 ); p_sys->i_packet_count = GetDWLE( p_sys->p_cmd + MMS_CMD_HEADERSIZE + 48 ); p_sys->i_max_bit_rate = GetDWLE( p_sys->p_cmd + MMS_CMD_HEADERSIZE + 56 ); p_sys->i_header_size = GetDWLE( p_sys->p_cmd + MMS_CMD_HEADERSIZE + 60 ); msg_Dbg( p_input, "answer 0x06 flags:0x%8.8x media_length:%ds packet_length:%d packet_count:%d max_bit_rate:%d header_size:%d", p_sys->i_flags_broadcast, p_sys->i_media_length, p_sys->i_packet_length, p_sys->i_packet_count, p_sys->i_max_bit_rate, p_sys->i_header_size ); /* XXX XXX dirty hack XXX XXX */ p_input->i_mtu = 3 * p_sys->i_packet_length; /* *** send command 15 *** */ var_buffer_reinitwrite( &buffer, 0 ); var_buffer_add32( &buffer, 0 ); var_buffer_add32( &buffer, 0x8000 ); var_buffer_add32( &buffer, 0xffffffff ); var_buffer_add32( &buffer, 0x00 ); var_buffer_add32( &buffer, 0x00 ); var_buffer_add32( &buffer, 0x00 ); var_buffer_add64( &buffer, (((uint64_t)0x40ac2000)<<32) ); var_buffer_add32( &buffer, p_sys->i_header_packet_id_type ); var_buffer_add32( &buffer, 0x00 ); mms_CommandSend( p_input, 0x15, p_sys->i_command_level, 0x00, buffer.p_data, buffer.i_data ); /* *** wait for reponse *** */ /* Commented out because it fails on some stream (no 0x11 answer) */#if 0 mms_CommandRead( p_input, 0x11, 0 ); if( p_sys->i_command != 0x11 ) { msg_Err( p_input, "unknown answer (0x%x instead of 0x11)", p_sys->i_command ); var_buffer_free( &buffer ); MMSClose( p_input ); return( -1 ); }#endif /* *** now read header packet *** */ /* XXX could be split over multiples packets */ msg_Dbg( p_input, "reading header" ); for( ;; ) { if( mms_HeaderMediaRead( p_input, MMS_PACKET_HEADER ) < 0 ) { msg_Err( p_input, "cannot receive header" ); var_buffer_free( &buffer ); MMSClose( p_input ); return VLC_EGENERIC; } if( p_sys->i_header >= p_sys->i_header_size ) { msg_Dbg( p_input, "header complete(%d)", p_sys->i_header ); break; } msg_Dbg( p_input, "header incomplete (%d/%d), reading more", p_sys->i_header, p_sys->i_header_size ); } /* *** parse header and get stream and their id *** */ /* get all streams properties, * * TODO : stream bitrates properties(optional) * and bitrate mutual exclusion(optional) */ E_( asf_HeaderParse )( &p_sys->asfh, p_sys->p_header, p_sys->i_header ); E_( asf_StreamSelect)( &p_sys->asfh, config_GetInt( p_input, "mms-maxbitrate" ), config_GetInt( p_input, "mms-all" ), config_GetInt( p_input, "audio" ), config_GetInt( p_input, "video" ) ); /* *** now select stream we want to receive *** */ /* TODO take care of stream bitrate TODO */ i_streams = 0; i_first = -1; var_buffer_reinitwrite( &buffer, 0 ); /* for now, select first audio and video stream */ for( i = 1; i < 128; i++ ) { if( p_sys->asfh.stream[i].i_cat != ASF_STREAM_UNKNOWN ) { i_streams++; if( i_first != -1 ) { var_buffer_add16( &buffer, 0xffff ); var_buffer_add16( &buffer, i ); } else { i_first = i; } if( p_sys->asfh.stream[i].i_selected ) { var_buffer_add16( &buffer, 0x0000 ); msg_Info( p_input, "selecting stream[0x%x] %s (%d kb/s)", i, ( p_sys->asfh.stream[i].i_cat == ASF_STREAM_AUDIO ) ? "audio" : "video" , p_sys->asfh.stream[i].i_bitrate / 1024); } else { var_buffer_add16( &buffer, 0x0002 ); msg_Info( p_input, "ignoring stream[0x%x] %s (%d kb/s)", i, ( p_sys->asfh.stream[i].i_cat == ASF_STREAM_AUDIO ) ? "audio" : "video" , p_sys->asfh.stream[i].i_bitrate / 1024); } } } if( i_streams == 0 ) { msg_Err( p_input, "cannot find any stream" ); var_buffer_free( &buffer ); MMSClose( p_input ); return VLC_EGENERIC; } mms_CommandSend( p_input, 0x33, i_streams, 0xffff | ( i_first << 16 ), buffer.p_data, buffer.i_data ); mms_CommandRead( p_input, 0x21, 0 ); if( p_sys->i_command != 0x21 ) { msg_Err( p_input, "unknown answer (0x%x instead of 0x21)", p_sys->i_command ); var_buffer_free( &buffer ); MMSClose( p_input ); return VLC_EGENERIC; } var_buffer_free( &buffer ); msg_Info( p_input, "connection sucessful" ); return VLC_SUCCESS;}/**************************************************************************** * MMSStart : Start streaming ****************************************************************************/static int MMSStart( input_thread_t *p_input, uint32_t i_packet ){ access_sys_t *p_sys = p_input->p_access_data; var_buffer_t buffer; /* *** start stream from packet 0 *** */ 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_input, 0x07, p_sys->i_command_level, 0x0001ffff, buffer.p_data, buffer.i_data ); var_buffer_free( &buffer ); mms_CommandRead( p_input, 0x05, 0 ); if( p_sys->i_command != 0x05 ) { msg_Err( p_input, "unknown answer (0x%x instead of 0x05)", p_sys->i_command ); return( -1 ); } else { /* get a packet */ mms_HeaderMediaRead( p_input, MMS_PACKET_MEDIA ); msg_Dbg( p_input, "Streaming started" ); return( 0 ); }}/**************************************************************************** * MMSStop : Stop streaming ****************************************************************************/static int MMSStop( input_thread_t *p_input ){ access_sys_t *p_sys = p_input->p_access_data; /* *** stop stream but keep connection alive *** */ mms_CommandSend( p_input, 0x09, p_sys->i_command_level, 0x001fffff, NULL, 0 ); return( 0 );}/**************************************************************************** * MMSClose : Close streaming and connection ****************************************************************************/static void MMSClose( input_thread_t *p_input ){ access_sys_t *p_sys = p_input->p_access_data; msg_Dbg( p_input, "Connection closed" ); /* *** tell server that we will disconnect *** */ mms_CommandSend( p_input, 0x0d, p_sys->i_command_level, 0x00000001, NULL, 0 ); /* *** close sockets *** */ net_Close( p_sys->socket_tcp.i_handle ); if( p_sys->i_proto == MMS_PROTO_UDP ) { net_Close( p_sys->socket_udp.i_handle ); } FREE( p_sys->p_cmd ); FREE( p_sys->p_media ); FREE( p_sys->p_header ); FREE( p_sys->psz_server_version ); FREE( p_sys->psz_tool_version ); FREE( p_sys->psz_update_player_url ); FREE( p_sys->psz_encryption_type );}/**************************************************************************** * * MMS specific functions * ****************************************************************************/static int mms_CommandSend( input_thread_t *p_input, int i_command, uint32_t i_prefix1, uint32_t i_prefix2, uint8_t *p_data, int i_data ){ var_buffer_t buffer; access_sys_t *p_sys = p_input->p_access_data; int i_data_by8; i_data_by8 = ( i_data + 7 ) / 8; /* first init uffer */ var_buffer_initwrite( &buffer, 0 ); var_buffer_add32( &buffer, 0x00000001 ); /* start sequence */ var_buffer_add32( &buffer, 0xB00BFACE ); /* size after protocol type */ var_buffer_add32( &buffer, i_data + MMS_CMD_HEADERSIZE - 16 ); var_buffer_add32( &buffer, 0x20534d4d ); /* protocol "MMS " */ var_buffer_add32( &buffer, i_data_by8 + 4 ); var_buffer_add32( &buffer, p_sys->i_seq_num ); p_sys->i_seq_num++; var_buffer_add64( &buffer, 0 ); var_buffer_add32( &buffer, i_data_by8 + 2 ); var_buffer_add32( &buffer, 0x00030000 | i_command ); /* dir | command */ var_buffer_add32( &buffer, i_prefix1 ); /* command specific */ var_buffer_add32( &buffer, i_prefix2 ); /* command specific */ /* specific command data */ if( p_data && i_data > 0 ) { var_buffer_addmemory( &buffer, p_data, i_data ); } /* send it */ if( send( p_sys->socket_tcp.i_handle, buffer.p_data, buffer.i_data, 0 ) == -1 ) { msg_Err( p_input, "failed to send command" ); return VLC_EGENERIC; } var_buffer_free( &buffer ); return VLC_SUCCESS;}static int NetFillBuffer( input_thread_t *p_input ){#ifdef UNDER_CE return -1;#else access_sys_t *p_sys = p_input->p_access_data; struct timeval timeout; fd_set fds; int i_ret; /* FIXME when using udp */ ssize_t i_tcp, i_udp; ssize_t i_tcp_read, i_udp_read; int i_handle_max; int i_try; /* Initialize file descriptor set */ FD_ZERO( &fds ); i_tcp = MMS_BUFFER_SIZE/2 - p_sys->i_buffer_tcp; if( p_sys->i_proto == MMS_PROTO_UDP ) { i_udp = MMS_BUFFER_SIZE/2 - p_sys->i_buffer_udp; } else { i_udp = 0; /* there isn't udp socket */ } i_handle_max = 0; if( i_tcp > 0 ) { FD_SET( p_sys->socket_tcp.i_handle, &fds ); i_handle_max = __MAX( i_handle_max, p_sys->socket_tcp.i_handle ); } if( i_udp > 0 ) { FD_SET( p_sys->socket_udp.i_handle, &fds ); i_handle_max = __MAX( i_handle_max, p_sys->socket_udp.i_handle ); } if( i_handle_max == 0 ) { msg_Warn( p_input, "nothing to read %d:%d", i_tcp, i_udp ); return( 0 ); } else {// msg_Warn( p_input, "ask for tcp:%d udp:%d", i_tcp, i_udp ); } /* We'll wait 0.5 second if nothing happens */ timeout.tv_sec = 0; timeout.tv_usec = 500000; i_try = 0; /* Find if some data is available */ while( (i_ret = select( i_handle_max + 1, &fds, NULL, NULL, &timeout )) == 0 || (i_ret < 0 && errno == EINTR) ) { i_try++; FD_ZERO( &fds ); if( i_tcp > 0 ) FD_SET( p_sys->socket_tcp.i_handle, &fds ); if( i_udp > 0 ) FD_SET( p_sys->socket_udp.i_handle, &fds ); timeout.tv_sec = 0; timeout.tv_usec = 500000; if( i_try > 2 && ( p_sys->i_buffer_tcp > 0 || p_sys->i_buffer_udp > 0 ) )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?