Much less efficient than YUV444, but easy to support using the YUV444 framework.
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;
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;
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;
}
}
}
+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 )
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;
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 );
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;
}
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 */
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 )
}
#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 )
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;
/* 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
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
{
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 ) )
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:
#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 */