[vlc-devel] [PATCH] restore cache_block equivalent code and remove bugs
Francois Cartegnie
fcvlcdev at free.fr
Fri May 18 15:22:03 CEST 2018
Demonstrating the little benefit of using block bytestream
(which does not work with uint64) for that purpose,
once you have restored code equivalence and fixed bugs.
---
modules/stream_filter/cache_block.c | 163 +++++++++++++++++++++++++++++-------
1 file changed, 133 insertions(+), 30 deletions(-)
diff --git a/modules/stream_filter/cache_block.c b/modules/stream_filter/cache_block.c
index 86237de654..8901e97b31 100644
--- a/modules/stream_filter/cache_block.c
+++ b/modules/stream_filter/cache_block.c
@@ -67,6 +67,7 @@
typedef struct
{
+ uint64_t i_pos; /* Current reading offset */
block_bytestream_t cache; /* bytestream chain for storing cache */
struct
@@ -74,6 +75,7 @@ typedef struct
/* Stats for calculating speed */
uint64_t read_bytes;
uint64_t read_time;
+ int read_count;
} stat;
} stream_sys_t;
@@ -89,7 +91,7 @@ static int AStreamRefillBlock(stream_t *s)
cache_size = sys->cache.i_total;
}
if (cache_size >= STREAM_CACHE_SIZE &&
- sys->cache.p_chain != *sys->cache.pp_last)
+ sys->cache.p_chain != *sys->cache.pp_last) /* At least 2 packets */
{
/* Enough data, don't read more */
return VLC_SUCCESS;
@@ -110,12 +112,15 @@ static int AStreamRefillBlock(stream_t *s)
if (vlc_stream_Eof(s->s))
return VLC_EGENERIC;
}
- sys->stat.read_time += mdate() - start;
- size_t added_bytes;
- block_ChainProperties( b, NULL, &added_bytes, NULL );
- sys->stat.read_bytes += added_bytes;
block_BytestreamPush( &sys->cache, b );
+ sys->stat.read_time += mdate() - start;
+ for( ; b; b = b->p_next )
+ {
+ sys->stat.read_bytes += b->i_buffer;
+ sys->stat.read_count++;
+ }
+
return VLC_SUCCESS;
}
@@ -158,6 +163,8 @@ static void AStreamPrebufferBlock(stream_t *s)
}
block_BytestreamPush( &sys->cache, b);
+ for( ; b; b=b->p_next )
+ sys->stat.read_count++;
if (first)
{
@@ -175,6 +182,8 @@ static void AStreamControlReset(stream_t *s)
{
stream_sys_t *sys = s->p_sys;
+ sys->i_pos = 0;
+
block_BytestreamEmpty( &sys->cache );
/* Do the prebuffering */
@@ -184,52 +193,142 @@ static void AStreamControlReset(stream_t *s)
static int AStreamSeekBlock(stream_t *s, uint64_t i_pos)
{
stream_sys_t *sys = s->p_sys;
+ bool b_seek;
- if( block_SkipBytes( &sys->cache, i_pos) == VLC_SUCCESS )
- return VLC_SUCCESS;
+ if(i_pos >= sys->i_pos && i_pos - sys->i_pos < SIZE_MAX)
+ {
+ size_t i_offset = i_pos - sys->i_pos;
+ if(block_SkipBytes( &sys->cache, i_offset) == VLC_SUCCESS)
+ {
+ sys->i_pos = i_pos;
+ return VLC_SUCCESS;
+ }
+ }
+
+ /* We may need to seek or to read data */
+ if (i_pos < sys->i_pos)
+ {
+ bool b_aseek;
+ vlc_stream_Control(s->s, STREAM_CAN_SEEK, &b_aseek);
- /* Not enought bytes, empty and seek */
- /* Do the access seek */
- if (vlc_stream_Seek(s->s, i_pos)) return VLC_EGENERIC;
+ if (!b_aseek)
+ {
+ msg_Err(s, "backward seeking impossible (access not seekable)");
+ return VLC_EGENERIC;
+ }
- block_BytestreamEmpty( &sys->cache );
+ b_seek = true;
+ }
+ else
+ {
+ bool b_aseek, b_aseekfast;
+ uint64_t i_offset = i_pos - sys->i_pos;
- /* Refill a block */
- if (AStreamRefillBlock(s))
- return VLC_EGENERIC;
+ vlc_stream_Control(s->s, STREAM_CAN_SEEK, &b_aseek);
+ vlc_stream_Control(s->s, STREAM_CAN_FASTSEEK, &b_aseekfast);
- return VLC_SUCCESS;
+ size_t i_cached = block_BytestreamRemaining(&sys->cache);
+ if (!b_aseek)
+ {
+ b_seek = false;
+ msg_Warn(s, "%"PRId64" bytes need to be skipped "
+ "(access non seekable)", i_offset - i_cached);
+ }
+ else
+ {
+ uint64_t i_skip = i_offset - i_cached;
+
+ /* Avg bytes per packets */
+ uint64_t i_avg = sys->stat.read_bytes / sys->stat.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=%"PRIu64" skip=%"PRIu64,
+ b_seek, i_th*i_avg, i_skip);
+ }
+ }
+
+ if( b_seek )
+ {
+ /* Do the access seek */
+ if (vlc_stream_Seek(s->s, i_pos)) return VLC_EGENERIC;
+
+ /* Release data */
+ block_BytestreamEmpty(&sys->cache);
+
+ /* Refill a block */
+ if (AStreamRefillBlock(s))
+ return VLC_EGENERIC;
+
+ return VLC_SUCCESS;
+ }
+ else
+ {
+ uint64_t i_offset = i_pos - sys->i_pos;
+ while(i_offset > 0)
+ {
+ size_t i_cached = block_BytestreamRemaining(&sys->cache);
+ if(i_cached > 0)
+ {
+ if(i_offset > i_cached)
+ {
+ block_BytestreamEmpty(&sys->cache);
+ i_offset -= i_cached;
+ i_cached = 0;
+ }
+ else
+ {
+ size_t i_skip = i_offset < SIZE_MAX ? i_offset : SIZE_MAX;
+ assert(!block_SkipBytes(&sys->cache, i_skip));
+ i_offset -= i_skip;
+ i_cached -= i_skip;
+ }
+ }
+
+ if (i_cached > i_offset && AStreamRefillBlock(s))
+ break;
+ }
+
+ sys->i_pos = i_pos - i_offset;
+
+ return (sys->i_pos == i_pos) ? VLC_SUCCESS: VLC_EGENERIC;
+ }
+
+ vlc_assert_unreachable();
+ return VLC_EGENERIC;
}
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);
+ size_t i_remain = block_BytestreamRemaining(&sys->cache);
/**
* we should not signal end-of-file if we have not exhausted
- * the cache. i_copy == 0 just means that the cache currently does
+ * the cache. i_remain == 0 just means that the cache currently does
* not contain data at the offset that we want, not EOF.
**/
- if( i_copy == 0 )
+
+ /* Get a new block if needed */
+ if(i_remain == 0 && len > 0)
{
- /* Return EOF if we are unable to refill cache, most likely
- * really EOF */
- if( AStreamRefillBlock(s) == VLC_EGENERIC )
+ if(AStreamRefillBlock(s))
return 0;
+ i_remain = block_BytestreamRemaining(&sys->cache);
}
+ size_t i_copy = VLC_CLIP(i_remain, 0, len);
/* 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 );
+ assert(!block_GetBytes(&sys->cache, buf, i_copy));
+ sys->i_pos += i_copy;
return i_copy;
}
@@ -289,8 +388,12 @@ static int Open(vlc_object_t *obj)
msg_Dbg(s, "Using block method for AStream*");
- /* Init all fields of sys->block */
+ /* Init all fields of sys->cache */
block_BytestreamInit( &sys->cache );
+ sys->i_pos = 0;
+ sys->stat.read_bytes = 0;
+ sys->stat.read_time = 0;
+ sys->stat.read_count = 0;
s->p_sys = sys;
/* Do the prebuffering */
--
2.14.3
More information about the vlc-devel
mailing list