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

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