add plumbing for stream minimise

and ::finish becomes a vfunc
This commit is contained in:
John Cupitt 2019-10-13 20:59:02 +01:00
parent a8fd5602ea
commit 6f0002c023
4 changed files with 90 additions and 39 deletions

View File

@ -71,6 +71,11 @@ typedef enum {
char *vips_path_filename7( const char *path );
char *vips_path_mode7( const char *path );
struct _VipsImage;
typedef struct _VipsImage VipsImage;
struct _VipsRegion;
typedef struct _VipsRegion VipsRegion;
#ifdef __cplusplus
}
#endif /*__cplusplus*/

View File

@ -133,9 +133,6 @@ typedef enum {
VIPS_ACCESS_LAST
} VipsAccess;
struct _VipsImage;
struct _VipsRegion;
typedef void *(*VipsStartFn)( struct _VipsImage *out, void *a, void *b );
typedef int (*VipsGenerateFn)( struct _VipsRegion *out,
void *seq, void *a, void *b, gboolean *stop );

View File

@ -68,7 +68,7 @@ typedef struct _VipsStream {
*/
int tracked_descriptor;
/* A descriptor we close close().
/* A descriptor we close with close().
*/
int close_descriptor;
@ -86,8 +86,6 @@ typedef struct _VipsStreamClass {
GType vips_stream_get_type( void );
void vips_stream_attach( VipsStream *stream );
#define VIPS_TYPE_STREAM_INPUT (vips_stream_input_get_type())
#define VIPS_STREAM_INPUT( obj ) \
(G_TYPE_CHECK_INSTANCE_CAST( (obj), \
@ -162,6 +160,15 @@ typedef struct _VipsStreamInputClass {
ssize_t (*read)( VipsStreamInput *, unsigned char *, size_t );
int (*rewind)( VipsStreamInput * );
/* Shut down anything that can safely restarted. For example, if
* there's a fd that supports lseek(), it can be closed, since later
* (if neccessary) it can be reopened and lseek()ed back to the
* correct point.
*
* Non-restartable shutdown shuld be in _finalize().
*/
void (*minimise)( VipsStreamInput * );
} VipsStreamInputClass;
GType vips_stream_input_get_type( void );
@ -176,6 +183,8 @@ VipsStreamInput *vips_stream_input_new_from_options( const char *options );
ssize_t vips_stream_input_read( VipsStreamInput *input,
unsigned char *data, size_t length );
int vips_stream_input_rewind( VipsStreamInput *input );
void vips_stream_minimise( VipsStreamInput *input );
void vips_stream_set_image( VipsStreamInput *input, VipsImage *image );
void vips_stream_input_decode( VipsStreamInput *input );
gboolean vips_stream_input_eof( VipsStreamInput *input );
unsigned char *vips_stream_input_sniff( VipsStreamInput *input, size_t length );
@ -219,6 +228,11 @@ typedef struct _VipsStreamOutputClass {
*/
ssize_t (*write)( VipsStreamOutput *, const unsigned char *, size_t );
/* A complete output image has been generated, so do any clearing up,
* eg. copy the bytes we saved in memory to the output blob.
*/
void (*finish)( VipsStreamOutput * );
} VipsStreamOutputClass;
GType vips_stream_output_get_type( void );
@ -226,7 +240,7 @@ GType vips_stream_output_get_type( void );
VipsStreamOutput *vips_stream_output_new_from_descriptor( int descriptor );
VipsStreamOutput *vips_stream_output_new_from_filename( const char *filename );
VipsStreamOutput *vips_stream_output_new_memory( void );
int vips_stream_output_write( VipsStreamOutput *stream,
int vips_stream_output_write( VipsStreamOutput *output,
const unsigned char *data, size_t length );
void vips_stream_output_finish( VipsStreamOutput *output );

View File

@ -65,6 +65,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <vips/vips.h>
#include <vips/debug.h>
@ -114,19 +115,10 @@
G_DEFINE_ABSTRACT_TYPE( VipsStream, vips_stream, VIPS_TYPE_OBJECT );
static void
vips_stream_close( VipsStream *stream )
{
if( stream->close_descriptor >= 0 ) {
close( stream->close_descriptor );
stream->close_descriptor = -1;
}
if( stream->tracked_descriptor >= 0 ) {
vips_tracked_close( stream->tracked_descriptor );
stream->tracked_descriptor = -1;
}
}
#define STREAM_NAME( STREAM ) \
(VIPS_STREAM( STREAM )->filename ? \
VIPS_STREAM( STREAM )->filename : \
VIPS_OBJECT( STREAM )->nickname)
static void
vips_stream_finalize( GObject *gobject )
@ -139,7 +131,16 @@ vips_stream_finalize( GObject *gobject )
VIPS_DEBUG_MSG( "\n" );
#endif /*VIPS_DEBUG*/
vips_stream_close( stream );
if( stream->close_descriptor >= 0 ) {
close( stream->close_descriptor );
stream->close_descriptor = -1;
}
if( stream->tracked_descriptor >= 0 ) {
vips_tracked_close( stream->tracked_descriptor );
stream->tracked_descriptor = -1;
}
VIPS_FREE( stream->filename );
G_OBJECT_CLASS( vips_stream_parent_class )->finalize( gobject );
@ -178,11 +179,6 @@ vips_stream_init( VipsStream *stream )
stream->close_descriptor = -1;
}
#define STREAM_NAME( STREAM ) \
(VIPS_STREAM( STREAM )->filename ? \
VIPS_STREAM( STREAM )->filename : \
VIPS_OBJECT( STREAM )->nickname)
G_DEFINE_TYPE( VipsStreamInput, vips_stream_input, VIPS_TYPE_STREAM );
static void
@ -313,6 +309,12 @@ vips_stream_input_rewind_real( VipsStreamInput *input )
return( 0 );
}
static void
vips_stream_input_minimise_real( VipsStreamInput *input )
{
VIPS_DEBUG_MSG( "vips_stream_minimise_real:\n" );
}
static void
vips_stream_input_class_init( VipsStreamInputClass *class )
{
@ -330,6 +332,7 @@ vips_stream_input_class_init( VipsStreamInputClass *class )
class->read = vips_stream_input_read_real;
class->rewind = vips_stream_input_rewind_real;
class->minimise = vips_stream_input_minimise_real;
VIPS_ARG_BOXED( class, "blob", 3,
_( "Blob" ),
@ -572,6 +575,14 @@ vips_stream_input_rewind( VipsStreamInput *input )
return( class->rewind( input ) );
}
void
vips_stream_input_minimise( VipsStreamInput *input )
{
VipsStreamInputClass *class = VIPS_STREAM_INPUT_GET_CLASS( input );
class->minimise( input );
}
gboolean
vips_stream_input_eof( VipsStreamInput *input )
{
@ -592,6 +603,19 @@ vips_stream_input_decode( VipsStreamInput *input )
}
}
static void
vips_stream_input_minimise_cb( VipsImage *image, VipsStreamInput *input )
{
vips_stream_input_minimise( input );
}
void
vips_stream_input_set_image( VipsStreamInput *input, VipsImage *image )
{
g_signal_connect( image, "minimise",
G_CALLBACK( vips_stream_input_minimise_cb ), input );
}
/**
* vips_stream_input_sniff:
* @bytes: number of bytes to sniff
@ -704,6 +728,25 @@ vips_stream_output_write_real( VipsStreamOutput *output,
return( len );
}
static void
vips_stream_output_finish_real( VipsStreamOutput *output )
{
VIPS_DEBUG_MSG( "vips_stream_output_finish_real:\n" );
/* Move the output buffer into the blob so it can be read out.
*/
if( output->memory ) {
unsigned char *data;
size_t length;
length = output->memory->len;
data = g_byte_array_free( output->memory, FALSE );
output->memory = NULL;
vips_blob_set( output->blob,
(VipsCallbackFn) g_free, data, length );
}
}
static void
vips_stream_output_class_init( VipsStreamOutputClass *class )
{
@ -720,6 +763,7 @@ vips_stream_output_class_init( VipsStreamOutputClass *class )
object_class->build = vips_stream_output_build;
class->write = vips_stream_output_write_real;
class->finish = vips_stream_output_finish_real;
/* SET_ALWAYS means that blob is set by C and the obj system is not
* involved in creation or destruction. It can be read at any time.
@ -866,20 +910,11 @@ vips_stream_output_write( VipsStreamOutput *output,
}
void
vips_stream_output_finish( VipsStreamOutput *output )
vips_stream_output_finish( VipsStreamOutput *output )
{
VipsStreamOutputClass *class = VIPS_STREAM_OUTPUT_GET_CLASS( output );
VIPS_DEBUG_MSG( "vips_stream_output_finish:\n" );
if( output->memory ) {
unsigned char *data;
size_t length;
length = output->memory->len;
data = g_byte_array_free( output->memory, FALSE );
output->memory = NULL;
vips_blob_set( output->blob,
(VipsCallbackFn) g_free, data, length );
}
vips_stream_close( VIPS_STREAM( output ) );
class->finish( output );
}