From 36c25b664e28e4e15ce49242af6ac306eb6f7cca Mon Sep 17 00:00:00 2001 From: Loren Merritt Date: Sat, 18 Mar 2006 09:20:06 +0000 Subject: [PATCH] if --threads > 1, then read the input stream in its own thread. git-svn-id: svn://svn.videolan.org/x264/trunk@473 df754926-b1dd-0310-bc7b-ec298dee348c --- common/common.h | 21 ++++++ configure | 2 +- encoder/encoder.c | 24 +------ muxers.c | 176 +++++++++++++++++++++++++++++++++++++--------- muxers.h | 26 +++++-- x264.c | 29 ++++++-- 6 files changed, 210 insertions(+), 68 deletions(-) diff --git a/common/common.h b/common/common.h index b0ae118f..8ae1b55e 100644 --- a/common/common.h +++ b/common/common.h @@ -37,6 +37,27 @@ #define X264_VERSION "" // no configure script for msvc #endif +/* threads */ +#ifdef __WIN32__ +#include +#define pthread_t HANDLE +#define pthread_create(t,u,f,d) *(t)=CreateThread(NULL,0,f,d,0,NULL) +#define pthread_join(t,s) { WaitForSingleObject(t,INFINITE); \ + CloseHandle(t); } +#define HAVE_PTHREAD 1 + +#elif defined(SYS_BEOS) +#include +#define pthread_t thread_id +#define pthread_create(t,u,f,d) { *(t)=spawn_thread(f,"",10,d); \ + resume_thread(*(t)); } +#define pthread_join(t,s) wait_for_thread(t,(long*)s) +#define HAVE_PTHREAD 1 + +#elif defined(HAVE_PTHREAD) +#include +#endif + /**************************************************************************** * Macros ****************************************************************************/ diff --git a/configure b/configure index 8530c48b..74d445f5 100755 --- a/configure +++ b/configure @@ -281,7 +281,7 @@ if test "$pthread" = "auto" ; then esac fi if test "$pthread" = "yes" ; then - CFLAGS="$CFLAGS -DHAVE_PTHREAD=1" + CFLAGS="$CFLAGS -DHAVE_PTHREAD" case $SYS in MINGW|CYGWIN|BEOS) ;; diff --git a/encoder/encoder.c b/encoder/encoder.c index 6ed7862e..97f6e363 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -25,26 +25,6 @@ #include #include -#ifdef __WIN32__ -#include -#define pthread_t HANDLE -#define pthread_create(t,u,f,d) *(t)=CreateThread(NULL,0,f,d,0,NULL) -#define pthread_join(t,s) { WaitForSingleObject(t,INFINITE); \ - CloseHandle(t); } -#define HAVE_PTHREAD 1 - -#elif defined(SYS_BEOS) -#include -#define pthread_t thread_id -#define pthread_create(t,u,f,d) { *(t)=spawn_thread(f,"",10,d); \ - resume_thread(*(t)); } -#define pthread_join(t,s) wait_for_thread(t,(long*)s) -#define HAVE_PTHREAD 1 - -#elif HAVE_PTHREAD -#include -#endif - #include "common/common.h" #include "common/cpu.h" @@ -350,7 +330,7 @@ static int x264_validate_parameters( x264_t *h ) h->param.i_threads = x264_clip3( h->param.i_threads, 1, X264_SLICE_MAX ); h->param.i_threads = X264_MIN( h->param.i_threads, (h->param.i_height + 15) / 16 ); -#if !(HAVE_PTHREAD) +#ifndef HAVE_PTHREAD if( h->param.i_threads > 1 ) { x264_log( h, X264_LOG_WARNING, "not compiled with pthread support!\n"); @@ -1115,7 +1095,7 @@ static inline int x264_slices_write( x264_t *h ) x264_ratecontrol_threads_start( h ); /* dispatch */ -#if HAVE_PTHREAD +#ifdef HAVE_PTHREAD { pthread_t handles[X264_SLICE_MAX]; void *status; diff --git a/muxers.c b/muxers.c index 0efd67fd..5bfb9245 100644 --- a/muxers.c +++ b/muxers.c @@ -42,59 +42,75 @@ #include #endif +typedef struct { + FILE *fh; + int width, height; + int next_frame; +} yuv_input_t; + /* raw 420 yuv file operation */ int open_file_yuv( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param ) { - if ((*p_handle = fopen(psz_filename, "rb")) == NULL) + yuv_input_t *h = malloc(sizeof(yuv_input_t)); + h->width = p_param->i_width; + h->height = p_param->i_height; + h->fh = fopen(psz_filename, "rb"); + h->next_frame = 0; + *p_handle = (hnd_t)h; + if( h->fh == NULL ) return -1; return 0; } -int get_frame_total_yuv( hnd_t handle, int i_width, int i_height ) +int get_frame_total_yuv( hnd_t handle ) { - FILE *f = (FILE *)handle; + yuv_input_t *h = handle; int i_frame_total = 0; - if( !fseek( f, 0, SEEK_END ) ) + if( !fseek( h->fh, 0, SEEK_END ) ) { - uint64_t i_size = ftell( f ); - fseek( f, 0, SEEK_SET ); - i_frame_total = (int)(i_size / ( i_width * i_height * 3 / 2 )); + uint64_t i_size = ftell( h->fh ); + fseek( h->fh, 0, SEEK_SET ); + i_frame_total = (int)(i_size / ( h->width * h->height * 3 / 2 )); } return i_frame_total; } -int read_frame_yuv( x264_picture_t *p_pic, hnd_t handle, int i_frame, int i_width, int i_height ) +int read_frame_yuv( x264_picture_t *p_pic, hnd_t handle, int i_frame ) { - static int prev_frame = -1; - FILE *f = (FILE *)handle; + yuv_input_t *h = handle; - if( i_frame != prev_frame+1 ) - if( fseek( f, (uint64_t)i_frame * i_width * i_height * 3 / 2, SEEK_SET ) ) + if( i_frame != h->next_frame ) + if( fseek( h->fh, (uint64_t)i_frame * h->width * h->height * 3 / 2, SEEK_SET ) ) return -1; - if( fread( p_pic->img.plane[0], 1, i_width * i_height, f ) <= 0 - || fread( p_pic->img.plane[1], 1, i_width * i_height / 4, f ) <= 0 - || fread( p_pic->img.plane[2], 1, i_width * i_height / 4, f ) <= 0 ) + if( fread( p_pic->img.plane[0], 1, h->width * h->height, h->fh ) <= 0 + || fread( p_pic->img.plane[1], 1, h->width * h->height / 4, h->fh ) <= 0 + || fread( p_pic->img.plane[2], 1, h->width * h->height / 4, h->fh ) <= 0 ) return -1; - prev_frame = i_frame; + h->next_frame = i_frame+1; return 0; } int close_file_yuv(hnd_t handle) { - if (handle == NULL) + yuv_input_t *h = handle; + if( !h || !h->fh ) return 0; - return fclose((FILE *)handle); + return fclose(h->fh); } /* avs/avi input file support under cygwin */ #ifdef AVIS_INPUT +typedef struct { + PAVISTREAM p_avi; + int width, height; +} avis_input_t; int gcd(int a, int b) { @@ -112,22 +128,22 @@ int gcd(int a, int b) int open_file_avis( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param ) { + avis_input_t *h = malloc(sizeof(avis_input_t)); AVISTREAMINFO info; - PAVISTREAM p_avi = NULL; int i; - *p_handle = NULL; + *p_handle = (hnd_t)h; AVIFileInit(); - if( AVIStreamOpenFromFile( &p_avi, psz_filename, streamtypeVIDEO, 0, OF_READ, NULL ) ) + if( AVIStreamOpenFromFile( &h->p_avi, psz_filename, streamtypeVIDEO, 0, OF_READ, NULL ) ) { AVIFileExit(); return -1; } - if( AVIStreamInfo(p_avi, &info, sizeof(AVISTREAMINFO)) ) + if( AVIStreamInfo(h->p_avi, &info, sizeof(AVISTREAMINFO)) ) { - AVIStreamRelease(p_avi); + AVIStreamRelease(h->p_avi); AVIFileExit(); return -1; } @@ -139,13 +155,15 @@ int open_file_avis( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param ) (char)(info.fccHandler & 0xff), (char)((info.fccHandler >> 8) & 0xff), (char)((info.fccHandler >> 16) & 0xff), (char)((info.fccHandler >> 24)) ); - AVIStreamRelease(p_avi); + AVIStreamRelease(h->p_avi); AVIFileExit(); return -1; } + h->width = p_param->i_width = info.rcFrame.right - info.rcFrame.left; + h->height = p_param->i_height = info.rcFrame.bottom - info.rcFrame.top; i = gcd(info.dwRate, info.dwScale); p_param->i_fps_den = info.dwScale / i; @@ -156,29 +174,27 @@ int open_file_avis( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param ) (double)p_param->i_fps_num / (double)p_param->i_fps_den, (int)info.dwLength ); - *p_handle = (hnd_t)p_avi; - return 0; } -int get_frame_total_avis( hnd_t handle, int i_width, int i_height ) +int get_frame_total_avis( hnd_t handle ) { - PAVISTREAM p_avi = (PAVISTREAM)handle; + avis_input_t *h = handle; AVISTREAMINFO info; - if( AVIStreamInfo(p_avi, &info, sizeof(AVISTREAMINFO)) ) + if( AVIStreamInfo(h->p_avi, &info, sizeof(AVISTREAMINFO)) ) return -1; return info.dwLength; } -int read_frame_avis( x264_picture_t *p_pic, hnd_t handle, int i_frame, int i_width, int i_height ) +int read_frame_avis( x264_picture_t *p_pic, hnd_t handle, int i_frame ) { - PAVISTREAM p_avi = (PAVISTREAM)handle; + avis_input_t *h = handle; p_pic->img.i_csp = X264_CSP_YV12; - if( AVIStreamRead(p_avi, i_frame, 1, p_pic->img.plane[0], i_width * i_height * 3 / 2, NULL, NULL ) ) + if( AVIStreamRead(h->p_avi, i_frame, 1, p_pic->img.plane[0], h->width * h->height * 3 / 2, NULL, NULL ) ) return -1; return 0; @@ -186,14 +202,104 @@ int read_frame_avis( x264_picture_t *p_pic, hnd_t handle, int i_frame, int i_wid int close_file_avis( hnd_t handle ) { - PAVISTREAM p_avi = (PAVISTREAM)handle; - - AVIStreamRelease(p_avi); + avis_input_t *h = handle; + AVIStreamRelease(h->p_avi); AVIFileExit(); + free(h); + return 0; +} +#endif + +#ifdef HAVE_PTHREAD +typedef struct { + int (*p_read_frame)( x264_picture_t *p_pic, hnd_t handle, int i_frame ); + int (*p_close_infile)( hnd_t handle ); + hnd_t p_handle; + x264_picture_t pic; + pthread_t tid; + int next_frame; + int frame_total; + struct thread_input_arg_t *next_args; +} thread_input_t; + +typedef struct thread_input_arg_t { + thread_input_t *h; + x264_picture_t *pic; + int i_frame; + int status; +} thread_input_arg_t; + +int open_file_thread( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param ) +{ + thread_input_t *h = malloc(sizeof(thread_input_t)); + x264_picture_alloc( &h->pic, X264_CSP_I420, p_param->i_width, p_param->i_height ); + h->p_read_frame = p_read_frame; + h->p_close_infile = p_close_infile; + h->p_handle = *p_handle; + h->next_frame = -1; + h->next_args = malloc(sizeof(thread_input_arg_t)); + h->next_args->h = h; + h->next_args->status = 0; + h->frame_total = p_get_frame_total( h->p_handle ); + + *p_handle = (hnd_t)h; return 0; } +int get_frame_total_thread( hnd_t handle ) +{ + thread_input_t *h = handle; + return h->frame_total; +} + +void read_frame_thread_int( thread_input_arg_t *i ) +{ + i->status = i->h->p_read_frame( i->pic, i->h->p_handle, i->i_frame ); +} + +int read_frame_thread( x264_picture_t *p_pic, hnd_t handle, int i_frame ) +{ + thread_input_t *h = handle; + UNUSED void *stuff; + int ret = 0; + + if( h->next_frame >= 0 ) + { + pthread_join( h->tid, &stuff ); + ret |= h->next_args->status; + } + + if( h->next_frame == i_frame ) + { + XCHG( x264_picture_t, *p_pic, h->pic ); + } + else + { + ret |= h->p_read_frame( p_pic, h->p_handle, i_frame ); + } + + if( i_frame+1 < h->frame_total ) + { + h->next_frame = + h->next_args->i_frame = i_frame+1; + h->next_args->pic = &h->pic; + pthread_create( &h->tid, NULL, (void*)read_frame_thread_int, h->next_args ); + } + else + h->next_frame = -1; + + return ret; +} + +int close_file_thread( hnd_t handle ) +{ + thread_input_t *h = handle; + h->p_close_infile( h->p_handle ); + x264_picture_clean( &h->pic ); + free( h ); + return 0; +} #endif diff --git a/muxers.h b/muxers.h index 1386ed4d..9762053f 100644 --- a/muxers.h +++ b/muxers.h @@ -4,17 +4,24 @@ typedef void *hnd_t; int open_file_yuv( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param ); -int get_frame_total_yuv( hnd_t handle, int i_width, int i_height ); -int read_frame_yuv( x264_picture_t *p_pic, hnd_t handle, int i_frame, int i_width, int i_height ); +int get_frame_total_yuv( hnd_t handle ); +int read_frame_yuv( x264_picture_t *p_pic, hnd_t handle, int i_frame ); int close_file_yuv( hnd_t handle ); #ifdef AVIS_INPUT int open_file_avis( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param ); -int get_frame_total_avis( hnd_t handle, int i_width, int i_height ); -int read_frame_avis( x264_picture_t *p_pic, hnd_t handle, int i_frame, int i_width, int i_height ); +int get_frame_total_avis( hnd_t handle ); +int read_frame_avis( x264_picture_t *p_pic, hnd_t handle, int i_frame ); int close_file_avis( hnd_t handle ); #endif +#ifdef HAVE_PTHREAD +int open_file_thread( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param ); +int get_frame_total_thread( hnd_t handle ); +int read_frame_thread( x264_picture_t *p_pic, hnd_t handle, int i_frame ); +int close_file_thread( hnd_t handle ); +#endif + int open_file_bsf( char *psz_filename, hnd_t *p_handle ); int set_param_bsf( hnd_t handle, x264_param_t *p_param ); int write_nalu_bsf( hnd_t handle, uint8_t *p_nal, int i_size ); @@ -35,4 +42,15 @@ int write_nalu_mkv( hnd_t handle, uint8_t *p_nal, int i_size ); int set_eop_mkv( hnd_t handle, x264_picture_t *p_picture ); int close_file_mkv( hnd_t handle ); +extern int (*p_open_infile)( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param ); +extern int (*p_get_frame_total)( hnd_t handle ); +extern int (*p_read_frame)( x264_picture_t *p_pic, hnd_t handle, int i_frame ); +extern int (*p_close_infile)( hnd_t handle ); + +extern int (*p_open_outfile)( char *psz_filename, hnd_t *p_handle ); +extern int (*p_set_outfile_param)( hnd_t handle, x264_param_t *p_param ); +extern int (*p_write_nalu)( hnd_t handle, uint8_t *p_nal, int i_size ); +extern int (*p_set_eop)( hnd_t handle, x264_picture_t *p_picture ); +extern int (*p_close_outfile)( hnd_t handle ); + #endif diff --git a/x264.c b/x264.c index 81ff0943..e685657a 100644 --- a/x264.c +++ b/x264.c @@ -68,10 +68,10 @@ typedef struct { } cli_opt_t; /* input file operation function pointers */ -static int (*p_open_infile)( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param ); -static int (*p_get_frame_total)( hnd_t handle, int i_width, int i_height ); -static int (*p_read_frame)( x264_picture_t *p_pic, hnd_t handle, int i_frame, int i_width, int i_height ); -static int (*p_close_infile)( hnd_t handle ); +int (*p_open_infile)( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param ); +int (*p_get_frame_total)( hnd_t handle ); +int (*p_read_frame)( x264_picture_t *p_pic, hnd_t handle, int i_frame ); +int (*p_close_infile)( hnd_t handle ); /* output file operation function pointers */ static int (*p_open_outfile)( char *psz_filename, hnd_t *p_handle ); @@ -975,6 +975,23 @@ static int Parse( int argc, char **argv, } } +#ifdef HAVE_PTHREAD + if( param->i_threads > 1 ) + { + if( open_file_thread( NULL, &opt->hin, param ) ) + { + fprintf( stderr, "threaded input failed\n" ); + } + else + { + p_open_infile = open_file_thread; + p_get_frame_total = get_frame_total_thread; + p_read_frame = read_frame_thread; + p_close_infile = close_file_thread; + } + } +#endif + return 0; } @@ -1035,7 +1052,7 @@ static int Encode( x264_param_t *param, cli_opt_t *opt ) int i_frame_size; int i_progress; - i_frame_total = p_get_frame_total( opt->hin, param->i_width, param->i_height ); + i_frame_total = p_get_frame_total( opt->hin ); i_frame_total -= opt->i_seek; if( ( i_frame_total == 0 || param->i_frame_total < i_frame_total ) && param->i_frame_total > 0 ) @@ -1067,7 +1084,7 @@ static int Encode( x264_param_t *param, cli_opt_t *opt ) for( i_frame = 0, i_file = 0, i_progress = 0; b_ctrl_c == 0 && (i_frame < i_frame_total || i_frame_total == 0); ) { - if( p_read_frame( &pic, opt->hin, i_frame + opt->i_seek, param->i_width, param->i_height ) ) + if( p_read_frame( &pic, opt->hin, i_frame + opt->i_seek ) ) break; pic.i_pts = (int64_t)i_frame * param->i_fps_den; -- 2.39.2