]> git.sesse.net Git - x264/commitdiff
RGB encoding support
authorxvidfan <xvidfan@freenet.de>
Thu, 23 Jun 2011 01:46:14 +0000 (18:46 -0700)
committerFiona Glaser <fiona@x264.com>
Sun, 10 Jul 2011 04:15:56 +0000 (21:15 -0700)
Much less efficient than YUV444, but easy to support using the YUV444 framework.

common/common.c
common/frame.c
common/mc.c
common/mc.h
encoder/encoder.c
encoder/set.c
input/avs.c
input/input.h
x264.c
x264.h

index 99cb3d2f7fc9ad2558f672592d3c445b51211f9b..5a5e036b38e3b1f716b1701dd5017d7551210949 100644 (file)
@@ -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;
index daf446e248e56437317d332a8b80ff8ccc5d820b..09f2079075e270f0caced28a31615e585205bc8d 100644 (file)
@@ -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;
 }
index 8c4c2b9e3cd622f6111e77f0cdae596fc32926d9..de1c67847fa89db520111db10480ed99b6d8bcb9 100644 (file)
@@ -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;
 
index 4882707d146987943ea99c54653a06985dacb855..f19a9979625f28b9645168b18078badc60bcf19c 100644 (file)
@@ -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 );
 
index b988b9a602c32e90dafa751cba5f6f7ecdcb875d..a6a3415cb5f2d16300b46824b984fa1492509870 100644 (file)
@@ -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 */
index 0044e584fbd1ec218c540f636a4036c083003826..c519012910b4d62cb0da6da60f351b52171783d3 100644 (file)
@@ -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 )
index f3f1118d0df931895b8c92b5857bfe9bec1c01ca..59fab8cc5c682318d3454e9232838c55f52ed492 100644 (file)
@@ -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;
index 488833d0a1f0c1545a0278070080fef3bef170d9..eb928eaceeadf747b6063871a16ea517c1e99a1e 100644 (file)
@@ -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
diff --git a/x264.c b/x264.c
index ea7c5cdfd8bd7e97f311ad0953674e8574e6b8a0..3b58aa7d55b79a11809dcd5a4bf8dddc787e5ef6 100644 (file)
--- a/x264.c
+++ b/x264.c
@@ -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:
diff --git a/x264.h b/x264.h
index f936443d20904d46f95596b6f0966d895d737406..809cefd7eec4f3fec22f297e8e4bfb79d6e11f96 100644 (file)
--- a/x264.h
+++ b/x264.h
@@ -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 */