[vlc-devel] [PATCH] adjust: add 10-bit support (Fixes #9600)
Tristan Matthews
tmatth at videolan.org
Tue May 5 16:53:43 CEST 2015
---
modules/video_filter/adjust.c | 153 ++++++++++++++++++++++++----------
modules/video_filter/adjust_sat_hue.c | 124 +++++++++++++++++++++++----
modules/video_filter/adjust_sat_hue.h | 12 +++
3 files changed, 233 insertions(+), 56 deletions(-)
diff --git a/modules/video_filter/adjust.c b/modules/video_filter/adjust.c
index 620f36e..9573f72 100644
--- a/modules/video_filter/adjust.c
+++ b/modules/video_filter/adjust.c
@@ -45,6 +45,12 @@
# define M_PI 3.14159265358979323846
#endif
+#define CASE_PLANAR_YUV10 \
+ case VLC_CODEC_I420_10L: \
+ case VLC_CODEC_I420_10B: \
+ case VLC_CODEC_I444_10L: \
+ case VLC_CODEC_I444_10B:
+
/*****************************************************************************
* Local prototypes
*****************************************************************************/
@@ -173,6 +179,13 @@ static int Create( vlc_object_t *p_this )
p_sys->pf_process_sat_hue = planar_sat_hue_C;
break;
+ CASE_PLANAR_YUV10
+ /* Planar YUV 10-bit */
+ p_filter->pf_video_filter = FilterPlanar;
+ p_sys->pf_process_sat_hue_clip = planar_sat_hue_clip_C_10bpp;
+ p_sys->pf_process_sat_hue = planar_sat_hue_C_10bpp;
+ break;
+
CASE_PACKED_YUV_422
/* Packed YUV 4:2:2 */
p_filter->pf_video_filter = FilterPacked;
@@ -223,12 +236,11 @@ static void Destroy( vlc_object_t *p_this )
*****************************************************************************/
static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic )
{
- int pi_luma[256];
- int pi_gamma[256];
+ /* The full range will only be used for 10-bit */
+ int pi_luma[1024];
+ int pi_gamma[1024];
picture_t *p_outpic;
- uint8_t *p_in, *p_in_end, *p_line_end;
- uint8_t *p_out;
filter_sys_t *p_sys = p_filter->p_sys;
@@ -241,12 +253,28 @@ static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic )
return NULL;
}
+ bool b_10bpp;
+ switch( p_filter->fmt_in.video.i_chroma )
+ {
+ CASE_PLANAR_YUV10
+ b_10bpp = true;
+ break;
+ default:
+ b_10bpp = false;
+ }
+
+ const float f_range = b_10bpp ? 1024.f : 256.f;
+ const float f_max = f_range - 1.f;
+ const int i_max = f_max;
+ const int i_range = f_range;
+ const unsigned i_mid = i_range >> 1;
+
/* Get variables */
vlc_mutex_lock( &p_sys->lock );
- int32_t i_cont = lroundf( p_sys->f_contrast * 255.f );
- int32_t i_lum = lroundf( (p_sys->f_brightness - 1.f) * 255.f );
+ int32_t i_cont = lroundf( p_sys->f_contrast * f_max );
+ int32_t i_lum = lroundf( (p_sys->f_brightness - 1.f) * f_max );
float f_hue = p_sys->f_hue * (float)(M_PI / 180.);
- int i_sat = (int)( p_sys->f_saturation * 256.f );
+ int i_sat = (int)( p_sys->f_saturation * f_range );
float f_gamma = 1.f / p_sys->f_gamma;
bool b_thres = p_sys->b_brightness_threshold;
vlc_mutex_unlock( &p_sys->lock );
@@ -259,18 +287,18 @@ static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic )
/* Contrast is a fast but kludged function, so I put this gap to be
* cleaner :) */
- i_lum += 128 - i_cont / 2;
+ i_lum += i_mid - i_cont / 2;
/* Fill the gamma lookup table */
- for( unsigned i = 0 ; i < 256 ; i++ )
+ for( int i = 0 ; i < i_range; i++ )
{
- pi_gamma[ i ] = clip_uint8_vlc( powf(i / 255.f, f_gamma) * 255.f);
+ pi_gamma[ i ] = VLC_CLIP( powf(i / f_max, f_gamma) * f_max, 0, i_max );
}
/* Fill the luma lookup table */
- for( unsigned i = 0 ; i < 256 ; i++ )
+ for( int i = 0 ; i < i_range; i++ )
{
- pi_luma[ i ] = pi_gamma[clip_uint8_vlc( i_lum + i_cont * i / 256)];
+ pi_luma[ i ] = pi_gamma[VLC_CLIP( ( i_lum + i_cont * i / i_range), 0, i_max )];
}
}
else
@@ -279,9 +307,9 @@ static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic )
* We get luma as threshold value: the higher it is, the darker is
* the image. Should I reverse this?
*/
- for( int i = 0 ; i < 256 ; i++ )
+ for( int i = 0 ; i < i_range; i++ )
{
- pi_luma[ i ] = (i < i_lum) ? 0 : 255;
+ pi_luma[ i ] = (i < i_lum) ? 0 : i_max;
}
/*
@@ -293,50 +321,91 @@ static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic )
/*
* Do the Y plane
*/
-
- p_in = p_pic->p[Y_PLANE].p_pixels;
- p_in_end = p_in + p_pic->p[Y_PLANE].i_visible_lines
- * p_pic->p[Y_PLANE].i_pitch - 8;
-
- p_out = p_outpic->p[Y_PLANE].p_pixels;
-
- for( ; p_in < p_in_end ; )
+ if ( b_10bpp )
{
- p_line_end = p_in + p_pic->p[Y_PLANE].i_visible_pitch - 8;
+ uint16_t *p_in, *p_in_end, *p_line_end;
+ uint16_t *p_out;
+ p_in = (uint16_t *) p_pic->p[Y_PLANE].p_pixels;
+ p_in_end = p_in + p_pic->p[Y_PLANE].i_visible_lines
+ * (p_pic->p[Y_PLANE].i_pitch >> 1) - 8;
- for( ; p_in < p_line_end ; )
+ p_out = (uint16_t *) p_outpic->p[Y_PLANE].p_pixels;
+
+ for( ; p_in < p_in_end ; )
{
- /* Do 8 pixels at a time */
- *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
- *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
- *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
- *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
+ p_line_end = p_in + (p_pic->p[Y_PLANE].i_visible_pitch >> 1) - 8;
+
+ for( ; p_in < p_line_end ; )
+ {
+ /* Do 8 pixels at a time */
+ *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
+ *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
+ *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
+ *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
+ }
+
+ p_line_end += 8;
+
+ for( ; p_in < p_line_end ; )
+ {
+ *p_out++ = pi_luma[ *p_in++ ];
+ }
+
+ p_in += (p_pic->p[Y_PLANE].i_pitch >> 1)
+ - (p_pic->p[Y_PLANE].i_visible_pitch >> 1);
+ p_out += (p_outpic->p[Y_PLANE].i_pitch >> 1)
+ - (p_outpic->p[Y_PLANE].i_visible_pitch >> 1);
}
+ }
+ else
+ {
+ uint8_t *p_in, *p_in_end, *p_line_end;
+ uint8_t *p_out;
+ p_in = p_pic->p[Y_PLANE].p_pixels;
+ p_in_end = p_in + p_pic->p[Y_PLANE].i_visible_lines
+ * p_pic->p[Y_PLANE].i_pitch - 8;
- p_line_end += 8;
+ p_out = p_outpic->p[Y_PLANE].p_pixels;
- for( ; p_in < p_line_end ; )
+ for( ; p_in < p_in_end ; )
{
- *p_out++ = pi_luma[ *p_in++ ];
+ p_line_end = p_in + p_pic->p[Y_PLANE].i_visible_pitch - 8;
+
+ for( ; p_in < p_line_end ; )
+ {
+ /* Do 8 pixels at a time */
+ *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
+ *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
+ *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
+ *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
+ }
+
+ p_line_end += 8;
+
+ for( ; p_in < p_line_end ; )
+ {
+ *p_out++ = pi_luma[ *p_in++ ];
+ }
+
+ p_in += p_pic->p[Y_PLANE].i_pitch
+ - p_pic->p[Y_PLANE].i_visible_pitch;
+ p_out += p_outpic->p[Y_PLANE].i_pitch
+ - p_outpic->p[Y_PLANE].i_visible_pitch;
}
-
- p_in += p_pic->p[Y_PLANE].i_pitch
- - p_pic->p[Y_PLANE].i_visible_pitch;
- p_out += p_outpic->p[Y_PLANE].i_pitch
- - p_outpic->p[Y_PLANE].i_visible_pitch;
}
/*
* Do the U and V planes
*/
- int i_sin = sinf(f_hue) * 256.f;
- int i_cos = cosf(f_hue) * 256.f;
+ int i_sin = sinf(f_hue) * f_max;
+ int i_cos = cosf(f_hue) * f_max;
- int i_x = ( cosf(f_hue) + sinf(f_hue) ) * 32768.f;
- int i_y = ( cosf(f_hue) - sinf(f_hue) ) * 32768.f;
+ /* pow(2, (bpp * 2) - 1) */
+ int i_x = ( cosf(f_hue) + sinf(f_hue) ) * f_range * i_mid;
+ int i_y = ( cosf(f_hue) - sinf(f_hue) ) * f_range * i_mid;
- if ( i_sat > 256 )
+ if ( i_sat > i_range )
{
/* Currently no errors are implemented in the function, if any are added
* check them here */
diff --git a/modules/video_filter/adjust_sat_hue.c b/modules/video_filter/adjust_sat_hue.c
index ab7b826..9d52297 100644
--- a/modules/video_filter/adjust_sat_hue.c
+++ b/modules/video_filter/adjust_sat_hue.c
@@ -30,19 +30,23 @@
#include "filter_picture.h"
#include "adjust_sat_hue.h"
-#define PLANAR_WRITE_UV_CLIP() \
+#define I_RANGE( i_bpp ) (1 << i_bpp)
+#define I_MAX( i_bpp ) (I_RANGE( i_bpp ) - 1)
+#define I_MID( i_bpp ) (I_RANGE( i_bpp ) >> 1)
+
+#define PLANAR_WRITE_UV_CLIP( i_bpp ) \
i_u = *p_in++ ; i_v = *p_in_v++ ; \
- *p_out++ = clip_uint8_vlc( (( ((i_u * i_cos + i_v * i_sin - i_x) >> 8) \
- * i_sat) >> 8) + 128); \
- *p_out_v++ = clip_uint8_vlc( (( ((i_v * i_cos - i_u * i_sin - i_y) >> 8) \
- * i_sat) >> 8) + 128)
+ *p_out++ = VLC_CLIP( (( ((i_u * i_cos + i_v * i_sin - i_x) >> i_bpp) \
+ * i_sat) >> i_bpp) + I_MID( i_bpp ), 0, I_MAX( i_bpp ) ); \
+ *p_out_v++ = VLC_CLIP( (( ((i_v * i_cos - i_u * i_sin - i_y) >> i_bpp) \
+ * i_sat) >> i_bpp) + I_MID( i_bpp ), 0, I_MAX( i_bpp ) )
-#define PLANAR_WRITE_UV() \
+#define PLANAR_WRITE_UV( i_bpp ) \
i_u = *p_in++ ; i_v = *p_in_v++ ; \
- *p_out++ = (( ((i_u * i_cos + i_v * i_sin - i_x) >> 8) \
- * i_sat) >> 8) + 128; \
- *p_out_v++ = (( ((i_v * i_cos - i_u * i_sin - i_y) >> 8) \
- * i_sat) >> 8) + 128
+ *p_out++ = (( ((i_u * i_cos + i_v * i_sin - i_x) >> i_bpp) \
+ * i_sat) >> i_bpp) + I_MID( i_bpp ); \
+ *p_out_v++ = (( ((i_v * i_cos - i_u * i_sin - i_y) >> i_bpp) \
+ * i_sat) >> i_bpp) + I_MID( i_bpp )
#define PACKED_WRITE_UV_CLIP() \
i_u = *p_in; p_in += 4; i_v = *p_in_v; p_in_v += 4; \
@@ -93,14 +97,14 @@ int planar_sat_hue_clip_C( picture_t * p_pic, picture_t * p_outpic, int i_sin, i
for( ; p_in < p_line_end ; )
{
/* Do 8 pixels at a time */
- ADJUST_8_TIMES( PLANAR_WRITE_UV_CLIP() );
+ ADJUST_8_TIMES( PLANAR_WRITE_UV_CLIP( 8 ) );
}
p_line_end += 8;
for( ; p_in < p_line_end ; )
{
- PLANAR_WRITE_UV_CLIP();
+ PLANAR_WRITE_UV_CLIP( 8 );
}
p_in += p_pic->p[U_PLANE].i_pitch
@@ -139,14 +143,14 @@ int planar_sat_hue_C( picture_t * p_pic, picture_t * p_outpic, int i_sin, int i_
for( ; p_in < p_line_end ; )
{
/* Do 8 pixels at a time */
- ADJUST_8_TIMES( PLANAR_WRITE_UV() );
+ ADJUST_8_TIMES( PLANAR_WRITE_UV( 8 ) );
}
p_line_end += 8;
for( ; p_in < p_line_end ; )
{
- PLANAR_WRITE_UV();
+ PLANAR_WRITE_UV( 8 );
}
p_in += p_pic->p[U_PLANE].i_pitch
@@ -162,6 +166,98 @@ int planar_sat_hue_C( picture_t * p_pic, picture_t * p_outpic, int i_sin, int i_
return VLC_SUCCESS;
}
+int planar_sat_hue_clip_C_10bpp( picture_t * p_pic, picture_t * p_outpic, int i_sin, int i_cos,
+ int i_sat, int i_x, int i_y )
+{
+ uint16_t *p_in, *p_in_v, *p_in_end, *p_line_end;
+ uint16_t *p_out, *p_out_v;
+
+ p_in = (uint16_t *) p_pic->p[U_PLANE].p_pixels;
+ p_in_v = (uint16_t *) p_pic->p[V_PLANE].p_pixels;
+ p_in_end = p_in + p_pic->p[U_PLANE].i_visible_lines
+ * (p_pic->p[U_PLANE].i_pitch >> 1) - 8;
+
+ p_out = (uint16_t *) p_outpic->p[U_PLANE].p_pixels;
+ p_out_v = (uint16_t *) p_outpic->p[V_PLANE].p_pixels;
+
+ uint16_t i_u, i_v;
+
+ for( ; p_in < p_in_end ; )
+ {
+ p_line_end = p_in + (p_pic->p[U_PLANE].i_visible_pitch >> 1) - 8;
+
+ for( ; p_in < p_line_end ; )
+ {
+ /* Do 8 pixels at a time */
+ ADJUST_8_TIMES( PLANAR_WRITE_UV_CLIP( 10 ) );
+ }
+
+ p_line_end += 8;
+
+ for( ; p_in < p_line_end ; )
+ {
+ PLANAR_WRITE_UV_CLIP( 10 );
+ }
+
+ p_in += (p_pic->p[U_PLANE].i_pitch >> 1)
+ - (p_pic->p[U_PLANE].i_visible_pitch >> 1);
+ p_in_v += (p_pic->p[V_PLANE].i_pitch >> 1)
+ - (p_pic->p[V_PLANE].i_visible_pitch >> 1);
+ p_out += (p_outpic->p[U_PLANE].i_pitch >> 1)
+ - (p_outpic->p[U_PLANE].i_visible_pitch >> 1);
+ p_out_v += (p_outpic->p[V_PLANE].i_pitch >> 1)
+ - (p_outpic->p[V_PLANE].i_visible_pitch >> 1);
+ }
+
+ return VLC_SUCCESS;
+}
+
+int planar_sat_hue_C_10bpp( picture_t * p_pic, picture_t * p_outpic, int i_sin, int i_cos,
+ int i_sat, int i_x, int i_y )
+{
+ uint16_t *p_in, *p_in_v, *p_in_end, *p_line_end;
+ uint16_t *p_out, *p_out_v;
+
+ p_in = (uint16_t *) p_pic->p[U_PLANE].p_pixels;
+ p_in_v = (uint16_t *) p_pic->p[V_PLANE].p_pixels;
+ p_in_end = (uint16_t *) p_in + p_pic->p[U_PLANE].i_visible_lines
+ * (p_pic->p[U_PLANE].i_pitch >> 1) - 8;
+
+ p_out = (uint16_t *) p_outpic->p[U_PLANE].p_pixels;
+ p_out_v = (uint16_t *) p_outpic->p[V_PLANE].p_pixels;
+
+ uint16_t i_u, i_v;
+
+ for( ; p_in < p_in_end ; )
+ {
+ p_line_end = p_in + (p_pic->p[U_PLANE].i_visible_pitch >> 1) - 8;
+
+ for( ; p_in < p_line_end ; )
+ {
+ /* Do 8 pixels at a time */
+ ADJUST_8_TIMES( PLANAR_WRITE_UV( 10 ) );
+ }
+
+ p_line_end += 8;
+
+ for( ; p_in < p_line_end ; )
+ {
+ PLANAR_WRITE_UV( 10 );
+ }
+
+ p_in += (p_pic->p[U_PLANE].i_pitch >> 1)
+ - (p_pic->p[U_PLANE].i_visible_pitch >> 1);
+ p_in_v += (p_pic->p[V_PLANE].i_pitch >> 1)
+ - (p_pic->p[V_PLANE].i_visible_pitch >> 1);
+ p_out += (p_outpic->p[U_PLANE].i_pitch >> 1)
+ - (p_outpic->p[U_PLANE].i_visible_pitch >> 1);
+ p_out_v += (p_outpic->p[V_PLANE].i_pitch >> 1)
+ - (p_outpic->p[V_PLANE].i_visible_pitch >> 1);
+ }
+
+ return VLC_SUCCESS;
+}
+
int packed_sat_hue_clip_C( picture_t * p_pic, picture_t * p_outpic, int i_sin, int i_cos,
int i_sat, int i_x, int i_y )
{
diff --git a/modules/video_filter/adjust_sat_hue.h b/modules/video_filter/adjust_sat_hue.h
index f4dcd66..f4514d4 100644
--- a/modules/video_filter/adjust_sat_hue.h
+++ b/modules/video_filter/adjust_sat_hue.h
@@ -49,6 +49,18 @@ int planar_sat_hue_clip_C( picture_t * p_pic, picture_t * p_outpic,
*/
int planar_sat_hue_C( picture_t * p_pic, picture_t * p_outpic,
int i_sin, int i_cos, int i_sat, int i_x, int i_y );
+/**
+ * Basic C compiler generated function for 10-bit planar format, i_sat > 1024
+ */
+int planar_sat_hue_clip_C_10bpp( picture_t * p_pic, picture_t * p_outpic,
+ int i_sin, int i_cos, int i_sat, int i_x, int i_y );
+
+/**
+ * Basic C compiler generated function for 10-bit planar format, i_sat <= 1024
+ */
+int planar_sat_hue_C_10bpp( picture_t * p_pic, picture_t * p_outpic,
+ int i_sin, int i_cos, int i_sat, int i_x, int i_y );
+
/**
* Basic C compiler generated function for packed format, i_sat > 256
--
2.1.0
More information about the vlc-devel
mailing list