diff options
-rw-r--r-- | libhb/common.h | 2 | ||||
-rw-r--r-- | libhb/decsub.c | 8 | ||||
-rw-r--r-- | libhb/denoise.c | 5 | ||||
-rw-r--r-- | libhb/fifo.c | 278 | ||||
-rw-r--r-- | libhb/hb.c | 10 | ||||
-rw-r--r-- | libhb/internal.h | 3 | ||||
-rw-r--r-- | libhb/reader.c | 28 | ||||
-rw-r--r-- | libhb/render.c | 10 | ||||
-rwxr-xr-x | libhb/stream.c | 2 | ||||
-rw-r--r-- | libhb/work.c | 37 | ||||
-rw-r--r-- | macosx/Controller.mm | 7 | ||||
-rw-r--r-- | test/test.c | 8 |
12 files changed, 336 insertions, 62 deletions
diff --git a/libhb/common.h b/libhb/common.h index f32c620ab..e71959142 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -258,7 +258,7 @@ struct hb_job_s int largeFileSize; - int subtitle_scan; + int indepth_scan; hb_subtitle_t ** select_subtitle; int subtitle_force; char * native_language; diff --git a/libhb/decsub.c b/libhb/decsub.c index eb3b35a34..2b76ecf29 100644 --- a/libhb/decsub.c +++ b/libhb/decsub.c @@ -177,7 +177,7 @@ static void ParseControls( hb_work_object_t * w ) /* * If we are doing a subtitle scan then note down */ - if( job->subtitle_scan ) + if( job->indepth_scan ) { for( n=0; n < hb_list_count(title->list_subtitle); n++ ) { @@ -198,8 +198,8 @@ static void ParseControls( hb_work_object_t * w ) break; case 0x02: // 0x02 - STP_DSP - Stop Display, no arguments - if(!pv->pts_stop) - pv->pts_stop = pv->pts + date * 900; + if(!pv->pts_stop) + pv->pts_stop = pv->pts + date * 900; break; case 0x03: // 0x03 - SET_COLOR - Set Colour indices @@ -463,7 +463,7 @@ static hb_buffer_t * Decode( hb_work_object_t * w ) /* Get infos about the subtitle */ ParseControls( w ); - if( job->subtitle_scan || ( job->subtitle_force && pv->pts_forced == 0 ) ) + if( job->indepth_scan || ( job->subtitle_force && pv->pts_forced == 0 ) ) { /* * Don't encode subtitles when doing a scan. diff --git a/libhb/denoise.c b/libhb/denoise.c index 5022d4721..70902a6ec 100644 --- a/libhb/denoise.c +++ b/libhb/denoise.c @@ -304,6 +304,11 @@ hb_filter_private_t * hb_denoise_init( int pix_fmt, } hb_filter_private_t * pv = malloc( sizeof(struct hb_filter_private_s) ); + + /* + * Clear the memory to avoid freeing uninitialised memory later. + */ + memset( pv, 0, sizeof( struct hb_filter_private_s ) ); pv->pix_fmt = pix_fmt; pv->width[0] = width; diff --git a/libhb/fifo.c b/libhb/fifo.c index 44c64d9b0..a36bb7774 100644 --- a/libhb/fifo.c +++ b/libhb/fifo.c @@ -10,27 +10,181 @@ #include <malloc.h> #endif -hb_buffer_t * hb_buffer_init( int size ) +/* Fifo */ +struct hb_fifo_s { - hb_buffer_t * b; + hb_lock_t * lock; + int capacity; + int size; + int buffer_size; + hb_buffer_t * first; + hb_buffer_t * last; +}; + +#define MAX_BUFFER_POOLS 15 +#define BUFFER_POOL_MAX_ELEMENTS 2048 + +struct hb_buffer_pools_s +{ + int entries; + int allocated; + hb_fifo_t *pool[MAX_BUFFER_POOLS]; + hb_lock_t *lock; +}; + +struct hb_buffer_pools_s buffers; + +void hb_buffer_pool_init( void ) +{ + hb_fifo_t *buffer_pool; + int size = 512; + int max_size = 32768;; + + buffers.entries = 0; + buffers.lock = hb_lock_init(); + buffers.allocated = 0; + while(size <= max_size) { + buffer_pool = buffers.pool[buffers.entries++] = hb_fifo_init(BUFFER_POOL_MAX_ELEMENTS); + buffer_pool->buffer_size = size; + size *= 2; + } +} + +void hb_buffer_pool_free( void ) +{ + int i; + int count; + int freed = 0; + hb_buffer_t *b; + + hb_lock(buffers.lock); + + for( i = 0; i < buffers.entries; i++) + { + count = 0; + while( ( b = hb_fifo_get(buffers.pool[i]) ) ) + { + freed += b->alloc; + if( b->data ) + { + free( b->data ); + b->data = NULL; + } + free( b ); + count++; + } + hb_log("Freed %d buffers of size %d", count, buffers.pool[i]->buffer_size); + } + + hb_log("Allocated %d bytes of buffers on this pass and Freed %d bytes, %d bytes leaked", + buffers.allocated, freed, buffers.allocated - freed); + buffers.allocated = 0; + hb_unlock(buffers.lock); +} + + +hb_buffer_t * hb_buffer_init( int size ) +{ + hb_buffer_t * b; + int i; + hb_fifo_t *buffer_pool = NULL; + uint8_t *data; + int b_alloc; + int resize = 0; + + /* + * The buffer pools are allocated in increasing size + */ + for( i = 0; i < buffers.entries; i++ ) + { + if( buffers.pool[i]->buffer_size >= size ) + { + /* + * This pool is big enough, but are there any buffers in it? + */ + if( hb_fifo_size( buffers.pool[i] ) ) + { + /* + * We've found a matching buffer pool, with buffers. + */ + buffer_pool = buffers.pool[i]; + resize = buffers.pool[i]->buffer_size; + } else { + /* + * Buffer pool is empty, + */ + if( resize ) { + /* + * This is the second time through, so break out of here to avoid + * using too large a buffer for a small job. + */ + break; + } + resize = buffers.pool[i]->buffer_size; + } + } + } + + /* + * Don't reuse the 0 size buffers, not much gain. + */ + if( size != 0 && buffer_pool ) + { + b = hb_fifo_get( buffer_pool ); + + if( b ) + { + /* + * Zero the contents of the buffer, would be nice if we + * didn't have to do this. + * + hb_log("Reused buffer size %d for size %d from pool %d depth %d", + b->alloc, size, smallest_pool->buffer_size, + hb_fifo_size(smallest_pool)); + */ + data = b->data; + b_alloc = b->alloc; + memset( b, 0, sizeof(hb_buffer_t) ); + b->alloc = b_alloc; + b->size = size; + b->data = data; + return( b ); + } + } + + /* + * No existing buffers, create a new one + */ if( !( b = calloc( sizeof( hb_buffer_t ), 1 ) ) ) { hb_log( "out of memory" ); return NULL; } - b->alloc = size; b->size = size; + + if( resize ) + { + size = resize; + } + b->alloc = size; + + /* + hb_log("Allocating new buffer of size %d for size %d", + b->alloc, + b->size); + */ + if (!size) return b; #if defined( SYS_DARWIN ) || defined( SYS_FREEBSD ) - b->data = malloc( size ); + b->data = malloc( b->alloc ); #elif defined( SYS_CYGWIN ) /* FIXME */ - b->data = malloc( size + 17 ); + b->data = malloc( b->alloc + 17 ); #else - b->data = memalign( 16, size ); + b->data = memalign( 16, b->alloc ); #endif if( !b->data ) @@ -39,27 +193,122 @@ hb_buffer_t * hb_buffer_init( int size ) free( b ); return NULL; } + + buffers.allocated += b->alloc; + return b; } void hb_buffer_realloc( hb_buffer_t * b, int size ) { /* No more alignment, but we don't care */ + if( size < 2048 ) { + size = 2048; + } b->data = realloc( b->data, size ); + buffers.allocated -= b->alloc; b->alloc = size; + buffers.allocated += b->alloc; } void hb_buffer_close( hb_buffer_t ** _b ) { hb_buffer_t * b = *_b; + hb_fifo_t *buffer_pool = NULL; + int i; + + /* + * Put the buffer into our free list in the matching buffer pool, if there is one. + */ + if( b->alloc != 0 ) + { + for( i = 0; i < buffers.entries; i++ ) + { + if( b->alloc == buffers.pool[i]->buffer_size ) + { + buffer_pool = buffers.pool[i]; + break; + } + } + } - if( b->data ) + if( buffer_pool ) { - free( b->data ); + if( !hb_fifo_is_full( buffer_pool ) ) + { + if(b->data) + { + /* + hb_log("Putting a buffer of size %d on pool %d, depth %d", + b->alloc, + buffer_pool->buffer_size, + hb_fifo_size(buffer_pool)); + */ + hb_fifo_push( buffer_pool, b ); + } else { + free(b); + } + } else { + /* + * Got a load of these size ones already, free this buffer. + * + hb_log("Buffer pool for size %d full, freeing buffer", b->alloc); + */ + if( b->data ) + { + free( b->data ); + } + buffers.allocated -= b->alloc; + free( b ); + } + } else { + /* + * Need a new buffer pool for this size. + */ + hb_lock(buffers.lock); + if ( b->alloc != 0 && buffers.entries < MAX_BUFFER_POOLS) + { + buffer_pool = buffers.pool[buffers.entries++] = hb_fifo_init(BUFFER_POOL_MAX_ELEMENTS); + buffer_pool->buffer_size = b->alloc; + hb_fifo_push( buffer_pool, b ); + /* + hb_log("*** Allocated a new buffer pool for size %d [%d]", b->alloc, + buffers.entries ); + */ + } else { + if( b->alloc != 0 ) + { + for( i = buffers.entries-1; i >= 0; i-- ) + { + if( hb_fifo_size(buffers.pool[i]) == 0 ) + { + /* + * Reuse this pool as it is empty. + */ + buffers.pool[i]->buffer_size = b->alloc; + hb_fifo_push( buffers.pool[i], b ); + b = NULL; + break; + } + } + } + + if( b ) + { + if( b->data ) + { + free( b->data ); + b->data = NULL; + buffers.allocated -= b->alloc; + } + free( b ); + } + } + hb_unlock(buffers.lock); } - free( b ); *_b = NULL; + } void hb_buffer_copy_settings( hb_buffer_t * dst, const hb_buffer_t * src ) @@ -71,22 +320,13 @@ void hb_buffer_copy_settings( hb_buffer_t * dst, const hb_buffer_t * src ) dst->flags = src->flags; } -/* Fifo */ -struct hb_fifo_s -{ - hb_lock_t * lock; - int capacity; - int size; - hb_buffer_t * first; - hb_buffer_t * last; -}; - hb_fifo_t * hb_fifo_init( int capacity ) { hb_fifo_t * f; f = calloc( sizeof( hb_fifo_t ), 1 ); f->lock = hb_lock_init(); f->capacity = capacity; + f->buffer_size = 0; return f; } diff --git a/libhb/hb.c b/libhb/hb.c index fbcd81043..7a15a1181 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -104,6 +104,11 @@ hb_handle_t * hb_init_real( int verbose, int update_check ) } } + /* + * Initialise buffer pool + */ + hb_buffer_pool_init(); + /* CPU count detection */ hb_log( "hb_init: checking cpu count" ); h->cpu_count = hb_get_cpu_count(); @@ -607,7 +612,7 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) */ memset( audio_lang, 0, sizeof( audio_lang ) ); - if ( job->subtitle_scan || job->native_language ) { + if ( job->indepth_scan || job->native_language ) { /* * Find the first audio language that is being encoded @@ -659,7 +664,7 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) * If doing a subtitle scan then add all the matching subtitles for this * language. */ - if ( job->subtitle_scan ) + if ( job->indepth_scan ) { for( i=0; i < hb_list_count( title->list_subtitle ); i++ ) { @@ -926,6 +931,7 @@ void hb_close( hb_handle_t ** _h ) hb_lock_close( &h->pause_lock ); free( h ); *_h = NULL; + } /** diff --git a/libhb/internal.h b/libhb/internal.h index 0b460593c..d3bbb637d 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -64,6 +64,9 @@ struct hb_buffer_s hb_buffer_t * next; }; +void hb_buffer_pool_init( void ); +void hb_buffer_pool_free( void ); + hb_buffer_t * hb_buffer_init( int size ); void hb_buffer_realloc( hb_buffer_t *, int size ); void hb_buffer_close( hb_buffer_t ** ); diff --git a/libhb/reader.c b/libhb/reader.c index 506774557..2fd39eb63 100644 --- a/libhb/reader.c +++ b/libhb/reader.c @@ -118,7 +118,7 @@ static void ReaderFunc( void * _r ) } } - if( r->job->subtitle_scan ) + if( r->job->indepth_scan ) { /* * Need to update the progress during a subtitle scan @@ -139,7 +139,7 @@ static void ReaderFunc( void * _r ) p.seconds = -1; hb_set_state( r->job->h, &state ); } - + hb_demux_ps( r->ps, list ); while( ( buf = hb_list_item( list, 0 ) ) ) @@ -194,18 +194,21 @@ static hb_fifo_t * GetFifoForId( hb_job_t * job, int id ) if( id == 0xE0 ) { - if( !job->subtitle_scan ) + if( job->indepth_scan ) { - return job->fifo_mpeg2; - } else { /* - * Ditch the mpeg2 video when doing a subtitle scan. + * Ditch the video here during the indepth scan until + * we can improve the MPEG2 decode performance. */ return NULL; + } + else + { + return job->fifo_mpeg2; } } - if (job->subtitle_scan) { + if( job->indepth_scan ) { /* * Count the occurances of the subtitles, don't actually * return any to encode unless we are looking fro forced @@ -233,12 +236,15 @@ static hb_fifo_t * GetFifoForId( hb_job_t * job, int id ) return subtitle->fifo_in; } } - for( i = 0; i < hb_list_count( title->list_audio ); i++ ) + if( !job->indepth_scan ) { - audio = hb_list_item( title->list_audio, i ); - if( id == audio->id ) + for( i = 0; i < hb_list_count( title->list_audio ); i++ ) { - return audio->fifo_in; + audio = hb_list_item( title->list_audio, i ); + if( id == audio->id ) + { + return audio->fifo_in; + } } } diff --git a/libhb/render.c b/libhb/render.c index 5577c2f76..05dcdbbf9 100644 --- a/libhb/render.c +++ b/libhb/render.c @@ -160,6 +160,16 @@ int renderWork( hb_work_object_t * w, hb_buffer_t ** buf_in, *buf_out = hb_buffer_init(0); return HB_WORK_OK; } + + /* + * During the indepth_scan ditch the buffers here before applying filters or attempting to + * use the subtitles. + */ + if( job->indepth_scan ) + { + *buf_out = NULL; + return HB_WORK_OK; + } /* Push subtitles onto queue just in case we need to delay a frame */ if( in->sub ) diff --git a/libhb/stream.c b/libhb/stream.c index ab8963c41..b168308bd 100755 --- a/libhb/stream.c +++ b/libhb/stream.c @@ -676,7 +676,7 @@ static void hb_stream_put_back(hb_stream_t *stream, int i) stream->ps_decode_buffer[read_buffer_index].read_pos -= i; } else - fprintf(stderr, "hb_stream_put_back - trying to step beyond the start of the buffer, read_pos = %d amt to put back = %d\n", stream->ps_decode_buffer[read_buffer_index].read_pos, i); + hb_error("hb_stream_put_back - trying to step beyond the start of the buffer, read_pos = %d amt to put back = %d\n", stream->ps_decode_buffer[read_buffer_index].read_pos, i); } } diff --git a/libhb/work.c b/libhb/work.c index e73bf1693..5b3f914c2 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -22,6 +22,8 @@ static void work_func(); static void do_job( hb_job_t *, int cpu_count ); static void work_loop( void * ); +#define FIFO_SIZE 32 + /** * Allocates work object and launches work thread with work_func. * @param jobs Handle to hb_list_t. @@ -174,10 +176,10 @@ static void do_job( hb_job_t * job, int cpu_count ) } hb_log (" + PixelRatio: %d, width:%d, height: %d",job->pixel_ratio,job->width, job->height); job->fifo_mpeg2 = hb_fifo_init( 2048 ); - job->fifo_raw = hb_fifo_init( 8 ); - job->fifo_sync = hb_fifo_init( 8 ); - job->fifo_render = hb_fifo_init( 8 ); - job->fifo_mpeg4 = hb_fifo_init( 8 ); + job->fifo_raw = hb_fifo_init( FIFO_SIZE ); + job->fifo_sync = hb_fifo_init( FIFO_SIZE ); + job->fifo_render = hb_fifo_init( FIFO_SIZE ); + job->fifo_mpeg4 = hb_fifo_init( FIFO_SIZE ); /* Synchronization */ hb_list_add( job->list_work, ( w = getWork( WORK_SYNC ) ) ); @@ -216,7 +218,7 @@ static void do_job( hb_job_t * job, int cpu_count ) hb_list_add( job->list_work, w ); - if( job->select_subtitle && !job->subtitle_scan ) + if( job->select_subtitle && !job->indepth_scan ) { /* * Must be second pass of a two pass with subtitle scan enabled, so @@ -237,8 +239,8 @@ static void do_job( hb_job_t * job, int cpu_count ) { hb_log( " + subtitle %x, %s", subtitle->id, subtitle->lang ); - subtitle->fifo_in = hb_fifo_init( 8 ); - subtitle->fifo_raw = hb_fifo_init( 8 ); + subtitle->fifo_in = hb_fifo_init( FIFO_SIZE ); + subtitle->fifo_raw = hb_fifo_init( FIFO_SIZE ); /* * Disable forced subtitles if we didn't find any in the scan @@ -246,7 +248,7 @@ static void do_job( hb_job_t * job, int cpu_count ) * * select_subtitle implies that we did a scan. */ - if( !job->subtitle_scan && job->subtitle_force && + if( !job->indepth_scan && job->subtitle_force && job->select_subtitle ) { if( subtitle->forced_hits == 0 ) @@ -255,7 +257,7 @@ static void do_job( hb_job_t * job, int cpu_count ) } } - if (!job->subtitle_scan || job->subtitle_force) { + if (!job->indepth_scan || job->subtitle_force) { /* * Don't add threads for subtitles when we are scanning, unless * looking for forced subtitles. @@ -437,9 +439,9 @@ static void do_job( hb_job_t * job, int cpu_count ) /* set up the audio work structures */ audio->fifo_in = hb_fifo_init( 2048 ); - audio->fifo_raw = hb_fifo_init( 8 ); - audio->fifo_sync = hb_fifo_init( 8 ); - audio->fifo_out = hb_fifo_init( 8 ); + audio->fifo_raw = hb_fifo_init( FIFO_SIZE ); + audio->fifo_sync = hb_fifo_init( FIFO_SIZE ); + audio->fifo_out = hb_fifo_init( FIFO_SIZE ); switch( audio->codec ) { @@ -512,7 +514,7 @@ static void do_job( hb_job_t * job, int cpu_count ) { w = hb_list_item( job->list_work, i ); w->done = &job->done; - w->thread_sleep_interval = 10; + w->thread_sleep_interval = 10; w->init( w, job ); w->thread = hb_thread_init( w->name, work_loop, w, HB_LOW_PRIORITY ); @@ -520,7 +522,7 @@ static void do_job( hb_job_t * job, int cpu_count ) done = 0; w = hb_list_item( job->list_work, 0 ); - w->thread_sleep_interval = 50; + w->thread_sleep_interval = 50; w->init( w, job ); while( !*job->die ) { @@ -573,6 +575,9 @@ static void do_job( hb_job_t * job, int cpu_count ) hb_fifo_close( &job->fifo_sync ); hb_fifo_close( &job->fifo_render ); hb_fifo_close( &job->fifo_mpeg4 ); + + hb_buffer_pool_free(); + for (i=0; i < hb_list_count(title->list_subtitle); i++) { subtitle = hb_list_item( title->list_subtitle, i); if( subtitle ) @@ -590,7 +595,7 @@ static void do_job( hb_job_t * job, int cpu_count ) hb_fifo_close( &audio->fifo_out ); } - if( job->subtitle_scan ) + if( job->indepth_scan ) { /* * Before closing the title print out our subtitle stats if we need to @@ -661,7 +666,7 @@ static void do_job( hb_job_t * job, int cpu_count ) if( job->select_subtitle ) { - if( job->subtitle_scan ) + if( job->indepth_scan ) { for( i=0; i < hb_list_count( title->list_subtitle ); i++ ) { diff --git a/macosx/Controller.mm b/macosx/Controller.mm index b2fb41fe6..297eaf7e2 100644 --- a/macosx/Controller.mm +++ b/macosx/Controller.mm @@ -1590,7 +1590,7 @@ static int hb_group_count(hb_handle_t * h) job->x264opts = NULL; - job->subtitle_scan = 1; + job->indepth_scan = 1; job->select_subtitle = (hb_subtitle_t**)malloc(sizeof(hb_subtitle_t*)); *(job->select_subtitle) = NULL; @@ -1617,8 +1617,7 @@ static int hb_group_count(hb_handle_t * h) if( [fVidTwoPassCheck state] == NSOnState ) { hb_subtitle_t **subtitle_tmp = job->select_subtitle; - job->select_subtitle = NULL; - job->subtitle_scan = 0; + job->indepth_scan = 0; job->pass = 1; job->sequence_id++; // for job grouping @@ -1636,7 +1635,7 @@ static int hb_group_count(hb_handle_t * h) } else { - job->subtitle_scan = 0; + job->indepth_scan = 0; job->pass = 0; job->sequence_id++; // for job grouping hb_add( fHandle, job ); diff --git a/test/test.c b/test/test.c index cddcadf8e..a5ddddf25 100644 --- a/test/test.c +++ b/test/test.c @@ -632,7 +632,7 @@ static int HandleEvents( hb_handle_t * h ) job->x264opts = NULL; - job->subtitle_scan = subtitle_scan; + job->indepth_scan = subtitle_scan; fprintf( stderr, "Subtitle Scan Enabled - enabling " "subtitles if found for foreign language segments\n"); job->select_subtitle = malloc(sizeof(hb_subtitle_t*)); @@ -659,7 +659,7 @@ static int HandleEvents( hb_handle_t * h ) job->pass = 1; - job->subtitle_scan = 0; + job->indepth_scan = 0; /* * If turbo options have been selected then append them @@ -702,7 +702,7 @@ static int HandleEvents( hb_handle_t * h ) * selected in the first pass (using the whacky select-subtitle * attribute of the job). */ - job->subtitle_scan = 0; + job->indepth_scan = 0; job->x264opts = x264opts2; @@ -715,7 +715,7 @@ static int HandleEvents( hb_handle_t * h ) * precludes encoding of any actual subtitles. */ - job->subtitle_scan = 0; + job->indepth_scan = 0; job->pass = 0; hb_add( h, job ); } |