Commit ce55ae08 authored by xvidfan's avatar xvidfan Committed by Fiona Glaser
Browse files

RGB encoding support

Much less efficient than YUV444, but easy to support using the YUV444 framework.
parent a93e4c4a
......@@ -59,10 +59,10 @@ void x264_param_default( x264_param_t *param )
param->vui.i_sar_height= 0;
param->vui.i_overscan = 0; /* undef */
param->vui.i_vidformat = 5; /* undef */
param->vui.b_fullrange = 0; /* off */
param->vui.b_fullrange = -1; /* default depends on input */
param->vui.i_colorprim = 2; /* undef */
param->vui.i_transfer = 2; /* undef */
param->vui.i_colmatrix = 2; /* undef */
param->vui.i_colmatrix = -1; /* default depends on input */
param->vui.i_chroma_loc= 0; /* left center */
param->i_fps_num = 25;
param->i_fps_den = 1;
......
......@@ -52,6 +52,9 @@ static int x264_frame_internal_csp( int external_csp )
return X264_CSP_NV12;
case X264_CSP_I444:
case X264_CSP_YV24:
case X264_CSP_BGR:
case X264_CSP_BGRA:
case X264_CSP_RGB:
return X264_CSP_I444;
default:
return X264_CSP_NONE;
......@@ -346,32 +349,50 @@ int x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src )
uint8_t *pix[3];
int stride[3];
get_plane_ptr( h, src, &pix[0], &stride[0], 0, 0, 0 );
h->mc.plane_copy( dst->plane[0], dst->i_stride[0], (pixel*)pix[0],
stride[0]/sizeof(pixel), h->param.i_width, h->param.i_height );
if( i_csp == X264_CSP_NV12 )
{
get_plane_ptr( h, src, &pix[1], &stride[1], 1, 0, 1 );
h->mc.plane_copy( dst->plane[1], dst->i_stride[1], (pixel*)pix[1],
stride[1]/sizeof(pixel), h->param.i_width, h->param.i_height>>1 );
}
else if( i_csp == X264_CSP_I420 || i_csp == X264_CSP_YV12 )
if ( i_csp >= X264_CSP_BGR )
{
get_plane_ptr( h, src, &pix[1], &stride[1], i_csp==X264_CSP_I420 ? 1 : 2, 1, 1 );
get_plane_ptr( h, src, &pix[2], &stride[2], i_csp==X264_CSP_I420 ? 2 : 1, 1, 1 );
h->mc.plane_copy_interleave( dst->plane[1], dst->i_stride[1],
(pixel*)pix[1], stride[1]/sizeof(pixel),
(pixel*)pix[2], stride[2]/sizeof(pixel),
h->param.i_width>>1, h->param.i_height>>1 );
stride[0] = src->img.i_stride[0];
pix[0] = src->img.plane[0];
if( src->img.i_csp & X264_CSP_VFLIP )
{
pix[0] += (h->param.i_height-1) * stride[0];
stride[0] = -stride[0];
}
int b = i_csp==X264_CSP_RGB ? 2 : 0;
h->mc.plane_copy_deinterleave_rgb( dst->plane[1], dst->i_stride[1],
dst->plane[b], dst->i_stride[b],
dst->plane[2-b], dst->i_stride[2-b],
(pixel*)pix[0], stride[0]/sizeof(pixel), i_csp==X264_CSP_BGRA ? 4 : 3, h->param.i_width, h->param.i_height );
}
else //if( i_csp == X264_CSP_I444 || i_csp == X264_CSP_YV24 )
else
{
get_plane_ptr( h, src, &pix[1], &stride[1], i_csp==X264_CSP_I444 ? 1 : 2, 0, 0 );
get_plane_ptr( h, src, &pix[2], &stride[2], i_csp==X264_CSP_I444 ? 2 : 1, 0, 0 );
h->mc.plane_copy( dst->plane[1], dst->i_stride[1], (pixel*)pix[1],
stride[1]/sizeof(pixel), h->param.i_width, h->param.i_height );
h->mc.plane_copy( dst->plane[2], dst->i_stride[2], (pixel*)pix[2],
stride[2]/sizeof(pixel), h->param.i_width, h->param.i_height );
get_plane_ptr( h, src, &pix[0], &stride[0], 0, 0, 0 );
h->mc.plane_copy( dst->plane[0], dst->i_stride[0], (pixel*)pix[0],
stride[0]/sizeof(pixel), h->param.i_width, h->param.i_height );
if( i_csp == X264_CSP_NV12 )
{
get_plane_ptr( h, src, &pix[1], &stride[1], 1, 0, 1 );
h->mc.plane_copy( dst->plane[1], dst->i_stride[1], (pixel*)pix[1],
stride[1]/sizeof(pixel), h->param.i_width, h->param.i_height>>1 );
}
else if( i_csp == X264_CSP_I420 || i_csp == X264_CSP_YV12 )
{
get_plane_ptr( h, src, &pix[1], &stride[1], i_csp==X264_CSP_I420 ? 1 : 2, 1, 1 );
get_plane_ptr( h, src, &pix[2], &stride[2], i_csp==X264_CSP_I420 ? 2 : 1, 1, 1 );
h->mc.plane_copy_interleave( dst->plane[1], dst->i_stride[1],
(pixel*)pix[1], stride[1]/sizeof(pixel),
(pixel*)pix[2], stride[2]/sizeof(pixel),
h->param.i_width>>1, h->param.i_height>>1 );
}
else //if( i_csp == X264_CSP_I444 || i_csp == X264_CSP_YV24 )
{
get_plane_ptr( h, src, &pix[1], &stride[1], i_csp==X264_CSP_I444 ? 1 : 2, 0, 0 );
get_plane_ptr( h, src, &pix[2], &stride[2], i_csp==X264_CSP_I444 ? 2 : 1, 0, 0 );
h->mc.plane_copy( dst->plane[1], dst->i_stride[1], (pixel*)pix[1],
stride[1]/sizeof(pixel), h->param.i_width, h->param.i_height );
h->mc.plane_copy( dst->plane[2], dst->i_stride[2], (pixel*)pix[2],
stride[2]/sizeof(pixel), h->param.i_width, h->param.i_height );
}
}
return 0;
}
......
......@@ -314,6 +314,22 @@ void x264_plane_copy_deinterleave_c( pixel *dstu, int i_dstu,
}
}
void x264_plane_copy_deinterleave_rgb_c( pixel *dsta, int i_dsta,
pixel *dstb, int i_dstb,
pixel *dstc, int i_dstc,
pixel *src, int i_src, int pw, int w, int h )
{
for( int y=0; y<h; y++, dsta+=i_dsta, dstb+=i_dstb, dstc+=i_dstc, src+=i_src )
{
for( int x=0; x<w; x++ )
{
dsta[x] = src[x*pw];
dstb[x] = src[x*pw+1];
dstc[x] = src[x*pw+2];
}
}
}
static void store_interleave_8x8x2( pixel *dst, int i_dst, pixel *srcu, pixel *srcv )
{
for( int y=0; y<8; y++, dst+=i_dst, srcu+=FDEC_STRIDE, srcv+=FDEC_STRIDE )
......@@ -481,6 +497,7 @@ void x264_mc_init( int cpu, x264_mc_functions_t *pf )
pf->plane_copy = x264_plane_copy_c;
pf->plane_copy_interleave = x264_plane_copy_interleave_c;
pf->plane_copy_deinterleave = x264_plane_copy_deinterleave_c;
pf->plane_copy_deinterleave_rgb = x264_plane_copy_deinterleave_rgb_c;
pf->hpel_filter = hpel_filter;
......
......@@ -96,7 +96,10 @@ typedef struct
void (*plane_copy_deinterleave)( pixel *dstu, int i_dstu,
pixel *dstv, int i_dstv,
pixel *src, int i_src, int w, int h );
void (*plane_copy_deinterleave_rgb)( pixel *dsta, int i_dsta,
pixel *dstb, int i_dstb,
pixel *dstc, int i_dstc,
pixel *src, int i_src, int pw, int w, int h );
void (*hpel_filter)( pixel *dsth, pixel *dstv, pixel *dstc, pixel *src,
int i_stride, int i_width, int i_height, int16_t *buf );
......
......@@ -410,7 +410,7 @@ static int x264_validate_parameters( x264_t *h, int b_open )
int i_csp = h->param.i_csp & X264_CSP_MASK;
if( i_csp <= X264_CSP_NONE || i_csp >= X264_CSP_MAX )
{
x264_log( h, X264_LOG_ERROR, "invalid CSP (only I420/YV12/NV12/I444/YV24 supported)\n" );
x264_log( h, X264_LOG_ERROR, "invalid CSP (only I420/YV12/NV12/I444/YV24/BGR/BGRA/RGB supported)\n" );
return -1;
}
......@@ -767,7 +767,7 @@ static int x264_validate_parameters( x264_t *h, int b_open )
h->mb.i_psy_rd = h->param.analyse.i_subpel_refine >= 6 ? FIX8( h->param.analyse.f_psy_rd ) : 0;
h->mb.i_psy_trellis = h->param.analyse.i_trellis ? FIX8( h->param.analyse.f_psy_trellis / 4 ) : 0;
/* In 4:4:4 mode, chroma gets twice as much resolution, so we can halve its quality. */
if( b_open && i_csp >= X264_CSP_I444 && h->param.analyse.b_psy )
if( b_open && i_csp >= X264_CSP_I444 && i_csp < X264_CSP_BGR && h->param.analyse.b_psy )
h->param.analyse.i_chroma_qp_offset += 6;
/* Psy RDO increases overall quantizers to improve the quality of luma--this indirectly hurts chroma quality */
/* so we lower the chroma QP offset to compensate */
......
......@@ -202,12 +202,14 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
sps->vui.b_signal_type_present = 0;
sps->vui.i_vidformat = ( param->vui.i_vidformat >= 0 && param->vui.i_vidformat <= 5 ? param->vui.i_vidformat : 5 );
sps->vui.b_fullrange = ( param->vui.b_fullrange ? 1 : 0 );
sps->vui.b_fullrange = ( param->vui.b_fullrange >= 0 && param->vui.b_fullrange <= 1 ? param->vui.b_fullrange :
( param->i_csp >= X264_CSP_BGR ? 1 : 0 ) );
sps->vui.b_color_description_present = 0;
sps->vui.i_colorprim = ( param->vui.i_colorprim >= 0 && param->vui.i_colorprim <= 8 ? param->vui.i_colorprim : 2 );
sps->vui.i_transfer = ( param->vui.i_transfer >= 0 && param->vui.i_transfer <= 10 ? param->vui.i_transfer : 2 );
sps->vui.i_colmatrix = ( param->vui.i_colmatrix >= 0 && param->vui.i_colmatrix <= 8 ? param->vui.i_colmatrix : 2 );
sps->vui.i_colmatrix = ( param->vui.i_colmatrix >= 0 && param->vui.i_colmatrix <= 8 ? param->vui.i_colmatrix :
( param->i_csp >= X264_CSP_BGR ? 0 : 2 ) );
if( sps->vui.i_colorprim != 2 ||
sps->vui.i_transfer != 2 ||
sps->vui.i_colmatrix != 2 )
......
......@@ -219,11 +219,12 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
}
#if !HAVE_SWSCALE
/* if swscale is not available, convert the CSP if necessary */
if( (opt->output_csp == X264_CSP_I420 && !avs_is_yv12( vi )) || (opt->output_csp == X264_CSP_I444 && !avs_is_yv24( vi )) )
if( (opt->output_csp == X264_CSP_I420 && !avs_is_yv12( vi )) || (opt->output_csp == X264_CSP_I444 && !avs_is_yv24( vi )) ||
(opt->output_csp == X264_CSP_RGB && !avs_is_rgb( vi )) )
{
FAIL_IF_ERROR( avs_version < 2.6f && opt->output_csp == X264_CSP_I444, "avisynth >= 2.6 is required for i444 output\n" )
const char *csp = opt->output_csp == X264_CSP_I420 ? "YV12" : "YV24";
const char *csp = opt->output_csp == X264_CSP_I420 ? "YV12" : (opt->output_csp == X264_CSP_I444 ? "YV24" : "RGB");
x264_cli_log( "avs", X264_LOG_WARNING, "converting input clip to %s\n", csp );
FAIL_IF_ERROR( opt->output_csp == X264_CSP_I420 && (vi->width&1 || vi->height&1),
"input clip width or height not divisible by 2 (%dx%d)\n", vi->width, vi->height )
......@@ -244,33 +245,26 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
info->fps_den = vi->fps_denominator;
h->num_frames = info->num_frames = vi->num_frames;
info->thread_safe = 1;
#if HAVE_SWSCALE
if( avs_is_rgb32( vi ) )
info->csp = X264_CSP_BGRA | X264_CSP_VFLIP;
else if( avs_is_rgb24( vi ) )
info->csp = X264_CSP_BGR | X264_CSP_VFLIP;
else if( avs_is_yuy2( vi ) )
info->csp = PIX_FMT_YUYV422 | X264_CSP_OTHER;
else if( avs_is_yv24( vi ) )
info->csp = X264_CSP_I444;
else if( avs_is_yv12( vi ) )
info->csp = X264_CSP_I420;
#if HAVE_SWSCALE
else if( avs_is_yuy2( vi ) )
info->csp = PIX_FMT_YUYV422 | X264_CSP_OTHER;
else if( avs_is_yv16( vi ) )
info->csp = X264_CSP_I422;
else if( avs_is_yv12( vi ) )
info->csp = X264_CSP_I420;
else if( avs_is_yv411( vi ) )
info->csp = PIX_FMT_YUV411P | X264_CSP_OTHER;
else if( avs_is_y8( vi ) )
info->csp = PIX_FMT_GRAY8 | X264_CSP_OTHER;
#endif
else
info->csp = X264_CSP_NONE;
#else
if( avs_is_yv24( vi ) )
info->csp = X264_CSP_I444;
else if( avs_is_yv12( vi ) )
info->csp = X264_CSP_I420;
else
info->csp = X264_CSP_NONE;
#endif
info->vfr = 0;
*p_handle = h;
......
......@@ -104,10 +104,7 @@ extern cli_input_t input;
/* extended colorspace list that isn't supported by libx264 but by the cli */
#define X264_CSP_I422 X264_CSP_MAX /* yuv 4:2:2 planar */
#define X264_CSP_BGR (X264_CSP_MAX+1) /* packed bgr 24bits */
#define X264_CSP_BGRA (X264_CSP_MAX+2) /* packed bgr 32bits */
#define X264_CSP_RGB (X264_CSP_MAX+3) /* packed rgb 24bits */
#define X264_CSP_CLI_MAX (X264_CSP_MAX+4) /* end of list */
#define X264_CSP_CLI_MAX (X264_CSP_MAX+1) /* end of list */
#define X264_CSP_OTHER 0x4000 /* non x264 colorspace */
typedef struct
......
......@@ -121,7 +121,7 @@ static const char * const muxer_names[] =
static const char * const pulldown_names[] = { "none", "22", "32", "64", "double", "triple", "euro", 0 };
static const char * const log_level_names[] = { "none", "error", "warning", "info", "debug", 0 };
static const char * const output_csp_names[] = { "i420", "i444", 0 };
static const char * const output_csp_names[] = { "i420", "i444", "rgb", 0 };
typedef struct
{
......@@ -1129,6 +1129,8 @@ static int init_vid_filters( char *sequence, hnd_t *handle, video_info_t *info,
param->i_csp = X264_CSP_I420;
else if( output_csp == X264_CSP_I444 && (csp < X264_CSP_I444 || csp > X264_CSP_YV24) )
param->i_csp = X264_CSP_I444;
else if( output_csp == X264_CSP_RGB && (csp < X264_CSP_BGR || csp > X264_CSP_RGB) )
param->i_csp = X264_CSP_RGB;
param->i_csp |= info->csp & X264_CSP_HIGH_DEPTH;
if( x264_init_vid_filter( "resize", handle, &filter, info, param, NULL ) )
......@@ -1349,7 +1351,7 @@ static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
case OPT_OUTPUT_CSP:
FAIL_IF_ERROR( parse_enum_value( optarg, output_csp_names, &output_csp ), "Unknown output csp `%s'\n", optarg )
// correct the parsed value to the libx264 csp value
output_csp = !output_csp ? X264_CSP_I420 : X264_CSP_I444;
output_csp = !output_csp ? X264_CSP_I420 : (output_csp == 1 ? X264_CSP_I444 : X264_CSP_RGB);
break;
default:
generic_option:
......
......@@ -182,7 +182,10 @@ static const char * const x264_nal_hrd_names[] = { "none", "vbr", "cbr", 0 };
#define X264_CSP_NV12 0x0003 /* yuv 4:2:0, with one y plane and one packed u+v */
#define X264_CSP_I444 0x0004 /* yuv 4:4:4 planar */
#define X264_CSP_YV24 0x0005 /* yvu 4:4:4 planar */
#define X264_CSP_MAX 0x0006 /* end of list */
#define X264_CSP_BGR 0x0006 /* packed bgr 24bits */
#define X264_CSP_BGRA 0x0007 /* packed bgr 32bits */
#define X264_CSP_RGB 0x0008 /* packed rgb 24bits */
#define X264_CSP_MAX 0x0009 /* end of list */
#define X264_CSP_VFLIP 0x1000 /* the csp is vertically flipped */
#define X264_CSP_HIGH_DEPTH 0x2000 /* the csp has a depth of 16 bits per pixel component */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment