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

📄 stream.c

📁 uclinux 下的vlc播放器源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
            }        }        p_sys->block.i_offset = i_pos - p_sys->i_pos;        p_sys->i_pos = i_pos;        /* TODO read data */        return VLC_SUCCESS;    }    return VLC_EGENERIC;}static int AStreamRefillBlock( stream_t *s ){    stream_sys_t *p_sys = s->p_sys;    int64_t      i_start, i_stop;    block_t      *b;    /* Release data */    while( p_sys->block.i_size >= STREAM_CACHE_SIZE &&           p_sys->block.p_first != p_sys->block.p_current )    {        block_t *b = p_sys->block.p_first;        p_sys->block.i_start += b->i_buffer;        p_sys->block.i_size  -= b->i_buffer;        p_sys->block.p_first  = b->p_next;        block_Release( b );    }    if( p_sys->block.i_size >= STREAM_CACHE_SIZE &&        p_sys->block.p_current == p_sys->block.p_first &&        p_sys->block.p_current->p_next )    /* At least 2 packets */    {        /* Enough data, don't read more */        return VLC_SUCCESS;    }    /* Now read a new block */    i_start = mdate();    for( ;; )    {        vlc_bool_t b_eof;        if( s->b_die ) return VLC_EGENERIC;        /* Fetch a block */        if( ( b = AReadBlock( s, &b_eof ) ) ) break;        if( b_eof ) return VLC_EGENERIC;        msleep( STREAM_DATA_WAIT );    }    while( b )    {        i_stop = mdate();        /* 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;        /* Fix p_current */        if( p_sys->block.p_current == NULL )            p_sys->block.p_current = b;        /* Update stat */        p_sys->stat.i_bytes += b->i_buffer;        p_sys->stat.i_read_time += i_stop - i_start;        p_sys->stat.i_read_count++;        b = b->p_next;        i_start = mdate();    }    return VLC_SUCCESS;}/**************************************************************************** * Method 2: ****************************************************************************/static int AStreamRefillStream( stream_t *s );static int AStreamReadStream( stream_t *s, void *p_read, int i_read ){    stream_sys_t *p_sys = s->p_sys;    stream_track_t *tk = &p_sys->stream.tk[p_sys->stream.i_tk];    uint8_t *p_data = (uint8_t *)p_read;    int      i_data = 0;    if( tk->i_start >= tk->i_end ) return 0; /* EOF */    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;        vlc_bool_t   b_aseek;        access2_Control( p_access, ACCESS_CAN_SEEK, &b_aseek );        if( b_aseek )            return AStreamSeekStream( s, p_sys->i_pos + i_read ) ? 0 : i_read;    }#ifdef STREAM_DEBUG    msg_Dbg( s, "AStreamReadStream: %d pos="I64Fd" tk=%d start="I64Fd             " offset=%d end="I64Fd,             i_read, p_sys->i_pos, p_sys->stream.i_tk,             tk->i_start, p_sys->stream.i_offset, tk->i_end );#endif    while( i_data < i_read )    {        int i_off = (tk->i_start + p_sys->stream.i_offset) %                    STREAM_CACHE_TRACK_SIZE;        int i_current =            __MIN( tk->i_end - tk->i_start - p_sys->stream.i_offset,                   STREAM_CACHE_TRACK_SIZE - i_off );        int i_copy = __MIN( i_current, i_read - i_data );        if( i_copy <= 0 ) break; /* EOF */        /* Copy data */        /* msg_Dbg( s, "AStreamReadStream: copy %d", i_copy ); */        if( p_data )        {            memcpy( p_data, &tk->p_buffer[i_off], i_copy );            p_data += i_copy;        }        i_data += i_copy;        p_sys->stream.i_offset += i_copy;        /* Update pos now */        p_sys->i_pos += i_copy;        /* */        p_sys->stream.i_used += i_copy;        if( tk->i_start + p_sys->stream.i_offset >= tk->i_end ||            p_sys->stream.i_used >= p_sys->stream.i_read_size )        {            if( AStreamRefillStream( s ) )            {                /* EOF */                if( tk->i_start >= tk->i_end ) break;            }        }    }    return i_data;}static int AStreamPeekStream( stream_t *s, uint8_t **pp_peek, int i_read ){    stream_sys_t *p_sys = s->p_sys;    stream_track_t *tk = &p_sys->stream.tk[p_sys->stream.i_tk];    int64_t i_off;    if( tk->i_start >= tk->i_end ) return 0; /* EOF */#ifdef STREAM_DEBUG    msg_Dbg( s, "AStreamPeekStream: %d pos="I64Fd" tk=%d "             "start="I64Fd" offset=%d end="I64Fd,             i_read, p_sys->i_pos, p_sys->stream.i_tk,             tk->i_start, p_sys->stream.i_offset, tk->i_end );#endif    /* Avoid problem, but that should *never* happen */    if( i_read > STREAM_CACHE_TRACK_SIZE / 2 )        i_read = STREAM_CACHE_TRACK_SIZE / 2;    while( tk->i_end - tk->i_start - p_sys->stream.i_offset < i_read )    {        if( p_sys->stream.i_used <= 1 )        {            /* Be sure we will read something */            p_sys->stream.i_used += i_read -                (tk->i_end - tk->i_start - p_sys->stream.i_offset);        }        if( AStreamRefillStream( s ) ) break;    }    if( tk->i_end - tk->i_start - p_sys->stream.i_offset < i_read )        i_read = tk->i_end - tk->i_start - p_sys->stream.i_offset;    /* Now, direct pointer or a copy ? */    i_off = (tk->i_start + p_sys->stream.i_offset) % STREAM_CACHE_TRACK_SIZE;    if( i_off + i_read <= STREAM_CACHE_TRACK_SIZE )    {        *pp_peek = &tk->p_buffer[i_off];        return i_read;    }    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;    }    memcpy( p_sys->p_peek, &tk->p_buffer[i_off],            STREAM_CACHE_TRACK_SIZE - i_off );    memcpy( &p_sys->p_peek[STREAM_CACHE_TRACK_SIZE - i_off],            &tk->p_buffer[0], i_read - (STREAM_CACHE_TRACK_SIZE - i_off) );    *pp_peek = p_sys->p_peek;    return i_read;}static int AStreamSeekStream( stream_t *s, int64_t i_pos ){    stream_sys_t *p_sys = s->p_sys;    access_t     *p_access = p_sys->p_access;    vlc_bool_t   b_aseek;    vlc_bool_t   b_afastseek;    int i_maxth;    int i_new;    int i;#ifdef STREAM_DEBUG    msg_Dbg( s, "AStreamSeekStream: to "I64Fd" pos="I64Fd             " tk=%d start="I64Fd" offset=%d end="I64Fd,             i_pos, p_sys->i_pos, p_sys->stream.i_tk,             p_sys->stream.tk[p_sys->stream.i_tk].i_start,             p_sys->stream.i_offset,             p_sys->stream.tk[p_sys->stream.i_tk].i_end );#endif    /* Seek in our current track ? */    if( i_pos >= p_sys->stream.tk[p_sys->stream.i_tk].i_start &&        i_pos < p_sys->stream.tk[p_sys->stream.i_tk].i_end )    {        stream_track_t *tk = &p_sys->stream.tk[p_sys->stream.i_tk];#ifdef STREAM_DEBUG        msg_Dbg( s, "AStreamSeekStream: current track" );#endif        p_sys->i_pos = i_pos;        p_sys->stream.i_offset = i_pos - tk->i_start;        /* If there is not enough data left in the track, refill  */        /* \todo How to get a correct value for         *    - refilling threshold         *    - how much to refill         */        if( (tk->i_end - tk->i_start ) - p_sys->stream.i_offset <                                             p_sys->stream.i_read_size )        {            if( p_sys->stream.i_used < STREAM_READ_ATONCE / 2  )            {                p_sys->stream.i_used = STREAM_READ_ATONCE / 2 ;                AStreamRefillStream( s );            }        }        return VLC_SUCCESS;    }    access2_Control( p_access, ACCESS_CAN_SEEK, &b_aseek );    if( !b_aseek )    {        /* We can't do nothing */        msg_Dbg( s, "AStreamSeekStream: can't seek" );        return VLC_EGENERIC;    }    /* Date the current track */    p_sys->stream.tk[p_sys->stream.i_tk].i_date = mdate();    /* Try to reuse already read data */    for( i = 0; i < STREAM_CACHE_TRACK; i++ )    {        stream_track_t *tk = &p_sys->stream.tk[i];        if( i_pos >= tk->i_start && i_pos <= tk->i_end )        {#ifdef STREAM_DEBUG            msg_Dbg( s, "AStreamSeekStream: reusing %d start="I64Fd                     " end="I64Fd, i, tk->i_start, tk->i_end );#endif            /* Seek at the end of the buffer */            if( ASeek( s, tk->i_end ) ) return VLC_EGENERIC;            /* That's it */            p_sys->i_pos = i_pos;            p_sys->stream.i_tk = i;            p_sys->stream.i_offset = i_pos - tk->i_start;            if( p_sys->stream.i_used < 1024 )                p_sys->stream.i_used = 1024;            if( AStreamRefillStream( s ) && i_pos == tk->i_end )                return VLC_EGENERIC;            return VLC_SUCCESS;        }    }    access2_Control( p_access, ACCESS_CAN_SEEK, &b_afastseek );    /* FIXME compute seek cost (instead of static 'stupid' value) */    i_maxth = __MIN( p_sys->stream.i_read_size, STREAM_READ_ATONCE / 2 );    if( !b_afastseek )        i_maxth *= 3;    /* FIXME TODO */#if 0    /* Search closest segment TODO */    for( i = 0; i < STREAM_CACHE_TRACK; i++ )    {        stream_track_t *tk = &p_sys->stream.tk[i];        if( i_pos + i_maxth >= tk->i_start )        {            msg_Dbg( s, "good segment before current pos, TODO" );        }        if( i_pos - i_maxth <= tk->i_end )        {            msg_Dbg( s, "good segment after current pos, TODO" );        }    }#endif    /* Nothing good, seek and choose oldest segment */    if( ASeek( s, i_pos ) ) return VLC_EGENERIC;    p_sys->i_pos = i_pos;    i_new = 0;    for( i = 1; i < STREAM_CACHE_TRACK; i++ )    {        if( p_sys->stream.tk[i].i_date < p_sys->stream.tk[i_new].i_date )            i_new = i;    }    /* Reset the segment */    p_sys->stream.i_tk     = i_new;    p_sys->stream.i_offset =  0;    p_sys->stream.tk[i_new].i_start = i_pos;    p_sys->stream.tk[i_new].i_end   = i_pos;    /* Read data */    if( p_sys->stream.i_used < STREAM_READ_ATONCE / 2 )        p_sys->stream.i_used = STREAM_READ_ATONCE / 2;    if( AStreamRefillStream( s ) )        return VLC_EGENERIC;    return VLC_SUCCESS;}static int AStreamRefillStream( stream_t *s ){    stream_sys_t *p_sys = s->p_sys;    stream_track_t *tk = &p_sys->stream.tk[p_sys->stream.i_tk];    /* We read but won't increase i_start after initial start + offset */    int i_toread =        __MIN( p_sys->stream.i_used, STREAM_CACHE_TRACK_SIZE -               (tk->i_end - tk->i_start - p_sys->stream.i_offset) );    vlc_bool_t b_read = VLC_FALSE;    int64_t i_start, i_stop;    if( i_toread <= 0 ) return VLC_EGENERIC; /* EOF */#ifdef STREAM_DEBUG    msg_Dbg( s, "AStreamRefillStream: used=%d toread=%d",                 p_sys->stream.i_used, i_toread );#endif    i_start = mdate();    while( i_toread > 0 )    {        int i_off = tk->i_end % STREAM_CACHE_TRACK_SIZE;        int i_read;        if( s->b_die )            return VLC_EGENERIC;        i_read = __MIN( i_toread, STREAM_CACHE_TRACK_SIZE - i_off );        i_read = AReadStream( s, &tk->p_buffer[i_off], i_read );        /* msg_Dbg( s, "AStreamRefillStream: read=%d", i_read ); */        if( i_read <  0 )        {            msleep( STREAM_DATA_WAIT );            continue;        }        else if( i_read == 0 )        {            if( !b_read ) return VLC_EGENERIC;            return VLC_SUCCESS;        }        b_read = VLC_TRUE;        /* Update end */        tk->i_end += i_read;        /* Windows of STREAM_CACHE_TRACK_SIZE */        if( tk->i_end - tk->i_start > STREAM_CACHE_TRACK_SIZE )        {            int i_invalid = tk->i_end - tk->i_start - STREAM_CACHE_TRACK_SIZE;            tk->i_start += i_invalid;            p_sys->stream.i_offset -= i_invalid;        }        i_toread -= i_read;        p_sys->stream.i_used -= i_read;        p_sys->stat.i_bytes += i_read;        p_sys->stat.i_read_count++;    }    i_stop = mdate();    p_sys->stat.i_read_time += i_stop - i_start;    return VLC_SUCCESS;}static void AStreamPrebufferStream( 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;    int64_t i_prebuffer = p_sys->b_quick ? STREAM_CACHE_TRACK_SIZE /100 :        ( (p_access->info.i_title > 1 || p_access->info.i_seekpoint > 1) ?          STREAM_CACHE_PREBUFFER_SIZE : STREAM_CACHE_TRACK_SIZE / 3 );    msg_Dbg( s, "pre-buffering..." );    i_start = mdate();    for( ;; )    {        stream_track_t *tk = &p_sys->stream.tk[p_sys->stream.i_tk];        int64_t i_date = mdate();        int i_read;        if( s->b_die || tk->i_end >= i_prebuffer ||            (i_first > 0 && i_first + STREAM_CACHE_PREBUFFER_LENGTH < i_date) )        {

⌨️ 快捷键说明

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