diff --git a/libvips/foreign/heifload.c b/libvips/foreign/heifload.c index 08cdc68c..802fdc66 100644 --- a/libvips/foreign/heifload.c +++ b/libvips/foreign/heifload.c @@ -872,6 +872,9 @@ vips_foreign_load_heif_load( VipsForeignLoad *load ) vips_image_write( t[1], load->real ) ) return( -1 ); + if( vips_source_decode( heif->source ) ) + return( -1 ); + return( 0 ); } diff --git a/libvips/iofuncs/source.c b/libvips/iofuncs/source.c index b6cbc36b..cd0eb73c 100644 --- a/libvips/iofuncs/source.c +++ b/libvips/iofuncs/source.c @@ -42,8 +42,8 @@ */ /* -#define TEST_SANITY #define VIPS_DEBUG +#define TEST_SANITY */ #ifdef HAVE_CONFIG_H @@ -639,13 +639,15 @@ vips_source_decode( VipsSource *source ) SANITY( source ); - /* We have finished reading the header. We can discard the header bytes - * we saved. - */ if( !source->decode ) { source->decode = TRUE; - VIPS_FREEF( g_byte_array_unref, source->header_bytes ); VIPS_FREEF( g_byte_array_unref, source->sniff ); + + /* If this is still a pipe source, we can discard the header + * bytes we saved. + */ + if( source->is_pipe ) + VIPS_FREEF( g_byte_array_unref, source->header_bytes ); } vips_source_minimise( source ); @@ -655,6 +657,25 @@ vips_source_decode( VipsSource *source ) return( 0 ); } +#ifdef VIPS_DEBUG +static void +vips_source_print( VipsSource *source ) +{ + printf( "vips_source_print: %p\n", source ); + printf( " source->read_position = %zd\n", source->read_position ); + printf( " source->is_pipe = %d\n", source->is_pipe ); + printf( " source->length = %zd\n", source->length ); + printf( " source->data = %p\n", source->data ); + printf( " source->header_bytes = %p\n", source->header_bytes ); + if( source->header_bytes ) + printf( " source->header_bytes->len = %d\n", + source->header_bytes->len ); + printf( " source->sniff = %p\n", source->sniff ); + if( source->sniff ) + printf( " source->sniff->len = %d\n", source->sniff->len ); +} +#endif /*VIPS_DEBUG*/ + /** * vips_source_read: * @source: source to operate on @@ -761,31 +782,13 @@ vips_source_read( VipsSource *source, void *buffer, size_t length ) return( total_read ); } -#ifdef DEBUG -static void -vips_source_print( VipsSource *source ) -{ - printf( "vips_source_print: %p\n", source ); - printf( " source->read_position = %zd\n", source->read_position ); - printf( " source->is_pipe = %d\n", source->is_pipe ); - printf( " source->length = %zd\n", source->length ); - printf( " source->data = %p\n", source->data ); - printf( " source->header_bytes = %p\n", source->header_bytes ); - if( source->header_bytes ) - printf( " source->header_bytes->len = %d\n", - source->header_bytes->len ); - printf( " source->sniff = %p\n", source->sniff ); - if( source->sniff ) - printf( " source->sniff->len = %d\n", source->sniff->len ); -} -#endif /*DEBUG*/ - /* Read to a position. * * target == -1 means read to end of source -- useful for forcing a pipe into - * memory, for example. + * memory, for example. This will always set length to the pipe length. * - * If we hit EOF, set length on the pipe. + * If we hit EOF and we're buffering, set length on the pipe and turn it into + * a memory source. * * read_position is left somewhere indeterminate. */ @@ -800,6 +803,7 @@ vips_source_pipe_read_to_position( VipsSource *source, gint64 target ) * length). */ g_assert( source->length == -1 ); + g_assert( source->is_pipe ); while( target == -1 || source->read_position < target ) { @@ -813,6 +817,19 @@ vips_source_pipe_read_to_position( VipsSource *source, gint64 target ) /* No more bytes available, we must be at EOF. */ source->length = source->read_position; + + /* Have we been buffering the whole thing? We can + * become a memory source. + */ + if( source->header_bytes ) { + source->data = source->header_bytes->data; + source->is_pipe = FALSE; + + /* TODO ... we could close more fds here. + */ + vips_source_minimise( source ); + } + break; } @@ -853,8 +870,6 @@ vips_source_read_to_memory( VipsSource *source ) byte_array = g_byte_array_new(); g_byte_array_set_size( byte_array, source->length ); - /* Read in a series of chunks to reduce stress upstream. - */ read_position = 0; q = byte_array->data; while( read_position < source->length ) { @@ -887,34 +902,6 @@ vips_source_read_to_memory( VipsSource *source ) return( 0 ); } -/* Read the entire pipe into memory and turn this into a memory source. - */ -static int -vips_source_pipe_to_memory( VipsSource *source ) -{ - VIPS_DEBUG_MSG( "vips_source_pipe_to_memory:\n" ); - - g_assert( source->is_pipe ); - g_assert( !source->blob ); - g_assert( !source->decode ); - g_assert( source->header_bytes ); - - if( vips_source_pipe_read_to_position( source, -1 ) ) - return( -1 ); - - /* Steal the header_bytes pointer and turn into a memory source. - */ - source->length = source->header_bytes->len; - source->data = source->header_bytes->data; - source->is_pipe = FALSE; - - /* TODO ... we could close more fds here. - */ - vips_source_minimise( source ); - - return( 0 ); -} - static int vips_source_descriptor_to_memory( VipsSource *source ) { @@ -1002,7 +989,7 @@ vips_source_map( VipsSource *source, size_t *length_out ) return( NULL ); } else { - if( vips_source_pipe_to_memory( source ) ) + if( vips_source_pipe_read_to_position( source, -1 ) ) return( NULL ); } } @@ -1113,8 +1100,7 @@ vips_source_seek( VipsSource *source, gint64 offset, int whence ) /* We have to read the whole source into memory to get * the length. */ - if( source->length == -1 && - vips_source_pipe_to_memory( source ) ) + if( vips_source_pipe_read_to_position( source, -1 ) ) return( -1 ); new_pos = source->length + offset; @@ -1130,6 +1116,13 @@ vips_source_seek( VipsSource *source, gint64 offset, int whence ) return( -1 ); } + /* For pipes, we have to fake seek by reading to that point. This + * might hit EOF and turn the pipe into a memory source. + */ + if( source->is_pipe && + vips_source_pipe_read_to_position( source, new_pos ) ) + return( -1 ); + /* Don't allow out of range seeks. */ if( new_pos < 0 || @@ -1140,28 +1133,6 @@ vips_source_seek( VipsSource *source, gint64 offset, int whence ) return( -1 ); } - /* For pipes, we have to fake seek by reading to that point. - */ - if( source->is_pipe ) { - if( vips_source_pipe_read_to_position( source, new_pos ) ) - return( -1 ); - - /* We've hit EOF in the pipe, and we've got the whole thing - * buffered. Steal the header_bytes pointer and turn into a - * memory source. - */ - if( source->length != -1 && - source->header_bytes ) { - source->length = source->header_bytes->len; - source->data = source->header_bytes->data; - source->is_pipe = FALSE; - - /* TODO ... we could close more fds here. - */ - vips_source_minimise( source ); - } - } - source->read_position = new_pos; VIPS_DEBUG_MSG( " new_pos = %" G_GINT64_FORMAT "\n", new_pos );