[vlc-commits] [Git][videolan/vlc][master] 4 commits: archive: also send first sub items if truncated
Steve Lhomme (@robUx4)
gitlab at videolan.org
Wed Nov 20 14:41:02 UTC 2024
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
852fdf90 by Thomas Guillem at 2024-11-20T14:26:27+00:00
archive: also send first sub items if truncated
- - - - -
43dbfac5 by Thomas Guillem at 2024-11-20T14:26:27+00:00
archive: use archive_read_data_block()
Read what we can instead of reading what the user asks.
This fixes a fatal error when reading past an error.
This saves a memcpy when seeking by skiping data (likely).
- - - - -
497fba58 by Thomas Guillem at 2024-11-20T14:26:27+00:00
archive: re-indent to prepare for the next commit
No functional changes.
- - - - -
63f076b5 by Thomas Guillem at 2024-11-20T14:26:27+00:00
archive: restore original state after a seek/skip error
A failing seek should not be critical, the demuxer has the choice to
continue its parsing without seeking (like when loading index tables at the
end of the file).
- - - - -
1 changed file:
- modules/stream_extractor/archive.c
Changes:
=====================================
modules/stream_extractor/archive.c
=====================================
@@ -81,6 +81,9 @@ struct private_sys_t
libarchive_callback_t** pp_callback_data;
size_t i_callback_data;
+
+ const uint8_t *last_arcbuf;
+ size_t last_arcsize;
};
struct libarchive_callback_t {
@@ -399,6 +402,8 @@ static int archive_extractor_reset( stream_extractor_t* p_extractor )
p_sys->i_offset = 0;
p_sys->b_eof = false;
p_sys->b_dead = false;
+ p_sys->last_arcbuf = NULL;
+ p_sys->last_arcsize = 0;
return VLC_SUCCESS;
}
@@ -424,6 +429,8 @@ static private_sys_t* setup( vlc_object_t* obj, stream_t* source,
p_sys->source = source;
p_sys->p_obj = obj;
+ p_sys->last_arcbuf = NULL;
+ p_sys->last_arcsize = 0;
return p_sys;
@@ -530,6 +537,7 @@ static int ReadDir( stream_directory_t* p_directory, input_item_node_t* p_node )
vlc_readdir_helper_init( &rdh, p_directory, p_node);
struct archive_entry* entry;
int archive_status;
+ unsigned item_count = 0;
while( !( archive_status = archive_read_next_header( p_arc, &entry ) ) )
{
@@ -564,6 +572,7 @@ static int ReadDir( stream_directory_t* p_directory, input_item_node_t* p_node )
int64_t size = archive_entry_size( entry );
if( size >= 0 )
input_item_AddStat( p_item, "size", size );
+ item_count++;
}
free( mrl );
@@ -571,14 +580,14 @@ static int ReadDir( stream_directory_t* p_directory, input_item_node_t* p_node )
break;
}
- vlc_readdir_helper_finish( &rdh, archive_status == ARCHIVE_EOF );
- return archive_status == ARCHIVE_EOF ? VLC_SUCCESS : VLC_EGENERIC;
+ bool success = item_count > 0 || archive_status == ARCHIVE_EOF;
+
+ vlc_readdir_helper_finish( &rdh, success );
+ return success ? VLC_SUCCESS : VLC_EGENERIC;
}
static ssize_t Read( stream_extractor_t *p_extractor, void* p_data, size_t i_size )
{
- char dummy_buffer[ 8192 ];
-
private_sys_t* p_sys = p_extractor->p_sys;
libarchive_t* p_arc = p_sys->p_archive;
ssize_t i_ret;
@@ -589,12 +598,39 @@ static ssize_t Read( stream_extractor_t *p_extractor, void* p_data, size_t i_siz
if( p_sys->b_eof )
return 0;
- i_ret = archive_read_data( p_arc,
- p_data ? p_data : dummy_buffer,
- p_data ? i_size : __MIN( i_size, sizeof( dummy_buffer ) ) );
+ const void *arcbuf = NULL;
+ size_t arcsize = 0;
+ la_int64_t arcoffset = 0;
+ if( p_sys->last_arcbuf == NULL )
+ {
+ i_ret = archive_read_data_block( p_arc, &arcbuf, &arcsize, &arcoffset);
+ assert(arcoffset == (la_int64_t) p_sys->i_offset); (void)arcoffset;
+ }
+ else
+ {
+ i_ret = ARCHIVE_OK;
+ arcbuf = p_sys->last_arcbuf;
+ arcsize = p_sys->last_arcsize;
+ }
switch( i_ret )
{
+ case ARCHIVE_OK:
+ case ARCHIVE_EOF:
+ if( i_size >= arcsize )
+ {
+ i_size = arcsize;
+ p_sys->last_arcbuf = NULL;
+ p_sys->last_arcsize = 0;
+ }
+ else
+ {
+ p_sys->last_arcbuf = (uint8_t *)arcbuf + i_size;
+ p_sys->last_arcsize = arcsize - i_size;
+ }
+ if( p_data != NULL)
+ memcpy( p_data, arcbuf, i_size );
+ break;
case ARCHIVE_RETRY:
case ARCHIVE_FAILED:
msg_Dbg( p_extractor, "libarchive: %s", archive_error_string( p_arc ) );
@@ -609,8 +645,8 @@ static ssize_t Read( stream_extractor_t *p_extractor, void* p_data, size_t i_siz
goto fatal_error;
}
- p_sys->i_offset += i_ret;
- return i_ret;
+ p_sys->i_offset += i_size;
+ return i_size;
fatal_error:
p_sys->b_dead = true;
@@ -650,6 +686,7 @@ static int Seek( stream_extractor_t* p_extractor, uint64_t i_req )
}
p_sys->b_eof = false;
+ int ret = VLC_SUCCESS;
if( !p_sys->b_seekable_archive || p_sys->b_dead
|| archive_seek_data( p_sys->p_archive, i_req, SEEK_SET ) < 0 )
@@ -660,29 +697,47 @@ static int Seek( stream_extractor_t* p_extractor, uint64_t i_req )
uint64_t i_skip = i_req - p_sys->i_offset;
- /* RECREATE LIBARCHIVE HANDLE IF WE ARE SEEKING BACKWARDS */
- if( i_req < p_sys->i_offset )
+ /* The 1st try is the original skip.
+ * The 2nd try is to go back to the previous position in case of
+ * failure. */
+ uint64_t preskip_offset = p_sys->i_offset;
+ for (unsigned i = 0; i < 2; ++i)
{
- if( archive_extractor_reset( p_extractor ) )
+ if( i_req < p_sys->i_offset )
{
- msg_Err( p_extractor, "unable to reset libarchive handle" );
- return VLC_EGENERIC;
+ /* RECREATE LIBARCHIVE HANDLE IF WE ARE SEEKING BACKWARDS */
+ if( archive_extractor_reset( p_extractor ) )
+ {
+ msg_Err( p_extractor, "unable to reset libarchive handle" );
+ return VLC_EGENERIC;
+ }
+
+ i_skip = i_req;
}
- i_skip = i_req;
- }
- if( archive_skip_decompressed( p_extractor, &i_skip ) )
- {
- msg_Warn( p_extractor, "failed to skip to seek position %" PRIu64 "/%" PRId64,
- i_req, archive_entry_size( p_sys->p_entry ) );
- p_sys->i_offset += i_skip;
- return VLC_EGENERIC;
+ if( archive_skip_decompressed( p_extractor, &i_skip ) == 0 )
+ break; /* Success */
+ msg_Warn( p_extractor, "failed to skip to seek position %"
+ PRIu64 "/%" PRId64, i_req,
+ archive_entry_size( p_sys->p_entry ) );
+ ret = VLC_EGENERIC;
+
+ /* Seek back to the original offset before failure */
+ i_req = preskip_offset;
+ if( i_req == p_sys->i_offset )
+ break; /* no data was skipped, no need for a 2nd try */
+ assert( i_req < p_sys->i_offset );
}
}
+ else
+ {
+ p_sys->last_arcbuf = NULL;
+ p_sys->last_arcsize = 0;
+ }
p_sys->i_offset = i_req;
- return VLC_SUCCESS;
+ return ret;
}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/208f861adfa0e0e5b415f7a08c3ca1f794a72f7a...63f076b59416262a860724c3ea638e5079bccc19
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/208f861adfa0e0e5b415f7a08c3ca1f794a72f7a...63f076b59416262a860724c3ea638e5079bccc19
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list