⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stream.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
        msg_Dbg( s, "p_buffer %p-%p", p_sys->immediate.p_buffer,                p_sys->immediate.p_buffer + STREAM_CACHE_SIZE );        if( p_sys->immediate.p_buffer == NULL )        {            msg_Err( s, "Out of memory when allocating stream cache (%d bytes)",                        STREAM_CACHE_SIZE );            goto error;        }    }    else /* ( p_sys->method == Stream ) */    {        int i;        msg_Dbg( s, "Using AStream*Stream" );        s->pf_read = AStreamReadStream;        s->pf_peek = AStreamPeekStream;        /* Allocate/Setup our tracks */        p_sys->stream.i_offset = 0;        p_sys->stream.i_tk     = 0;        p_sys->stream.p_buffer = malloc( STREAM_CACHE_SIZE );        if( p_sys->stream.p_buffer == NULL )        {            msg_Err( s, "Out of memory when allocating stream cache (%d bytes)",                        STREAM_CACHE_SIZE );            goto error;        }        p_sys->stream.i_used   = 0;        access_Control( p_access, ACCESS_GET_MTU,                         &p_sys->stream.i_read_size );        if( p_sys->stream.i_read_size <= 0 )            p_sys->stream.i_read_size = STREAM_READ_ATONCE;        else if( p_sys->stream.i_read_size <= 256 )            p_sys->stream.i_read_size = 256;        for( i = 0; i < STREAM_CACHE_TRACK; i++ )        {            p_sys->stream.tk[i].i_date  = 0;            p_sys->stream.tk[i].i_start = p_sys->i_pos;            p_sys->stream.tk[i].i_end   = p_sys->i_pos;            p_sys->stream.tk[i].p_buffer=                &p_sys->stream.p_buffer[i * STREAM_CACHE_TRACK_SIZE];        }        /* Do the prebuffering */        AStreamPrebufferStream( s );        if( p_sys->stream.tk[p_sys->stream.i_tk].i_end <= 0 )        {            msg_Err( s, "cannot pre fill buffer" );            goto error;        }    }    return s;error:    if( p_sys->method == Block )    {        /* Nothing yet */    }    else    {        free( p_sys->stream.p_buffer );    }    while( p_sys->i_list > 0 )        free( p_sys->list[--(p_sys->i_list)] );    free( p_sys->list );    free( psz_list );    free( s->p_sys );    vlc_object_detach( s );    vlc_object_release( s );    return NULL;}/**************************************************************************** * AStreamDestroy: ****************************************************************************/static void AStreamDestroy( stream_t *s ){    stream_sys_t *p_sys = s->p_sys;    vlc_object_detach( s );    if( p_sys->method == Block ) block_ChainRelease( p_sys->block.p_first );    else if ( p_sys->method == Immediate ) free( p_sys->immediate.p_buffer );    else free( p_sys->stream.p_buffer );    free( p_sys->p_peek );    if( p_sys->p_list_access && p_sys->p_list_access != p_sys->p_access )        access_Delete( p_sys->p_list_access );    while( p_sys->i_list-- )    {        free( p_sys->list[p_sys->i_list]->psz_path );        free( p_sys->list[p_sys->i_list] );    }    free( p_sys->list );    free( p_sys );    vlc_object_release( s );}static void UStreamDestroy( stream_t *s ){    access_t *p_access = (access_t *)s->p_parent;    AStreamDestroy( s );    access_Delete( p_access );}/**************************************************************************** * stream_AccessReset: ****************************************************************************/void stream_AccessReset( stream_t *s ){    stream_sys_t *p_sys = s->p_sys;    p_sys->i_pos = p_sys->p_access->info.i_pos;    if( p_sys->method == Block )    {        block_ChainRelease( p_sys->block.p_first );        /* Init all fields of p_sys->block */        p_sys->block.i_start = p_sys->i_pos;        p_sys->block.i_offset = 0;        p_sys->block.p_current = NULL;        p_sys->block.i_size = 0;        p_sys->block.p_first = NULL;        p_sys->block.pp_last = &p_sys->block.p_first;        /* Do the prebuffering */        AStreamPrebufferBlock( s );    }    else if( p_sys->method == Immediate )    {        stream_buffer_empty( s, stream_buffered_size( s ) );    }    else /* ( p_sys->method == Stream ) */    {        int i;        /* Setup our tracks */        p_sys->stream.i_offset = 0;        p_sys->stream.i_tk     = 0;        p_sys->stream.i_used   = 0;        for( i = 0; i < STREAM_CACHE_TRACK; i++ )        {            p_sys->stream.tk[i].i_date  = 0;            p_sys->stream.tk[i].i_start = p_sys->i_pos;            p_sys->stream.tk[i].i_end   = p_sys->i_pos;        }        /* Do the prebuffering */        AStreamPrebufferStream( s );    }}/**************************************************************************** * stream_AccessUpdate: ****************************************************************************/void stream_AccessUpdate( stream_t *s ){    stream_sys_t *p_sys = s->p_sys;    p_sys->i_pos = p_sys->p_access->info.i_pos;    if( p_sys->i_list )    {        int i;        for( i = 0; i < p_sys->i_list_index; i++ )        {            p_sys->i_pos += p_sys->list[i]->i_size;        }    }}/**************************************************************************** * AStreamControl: ****************************************************************************/static int AStreamControl( stream_t *s, int i_query, va_list args ){    stream_sys_t *p_sys = s->p_sys;    access_t     *p_access = p_sys->p_access;    bool *p_bool;    int64_t    *pi_64, i_64;    int        i_int;    switch( i_query )    {        case STREAM_GET_SIZE:            pi_64 = (int64_t*)va_arg( args, int64_t * );            if( s->p_sys->i_list )            {                int i;                *pi_64 = 0;                for( i = 0; i < s->p_sys->i_list; i++ )                    *pi_64 += s->p_sys->list[i]->i_size;                break;            }            *pi_64 = p_access->info.i_size;            break;        case STREAM_CAN_SEEK:            p_bool = (bool*)va_arg( args, bool * );            access_Control( p_access, ACCESS_CAN_SEEK, p_bool );            break;        case STREAM_CAN_FASTSEEK:            p_bool = (bool*)va_arg( args, bool * );            access_Control( p_access, ACCESS_CAN_FASTSEEK, p_bool );            break;        case STREAM_GET_POSITION:            pi_64 = (int64_t*)va_arg( args, int64_t * );            *pi_64 = p_sys->i_pos;            break;        case STREAM_SET_POSITION:            i_64 = (int64_t)va_arg( args, int64_t );            if( p_sys->method == Block )                return AStreamSeekBlock( s, i_64 );            else if( p_sys->method == Immediate )                return AStreamSeekImmediate( s, i_64 );            else /* ( p_sys->method == Stream ) */                return AStreamSeekStream( s, i_64 );        case STREAM_GET_MTU:            return VLC_EGENERIC;        case STREAM_CONTROL_ACCESS:            i_int = (int) va_arg( args, int );            if( i_int != ACCESS_SET_PRIVATE_ID_STATE &&                i_int != ACCESS_SET_PRIVATE_ID_CA &&                i_int != ACCESS_GET_PRIVATE_ID_STATE )            {                msg_Err( s, "Hey, what are you thinking ?"                            "DON'T USE STREAM_CONTROL_ACCESS !!!" );                return VLC_EGENERIC;            }            return access_vaControl( p_access, i_int, args );        case STREAM_GET_CONTENT_TYPE:            return access_Control( p_access, ACCESS_GET_CONTENT_TYPE,                                    va_arg( args, char ** ) );        default:            msg_Err( s, "invalid stream_vaControl query=0x%x", i_query );            return VLC_EGENERIC;    }    return VLC_SUCCESS;}/**************************************************************************** * Method 1: ****************************************************************************/static void AStreamPrebufferBlock( stream_t *s ){    stream_sys_t *p_sys = s->p_sys;    access_t     *p_access = p_sys->p_access;    int64_t i_first = 0;    int64_t i_start;    msg_Dbg( s, "pre buffering" );    i_start = mdate();    for( ;; )    {        int64_t i_date = mdate();        bool b_eof;        block_t *b;        if( s->b_die || p_sys->block.i_size > STREAM_CACHE_PREBUFFER_SIZE ||            ( i_first > 0 && i_first + STREAM_CACHE_PREBUFFER_LENGTH < i_date ) )        {            int64_t i_byterate;            /* Update stat */            p_sys->stat.i_bytes = p_sys->block.i_size;            p_sys->stat.i_read_time = i_date - i_start;            i_byterate = ( INT64_C(1000000) * p_sys->stat.i_bytes ) /                         (p_sys->stat.i_read_time + 1);            msg_Dbg( s, "prebuffering done %"PRId64" bytes in %"PRId64"s - "                     "%"PRId64" kbytes/s",                     p_sys->stat.i_bytes,                     p_sys->stat.i_read_time / INT64_C(1000000),                     i_byterate / 1024 );            break;        }        /* Fetch a block */        if( ( b = AReadBlock( s, &b_eof ) ) == NULL )        {            if( b_eof ) break;            msleep( STREAM_DATA_WAIT );            continue;        }        while( b )        {            /* Append the block */            p_sys->block.i_size += b->i_buffer;            *p_sys->block.pp_last = b;            p_sys->block.pp_last = &b->p_next;            p_sys->stat.i_read_count++;            b = b->p_next;        }        if( p_access->info.b_prebuffered )        {            /* Access has already prebufferred - update stats and exit */            p_sys->stat.i_bytes = p_sys->block.i_size;            p_sys->stat.i_read_time = mdate() - i_start;            break;        }        if( i_first == 0 )        {            i_first = mdate();            msg_Dbg( s, "received first data for our buffer");        }    }    p_sys->block.p_current = p_sys->block.p_first;}static int AStreamRefillBlock( stream_t *s );static int AStreamReadBlock( stream_t *s, void *p_read, unsigned int i_read ){    stream_sys_t *p_sys = s->p_sys;    uint8_t *p_data= (uint8_t*)p_read;    unsigned int i_data = 0;    /* It means EOF */    if( p_sys->block.p_current == NULL )        return 0;    if( p_read == NULL )    {        /* seek within this stream if possible, else use plain old read and discard */        stream_sys_t *p_sys = s->p_sys;        access_t     *p_access = p_sys->p_access;        bool   b_aseek;        access_Control( p_access, ACCESS_CAN_SEEK, &b_aseek );        if( b_aseek )            return AStreamSeekBlock( s, p_sys->i_pos + i_read ) ? 0 : i_read;    }    while( i_data < i_read )    {        int i_current =            p_sys->block.p_current->i_buffer - p_sys->block.i_offset;        unsigned int i_copy = __MIN( (unsigned int)__MAX(i_current,0), i_read - i_data);        /* Copy data */        if( p_data )        {            memcpy( p_data,                    &p_sys->block.p_current->p_buffer[p_sys->block.i_offset],                    i_copy );            p_data += i_copy;        }        i_data += i_copy;        p_sys->block.i_offset += i_copy;        if( p_sys->block.i_offset >= p_sys->block.p_current->i_buffer )        {            /* Current block is now empty, switch to next */            if( p_sys->block.p_current )            {                p_sys->block.i_offset = 0;                p_sys->block.p_current = p_sys->block.p_current->p_next;            }            /*Get a new block if needed */            if( !p_sys->block.p_current && AStreamRefillBlock( s ) )            {                break;            }        }    }    p_sys->i_pos += i_data;    return i_data;}static int AStreamPeekBlock( stream_t *s, const uint8_t **pp_peek, unsigned int i_read ){    stream_sys_t *p_sys = s->p_sys;    uint8_t *p_data;    unsigned int i_data = 0;    block_t *b;    unsigned int i_offset;    if( p_sys->block.p_current == NULL ) return 0; /* EOF */    /* We can directly give a pointer over our buffer */    if( i_read <= p_sys->block.p_current->i_buffer - p_sys->block.i_offset )    {        *pp_peek = &p_sys->block.p_current->p_buffer[p_sys->block.i_offset];        return i_read;    }    /* We need to create a local copy */    if( p_sys->i_peek < i_read )    {        p_sys->p_peek = realloc( p_sys->p_peek, i_read );        if( !p_sys->p_peek )        {            p_sys->i_peek = 0;            return 0;        }        p_sys->i_peek = i_read;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -