Commit b5662ea9 authored by Tristan Matthews's avatar Tristan Matthews

adjust: add 9-bit and 10-bit support (Fixes #9600)

parent 3feced49
...@@ -173,6 +173,14 @@ static int Create( vlc_object_t *p_this ) ...@@ -173,6 +173,14 @@ static int Create( vlc_object_t *p_this )
p_sys->pf_process_sat_hue = planar_sat_hue_C; p_sys->pf_process_sat_hue = planar_sat_hue_C;
break; break;
CASE_PLANAR_YUV10
CASE_PLANAR_YUV9
/* Planar YUV 9-bit or 10-bit */
p_filter->pf_video_filter = FilterPlanar;
p_sys->pf_process_sat_hue_clip = planar_sat_hue_clip_C_16;
p_sys->pf_process_sat_hue = planar_sat_hue_C_16;
break;
CASE_PACKED_YUV_422 CASE_PACKED_YUV_422
/* Packed YUV 4:2:2 */ /* Packed YUV 4:2:2 */
p_filter->pf_video_filter = FilterPacked; p_filter->pf_video_filter = FilterPacked;
...@@ -223,12 +231,11 @@ static void Destroy( vlc_object_t *p_this ) ...@@ -223,12 +231,11 @@ static void Destroy( vlc_object_t *p_this )
*****************************************************************************/ *****************************************************************************/
static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic ) static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic )
{ {
int pi_luma[256]; /* The full range will only be used for 10-bit */
int pi_gamma[256]; int pi_luma[1024];
int pi_gamma[1024];
picture_t *p_outpic; 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; filter_sys_t *p_sys = p_filter->p_sys;
...@@ -241,12 +248,35 @@ static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic ) ...@@ -241,12 +248,35 @@ static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic )
return NULL; return NULL;
} }
bool b_16bit;
float f_range;
switch( p_filter->fmt_in.video.i_chroma )
{
CASE_PLANAR_YUV10
b_16bit = true;
f_range = 1024.f;
break;
CASE_PLANAR_YUV9
b_16bit = true;
f_range = 512.f;
break;
default:
b_16bit = false;
f_range = 256.f;
}
const float f_max = f_range - 1.f;
const unsigned i_max = f_max;
const int i_range = f_range;
const unsigned i_size = i_range;
const unsigned i_mid = i_range >> 1;
/* Get variables */ /* Get variables */
vlc_mutex_lock( &p_sys->lock ); vlc_mutex_lock( &p_sys->lock );
int32_t i_cont = lroundf( p_sys->f_contrast * 255.f ); int32_t i_cont = lroundf( p_sys->f_contrast * f_max );
int32_t i_lum = lroundf( (p_sys->f_brightness - 1.f) * 255.f ); int32_t i_lum = lroundf( (p_sys->f_brightness - 1.f) * f_max );
float f_hue = p_sys->f_hue * (float)(M_PI / 180.); 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; float f_gamma = 1.f / p_sys->f_gamma;
bool b_thres = p_sys->b_brightness_threshold; bool b_thres = p_sys->b_brightness_threshold;
vlc_mutex_unlock( &p_sys->lock ); vlc_mutex_unlock( &p_sys->lock );
...@@ -259,18 +289,18 @@ static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic ) ...@@ -259,18 +289,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 /* Contrast is a fast but kludged function, so I put this gap to be
* cleaner :) */ * cleaner :) */
i_lum += 128 - i_cont / 2; i_lum += i_mid - i_cont / 2;
/* Fill the gamma lookup table */ /* Fill the gamma lookup table */
for( unsigned i = 0 ; i < 256 ; i++ ) for( unsigned i = 0 ; i < i_size; 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 */ /* Fill the luma lookup table */
for( unsigned i = 0 ; i < 256 ; i++ ) for( unsigned i = 0 ; i < i_size; 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 else
...@@ -279,9 +309,9 @@ static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic ) ...@@ -279,9 +309,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 * We get luma as threshold value: the higher it is, the darker is
* the image. Should I reverse this? * 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 +323,91 @@ static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic ) ...@@ -293,50 +323,91 @@ static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic )
/* /*
* Do the Y plane * Do the Y plane
*/ */
if ( b_16bit )
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 ; )
{ {
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_line_end = p_in + (p_pic->p[Y_PLANE].i_visible_pitch >> 1) - 8;
*p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
*p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ]; for( ; p_in < p_line_end ; )
*p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ]; {
*p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ]; /* 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 * Do the U and V planes
*/ */
int i_sin = sinf(f_hue) * 256.f; int i_sin = sinf(f_hue) * f_max;
int i_cos = cosf(f_hue) * 256.f; int i_cos = cosf(f_hue) * f_max;
int i_x = ( cosf(f_hue) + sinf(f_hue) ) * 32768.f; /* pow(2, (bpp * 2) - 1) */
int i_y = ( cosf(f_hue) - sinf(f_hue) ) * 32768.f; 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 /* Currently no errors are implemented in the function, if any are added
* check them here */ * check them here */
......
...@@ -26,23 +26,28 @@ ...@@ -26,23 +26,28 @@
# include "config.h" # include "config.h"
#endif #endif
#include <assert.h>
#include <vlc_filter.h> #include <vlc_filter.h>
#include "filter_picture.h" #include "filter_picture.h"
#include "adjust_sat_hue.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++ ; \ 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) \ *p_out++ = VLC_CLIP( (( ((i_u * i_cos + i_v * i_sin - i_x) >> i_bpp) \
* i_sat) >> 8) + 128); \ * i_sat) >> i_bpp) + I_MID( i_bpp ), 0, I_MAX( i_bpp ) ); \
*p_out_v++ = clip_uint8_vlc( (( ((i_v * i_cos - i_u * i_sin - i_y) >> 8) \ *p_out_v++ = VLC_CLIP( (( ((i_v * i_cos - i_u * i_sin - i_y) >> i_bpp) \
* i_sat) >> 8) + 128) * 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++ ; \ i_u = *p_in++ ; i_v = *p_in_v++ ; \
*p_out++ = (( ((i_u * i_cos + i_v * i_sin - i_x) >> 8) \ *p_out++ = (( ((i_u * i_cos + i_v * i_sin - i_x) >> i_bpp) \
* i_sat) >> 8) + 128; \ * i_sat) >> i_bpp) + I_MID( i_bpp ); \
*p_out_v++ = (( ((i_v * i_cos - i_u * i_sin - i_y) >> 8) \ *p_out_v++ = (( ((i_v * i_cos - i_u * i_sin - i_y) >> i_bpp) \
* i_sat) >> 8) + 128 * i_sat) >> i_bpp) + I_MID( i_bpp )
#define PACKED_WRITE_UV_CLIP() \ #define PACKED_WRITE_UV_CLIP() \
i_u = *p_in; p_in += 4; i_v = *p_in_v; p_in_v += 4; \ i_u = *p_in; p_in += 4; i_v = *p_in_v; p_in_v += 4; \
...@@ -91,14 +96,14 @@ int planar_sat_hue_clip_C( picture_t * p_pic, picture_t * p_outpic, int i_sin, i ...@@ -91,14 +96,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 ; ) for( ; p_in < p_line_end ; )
{ {
/* Do 8 pixels at a time */ /* 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; p_line_end += 8;
for( ; p_in < p_line_end ; ) for( ; p_in < p_line_end ; )
{ {
PLANAR_WRITE_UV_CLIP(); PLANAR_WRITE_UV_CLIP( 8 );
} }
p_in += p_pic->p[U_PLANE].i_pitch p_in += p_pic->p[U_PLANE].i_pitch
...@@ -137,14 +142,14 @@ int planar_sat_hue_C( picture_t * p_pic, picture_t * p_outpic, int i_sin, int i_ ...@@ -137,14 +142,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 ; ) for( ; p_in < p_line_end ; )
{ {
/* Do 8 pixels at a time */ /* Do 8 pixels at a time */
ADJUST_8_TIMES( PLANAR_WRITE_UV() ); ADJUST_8_TIMES( PLANAR_WRITE_UV( 8 ) );
} }
p_line_end += 8; p_line_end += 8;
for( ; p_in < p_line_end ; ) for( ; p_in < p_line_end ; )
{ {
PLANAR_WRITE_UV(); PLANAR_WRITE_UV( 8 );
} }
p_in += p_pic->p[U_PLANE].i_pitch p_in += p_pic->p[U_PLANE].i_pitch
...@@ -160,6 +165,124 @@ int planar_sat_hue_C( picture_t * p_pic, picture_t * p_outpic, int i_sin, int i_ ...@@ -160,6 +165,124 @@ int planar_sat_hue_C( picture_t * p_pic, picture_t * p_outpic, int i_sin, int i_
return VLC_SUCCESS; return VLC_SUCCESS;
} }
int planar_sat_hue_clip_C_16( 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;
int i_bpp;
switch( p_pic->format.i_chroma )
{
CASE_PLANAR_YUV10
i_bpp = 10;
break;
CASE_PLANAR_YUV9
i_bpp = 9;
break;
default:
vlc_assert_unreachable();
}
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( i_bpp ) );
}
p_line_end += 8;
for( ; p_in < p_line_end ; )
{
PLANAR_WRITE_UV_CLIP( i_bpp );
}
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_16( 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;
int i_bpp;
switch( p_pic->format.i_chroma )
{
CASE_PLANAR_YUV10
i_bpp = 10;
break;
CASE_PLANAR_YUV9
i_bpp = 9;
break;
default:
vlc_assert_unreachable();
}
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( i_bpp ) );
}
p_line_end += 8;
for( ; p_in < p_line_end ; )
{
PLANAR_WRITE_UV( i_bpp );
}
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 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 ) int i_sat, int i_x, int i_y )
{ {
......
...@@ -49,6 +49,18 @@ int planar_sat_hue_clip_C( picture_t * p_pic, picture_t * p_outpic, ...@@ -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 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 ); int i_sin, int i_cos, int i_sat, int i_x, int i_y );
/**
* Basic C compiler generated function for {9,10}-bit planar format, i_sat > {512,1024}
*/
int planar_sat_hue_clip_C_16( 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 {9,10}-bit planar format, i_sat <= {512,1024}
*/
int planar_sat_hue_C_16( 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 * Basic C compiler generated function for packed format, i_sat > 256
......
...@@ -36,6 +36,18 @@ ...@@ -36,6 +36,18 @@
case VLC_CODEC_I422: \ case VLC_CODEC_I422: \
case VLC_CODEC_J422: case VLC_CODEC_J422:
#define CASE_PLANAR_YUV10 \
case VLC_CODEC_I420_10L: \
case VLC_CODEC_I420_10B: \
case VLC_CODEC_I444_10L: \
case VLC_CODEC_I444_10B:
#define CASE_PLANAR_YUV9 \
case VLC_CODEC_I420_9L: \
case VLC_CODEC_I420_9B: \
case VLC_CODEC_I444_9L: \
case VLC_CODEC_I444_9B:
#define CASE_PLANAR_YUV \ #define CASE_PLANAR_YUV \
CASE_PLANAR_YUV_SQUARE \ CASE_PLANAR_YUV_SQUARE \
CASE_PLANAR_YUV_NONSQUARE \ CASE_PLANAR_YUV_NONSQUARE \
......
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