int x264_threadpool_init( x264_threadpool_t **p_pool, int threads, void (*init_func)(void *), void *init_arg ) { if( threads <= 0 ) return -1; x264_threadpool_t *pool; CHECKED_MALLOCZERO( pool, sizeof(x264_threadpool_t) ); *p_pool = pool; pool->init_func = init_func; pool->init_arg = init_arg; pool->threads = threads; CHECKED_MALLOC( pool->thread_handle, pool->threads * sizeof(x264_pthread_t) ); if( x264_sync_frame_list_init( &pool->uninit, pool->threads ) || x264_sync_frame_list_init( &pool->run, pool->threads ) || x264_sync_frame_list_init( &pool->done, pool->threads ) ) goto fail; for( int i = 0; i < pool->threads; i++ ) { x264_threadpool_job_t *job; CHECKED_MALLOC( job, sizeof(x264_threadpool_job_t) ); x264_sync_frame_list_push( &pool->uninit, (void*)job ); } for( int i = 0; i < pool->threads; i++ ) if( x264_pthread_create( pool->thread_handle+i, NULL, (void*)x264_threadpool_thread, pool ) ) goto fail; return 0; fail: return -1; }
int x264_sei_version_write( x264_t *h, bs_t *s ) { // random ID number generated according to ISO-11578 static const uint8_t uuid[16] = { 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee, 0xef }; char *opts = x264_param2string( &h->param, 0 ); char *payload; int length; if( !opts ) return -1; CHECKED_MALLOC( payload, 200 + strlen( opts ) ); memcpy( payload, uuid, 16 ); sprintf( payload+16, "x264 - core %d%s - H.264/MPEG-4 AVC codec - " "Copy%s 2003-2011 - http://www.videolan.org/x264.html - options: %s", X264_BUILD, X264_VERSION, HAVE_GPL?"left":"right", opts ); length = strlen(payload)+1; x264_sei_write( s, (uint8_t *)payload, length, SEI_USER_DATA_UNREGISTERED ); x264_free( opts ); x264_free( payload ); return 0; fail: x264_free( opts ); return -1; }
int x264_visualize_init( x264_t *h ) { CHECKED_MALLOC( h->visualize, h->mb.i_mb_width * h->mb.i_mb_height * sizeof(visualize_t) ); return 0; fail: return -1; }
/* {{{ [fold] void x264_visualize_init( x264_t *h ) */ int x264_visualize_init( x264_t *h ) { int mb = h->sps->i_mb_width * h->sps->i_mb_height; CHECKED_MALLOC( h->visualize, mb * sizeof(visualize_t) ); return 0; fail: return -1; }
/* Try to load the cached compiled program binary, verify the device context is * still valid before reuse */ static cl_program x264_opencl_cache_load( x264_t *h, const char *dev_name, const char *dev_vendor, const char *driver_version ) { /* try to load cached program binary */ FILE *fp = x264_fopen( h->param.psz_clbin_file, "rb" ); x264_opencl_function_t *ocl; cl_program program; uint8_t *binary; size_t size; const uint8_t *ptr; cl_int status; if( !fp ) return NULL; ocl = h->opencl.ocl; program = NULL; binary = NULL; fseek( fp, 0, SEEK_END ); size = ftell( fp ); rewind( fp ); CHECKED_MALLOC( binary, size ); if ( fread( binary, 1, size, fp ) != size ) goto fail; ptr = (const uint8_t*)binary; #define CHECK_STRING( STR )\ do {\ size_t len = strlen( STR );\ if( size <= len || strncmp( (char*)ptr, STR, len ) )\ goto fail;\ else {\ size -= (len+1); ptr += (len+1);\ }\ } while( 0 ) CHECK_STRING( dev_name ); CHECK_STRING( dev_vendor ); CHECK_STRING( driver_version ); CHECK_STRING( x264_opencl_source_hash ); #undef CHECK_STRING program = ocl->clCreateProgramWithBinary( h->opencl.context, 1, &h->opencl.device, &size, &ptr, NULL, &status ); if( status != CL_SUCCESS ) program = NULL; fail: fclose( fp ); x264_free( binary ); return program; }
/* Save the compiled program binary to a file for later reuse. Device context * is also saved in the cache file so we do not reuse stale binaries */ static void x264_opencl_cache_save( x264_t *h, cl_program program, const char *dev_name, const char *dev_vendor, const char *driver_version ) { FILE *fp = x264_fopen( h->param.psz_clbin_file, "wb" ); x264_opencl_function_t *ocl; uint8_t *binary; size_t size; cl_int status; if( !fp ) { x264_log( h, X264_LOG_INFO, "OpenCL: unable to open clbin file for write\n" ); return; } ocl = h->opencl.ocl; binary = NULL; size = 0; status = ocl->clGetProgramInfo( program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &size, NULL ); if( status != CL_SUCCESS || !size ) { x264_log( h, X264_LOG_INFO, "OpenCL: Unable to query program binary size, no cache file generated\n" ); goto fail; } CHECKED_MALLOC( binary, size ); status = ocl->clGetProgramInfo( program, CL_PROGRAM_BINARIES, sizeof(uint8_t *), &binary, NULL ); if( status != CL_SUCCESS ) { x264_log( h, X264_LOG_INFO, "OpenCL: Unable to query program binary, no cache file generated\n" ); goto fail; } fputs( dev_name, fp ); fputc( '\n', fp ); fputs( dev_vendor, fp ); fputc( '\n', fp ); fputs( driver_version, fp ); fputc( '\n', fp ); fputs( x264_opencl_source_hash, fp ); fputc( '\n', fp ); fwrite( binary, 1, size, fp ); fail: fclose( fp ); x264_free( binary ); return; }
int x264_sei_version_write( x264_t *h, bs_t *s ) { int i; // random ID number generated according to ISO-11578 static const uint8_t uuid[16] = { 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee, 0xef }; char *opts = x264_param2string( &h->param, 0 ); char *version; int length; if( !opts ) return -1; CHECKED_MALLOC( version, 200 + strlen( opts ) ); sprintf( version, "x264 - core %d%s - H.264/MPEG-4 AVC codec - " "Copyleft 2003-2010 - http://www.videolan.org/x264.html - options: %s", X264_BUILD, X264_VERSION, opts ); length = strlen(version)+1+16; bs_realign( s ); bs_write( s, 8, SEI_USER_DATA_UNREGISTERED ); // payload_size for( i = 0; i <= length-255; i += 255 ) bs_write( s, 8, 255 ); bs_write( s, 8, length-i ); for( int j = 0; j < 16; j++ ) bs_write( s, 8, uuid[j] ); for( int j = 0; j < length-16; j++ ) bs_write( s, 8, version[j] ); bs_rbsp_trailing( s ); bs_flush( s ); x264_free( opts ); x264_free( version ); return 0; fail: x264_free( opts ); return -1; }
int x265_global_init ( x265_t *h ) { int32_t loop = 0, i_bit = 0 ; CHECKED_MALLOC( h->global.convert_to_bit, (X265_MAX_CU_SIZE + 1) * sizeof(int8_t) ); memset ( h->global.convert_to_bit, -1, (X265_MAX_CU_SIZE + 1)* sizeof(int8_t) ) ; i_bit = 0 ; for ( loop = 4 ; loop < X265_MAX_CU_SIZE ; loop *= 2 ) { h->global.convert_to_bit[loop] = i_bit ; ++ i_bit ; } h->global.convert_to_bit [loop] = i_bit ; return 0 ; fail: x265_global_deinit ( h ) ; return -1 ; }
x264_frame_t *x264_frame_new( x264_t *h ) { x264_frame_t *frame = x264_malloc( sizeof(x264_frame_t) ); int i, j; int i_mb_count = h->mb.i_mb_count; int i_stride; int i_lines; if( !frame ) return NULL; memset( frame, 0, sizeof(x264_frame_t) ); /* allocate frame data (+64 for extra data for me) */ i_stride = ( ( h->param.i_width + 15 )&0xfffff0 )+ 64; i_lines = ( ( h->param.i_height + 15 )&0xfffff0 ); frame->i_plane = 3; for( i = 0; i < 3; i++ ) { int i_divh = 1; int i_divw = 1; if( i > 0 ) { if( h->param.i_csp == X264_CSP_I420 ) i_divh = i_divw = 2; else if( h->param.i_csp == X264_CSP_I422 ) i_divw = 2; } frame->i_stride[i] = i_stride / i_divw; frame->i_lines[i] = i_lines / i_divh; CHECKED_MALLOC( frame->buffer[i], frame->i_stride[i] * ( frame->i_lines[i] + 64 / i_divh ) ); // frame->buffer[i]=x264_malloc(frame->i_stride[i] * ( frame->i_lines[i] + 64 / i_divh ) ); frame->plane[i] = ((uint8_t*)frame->buffer[i]) + frame->i_stride[i] * 32 / i_divh + 32 / i_divw; } frame->i_stride[3] = 0; frame->i_lines[3] = 0; frame->buffer[3] = NULL; frame->plane[3] = NULL; frame->filtered[0] = frame->plane[0]; for( i = 0; i < 3; i++ ) { CHECKED_MALLOC( frame->buffer[4+i], frame->i_stride[0] * ( frame->i_lines[0] + 64 ) ); frame->filtered[i+1] = ((uint8_t*)frame->buffer[4+i]) + frame->i_stride[0] * 32 + 32; } if( h->frames.b_have_lowres ) { frame->i_stride_lowres = frame->i_stride[0]/2 + 32; frame->i_lines_lowres = frame->i_lines[0]/2; for( i = 0; i < 4; i++ ) { CHECKED_MALLOC( frame->buffer[7+i], frame->i_stride_lowres * ( frame->i_lines[0]/2 + 64 ) ); frame->lowres[i] = ((uint8_t*)frame->buffer[7+i]) + frame->i_stride_lowres * 32 + 32; } } if( h->param.analyse.i_me_method == X264_ME_ESA ) { CHECKED_MALLOC( frame->buffer[11], frame->i_stride[0] * (frame->i_lines[0] + 64) * sizeof(uint16_t) ); frame->integral = (uint16_t*)frame->buffer[11] + frame->i_stride[0] * 32 + 32; } frame->i_poc = -1; frame->i_type = X264_TYPE_AUTO; frame->i_qpplus1 = 0; frame->i_pts = -1; frame->i_frame = -1; frame->i_frame_num = -1; CHECKED_MALLOC( frame->mb_type, i_mb_count * sizeof(int8_t)); CHECKED_MALLOC( frame->mv[0], 2*16 * i_mb_count * sizeof(int16_t) ); CHECKED_MALLOC( frame->ref[0], 4 * i_mb_count * sizeof(int8_t) ); if( h->param.i_bframe ) { CHECKED_MALLOC( frame->mv[1], 2*16 * i_mb_count * sizeof(int16_t) ); CHECKED_MALLOC( frame->ref[1], 4 * i_mb_count * sizeof(int8_t) ); } else { frame->mv[1] = NULL; frame->ref[1] = NULL; } CHECKED_MALLOC( frame->i_row_bits, i_lines/16 * sizeof(int) ); CHECKED_MALLOC( frame->i_row_qp, i_lines/16 * sizeof(int) ); for( i = 0; i < h->param.i_bframe + 2; i++ ) for( j = 0; j < h->param.i_bframe + 2; j++ ) CHECKED_MALLOC( frame->i_row_satds[i][j], i_lines/16 * sizeof(int) ); return frame; fail: x264_frame_delete( frame ); return NULL; }
/* The OpenCL source under common/opencl will be merged into common/oclobj.h by * the Makefile. It defines a x264_opencl_source byte array which we will pass * to clCreateProgramWithSource(). We also attempt to use a cache file for the * compiled binary, stored in the current working folder. */ static cl_program x264_opencl_compile( x264_t *h ) { x264_opencl_function_t *ocl = h->opencl.ocl; cl_program program; cl_int status; char devname[64]; char devvendor[64]; char driverversion[64]; status = ocl->clGetDeviceInfo( h->opencl.device, CL_DEVICE_NAME, sizeof(devname), devname, NULL ); status |= ocl->clGetDeviceInfo( h->opencl.device, CL_DEVICE_VENDOR, sizeof(devvendor), devvendor, NULL ); status |= ocl->clGetDeviceInfo( h->opencl.device, CL_DRIVER_VERSION, sizeof(driverversion), driverversion, NULL ); if( status != CL_SUCCESS ) return NULL; // Most AMD GPUs have vector registers int vectorize = !strcmp( devvendor, "Advanced Micro Devices, Inc." ); h->opencl.b_device_AMD_SI = 0; if( vectorize ) { /* Disable OpenCL on Intel/AMD switchable graphics devices */ if( x264_detect_switchable_graphics() ) { x264_log( h, X264_LOG_INFO, "OpenCL acceleration disabled, switchable graphics detected\n" ); return NULL; } /* Detect AMD SouthernIsland or newer device (single-width registers) */ cl_uint simdwidth = 4; status = ocl->clGetDeviceInfo( h->opencl.device, CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD, sizeof(cl_uint), &simdwidth, NULL ); if( status == CL_SUCCESS && simdwidth == 1 ) { vectorize = 0; h->opencl.b_device_AMD_SI = 1; } } x264_log( h, X264_LOG_INFO, "OpenCL acceleration enabled with %s %s %s\n", devvendor, devname, h->opencl.b_device_AMD_SI ? "(SI)" : "" ); program = x264_opencl_cache_load( h, devname, devvendor, driverversion ); if( !program ) { /* clCreateProgramWithSource() requires a pointer variable, you cannot just use &x264_opencl_source */ x264_log( h, X264_LOG_INFO, "Compiling OpenCL kernels...\n" ); const char *strptr = (const char*)x264_opencl_source; size_t size = sizeof(x264_opencl_source); program = ocl->clCreateProgramWithSource( h->opencl.context, 1, &strptr, &size, &status ); if( status != CL_SUCCESS || !program ) { x264_log( h, X264_LOG_WARNING, "OpenCL: unable to create program\n" ); return NULL; } } /* Build the program binary for the OpenCL device */ const char *buildopts = vectorize ? "-DVECTORIZE=1" : ""; status = ocl->clBuildProgram( program, 1, &h->opencl.device, buildopts, NULL, NULL ); if( status == CL_SUCCESS ) { x264_opencl_cache_save( h, program, devname, devvendor, driverversion ); return program; } /* Compile failure, should not happen with production code. */ size_t build_log_len = 0; status = ocl->clGetProgramBuildInfo( program, h->opencl.device, CL_PROGRAM_BUILD_LOG, build_log_len, NULL, &build_log_len ); if( status != CL_SUCCESS ) { x264_log( h, X264_LOG_WARNING, "OpenCL: Compilation failed, unable to query build log\n" ); return NULL; } char *build_log; CHECKED_MALLOC( build_log, build_log_len ); if( !build_log ) { x264_log( h, X264_LOG_WARNING, "OpenCL: Compilation failed, unable to alloc build log\n" ); return NULL; } status = ocl->clGetProgramBuildInfo( program, h->opencl.device, CL_PROGRAM_BUILD_LOG, build_log_len, build_log, NULL ); if( status != CL_SUCCESS ) { x264_log( h, X264_LOG_WARNING, "OpenCL: Compilation failed, unable to get build log\n" ); x264_free( build_log ); return NULL; } FILE *lg = fopen( "x264_kernel_build_log.txt", "w" ); if( lg ) { fwrite( build_log, 1, build_log_len, lg ); fclose( lg ); x264_log( h, X264_LOG_WARNING, "OpenCL: kernel build errors written to x264_kernel_build_log.txt\n" ); } x264_free( build_log ); fail: return NULL; }