📄 mmstu.c
字号:
*pi_used = i_length; } msg_Dbg( p_access, "recv command start_sequence:0x%8.8x command_id:0x%8.8x length:%d len8:%d sequence 0x%8.8x len8_II:%d dir_comm:0x%8.8x", GET32( 0 ), GET32( 4 ), GET32( 8 ), /* 12: protocol type "MMS " */ GET32( 16 ), GET32( 20 ), /* 24: unknown (0) */ /* 28: unknown (0) */ GET32( 32 ), GET32( 36 ) /* 40: switches */ /* 44: extra */ ); p_sys->i_command = GET32( 36 ) & 0xffff;#undef GET32 return MMS_PACKET_CMD;}static int mms_ParsePacket( access_t *p_access, uint8_t *p_data, size_t i_data, int *pi_used ){ access_sys_t *p_sys = p_access->p_sys; int i_packet_seq_num; size_t i_packet_length; uint32_t i_packet_id; uint8_t *p_packet; *pi_used = i_data; /* default */ if( i_data <= 8 ) { msg_Warn( p_access, "truncated packet (header incomplete)" ); return -1; } i_packet_id = p_data[4]; i_packet_seq_num = GetDWLE( p_data ); i_packet_length = GetWLE( p_data + 6 ); //msg_Warn( p_access, "------->i_packet_length=%d, i_data=%d", i_packet_length, i_data ); if( i_packet_length > i_data || i_packet_length <= 8) { /* msg_Dbg( p_access, "truncated packet (Declared %d bytes, Actual %d bytes)", i_packet_length, i_data ); */ *pi_used = 0; return -1; } else if( i_packet_length < i_data ) { *pi_used = i_packet_length; } if( i_packet_id == 0xff ) { msg_Warn( p_access, "receive MMS UDP pair timing" ); return( MMS_PACKET_UDP_TIMING ); } if( i_packet_id != p_sys->i_header_packet_id_type && i_packet_id != p_sys->i_media_packet_id_type ) { msg_Warn( p_access, "incorrect Packet Id Type (0x%x)", i_packet_id ); return -1; } /* we now have a media or a header packet */ p_packet = malloc( i_packet_length - 8 ); // don't bother with preheader memcpy( p_packet, p_data + 8, i_packet_length - 8 ); if( i_packet_seq_num != p_sys->i_packet_seq_num ) {#if 0 /* FIXME for udp could be just wrong order ? */ msg_Warn( p_access, "detected packet lost (%d != %d)", i_packet_seq_num, p_sys->i_packet_seq_num );#endif } p_sys->i_packet_seq_num = i_packet_seq_num + 1; if( i_packet_id == p_sys->i_header_packet_id_type ) { if( p_sys->p_header ) { p_sys->p_header = realloc( p_sys->p_header, p_sys->i_header + i_packet_length - 8 ); memcpy( &p_sys->p_header[p_sys->i_header], p_packet, i_packet_length - 8 ); p_sys->i_header += i_packet_length - 8; free( p_packet ); } else { p_sys->p_header = p_packet; p_sys->i_header = i_packet_length - 8; }/* msg_Dbg( p_access, "receive header packet (%d bytes)", i_packet_length - 8 ); */ return MMS_PACKET_HEADER; } else { FREENULL( p_sys->p_media ); p_sys->p_media = p_packet; p_sys->i_media = i_packet_length - 8; p_sys->i_media_used = 0;/* msg_Dbg( p_access, "receive media packet (%d bytes)", i_packet_length - 8 ); */ return MMS_PACKET_MEDIA; }}static int mms_ReceivePacket( access_t *p_access ){ access_sys_t *p_sys = p_access->p_sys; int i_packet_tcp_type; int i_packet_udp_type; for( ;; ) { bool b_refill = true; /* first if we need to refill buffer */ if( p_sys->i_buffer_tcp >= MMS_CMD_HEADERSIZE ) { if( GetDWLE( p_sys->buffer_tcp + 4 ) == 0xb00bface ) { if( GetDWLE( p_sys->buffer_tcp + 8 ) + 16 <= (uint32_t)p_sys->i_buffer_tcp ) { b_refill = false; } } else if( GetWLE( p_sys->buffer_tcp + 6 ) <= p_sys->i_buffer_tcp ) { b_refill = false; } } if( p_sys->i_proto == MMS_PROTO_UDP && p_sys->i_buffer_udp >= 8 && GetWLE( p_sys->buffer_udp + 6 ) <= p_sys->i_buffer_udp ) { b_refill = false; } if( b_refill && NetFillBuffer( p_access ) < 0 ) { msg_Warn( p_access, "cannot fill buffer" ); return -1; } i_packet_tcp_type = -1; i_packet_udp_type = -1; if( p_sys->i_buffer_tcp > 0 ) { int i_used; if( GetDWLE( p_sys->buffer_tcp + 4 ) == 0xb00bface ) { i_packet_tcp_type = mms_ParseCommand( p_access, p_sys->buffer_tcp, p_sys->i_buffer_tcp, &i_used ); } else { i_packet_tcp_type = mms_ParsePacket( p_access, p_sys->buffer_tcp, p_sys->i_buffer_tcp, &i_used ); } if( i_used > 0 && i_used < MMS_BUFFER_SIZE ) { memmove( p_sys->buffer_tcp, p_sys->buffer_tcp + i_used, MMS_BUFFER_SIZE - i_used ); } p_sys->i_buffer_tcp -= i_used; } else if( p_sys->i_buffer_udp > 0 ) { int i_used; i_packet_udp_type = mms_ParsePacket( p_access, p_sys->buffer_udp, p_sys->i_buffer_udp, &i_used ); if( i_used > 0 && i_used < MMS_BUFFER_SIZE ) { memmove( p_sys->buffer_udp, p_sys->buffer_udp + i_used, MMS_BUFFER_SIZE - i_used ); } p_sys->i_buffer_udp -= i_used; } if( i_packet_tcp_type == MMS_PACKET_CMD && p_sys->i_command == 0x1b ) { mms_CommandSend( p_access, 0x1b, 0, 0, NULL, 0 ); i_packet_tcp_type = -1; } if( i_packet_tcp_type != -1 ) { return i_packet_tcp_type; } else if( i_packet_udp_type != -1 ) { return i_packet_udp_type; } }}static int mms_ReceiveCommand( access_t *p_access ){ access_sys_t *p_sys = p_access->p_sys; for( ;; ) { int i_used; int i_status; if( NetFillBuffer( p_access ) < 0 ) { msg_Warn( p_access, "cannot fill buffer" ); return VLC_EGENERIC; } if( p_sys->i_buffer_tcp > 0 ) { i_status = mms_ParseCommand( p_access, p_sys->buffer_tcp, p_sys->i_buffer_tcp, &i_used ); if( i_used < MMS_BUFFER_SIZE ) { memmove( p_sys->buffer_tcp, p_sys->buffer_tcp + i_used, MMS_BUFFER_SIZE - i_used ); } p_sys->i_buffer_tcp -= i_used; if( i_status < 0 ) { return VLC_EGENERIC; } if( p_sys->i_command == 0x1b ) { mms_CommandSend( p_access, 0x1b, 0, 0, NULL, 0 ); } else { break; } } else { return VLC_EGENERIC; } } return VLC_SUCCESS;}#define MMS_RETRY_MAX 10#define MMS_RETRY_SLEEP 50000static int mms_CommandRead( access_t *p_access, int i_command1, int i_command2 ){ access_sys_t *p_sys = p_access->p_sys; int i_count; int i_status; for( i_count = 0; i_count < MMS_RETRY_MAX; ) { i_status = mms_ReceiveCommand( p_access ); if( i_status < 0 || p_sys->i_command == 0 ) { i_count++; msleep( MMS_RETRY_SLEEP ); } else if( i_command1 == 0 && i_command2 == 0) { return VLC_SUCCESS; } else if( p_sys->i_command == i_command1 || p_sys->i_command == i_command2 ) { return VLC_SUCCESS; } else { switch( p_sys->i_command ) { case 0x03: msg_Warn( p_access, "socket closed by server" ); p_access->info.b_eof = true; return VLC_EGENERIC; case 0x1e: msg_Warn( p_access, "end of media stream" ); p_access->info.b_eof = true; return VLC_EGENERIC; default: break; } } } p_access->info.b_eof = true; msg_Warn( p_access, "failed to receive command (aborting)" ); return VLC_EGENERIC;}static int mms_HeaderMediaRead( access_t *p_access, int i_type ){ access_sys_t *p_sys = p_access->p_sys; int i_count; for( i_count = 0; i_count < MMS_RETRY_MAX; ) { int i_status; if( !vlc_object_alive (p_access) ) return -1; i_status = mms_ReceivePacket( p_access ); if( i_status < 0 ) { i_count++; msg_Warn( p_access, "cannot receive header (%d/%d)", i_count, MMS_RETRY_MAX ); msleep( MMS_RETRY_SLEEP ); } else if( i_status == i_type || i_type == MMS_PACKET_ANY ) { return i_type; } else if( i_status == MMS_PACKET_CMD ) { switch( p_sys->i_command ) { case 0x03: msg_Warn( p_access, "socket closed by server" ); p_access->info.b_eof = true; return -1; case 0x1e: msg_Warn( p_access, "end of media stream" ); p_access->info.b_eof = true; return -1; case 0x20: /* XXX not too dificult to be done EXCEPT that we * need to restart demuxer... and I don't see how we * could do that :p */ msg_Err( p_access, "reinitialization needed --> unsupported" ); p_access->info.b_eof = true; return -1; default: break; } } } msg_Err( p_access, "cannot receive %s (aborting)", ( i_type == MMS_PACKET_HEADER ) ? "header" : "media data" ); p_access->info.b_eof = true; return -1;}static void* KeepAliveThread( vlc_object_t *p_this ){ mmstu_keepalive_thread_t *p_thread = (mmstu_keepalive_thread_t *) p_this; access_t *p_access = p_thread->p_access; bool b_paused; bool b_was_paused = false; vlc_object_lock( p_thread ); while( vlc_object_alive( p_thread) ) { b_paused = p_thread->b_paused; if( b_paused && b_was_paused ) mms_CommandSend( p_access, 0x1b, 0, 0, NULL, 0 ); b_was_paused = b_paused; vlc_object_timedwait( p_thread, mdate() + 10000000 ); } vlc_object_unlock( p_thread ); return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -