Browse Source
And use cache_read instead, cf. previous commit. Furthermore, there is only one access module: vcd, that could use cache_block since slow block based accesses will use prefetch. Fixes #28484pull/162/head
committed by
Steve Lhomme
4 changed files with 0 additions and 339 deletions
@ -1,330 +0,0 @@ |
|||
/*****************************************************************************
|
|||
* cache_block.c |
|||
***************************************************************************** |
|||
* Copyright (C) 1999-2004 VLC authors and VideoLAN |
|||
* |
|||
* Authors: Laurent Aimar <fenrir@via.ecp.fr> |
|||
* |
|||
* This program is free software; you can redistribute it and/or modify it |
|||
* under the terms of the GNU Lesser General Public License as published by |
|||
* the Free Software Foundation; either version 2.1 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Lesser General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Lesser General Public License |
|||
* along with this program; if not, write to the Free Software Foundation, |
|||
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
|||
*****************************************************************************/ |
|||
|
|||
#ifdef HAVE_CONFIG_H |
|||
# include "config.h" |
|||
#endif |
|||
|
|||
#include <assert.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
|
|||
#include <vlc_common.h> |
|||
#include <vlc_plugin.h> |
|||
#include <vlc_stream.h> |
|||
#include <vlc_interrupt.h> |
|||
#include <vlc_block_helper.h> |
|||
|
|||
/* TODO:
|
|||
* - tune the 2 methods (block/stream) |
|||
* - compute cost for seek |
|||
* - improve stream mode seeking with closest segments |
|||
* - ... |
|||
*/ |
|||
|
|||
/*
|
|||
* One linked list of data read |
|||
*/ |
|||
|
|||
/* How many tracks we have, currently only used for stream mode */ |
|||
#ifdef OPTIMIZE_MEMORY |
|||
/* Max size of our cache 128KiB per stream */ |
|||
# define STREAM_CACHE_SIZE (1024*128) |
|||
#else |
|||
/* Max size of our cache 48MiB per stream */ |
|||
# define STREAM_CACHE_SIZE (4*12*1024*1024) |
|||
#endif |
|||
|
|||
/* How many data we try to prebuffer
|
|||
* XXX it should be small to avoid useless latency but big enough for |
|||
* efficient demux probing */ |
|||
#define STREAM_CACHE_PREBUFFER_SIZE (128) |
|||
|
|||
/* Method: Simple, for pf_block.
|
|||
* We get blocks and put them in the linked list. |
|||
* We release blocks once the total size is bigger than STREAM_CACHE_SIZE |
|||
*/ |
|||
|
|||
typedef struct |
|||
{ |
|||
block_bytestream_t cache; /* bytestream chain for storing cache */ |
|||
|
|||
struct |
|||
{ |
|||
/* Stats for calculating speed */ |
|||
uint64_t read_bytes; |
|||
vlc_tick_t read_time; |
|||
} stat; |
|||
} stream_sys_t; |
|||
|
|||
static int AStreamRefillBlock(stream_t *s) |
|||
{ |
|||
stream_sys_t *sys = s->p_sys; |
|||
size_t cache_size = sys->cache.i_total; |
|||
|
|||
/* Release data */ |
|||
if (cache_size >= STREAM_CACHE_SIZE) |
|||
{ |
|||
block_BytestreamFlush( &sys->cache ); |
|||
cache_size = sys->cache.i_total; |
|||
} |
|||
if (cache_size >= STREAM_CACHE_SIZE && |
|||
sys->cache.p_chain != *sys->cache.pp_last) |
|||
{ |
|||
/* Enough data, don't read more */ |
|||
return VLC_SUCCESS; |
|||
} |
|||
|
|||
/* Now read a new block */ |
|||
const vlc_tick_t start = vlc_tick_now(); |
|||
block_t *b; |
|||
|
|||
for (;;) |
|||
{ |
|||
if (vlc_killed()) |
|||
return VLC_EGENERIC; |
|||
|
|||
/* Fetch a block */ |
|||
if ((b = vlc_stream_ReadBlock(s->s))) |
|||
break; |
|||
if (vlc_stream_Eof(s->s)) |
|||
return VLC_EGENERIC; |
|||
} |
|||
sys->stat.read_time += vlc_tick_now() - start; |
|||
size_t added_bytes; |
|||
block_ChainProperties( b, NULL, &added_bytes, NULL ); |
|||
sys->stat.read_bytes += added_bytes; |
|||
|
|||
block_BytestreamPush( &sys->cache, b ); |
|||
return VLC_SUCCESS; |
|||
} |
|||
|
|||
static void AStreamPrebufferBlock(stream_t *s) |
|||
{ |
|||
stream_sys_t *sys = s->p_sys; |
|||
vlc_tick_t start = vlc_tick_now(); |
|||
bool first = true; |
|||
|
|||
msg_Dbg(s, "starting pre-buffering"); |
|||
for (;;) |
|||
{ |
|||
const vlc_tick_t now = vlc_tick_now(); |
|||
size_t cache_size = block_BytestreamRemaining( &sys->cache ); |
|||
|
|||
if (vlc_killed() || cache_size > STREAM_CACHE_PREBUFFER_SIZE) |
|||
{ |
|||
int64_t byterate; |
|||
|
|||
/* Update stat */ |
|||
sys->stat.read_bytes = cache_size; |
|||
sys->stat.read_time = now - start; |
|||
byterate = (CLOCK_FREQ * sys->stat.read_bytes ) / |
|||
(sys->stat.read_time -1); |
|||
|
|||
msg_Dbg(s, "prebuffering done %zu bytes " |
|||
"in %"PRIu64"s - %"PRIu64"u KiB/s", cache_size, |
|||
SEC_FROM_VLC_TICK(sys->stat.read_time), byterate / 1024 ); |
|||
break; |
|||
} |
|||
|
|||
/* Fetch a block */ |
|||
block_t *b = vlc_stream_ReadBlock(s->s); |
|||
if (b == NULL) |
|||
{ |
|||
if (vlc_stream_Eof(s->s)) |
|||
break; |
|||
continue; |
|||
} |
|||
|
|||
block_BytestreamPush( &sys->cache, b); |
|||
|
|||
if (first) |
|||
{ |
|||
msg_Dbg(s, "received first data after %"PRId64" ms", |
|||
MS_FROM_VLC_TICK(vlc_tick_now() - start)); |
|||
first = false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/****************************************************************************
|
|||
* AStreamControlReset: |
|||
****************************************************************************/ |
|||
static void AStreamControlReset(stream_t *s) |
|||
{ |
|||
stream_sys_t *sys = s->p_sys; |
|||
|
|||
block_BytestreamEmpty( &sys->cache ); |
|||
|
|||
/* Do the prebuffering */ |
|||
AStreamPrebufferBlock(s); |
|||
} |
|||
|
|||
static int AStreamSeekBlock(stream_t *s, uint64_t i_pos) |
|||
{ |
|||
stream_sys_t *sys = s->p_sys; |
|||
|
|||
if( block_SkipBytes( &sys->cache, i_pos) == VLC_SUCCESS ) |
|||
return VLC_SUCCESS; |
|||
|
|||
/* Not enough bytes, empty and seek */ |
|||
/* Do the access seek */ |
|||
if (vlc_stream_Seek(s->s, i_pos)) return VLC_EGENERIC; |
|||
|
|||
block_BytestreamEmpty( &sys->cache ); |
|||
|
|||
/* Refill a block */ |
|||
if (AStreamRefillBlock(s)) |
|||
return VLC_EGENERIC; |
|||
|
|||
return VLC_SUCCESS; |
|||
} |
|||
|
|||
static ssize_t AStreamReadBlock(stream_t *s, void *buf, size_t len) |
|||
{ |
|||
stream_sys_t *sys = s->p_sys; |
|||
|
|||
ssize_t i_current = block_BytestreamRemaining( &sys->cache ); |
|||
size_t i_copy = VLC_CLIP((size_t)i_current, 0, len); |
|||
|
|||
/**
|
|||
* we should not signal end-of-file if we have not exhausted |
|||
* the cache. i_copy == 0 just means that the cache currently does |
|||
* not contain data at the offset that we want, not EOF. |
|||
**/ |
|||
if( i_copy == 0 ) |
|||
{ |
|||
/* Return EOF if we are unable to refill cache, most likely
|
|||
* really EOF */ |
|||
if( AStreamRefillBlock(s) == VLC_EGENERIC ) |
|||
return 0; |
|||
} |
|||
|
|||
/* Copy data */ |
|||
if( block_GetBytes( &sys->cache, buf, i_copy ) ) |
|||
return -1; |
|||
|
|||
|
|||
/* If we ended up on refill, try to read refilled cache */ |
|||
if( i_copy == 0 && sys->cache.p_chain ) |
|||
return AStreamReadBlock( s, buf, len ); |
|||
|
|||
return i_copy; |
|||
} |
|||
|
|||
/****************************************************************************
|
|||
* AStreamControl: |
|||
****************************************************************************/ |
|||
static int AStreamControl(stream_t *s, int i_query, va_list args) |
|||
{ |
|||
switch(i_query) |
|||
{ |
|||
case STREAM_CAN_SEEK: |
|||
case STREAM_CAN_FASTSEEK: |
|||
case STREAM_CAN_PAUSE: |
|||
case STREAM_CAN_CONTROL_PACE: |
|||
case STREAM_GET_MTIME: |
|||
case STREAM_GET_SIZE: |
|||
case STREAM_GET_PTS_DELAY: |
|||
case STREAM_GET_TITLE_INFO: |
|||
case STREAM_GET_TITLE: |
|||
case STREAM_GET_SEEKPOINT: |
|||
case STREAM_GET_META: |
|||
case STREAM_GET_CONTENT_TYPE: |
|||
case STREAM_GET_SIGNAL: |
|||
case STREAM_GET_TAGS: |
|||
case STREAM_SET_PAUSE_STATE: |
|||
case STREAM_SET_PRIVATE_ID_STATE: |
|||
case STREAM_SET_PRIVATE_ID_CA: |
|||
case STREAM_GET_PRIVATE_ID_STATE: |
|||
return vlc_stream_vaControl(s->s, i_query, args); |
|||
|
|||
case STREAM_SET_TITLE: |
|||
case STREAM_SET_SEEKPOINT: |
|||
{ |
|||
int ret = vlc_stream_vaControl(s->s, i_query, args); |
|||
if (ret == VLC_SUCCESS) |
|||
AStreamControlReset(s); |
|||
return ret; |
|||
} |
|||
|
|||
case STREAM_SET_RECORD_STATE: |
|||
default: |
|||
msg_Err(s, "invalid vlc_stream_vaControl query=0x%x", i_query); |
|||
return VLC_EGENERIC; |
|||
} |
|||
return VLC_SUCCESS; |
|||
} |
|||
|
|||
static int Open(vlc_object_t *obj) |
|||
{ |
|||
stream_t *s = (stream_t *)obj; |
|||
|
|||
if (s->s->pf_block == NULL) |
|||
return VLC_EGENERIC; |
|||
|
|||
stream_sys_t *sys = malloc(sizeof (*sys)); |
|||
if (unlikely(sys == NULL)) |
|||
return VLC_ENOMEM; |
|||
|
|||
msg_Dbg(s, "Using block method for AStream*"); |
|||
|
|||
/* Init all fields of sys->block */ |
|||
block_BytestreamInit( &sys->cache ); |
|||
|
|||
s->p_sys = sys; |
|||
/* Do the prebuffering */ |
|||
AStreamPrebufferBlock(s); |
|||
|
|||
if (block_BytestreamRemaining( &sys->cache ) <= 0) |
|||
{ |
|||
msg_Err(s, "cannot pre fill buffer"); |
|||
free(sys); |
|||
return VLC_EGENERIC; |
|||
} |
|||
|
|||
s->pf_read = AStreamReadBlock; |
|||
s->pf_seek = AStreamSeekBlock; |
|||
s->pf_control = AStreamControl; |
|||
return VLC_SUCCESS; |
|||
} |
|||
|
|||
/****************************************************************************
|
|||
* AStreamDestroy: |
|||
****************************************************************************/ |
|||
static void Close(vlc_object_t *obj) |
|||
{ |
|||
stream_t *s = (stream_t *)obj; |
|||
stream_sys_t *sys = s->p_sys; |
|||
|
|||
block_BytestreamEmpty( &sys->cache ); |
|||
free(sys); |
|||
} |
|||
|
|||
vlc_module_begin() |
|||
set_subcategory(SUBCAT_INPUT_STREAM_FILTER) |
|||
set_capability("stream_filter", 0) |
|||
add_shortcut("cache") |
|||
|
|||
set_description(N_("Block stream cache")) |
|||
set_callbacks(Open, Close) |
|||
vlc_module_end() |
|||
Loading…
Reference in new issue