📄 mmstu.c
字号:
asf_HeaderParse ( &p_sys->asfh, p_sys->p_header, p_sys->i_header ); asf_StreamSelect( &p_sys->asfh, var_CreateGetInteger( p_access, "mms-maxbitrate" ), var_CreateGetInteger( p_access, "mms-all" ), var_CreateGetInteger( p_access, "audio" ), var_CreateGetInteger( p_access, "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_access, "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_access, "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_access, "cannot find any stream" ); var_buffer_free( &buffer ); MMSClose( p_access ); return VLC_EGENERIC; } mms_CommandSend( p_access, 0x33, i_streams, 0xffff | ( i_first << 16 ), buffer.p_data, buffer.i_data ); mms_CommandRead( p_access, 0x21, 0 ); if( p_sys->i_command != 0x21 ) { msg_Err( p_access, "unknown answer (0x%x instead of 0x21)", p_sys->i_command ); var_buffer_free( &buffer ); MMSClose( p_access ); return VLC_EGENERIC; } var_buffer_free( &buffer ); msg_Info( p_access, "connection successful" ); return VLC_SUCCESS;}/**************************************************************************** * MMSStart : Start streaming ****************************************************************************/static int MMSStart( access_t *p_access, uint32_t i_packet ){ access_sys_t *p_sys = p_access->p_sys; 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_access, 0x07, p_sys->i_command_level, 0x0001ffff, buffer.p_data, buffer.i_data ); var_buffer_free( &buffer ); mms_CommandRead( p_access, 0x05, 0 ); if( p_sys->i_command != 0x05 ) { msg_Err( p_access, "unknown answer (0x%x instead of 0x05)", p_sys->i_command ); return -1; } else { /* get a packet */ if( mms_HeaderMediaRead( p_access, MMS_PACKET_MEDIA ) < 0 ) return -1; msg_Dbg( p_access, "streaming started" ); return 0; }}/**************************************************************************** * MMSStop : Stop streaming ****************************************************************************/static int MMSStop( access_t *p_access ){ access_sys_t *p_sys = p_access->p_sys; /* *** stop stream but keep connection alive *** */ mms_CommandSend( p_access, 0x09, p_sys->i_command_level, 0x001fffff, NULL, 0 ); return( 0 );}/**************************************************************************** * MMSClose : Close streaming and connection ****************************************************************************/static void MMSClose( access_t *p_access ){ access_sys_t *p_sys = p_access->p_sys; msg_Dbg( p_access, "Connection closed" ); /* *** tell server that we will disconnect *** */ mms_CommandSend( p_access, 0x0d, p_sys->i_command_level, 0x00000001, NULL, 0 ); /* *** close sockets *** */ net_Close( p_sys->i_handle_tcp ); if( p_sys->i_proto == MMS_PROTO_UDP ) { net_Close( p_sys->i_handle_udp ); } FREENULL( p_sys->p_cmd ); FREENULL( p_sys->p_media ); FREENULL( p_sys->p_header ); FREENULL( p_sys->psz_server_version ); FREENULL( p_sys->psz_tool_version ); FREENULL( p_sys->psz_update_player_url ); FREENULL( p_sys->psz_encryption_type );}/**************************************************************************** * * MMS specific functions * ****************************************************************************/static int mms_CommandSend( access_t *p_access, int i_command, uint32_t i_prefix1, uint32_t i_prefix2, uint8_t *p_data, int i_data_old ){ var_buffer_t buffer; access_sys_t *p_sys = p_access->p_sys; int i_data_by8, i_ret; int i_data = i_data_old; while( i_data & 0x7 ) i_data++; i_data_by8 = i_data >> 3; /* first init buffer */ 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_old ); } /* Append padding to the command data */ var_buffer_add64( &buffer, 0 ); /* send it */ vlc_mutex_lock( &p_sys->lock_netwrite ); i_ret = net_Write( p_access, p_sys->i_handle_tcp, NULL, buffer.p_data, buffer.i_data - ( 8 - ( i_data - i_data_old ) ) ); vlc_mutex_unlock( &p_sys->lock_netwrite ); if( i_ret != buffer.i_data - ( 8 - ( i_data - i_data_old ) ) ) { msg_Err( p_access, "failed to send command" ); return VLC_EGENERIC; } var_buffer_free( &buffer ); return VLC_SUCCESS;}static int NetFillBuffer( access_t *p_access ){#ifdef UNDER_CE return -1;#else access_sys_t *p_sys = p_access->p_sys; int i_ret; struct pollfd ufd[2]; unsigned timeout, nfd; /* FIXME when using udp */ ssize_t i_tcp, i_udp; ssize_t i_tcp_read, i_udp_read; int i_try = 0; 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 */ } if( ( i_udp <= 0 ) && ( i_tcp <= 0 ) ) { msg_Warn( p_access, "nothing to read %d:%d", (int)i_tcp, (int)i_udp ); return 0; } else { /* msg_Warn( p_access, "ask for tcp:%d udp:%d", i_tcp, i_udp ); */ } /* Find if some data is available */ do { i_try++; /* Initialize file descriptor set */ memset (ufd, 0, sizeof (ufd)); nfd = 0; if( i_tcp > 0 ) { ufd[nfd].fd = p_sys->i_handle_tcp; ufd[nfd].events = POLLIN; nfd++; } if( i_udp > 0 ) { ufd[nfd].fd = p_sys->i_handle_tcp; ufd[nfd].events = POLLIN; nfd++; } /* We'll wait 0.5 second if nothing happens */ timeout = 500; if( i_try * timeout > p_sys->i_timeout ) { msg_Err(p_access, "no data received"); return -1; } if( i_try > 3 && (p_sys->i_buffer_tcp > 0 || p_sys->i_buffer_udp > 0) ) { return -1; } if( !vlc_object_alive (p_access) || p_access->b_error ) return -1; //msg_Dbg( p_access, "NetFillBuffer: trying again (select)" ); } while( !(i_ret = poll( ufd, nfd, timeout)) || (i_ret < 0 && errno == EINTR) ); if( i_ret < 0 ) { msg_Err( p_access, "network poll error (%m)" ); return -1; } i_tcp_read = i_udp_read = 0; if( ( i_tcp > 0 ) && ufd[0].revents ) { i_tcp_read = recv( p_sys->i_handle_tcp, p_sys->buffer_tcp + p_sys->i_buffer_tcp, i_tcp + MMS_BUFFER_SIZE/2, 0 ); } if( i_udp > 0 && ufd[i_tcp > 0].revents ) { i_udp_read = recv( p_sys->i_handle_udp, p_sys->buffer_udp + p_sys->i_buffer_udp, i_udp + MMS_BUFFER_SIZE/2, 0 ); }#ifdef MMS_DEBUG if( p_sys->i_proto == MMS_PROTO_UDP ) { msg_Dbg( p_access, "filling buffer TCP:%d+%d UDP:%d+%d", p_sys->i_buffer_tcp, i_tcp_read, p_sys->i_buffer_udp, i_udp_read ); } else { msg_Dbg( p_access, "filling buffer TCP:%d+%d", p_sys->i_buffer_tcp, i_tcp_read ); }#endif if( i_tcp_read > 0 ) p_sys->i_buffer_tcp += i_tcp_read; if( i_udp_read > 0 ) p_sys->i_buffer_udp += i_udp_read; return i_tcp_read + i_udp_read;#endif}static int mms_ParseCommand( access_t *p_access, uint8_t *p_data, size_t i_data, int *pi_used ){ #define GET32( i_pos ) \ ( p_sys->p_cmd[i_pos] + ( p_sys->p_cmd[i_pos +1] << 8 ) + \ ( p_sys->p_cmd[i_pos + 2] << 16 ) + \ ( p_sys->p_cmd[i_pos + 3] << 24 ) ) access_sys_t *p_sys = p_access->p_sys; uint32_t i_length; uint32_t i_id; free( p_sys->p_cmd ); p_sys->i_cmd = i_data; p_sys->p_cmd = malloc( i_data ); memcpy( p_sys->p_cmd, p_data, i_data ); *pi_used = i_data; /* by default */ if( i_data < MMS_CMD_HEADERSIZE ) { msg_Warn( p_access, "truncated command (header incomplete)" ); p_sys->i_command = 0; return -1; } i_id = GetDWLE( p_data + 4 ); i_length = GetDWLE( p_data + 8 ) + 16; if( i_id != 0xb00bface || i_length < 16 ) { msg_Err( p_access, "incorrect command header (0x%"PRIx32")", i_id ); p_sys->i_command = 0; return -1; } if( i_length > p_sys->i_cmd ) { msg_Warn( p_access, "truncated command (missing %zu bytes)", (size_t)i_length - i_data ); p_sys->i_command = 0; return -1; } else if( i_length < p_sys->i_cmd ) { p_sys->i_cmd = i_length;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -