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 + -
显示快捷键?