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

📄 stream.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* Fill enough data */    while( p_sys->block.i_size - (p_sys->i_pos - p_sys->block.i_start)           < i_read )    {        block_t **pp_last = p_sys->block.pp_last;        if( AStreamRefillBlock( s ) ) break;        /* Our buffer are probably filled enough, don't try anymore */        if( pp_last == p_sys->block.pp_last ) break;    }    /* Copy what we have */    b = p_sys->block.p_current;    i_offset = p_sys->block.i_offset;    p_data = p_sys->p_peek;    while( b && i_data < i_read )    {        unsigned int i_current = __MAX(b->i_buffer - i_offset,0);        int i_copy = __MIN( i_current, i_read - i_data );        memcpy( p_data, &b->p_buffer[i_offset], i_copy );        i_data += i_copy;        p_data += i_copy;        i_offset += i_copy;        if( i_offset >= b->i_buffer )        {            i_offset = 0;            b = b->p_next;        }    }    *pp_peek = p_sys->p_peek;    return i_data;}static int AStreamSeekBlock( stream_t *s, int64_t i_pos ){    stream_sys_t *p_sys = s->p_sys;    access_t   *p_access = p_sys->p_access;    int64_t    i_offset = i_pos - p_sys->block.i_start;    bool b_seek;    /* We already have thoses data, just update p_current/i_offset */    if( i_offset >= 0 && i_offset < p_sys->block.i_size )    {        block_t *b = p_sys->block.p_first;        int i_current = 0;        while( i_current + b->i_buffer < i_offset )        {            i_current += b->i_buffer;            b = b->p_next;        }        p_sys->block.p_current = b;        p_sys->block.i_offset = i_offset - i_current;        p_sys->i_pos = i_pos;        return VLC_SUCCESS;    }    /* We may need to seek or to read data */    if( i_offset < 0 )    {        bool b_aseek;        access_Control( p_access, ACCESS_CAN_SEEK, &b_aseek );        if( !b_aseek )        {            msg_Err( s, "backward seeking impossible (access not seekable)" );            return VLC_EGENERIC;        }        b_seek = true;    }    else    {        bool b_aseek, b_aseekfast;        access_Control( p_access, ACCESS_CAN_SEEK, &b_aseek );        access_Control( p_access, ACCESS_CAN_FASTSEEK, &b_aseekfast );        if( !b_aseek )        {            b_seek = false;            msg_Warn( s, "%"PRId64" bytes need to be skipped "                      "(access non seekable)",                      i_offset - p_sys->block.i_size );        }        else        {            int64_t i_skip = i_offset - p_sys->block.i_size;            /* Avg bytes per packets */            int i_avg = p_sys->stat.i_bytes / p_sys->stat.i_read_count;            /* TODO compute a seek cost instead of fixed threshold */            int i_th = b_aseekfast ? 1 : 5;            if( i_skip <= i_th * i_avg &&                i_skip < STREAM_CACHE_SIZE )                b_seek = false;            else                b_seek = true;            msg_Dbg( s, "b_seek=%d th*avg=%d skip=%"PRId64,                     b_seek, i_th*i_avg, i_skip );        }    }    if( b_seek )    {        int64_t i_start, i_end;        /* Do the access seek */        i_start = mdate();        if( ASeek( s, i_pos ) ) return VLC_EGENERIC;        i_end = mdate();        /* Release data */        block_ChainRelease( p_sys->block.p_first );        /* Reinit */        p_sys->block.i_start = p_sys->i_pos = 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;        /* Refill a block */        if( AStreamRefillBlock( s ) )            return VLC_EGENERIC;        /* Update stat */        p_sys->stat.i_seek_time += i_end - i_start;        p_sys->stat.i_seek_count++;        return VLC_SUCCESS;    }    else    {        do        {            /* Read and skip enough data */            if( AStreamRefillBlock( s ) )                return VLC_EGENERIC;            while( p_sys->block.p_current &&                   p_sys->i_pos + p_sys->block.p_current->i_buffer - p_sys->block.i_offset < i_pos )            {                p_sys->i_pos += p_sys->block.p_current->i_buffer - p_sys->block.i_offset;                p_sys->block.p_current = p_sys->block.p_current->p_next;                p_sys->block.i_offset = 0;            }        }        while( p_sys->block.i_start + p_sys->block.i_size < i_pos );        p_sys->block.i_offset = i_pos - p_sys->i_pos;        p_sys->i_pos = i_pos;        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( ;; )    {        bool 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, unsigned 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;    unsigned 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;        /* seeking after EOF is not what we want */        if( !( p_access->info.b_eof ) )        {            bool   b_aseek;            access_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=%"PRId64" tk=%d start=%"PRId64             " offset=%d end=%"PRId64,             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;        unsigned int i_current =            __MAX(0,__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, const uint8_t **pp_peek, unsigned 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=%"PRId64" tk=%d "             "start=%"PRId64" offset=%d end=%"PRId64,             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;    bool   b_aseek;    bool   b_afastseek;    int i_maxth;    int i_new;    int i;#ifdef STREAM_DEBUG    msg_Dbg( s, "AStreamSeekStream: to %"PRId64" pos=%"PRId64             " tk=%d start=%"PRId64" offset=%d end=%"PRId64,             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;    }    access_Control( p_access, ACCESS_CAN_SEEK, &b_aseek );    if( !b_aseek )    {        /* We can't do nothing */        msg_Dbg( s, "AStreamSeekStream: can't seek" );

⌨️ 快捷键说明

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