📄 mmstu.c
字号:
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 == 0x05 ) { msg_Dbg( p_access, "received 0x05 (seek)" ); break; } } /* get a packet */ if( mms_HeaderMediaRead( p_access, MMS_PACKET_MEDIA ) < 0 ) { p_access->info.b_eof = true; return VLC_EGENERIC; } 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 = false; return VLC_SUCCESS;}/***************************************************************************** * Read: *****************************************************************************/static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len ){ access_sys_t *p_sys = p_access->p_sys; size_t i_data; size_t i_copy; if( p_access->info.b_eof ) { return 0; } i_data = 0; /* *** now send data if needed *** */ while( i_data < i_len ) { if( p_access->info.i_pos < p_sys->i_header ) { i_copy = __MIN( i_len, p_sys->i_header - p_access->info.i_pos ); memcpy( &p_buffer[i_data], &p_sys->p_header[p_access->info.i_pos], i_copy ); i_data += i_copy; p_access->info.i_pos += i_copy; } else if( p_sys->i_media_used < p_sys->i_media ) { i_copy = __MIN( i_len - i_data , p_sys->i_media - p_sys->i_media_used ); memcpy( &p_buffer[i_data], &p_sys->p_media[p_sys->i_media_used], i_copy ); i_data += i_copy; p_sys->i_media_used += i_copy; p_access->info.i_pos += i_copy; } else if( p_sys->p_media != NULL && p_sys->i_media_used < p_sys->i_packet_length ) { i_copy = __MIN( i_len - i_data, p_sys->i_packet_length - p_sys->i_media_used); memset( &p_buffer[i_data], 0, i_copy ); i_data += i_copy; p_sys->i_media_used += i_copy; p_access->info.i_pos += i_copy; } else if( p_access->info.b_eof || mms_HeaderMediaRead( p_access, MMS_PACKET_MEDIA ) < 0 ) { break; } } return i_data;}/**************************************************************************** * MMSOpen : Open a connection with the server over mmst or mmsu ****************************************************************************/static int MMSOpen( access_t *p_access, vlc_url_t *p_url, int i_proto ){ access_sys_t *p_sys = p_access->p_sys; int b_udp = ( i_proto == MMS_PROTO_UDP ) ? 1 : 0; var_buffer_t buffer; char tmp[4096]; uint16_t *p; int i_server_version; int i_tool_version; int i_update_player_url; int i_encryption_type; int i; int i_streams; int i_first; char *mediapath; /* *** Open a TCP connection with server *** */ msg_Dbg( p_access, "waiting for connection..." ); p_sys->i_handle_tcp = net_ConnectTCP( p_access, p_url->psz_host, p_url->i_port ); if( p_sys->i_handle_tcp < 0 ) { msg_Err( p_access, "failed to open a connection (tcp)" ); return VLC_EGENERIC; } msg_Dbg( p_access, "connection(tcp) with \"%s:%d\" successful", p_url->psz_host, p_url->i_port ); /* *** Bind port if UDP protocol is selected *** */ if( b_udp ) { if( net_GetSockAddress( p_sys->i_handle_tcp, p_sys->sz_bind_addr, NULL ) ) { net_Close( p_sys->i_handle_tcp ); return VLC_EGENERIC; } p_sys->i_handle_udp = net_ListenUDP1( (vlc_object_t *)p_access, p_sys->sz_bind_addr, 7000 ); if( p_sys->i_handle_udp < 0 ) { msg_Err( p_access, "failed to open a connection (udp)" ); net_Close( p_sys->i_handle_tcp ); return VLC_EGENERIC; } msg_Dbg( p_access, "connection(udp) at \"%s:%d\" successful", p_sys->sz_bind_addr, 7000 ); } /* *** Init context for mms prototcol *** */ GenerateGuid ( &p_sys->guid ); /* used to identify client by server */ msg_Dbg( p_access, "generated guid: "GUID_FMT, GUID_PRINT( p_sys->guid ) ); p_sys->i_command_level = 1; /* updated after 0x1A command */ p_sys->i_seq_num = 0; p_sys->i_media_packet_id_type = 0x04; p_sys->i_header_packet_id_type = 0x02; p_sys->i_proto = i_proto; p_sys->i_packet_seq_num = 0; p_sys->p_header = NULL; p_sys->i_header = 0; p_sys->p_media = NULL; p_sys->i_media = 0; p_sys->i_media_used = 0; p_access->info.i_pos = 0; p_sys->i_buffer_tcp = 0; p_sys->i_buffer_udp = 0; p_sys->p_cmd = NULL; p_sys->i_cmd = 0; p_access->info.b_eof = false; /* *** send command 1 : connection request *** */ var_buffer_initwrite( &buffer, 0 ); var_buffer_add16( &buffer, 0x001c ); var_buffer_add16( &buffer, 0x0003 ); sprintf( tmp, "NSPlayer/7.0.0.1956; {"GUID_FMT"}; Host: %s", GUID_PRINT( p_sys->guid ), p_url->psz_host ); var_buffer_addUTF16( &buffer, tmp ); mms_CommandSend( p_access, 0x01, /* connexion request */ 0x00000000, /* flags, FIXME */ 0x0004000b, /* ???? */ buffer.p_data, buffer.i_data ); if( mms_CommandRead( p_access, 0x01, 0 ) < 0 ) { var_buffer_free( &buffer ); MMSClose( p_access ); 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 += ( 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_access, "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->sz_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_access, 0x02, /* connexion request */ 0x00000000, /* flags, FIXME */ 0xffffffff, /* ???? */ buffer.p_data, buffer.i_data ); /* *** response from server, should be 0x02 or 0x03 *** */ mms_CommandRead( p_access, 0x02, 0x03 ); if( p_sys->i_command == 0x03 ) { msg_Err( p_access, "%s protocol selection failed", b_udp ? "UDP" : "TCP" ); var_buffer_free( &buffer ); MMSClose( p_access ); return VLC_EGENERIC; } else if( p_sys->i_command != 0x02 ) { msg_Warn( p_access, "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 ); /* media file path shouldn't start with / character */ mediapath = p_url->psz_path; if ( *mediapath == '/' ) { mediapath++; } var_buffer_addUTF16( &buffer, mediapath ); mms_CommandSend( p_access, 0x05, p_sys->i_command_level, 0xffffffff, buffer.p_data, buffer.i_data ); /* *** wait for reponse *** */ mms_CommandRead( p_access, 0x1a, 0x06 ); /* test if server send 0x1A answer */ if( p_sys->i_command == 0x1A ) { msg_Err( p_access, "id/password requested (not yet supported)" ); /* FIXME */ var_buffer_free( &buffer ); MMSClose( p_access ); return VLC_EGENERIC; } if( p_sys->i_command != 0x06 ) { msg_Err( p_access, "unknown answer (0x%x instead of 0x06)", p_sys->i_command ); var_buffer_free( &buffer ); MMSClose( p_access ); return( -1 ); } /* 1 for file ok, 2 for authen ok */ switch( GetDWLE( p_sys->p_cmd + MMS_CMD_HEADERSIZE ) ) { case 0x0001: msg_Dbg( p_access, "media file name/path accepted" ); break; case 0x0002: msg_Dbg( p_access, "authentication accepted" ); break; case -1: default: msg_Err( p_access, "error while asking for file %d", GetDWLE( p_sys->p_cmd + MMS_CMD_HEADERSIZE ) ); var_buffer_free( &buffer ); MMSClose( p_access ); 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_access, "answer 0x06 flags:0x%8.8"PRIx32" media_length:%"PRIu32"s " "packet_length:%zul packet_count:%"PRId32" max_bit_rate:%d " "header_size:%zu", p_sys->i_flags_broadcast, p_sys->i_media_length, (unsigned)p_sys->i_packet_length, p_sys->i_packet_count, p_sys->i_max_bit_rate, p_sys->i_header_size ); /* *** 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_access, 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_access, 0x11, 0 ); if( p_sys->i_command != 0x11 ) { msg_Err( p_access, "unknown answer (0x%x instead of 0x11)", p_sys->i_command ); var_buffer_free( &buffer ); MMSClose( p_access ); return( -1 ); }#endif /* *** now read header packet *** */ /* XXX could be split over multiples packets */ msg_Dbg( p_access, "reading header" ); for( ;; ) { if( mms_HeaderMediaRead( p_access, MMS_PACKET_HEADER ) < 0 ) { msg_Err( p_access, "cannot receive header" ); var_buffer_free( &buffer ); MMSClose( p_access ); return VLC_EGENERIC; } if( p_sys->i_header >= p_sys->i_header_size ) { msg_Dbg( p_access, "header complete(%zu)", p_sys->i_header ); break; } msg_Dbg( p_access, "header incomplete (%zu/%zu), 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) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -