diff -uNrp src.20110124/codec.c src/codec.c --- src.20110124/codec.c 2011-01-22 20:28:31 +0200 +++ src/codec.c 2011-01-24 20:42:21 +0200 @@ -44,6 +44,9 @@ const char * const muxer_names[] = const char * const log_level_names[] = { "none", "error", "warning", "info", "debug", NULL }; +const char * const input_csp_rec_names[] = { "bt601", "bt709", NULL }; +const char * const input_csp_scale_names[] = { "tv", "pc", NULL }; + /* Return a valid x264 colorspace or X264VFW_CSP_NONE if it is not supported */ static int get_csp(BITMAPINFOHEADER *hdr) { @@ -418,6 +421,8 @@ enum { OPT_PULLDOWN, OPT_LOG_LEVEL, OPT_DTS_COMPRESSION, + OPT_INPUT_CSP_REC, + OPT_INPUT_CSP_SCALE, #if X264VFW_USE_VIRTUALDUB_HACK OPT_VD_HACK, #endif @@ -588,6 +593,8 @@ static struct option long_options[] = { "log-file-level", required_argument, NULL, 0 }, { "level-force", no_argument, NULL, 0 }, { "fade-compensate", required_argument, NULL, 0 }, + { "input-csp-rec", required_argument, NULL, OPT_INPUT_CSP_REC }, + { "input-csp-scale", required_argument, NULL, OPT_INPUT_CSP_SCALE }, { NULL, 0, NULL, 0 } }; @@ -873,6 +880,22 @@ static int parse_cmdline(int argc, char codec->b_no_output = TRUE; break; + case OPT_INPUT_CSP_REC: + if (parse_enum_value(optarg, input_csp_rec_names, &codec->i_input_csp_rec) < 0) + { + x264vfw_log(codec, X264_LOG_ERROR, "unknown csp-rec '%s' for input\n", optarg); + return -1; + } + break; + + case OPT_INPUT_CSP_SCALE: + if (parse_enum_value(optarg, input_csp_scale_names, &codec->i_input_csp_scale) < 0) + { + x264vfw_log(codec, X264_LOG_ERROR, "unknown csp-scale '%s' for input\n", optarg); + return -1; + } + break; + default: if (long_options_index < 0) { @@ -954,6 +977,8 @@ LRESULT compress_begin(CODEC *codec, BIT codec->b_use_vd_hack = FALSE; /* Don't use "VD hack" by default */ codec->save_fourcc = lpbiOutput->bmiHeader.biCompression; #endif + codec->i_input_csp_rec = + codec->i_input_csp_scale = 0; codec->b_no_output = FALSE; codec->b_fast1pass = FALSE; codec->i_frame_remain = codec->i_frame_total ? codec->i_frame_total : -1; @@ -971,10 +996,6 @@ LRESULT compress_begin(CODEC *codec, BIT param.i_fps_den = codec->i_fps_den; } - /* Colorspace conversion */ - x264vfw_csp_init(&codec->csp, param.i_csp); - x264_picture_alloc(&codec->conv_pic, param.i_csp, param.i_width, param.i_height); - /* Log */ param.pf_log = x264_log_vfw; param.p_log_private = codec; @@ -1202,6 +1223,10 @@ LRESULT compress_begin(CODEC *codec, BIT goto fail; } + /* Colorspace conversion */ + x264vfw_csp_init(&codec->csp, param.i_csp, codec->i_input_csp_rec, codec->i_input_csp_scale); + x264_picture_alloc(&codec->conv_pic, param.i_csp, param.i_width, param.i_height); + /* VFW supports only CFR */ param.b_vfr_input = 0; param.i_timebase_num = param.i_fps_den; diff -uNrp src.20110124/csp.c src/csp.c --- src.20110124/csp.c 2010-04-22 13:49:10 +0300 +++ src/csp.c 2011-01-24 20:22:10 +0200 @@ -315,66 +315,51 @@ static void uyvy_to_i420( x264_image_t * } } -#if X264VFW_CSP_BT_709 -//BT.709 -#define Kb 0.0722 -#define Kr 0.2126 -#else -//BT.601 -#define Kb 0.114 -#define Kr 0.299 -#endif - -#define Kg (1.0 - Kb - Kr) -#define Sb (1.0 - Kb) -#define Sr (1.0 - Kr) - -#if X264VFW_CSP_PC_SCALE -//PC Scale -//0 <= Y <= 255 -//0 <= U <= 255 -//0 <= V <= 255 -#define Ky 1.0 -#define Ku (0.5 / Sb) -#define Kv (0.5 / Sr) -#define Ay 0.0 -#define Au 127.5 -#define Av 127.5 -#else -//TV Scale -//16 <= Y <= 235 -//16 <= U <= 240 -//16 <= V <= 240 -#define Ky (1.0 * 219.0 / 255.0) -#define Ku ((0.5 / Sb) * 224.0 / 255.0) -#define Kv ((0.5 / Sr) * 224.0 / 255.0) -#define Ay 16.0 -#define Au 128.0 -#define Av 128.0 -#endif - -#define BITS 22 -#define INT_FIX (1 << BITS) -#define INT_ROUND (INT_FIX >> 1) -#define FIX(f) ((uint32_t)((f) * INT_FIX + 0.5)) - -#define Y_R FIX(Kr*Ky) -#define Y_G FIX(Kg*Ky) -#define Y_B FIX(Kb*Ky) -#define Y_ADD ((uint32_t)(Ay * INT_FIX + INT_ROUND + 0.5)) - -#define U_R FIX(Kr*Ku) -#define U_G FIX(Kg*Ku) -#define U_B FIX(Sb*Ku) -#define U_ADD ((uint32_t)((Au * INT_FIX + INT_ROUND) * 4 + 0.5)) - -#define V_R FIX(Sr*Kv) -#define V_G FIX(Kg*Kv) -#define V_B FIX(Kb*Kv) -#define V_ADD ((uint32_t)((Av * INT_FIX + INT_ROUND) * 4 + 0.5)) +#define BITS 22 +#define INT_FIX (1 << BITS) +#define INT_ROUND (INT_FIX >> 1) +#define FIX(f) ((uint32_t)((f) * INT_FIX + 0.5)) + +#define Kb_601 0.114 +#define Kr_601 0.299 +#define Kb_709 0.0722 +#define Kr_709 0.2126 + +#define Kg( rec ) (1.0 - Kb_##rec - Kr_##rec) +#define Sb( rec ) (1.0 - Kb_##rec) +#define Sr( rec ) (1.0 - Kr_##rec) + +#define Ky_tv (1.0 * 219.0 / 255.0) +#define Ku_tv( rec ) ((0.5 / Sb(rec)) * 224.0 / 255.0) +#define Kv_tv( rec ) ((0.5 / Sr(rec)) * 224.0 / 255.0) +#define Ay_tv 16.0 +#define Au_tv 128.0 +#define Av_tv 128.0 + +#define Ky_pc 1.0 +#define Ku_pc( rec ) (0.5 / Sb(rec)) +#define Kv_pc( rec ) (0.5 / Sr(rec)) +#define Ay_pc 0.0 +#define Au_pc 127.5 +#define Av_pc 127.5 + +#define Y_R( rec, scale ) FIX(Kr_##rec * Ky_##scale) +#define Y_G( rec, scale ) FIX(Kg(rec) * Ky_##scale) +#define Y_B( rec, scale ) FIX(Kb_##rec * Ky_##scale) +#define Y_ADD( scale ) ((uint32_t)(Ay_##scale * INT_FIX + INT_ROUND + 0.5)) + +#define U_R( rec, scale ) FIX(Kr_##rec * Ku_##scale(rec)) +#define U_G( rec, scale ) FIX(Kg(rec) * Ku_##scale(rec)) +#define U_B( rec, scale ) FIX(Sb(rec) * Ku_##scale(rec)) +#define U_ADD( scale ) ((uint32_t)((Au_##scale * INT_FIX + INT_ROUND) * 4 + 0.5)) + +#define V_R( rec, scale ) FIX(Sr(rec) * Kv_##scale(rec)) +#define V_G( rec, scale ) FIX(Kg(rec) * Kv_##scale(rec)) +#define V_B( rec, scale ) FIX(Kb_##rec * Kv_##scale(rec)) +#define V_ADD( scale ) ((uint32_t)((Av_##scale * INT_FIX + INT_ROUND) * 4 + 0.5)) -#define RGB_TO_I420( name, POS_R, POS_G, POS_B, S_RGB ) \ -static void name( x264_image_t *img_dst, x264_image_t *img_src, \ +#define RGB_TO_I420( name, POS_R, POS_G, POS_B, S_RGB, rec, scale ) \ +static void name##_##rec##_##scale( x264_image_t *img_dst, x264_image_t *img_src, \ int i_width, int i_height ) \ { \ uint8_t *src = img_src->plane[0]; \ @@ -408,12 +393,15 @@ static void name( x264_image_t *img_dst, cg = g = ss[POS_G]; \ cb = b = ss[POS_B]; \ \ - yy[0] = (Y_ADD + Y_R * r + Y_G * g + Y_B * b) >> BITS; \ + yy[0] = (Y_ADD(scale) + \ + Y_R(rec, scale) * r + \ + Y_G(rec, scale) * g + \ + Y_B(rec, scale) * b) >> BITS; \ \ cr+= r = ss[POS_R+i_src]; \ cg+= g = ss[POS_G+i_src]; \ cb+= b = ss[POS_B+i_src]; \ - yy[i_y] = (Y_ADD + Y_R * r + Y_G * g + Y_B * b) >> BITS; \ + yy[i_y] = (Y_ADD(scale) + Y_R(rec, scale) * r + Y_G(rec, scale) * g + Y_B(rec, scale) * b) >> BITS; \ yy++; \ ss += S_RGB; \ \ @@ -421,18 +409,18 @@ static void name( x264_image_t *img_dst, cg+= g = ss[POS_G]; \ cb+= b = ss[POS_B]; \ \ - yy[0] = (Y_ADD + Y_R * r + Y_G * g + Y_B * b) >> BITS; \ + yy[0] = (Y_ADD(scale) + Y_R(rec, scale) * r + Y_G(rec, scale) * g + Y_B(rec, scale) * b) >> BITS; \ \ cr+= r = ss[POS_R+i_src]; \ cg+= g = ss[POS_G+i_src]; \ cb+= b = ss[POS_B+i_src]; \ - yy[i_y] = (Y_ADD + Y_R * r + Y_G * g + Y_B * b) >> BITS; \ + yy[i_y] = (Y_ADD(scale) + Y_R(rec, scale) * r + Y_G(rec, scale) * g + Y_B(rec, scale) * b) >> BITS; \ yy++; \ ss += S_RGB; \ \ /* Chroma */ \ - *uu++ = (uint8_t)((U_ADD + U_B * cb - U_R * cr - U_G * cg) >> (BITS+2)); \ - *vv++ = (uint8_t)((V_ADD + V_R * cr - V_G * cg - V_B * cb) >> (BITS+2)); \ + *uu++ = (uint8_t)((U_ADD(scale) + U_B(rec, scale) * cb - U_R(rec, scale) * cr - U_G(rec, scale) * cg) >> (BITS+2)); \ + *vv++ = (uint8_t)((V_ADD(scale) + V_R(rec, scale) * cr - V_G(rec, scale) * cg - V_B(rec, scale) * cb) >> (BITS+2)); \ } \ \ src += 2*i_src; \ @@ -442,11 +430,20 @@ static void name( x264_image_t *img_dst, } \ } -RGB_TO_I420( rgb_to_i420, 0, 1, 2, 3 ) -RGB_TO_I420( bgr_to_i420, 2, 1, 0, 3 ) -RGB_TO_I420( bgra_to_i420, 2, 1, 0, 4 ) +RGB_TO_I420( rgb_to_i420, 0, 1, 2, 3, 601, tv ) +RGB_TO_I420( bgr_to_i420, 2, 1, 0, 3, 601, tv ) +RGB_TO_I420( bgra_to_i420, 2, 1, 0, 4, 601, tv ) +RGB_TO_I420( rgb_to_i420, 0, 1, 2, 3, 601, pc ) +RGB_TO_I420( bgr_to_i420, 2, 1, 0, 3, 601, pc ) +RGB_TO_I420( bgra_to_i420, 2, 1, 0, 4, 601, pc ) +RGB_TO_I420( rgb_to_i420, 0, 1, 2, 3, 709, tv ) +RGB_TO_I420( bgr_to_i420, 2, 1, 0, 3, 709, tv ) +RGB_TO_I420( bgra_to_i420, 2, 1, 0, 4, 709, tv ) +RGB_TO_I420( rgb_to_i420, 0, 1, 2, 3, 709, pc ) +RGB_TO_I420( bgr_to_i420, 2, 1, 0, 3, 709, pc ) +RGB_TO_I420( bgra_to_i420, 2, 1, 0, 4, 709, pc ) -void x264vfw_csp_init( x264vfw_csp_function_t *pf, int i_x264_csp ) +void x264vfw_csp_init( x264vfw_csp_function_t *pf, int i_x264_csp, int i_x264_csp_rec, int i_x264_csp_scale ) { switch( i_x264_csp ) { @@ -457,9 +454,42 @@ void x264vfw_csp_init( x264vfw_csp_funct pf->convert[X264VFW_CSP_YV12] = yv12_to_i420; pf->convert[X264VFW_CSP_YUYV] = yuyv_to_i420; pf->convert[X264VFW_CSP_UYVY] = uyvy_to_i420; - pf->convert[X264VFW_CSP_RGB ] = rgb_to_i420; - pf->convert[X264VFW_CSP_BGR ] = bgr_to_i420; - pf->convert[X264VFW_CSP_BGRA] = bgra_to_i420; + if( i_x264_csp_rec ) + { + // BT.709 + if( i_x264_csp_scale ) + { + // PC Scale + pf->convert[X264VFW_CSP_RGB ] = rgb_to_i420_709_pc; + pf->convert[X264VFW_CSP_BGR ] = bgr_to_i420_709_pc; + pf->convert[X264VFW_CSP_BGRA] = bgra_to_i420_709_pc; + } + else + { + // TV Scale + pf->convert[X264VFW_CSP_RGB ] = rgb_to_i420_709_tv; + pf->convert[X264VFW_CSP_BGR ] = bgr_to_i420_709_tv; + pf->convert[X264VFW_CSP_BGRA] = bgra_to_i420_709_tv; + } + } + else + { + // BT.601 + if( i_x264_csp_scale ) + { + // PC Scale + pf->convert[X264VFW_CSP_RGB ] = rgb_to_i420_601_pc; + pf->convert[X264VFW_CSP_BGR ] = bgr_to_i420_601_pc; + pf->convert[X264VFW_CSP_BGRA] = bgra_to_i420_601_pc; + } + else + { + // TV Scale + pf->convert[X264VFW_CSP_RGB ] = rgb_to_i420_601_tv; + pf->convert[X264VFW_CSP_BGR ] = bgr_to_i420_601_tv; + pf->convert[X264VFW_CSP_BGRA] = bgra_to_i420_601_tv; + } + } break; default: diff -uNrp src.20110124/csp.h src/csp.h --- src.20110124/csp.h 2010-04-24 21:19:24 +0300 +++ src/csp.h 2011-01-24 20:22:56 +0200 @@ -50,6 +50,6 @@ typedef struct x264vfw_csp_t convert[X264VFW_CSP_MAX]; } x264vfw_csp_function_t; -void x264vfw_csp_init( x264vfw_csp_function_t *pf, int i_csp ); +void x264vfw_csp_init( x264vfw_csp_function_t *pf, int i_x264_csp, int i_x264_csp_rec, int i_x264_csp_scale ); #endif diff -uNrp src.20110124/x264vfw.h src/x264vfw.h --- src.20110124/x264vfw.h 2010-10-16 18:25:11 +0300 +++ src/x264vfw.h 2011-01-24 20:42:39 +0200 @@ -251,6 +251,10 @@ typedef struct cli_output_opt_t cli_output_opt; hnd_t cli_hout; + /* Input CSP */ + int i_input_csp_rec; /* 0 - BT.601; 1 - BT.709 */ + int i_input_csp_scale; /* 0 - TV Scale; 1 - PC Scale */ + /* Decoder */ #if defined(HAVE_FFMPEG) && X264VFW_USE_DECODER int decoder_enabled;