/*****************************************************************************
* sepia.c : Sepia video plugin for vlc
*****************************************************************************
- * Copyright (C) 2010 the VideoLAN team
+ * Copyright (C) 2010 VLC authors and VideoLAN
* $Id$
*
* Authors: Branko Kokanovic <branko.kokanovic@gmail.com>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_filter.h>
+#include <vlc_cpu.h>
+#include <vlc_atomic.h>
#include <assert.h>
#include "filter_picture.h"
static void RVSepia( picture_t *, picture_t *, int );
static void PlanarI420Sepia( picture_t *, picture_t *, int);
static void PackedYUVSepia( picture_t *, picture_t *, int);
-static void YuvSepia2( uint8_t *, uint8_t *, uint8_t *, uint8_t *,
- const uint8_t, const uint8_t, const uint8_t, const uint8_t,
- int );
-static void YuvSepia4( uint8_t *, uint8_t *, uint8_t *, uint8_t *, uint8_t *,
- uint8_t *, const uint8_t, const uint8_t, const uint8_t,
- const uint8_t, const uint8_t, const uint8_t, int );
-static void Sepia( int *, int *, int *, int );
static picture_t *Filter( filter_t *, picture_t * );
-
static const char *const ppsz_filter_options[] = {
"intensity", NULL
};
set_category( CAT_VIDEO )
set_subcategory( SUBCAT_VIDEO_VFILTER )
set_capability( "video filter2", 0 )
- add_integer_with_range( CFG_PREFIX "intensity", 30, 0, 255, NULL,
+ add_integer_with_range( CFG_PREFIX "intensity", 120, 0, 255,
SEPIA_INTENSITY_TEXT, SEPIA_INTENSITY_LONGTEXT,
false )
set_callbacks( Create, Destroy )
struct filter_sys_t
{
SepiaFunction pf_sepia;
- int i_intensity;
- vlc_spinlock_t lock;
+ atomic_int i_intensity;
};
/*****************************************************************************
config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
p_filter->p_cfg );
- p_sys->i_intensity= var_CreateGetIntegerCommand( p_filter,
- CFG_PREFIX "intensity" );
-
- vlc_spin_init( &p_sys->lock );
-
+ atomic_init( &p_sys->i_intensity,
+ var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "intensity" ) );
var_AddCallback( p_filter, CFG_PREFIX "intensity", FilterCallback, NULL );
p_filter->pf_video_filter = Filter;
var_DelCallback( p_filter, CFG_PREFIX "intensity", FilterCallback, NULL );
- vlc_spin_destroy( &p_filter->p_sys->lock );
free( p_filter->p_sys );
}
static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
{
picture_t *p_outpic;
- int intensity;
if( !p_pic ) return NULL;
filter_sys_t *p_sys = p_filter->p_sys;
- vlc_spin_lock( &p_sys->lock );
- intensity = p_sys->i_intensity;
- vlc_spin_unlock( &p_sys->lock );
+ int intensity = atomic_load( &p_sys->i_intensity );
p_outpic = filter_NewPicture( p_filter );
if( !p_outpic )
return CopyInfoAndRelease( p_outpic, p_pic );
}
+#if defined(CAN_COMPILE_SSE2)
+/*****************************************************************************
+ * Sepia8ySSE2
+ *****************************************************************************
+ * This function applies sepia effect to eight bytes of yellow using SSE4.1
+ * instructions. It copies those 8 bytes to 128b register and fills the gaps
+ * with zeroes and following operations are made with word-operating instructs.
+ *****************************************************************************/
+VLC_SSE
+static inline void Sepia8ySSE2(uint8_t * dst, const uint8_t * src,
+ int i_intensity_spread)
+{
+ __asm__ volatile (
+ // y = y - y / 4 + i_intensity / 4
+ "movq (%1), %%xmm1\n"
+ "punpcklbw %%xmm7, %%xmm1\n"
+ "movq (%1), %%xmm2\n" // store bytes as words with 0s in between
+ "punpcklbw %%xmm7, %%xmm2\n"
+ "movd %2, %%xmm3\n"
+ "pshufd $0, %%xmm3, %%xmm3\n"
+ "psrlw $2, %%xmm2\n" // rotate right 2
+ "psubusb %%xmm1, %%xmm2\n" // subtract
+ "psrlw $2, %%xmm3\n"
+ "paddsb %%xmm1, %%xmm3\n" // add
+ "packuswb %%xmm2, %%xmm1\n" // pack back to bytes
+ "movq %%xmm1, (%0) \n" // load to dest
+ :
+ :"r" (dst), "r"(src), "r"(i_intensity_spread)
+ :"memory", "xmm1", "xmm2", "xmm3");
+}
+
+VLC_SSE
+static void PlanarI420SepiaSSE( picture_t *p_pic, picture_t *p_outpic,
+ int i_intensity )
+{
+ /* prepared values to copy for U and V channels */
+ const uint8_t filling_const_8u = 128 - i_intensity / 6;
+ const uint8_t filling_const_8v = 128 + i_intensity / 14;
+ /* prepared value for faster broadcasting in xmm register */
+ int i_intensity_spread = 0x10001 * (uint8_t) i_intensity;
+
+ __asm__ volatile(
+ "pxor %%xmm7, %%xmm7\n"
+ ::: "xmm7");
+
+ /* iterate for every two visible line in the frame */
+ for (int y = 0; y < p_pic->p[Y_PLANE].i_visible_lines - 1; y += 2)
+ {
+ const int i_dy_line1_start = y * p_outpic->p[Y_PLANE].i_pitch;
+ const int i_dy_line2_start = (y + 1) * p_outpic->p[Y_PLANE].i_pitch;
+ const int i_du_line_start = (y / 2) * p_outpic->p[U_PLANE].i_pitch;
+ const int i_dv_line_start = (y / 2) * p_outpic->p[V_PLANE].i_pitch;
+ int x = 0;
+ /* iterate for every visible line in the frame (eight values at once) */
+ for ( ; x < p_pic->p[Y_PLANE].i_visible_pitch - 15; x += 16 )
+ {
+ /* Compute yellow channel values with asm function */
+ Sepia8ySSE2(&p_outpic->p[Y_PLANE].p_pixels[i_dy_line1_start + x],
+ &p_pic->p[Y_PLANE].p_pixels[i_dy_line1_start + x],
+ i_intensity_spread );
+ Sepia8ySSE2(&p_outpic->p[Y_PLANE].p_pixels[i_dy_line2_start + x],
+ &p_pic->p[Y_PLANE].p_pixels[i_dy_line2_start + x],
+ i_intensity_spread );
+ Sepia8ySSE2(&p_outpic->p[Y_PLANE].p_pixels[i_dy_line1_start + x + 8],
+ &p_pic->p[Y_PLANE].p_pixels[i_dy_line1_start + x + 8],
+ i_intensity_spread );
+ Sepia8ySSE2(&p_outpic->p[Y_PLANE].p_pixels[i_dy_line2_start + x + 8],
+ &p_pic->p[Y_PLANE].p_pixels[i_dy_line2_start + x + 8],
+ i_intensity_spread );
+ /* Copy precomputed values to destination memory location */
+ memset(&p_outpic->p[U_PLANE].p_pixels[i_du_line_start + (x / 2)],
+ filling_const_8u, 8 );
+ memset(&p_outpic->p[V_PLANE].p_pixels[i_dv_line_start + (x / 2)],
+ filling_const_8v, 8 );
+ }
+ /* Completing the job, the cycle above takes really big chunks, so
+ this makes sure the job will be done completely */
+ for ( ; x < p_pic->p[Y_PLANE].i_visible_pitch - 1; x += 2 )
+ {
+ // y = y - y/4 {to prevent overflow} + intensity / 4
+ p_outpic->p[Y_PLANE].p_pixels[i_dy_line1_start + x] =
+ p_pic->p[Y_PLANE].p_pixels[i_dy_line1_start + x] -
+ (p_pic->p[Y_PLANE].p_pixels[i_dy_line1_start + x] >> 2) +
+ (i_intensity >> 2);
+ p_outpic->p[Y_PLANE].p_pixels[i_dy_line1_start + x + 1] =
+ p_pic->p[Y_PLANE].p_pixels[i_dy_line1_start + x + 1] -
+ (p_pic->p[Y_PLANE].p_pixels[i_dy_line1_start + x + 1] >> 2) +
+ (i_intensity >> 2);
+ p_outpic->p[Y_PLANE].p_pixels[i_dy_line2_start + x] =
+ p_pic->p[Y_PLANE].p_pixels[i_dy_line2_start + x] -
+ (p_pic->p[Y_PLANE].p_pixels[i_dy_line2_start + x] >> 2) +
+ (i_intensity >> 2);
+ p_outpic->p[Y_PLANE].p_pixels[i_dy_line2_start + x + 1] =
+ p_pic->p[Y_PLANE].p_pixels[i_dy_line2_start + x + 1] -
+ (p_pic->p[Y_PLANE].p_pixels[i_dy_line2_start + x + 1] >> 2) +
+ (i_intensity >> 2);
+ // u = 128 {half => B&W} - intensity / 6
+ p_outpic->p[U_PLANE].p_pixels[i_du_line_start + (x / 2)] =
+ filling_const_8u;
+ // v = 128 {half => B&W} + intensity / 14
+ p_outpic->p[V_PLANE].p_pixels[i_dv_line_start + (x / 2)] =
+ filling_const_8v;
+ }
+ }
+}
+#endif
+
/*****************************************************************************
* PlanarI420Sepia: Applies sepia to one frame of the planar I420 video
*****************************************************************************
static void PlanarI420Sepia( picture_t *p_pic, picture_t *p_outpic,
int i_intensity )
{
+#if defined(CAN_COMPILE_SSE2)
+ if (vlc_CPU_SSE2())
+ return PlanarI420SepiaSSE( p_pic, p_outpic, i_intensity );
+#endif
+
+ // prepared values to copy for U and V channels
+ const uint8_t filling_const_8u = 128 - i_intensity / 6;
+ const uint8_t filling_const_8v = 128 + i_intensity / 14;
+
/* iterate for every two visible line in the frame */
for( int y = 0; y < p_pic->p[Y_PLANE].i_visible_lines - 1; y += 2)
{
- const int i_sy_line1_start = y * p_pic->p[Y_PLANE].i_pitch;
- const int i_sy_line2_start = ( y + 1 ) * p_pic->p[Y_PLANE].i_pitch;
- const int i_su_line_start = (y/2) * p_pic->p[U_PLANE].i_pitch;
- const int i_sv_line_start = (y/2) * p_pic->p[V_PLANE].i_pitch;
-
const int i_dy_line1_start = y * p_outpic->p[Y_PLANE].i_pitch;
const int i_dy_line2_start = ( y + 1 ) * p_outpic->p[Y_PLANE].i_pitch;
const int i_du_line_start = (y/2) * p_outpic->p[U_PLANE].i_pitch;
const int i_dv_line_start = (y/2) * p_outpic->p[V_PLANE].i_pitch;
+ // to prevent sigsegv if one pic is smaller (theoretically)
+ int i_picture_size_limit = p_pic->p[Y_PLANE].i_visible_pitch
+ < p_outpic->p[Y_PLANE].i_visible_pitch
+ ? (p_pic->p[Y_PLANE].i_visible_pitch - 1) :
+ (p_outpic->p[Y_PLANE].i_visible_pitch - 1);
/* iterate for every two visible line in the frame */
- for( int x = 0; x < p_pic->p[Y_PLANE].i_visible_pitch - 1; x += 2)
+ for( int x = 0; x < i_picture_size_limit; x += 2)
{
- uint8_t sy1, sy2, sy3, sy4, su, sv;
- uint8_t dy1, dy2, dy3, dy4, du, dv;
- const int i_sy_line1_offset = i_sy_line1_start + x;
- const int i_sy_line2_offset = i_sy_line2_start + x;
- const int i_dy_line1_offset = i_dy_line1_start + x;
- const int i_dy_line2_offset = i_dy_line2_start + x;
- /* get four y components and u and v component */
- sy1 = p_pic->p[Y_PLANE].p_pixels[i_sy_line1_offset];
- sy2 = p_pic->p[Y_PLANE].p_pixels[i_sy_line1_offset + 1];
- sy3 = p_pic->p[Y_PLANE].p_pixels[i_sy_line2_offset];
- sy4 = p_pic->p[Y_PLANE].p_pixels[i_sy_line2_offset + 1];
- su = p_pic->p[U_PLANE].p_pixels[i_su_line_start + (x/2)];
- sv = p_pic->p[V_PLANE].p_pixels[i_sv_line_start + (x/2)];
- /* calculate sepia values */
- YuvSepia4( &dy1, &dy2, &dy3, &dy4, &du, &dv,
- sy1, sy2, sy3, sy4, su, sv, i_intensity );
- /* put new sepia values for all four y components and u and v */
- p_outpic->p[Y_PLANE].p_pixels[i_dy_line1_offset] = dy1;
- p_outpic->p[Y_PLANE].p_pixels[i_dy_line1_offset + 1] = dy2;
- p_outpic->p[Y_PLANE].p_pixels[i_dy_line2_offset] = dy3;
- p_outpic->p[Y_PLANE].p_pixels[i_dy_line2_offset + 1] = dy4;
- p_outpic->p[U_PLANE].p_pixels[i_du_line_start + (x/2)] = du;
- p_outpic->p[V_PLANE].p_pixels[i_dv_line_start + (x/2)] = dv;
+ // y = y - y/4 {to prevent overflow} + intensity / 4
+ p_outpic->p[Y_PLANE].p_pixels[i_dy_line1_start + x] =
+ p_pic->p[Y_PLANE].p_pixels[i_dy_line1_start + x] -
+ (p_pic->p[Y_PLANE].p_pixels[i_dy_line1_start + x] >> 2) +
+ (i_intensity >> 2);
+ p_outpic->p[Y_PLANE].p_pixels[i_dy_line1_start + x + 1] =
+ p_pic->p[Y_PLANE].p_pixels[i_dy_line1_start + x + 1] -
+ (p_pic->p[Y_PLANE].p_pixels[i_dy_line1_start + x + 1] >> 2) +
+ (i_intensity >> 2);
+ p_outpic->p[Y_PLANE].p_pixels[i_dy_line2_start + x] =
+ p_pic->p[Y_PLANE].p_pixels[i_dy_line2_start + x] -
+ (p_pic->p[Y_PLANE].p_pixels[i_dy_line2_start + x] >> 2) +
+ (i_intensity >> 2);
+ p_outpic->p[Y_PLANE].p_pixels[i_dy_line2_start + x + 1] =
+ p_pic->p[Y_PLANE].p_pixels[i_dy_line2_start + x + 1] -
+ (p_pic->p[Y_PLANE].p_pixels[i_dy_line2_start + x + 1] >> 2) +
+ (i_intensity >> 2);
+ // u = 128 {half => B&W} - intensity / 6
+ p_outpic->p[U_PLANE].p_pixels[i_du_line_start + (x / 2)] =
+ filling_const_8u;
+ // v = 128 {half => B&W} + intensity / 14
+ p_outpic->p[V_PLANE].p_pixels[i_dv_line_start + (x / 2)] =
+ filling_const_8v;
}
}
}
GetPackedYuvOffsets( p_outpic->format.i_chroma,
&i_yindex, &i_uindex, &i_vindex );
+ // prepared values to copy for U and V channels
+ const uint8_t filling_const_8u = 128 - i_intensity / 6;
+ const uint8_t filling_const_8v = 128 + i_intensity / 14;
+
p_in = p_pic->p[0].p_pixels;
p_in_end = p_in + p_pic->p[0].i_visible_lines
* p_pic->p[0].i_pitch;
p_out = p_outpic->p[0].p_pixels;
- while( p_in < p_in_end )
{
- p_line_end = p_in + p_pic->p[0].i_visible_pitch;
- while( p_in < p_line_end )
+ while( p_in < p_in_end )
{
- /* calculate new, sepia values */
- YuvSepia2( &p_out[i_yindex], &p_out[i_yindex + 2], &p_out[i_uindex],
- &p_out[i_vindex], p_in[i_yindex], p_in[i_yindex + 2],
- p_in[i_uindex], p_in[i_vindex], i_intensity );
- p_in += 4;
- p_out += 4;
+ p_line_end = p_in + p_pic->p[0].i_visible_pitch;
+ while( p_in < p_line_end )
+ {
+ /* calculate new, sepia values */
+ p_out[i_yindex] =
+ p_in[i_yindex] - (p_in[i_yindex] >> 2) + (i_intensity >> 2);
+ p_out[i_yindex + 2] =
+ p_in[i_yindex + 2] - (p_in[i_yindex + 2] >> 2)
+ + (i_intensity >> 2);
+ p_out[i_uindex] = filling_const_8u;
+ p_out[i_vindex] = filling_const_8v;
+ p_in += 4;
+ p_out += 4;
+ }
+ p_in += p_pic->p[0].i_pitch - p_pic->p[0].i_visible_pitch;
+ p_out += p_outpic->p[0].i_pitch
+ - p_outpic->p[0].i_visible_pitch;
}
- p_in += p_pic->p[0].i_pitch - p_pic->p[0].i_visible_pitch;
- p_out += p_outpic->p[0].i_pitch
- - p_outpic->p[0].i_visible_pitch;
}
}
*****************************************************************************/
static void RVSepia( picture_t *p_pic, picture_t *p_outpic, int i_intensity )
{
+#define SCALEBITS 10
+#define ONE_HALF (1 << (SCALEBITS - 1))
+#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
uint8_t *p_in, *p_in_end, *p_line_end, *p_out;
- int i_r, i_g, i_b;
bool b_isRV32 = p_pic->format.i_chroma == VLC_CODEC_RGB32;
int i_rindex = 0, i_gindex = 1, i_bindex = 2;
* p_pic->p[0].i_pitch;
p_out = p_outpic->p[0].p_pixels;
- while( p_in < p_in_end )
+ /* Precompute values constant for this certain i_intensity, using the same
+ * formula as YUV functions above */
+ uint8_t r_intensity = (( FIX( 1.40200 * 255.0 / 224.0 ) * (i_intensity * 14)
+ + ONE_HALF )) >> SCALEBITS;
+ uint8_t g_intensity = (( - FIX(0.34414*255.0/224.0) * ( - i_intensity / 6 )
+ - FIX( 0.71414 * 255.0 / 224.0) * ( i_intensity * 14 )
+ + ONE_HALF )) >> SCALEBITS;
+ uint8_t b_intensity = (( FIX( 1.77200 * 255.0 / 224.0) * ( - i_intensity / 6 )
+ + ONE_HALF )) >> SCALEBITS;
+
+ while (p_in < p_in_end)
{
p_line_end = p_in + p_pic->p[0].i_visible_pitch;
- while( p_in < p_line_end )
+ while (p_in < p_line_end)
{
- /* extract r,g,b values */
- i_r = p_in[i_rindex];
- i_g = p_in[i_gindex];
- i_b = p_in[i_bindex];
+ /* do sepia: this calculation is based on the formula to calculate
+ * YUV->RGB and RGB->YUV (in filter_picture.h) mode and that
+ * y = y - y/4 + intensity/4 . As Y is the only channel that changes
+ * through the whole image. After that, precomputed values are added
+ * for each RGB channel and saved in the output image.
+ * FIXME: needs cleanup */
+ uint8_t i_y = ((( 66 * p_in[i_rindex] + 129 * p_in[i_gindex] + 25
+ * p_in[i_bindex] + 128 ) >> 8 ) * FIX(255.0/219.0))
+ - (((( 66 * p_in[i_rindex] + 129 * p_in[i_gindex] + 25
+ * p_in[i_bindex] + 128 ) >> 8 )
+ * FIX( 255.0 / 219.0 )) >> 2 ) + ( i_intensity >> 2 );
+ p_out[i_rindex] = vlc_uint8(i_y + r_intensity);
+ p_out[i_gindex] = vlc_uint8(i_y + g_intensity);
+ p_out[i_bindex] = vlc_uint8(i_y + b_intensity);
p_in += 3;
- /* do sepia */
- Sepia( &i_r, &i_g, &i_b, i_intensity );
- /* put new r,g,b values */
- p_out[i_rindex] = i_r;
- p_out[i_gindex] = i_g;
- p_out[i_bindex] = i_b;
p_out += 3;
/* for rv32 we take 4 chunks at the time */
- if ( b_isRV32 )
- {
- /* alpha channel stays the same */
- *p_out++ = *p_in++;
+ if (b_isRV32) {
+ /* alpha channel stays the same */
+ *p_out++ = *p_in++;
}
}
+
p_in += p_pic->p[0].i_pitch - p_pic->p[0].i_visible_pitch;
p_out += p_outpic->p[0].i_pitch
- p_outpic->p[0].i_visible_pitch;
}
-}
-
-/*****************************************************************************
- * YuvSepia2: Calculates sepia to YUV values for two given Y values
- *****************************************************************************
- * This function calculates sepia values of YUV color space for a given sepia
- * intensity. It converts YUV color values to theirs RGB equivalents,
- * calculates sepia values and then converts RGB values to YUV values again.
- *****************************************************************************/
-static void YuvSepia2( uint8_t* sepia_y1, uint8_t* sepia_y2, uint8_t* sepia_u,
- uint8_t* sepia_v, const uint8_t y1, const uint8_t y2,
- const uint8_t u, const uint8_t v, int i_intensity )
-{
- int r1, g1, b1; /* for y1 new value */
- int r2, b2, g2; /* for y2 new value */
- int r3, g3, b3; /* for new values of u and v */
- /* fist convert YUV -> RGB */
- yuv_to_rgb( &r1, &g1, &b1, y1, u, v );
- yuv_to_rgb( &r2, &g2, &b2, y2, u, v );
- yuv_to_rgb( &r3, &g3, &b3, ( y1 + y2 ) / 2, u, v );
- /* calculates new values for r, g and b components */
- Sepia( &r1, &g1, &b1, i_intensity );
- Sepia( &r2, &g2, &b2, i_intensity );
- Sepia( &r3, &g3, &b3, i_intensity );
- /* convert from calculated RGB -> YUV */
- *sepia_y1 = ( ( 66 * r1 + 129 * g1 + 25 * b1 + 128 ) >> 8 ) + 16;
- *sepia_y2 = ( ( 66 * r2 + 129 * g2 + 25 * b2 + 128 ) >> 8 ) + 16;
- *sepia_u = ( ( -38 * r3 - 74 * g3 + 112 * b3 + 128 ) >> 8 ) + 128;
- *sepia_v = ( ( 112 * r3 - 94 * g3 - 18 * b3 + 128 ) >> 8 ) + 128;
-}
-
-/*****************************************************************************
- * YuvSepia4: Calculates sepia to YUV values for given four Y values
- *****************************************************************************
- * This function calculates sepia values of YUV color space for a given sepia
- * intensity. It converts YUV color values to theirs RGB equivalents,
- * calculates sepia values and then converts RGB values to YUV values again.
- *****************************************************************************/
-static void YuvSepia4( uint8_t* sepia_y1, uint8_t* sepia_y2, uint8_t* sepia_y3,
- uint8_t* sepia_y4, uint8_t* sepia_u, uint8_t* sepia_v,
- const uint8_t y1, const uint8_t y2, const uint8_t y3,
- const uint8_t y4, const uint8_t u, uint8_t v,
- int i_intensity )
-{
- int r1, g1, b1; /* for y1 new value */
- int r2, b2, g2; /* for y2 new value */
- int r3, b3, g3; /* for y3 new value */
- int r4, b4, g4; /* for y4 new value */
- int r5, g5, b5; /* for new values of u and v */
- /* fist convert YUV -> RGB */
- yuv_to_rgb( &r1, &g1, &b1, y1, u, v );
- yuv_to_rgb( &r2, &g2, &b2, y2, u, v );
- yuv_to_rgb( &r3, &g3, &b3, y3, u, v );
- yuv_to_rgb( &r4, &g4, &b4, y4, u, v );
- yuv_to_rgb( &r5, &g5, &b5, ( y1 + y2 + y3 + y4) / 4, u, v );
- /* calculates new values for r, g and b components */
- Sepia( &r1, &g1, &b1, i_intensity );
- Sepia( &r2, &g2, &b2, i_intensity );
- Sepia( &r3, &g3, &b3, i_intensity );
- Sepia( &r4, &g4, &b4, i_intensity );
- Sepia( &r5, &g5, &b5, i_intensity );
- /* convert from calculated RGB -> YUV */
- *sepia_y1 = ( ( 66 * r1 + 129 * g1 + 25 * b1 + 128 ) >> 8 ) + 16;
- *sepia_y2 = ( ( 66 * r2 + 129 * g2 + 25 * b2 + 128 ) >> 8 ) + 16;
- *sepia_y3 = ( ( 66 * r3 + 129 * g3 + 25 * b3 + 128 ) >> 8 ) + 16;
- *sepia_y4 = ( ( 66 * r4 + 129 * g4 + 25 * b4 + 128 ) >> 8 ) + 16;
- *sepia_u = ( ( -38 * r5 - 74 * g5 + 112 * b5 + 128 ) >> 8 ) + 128;
- *sepia_v = ( ( 112 * r5 - 94 * g5 - 18 * b5 + 128 ) >> 8 ) + 128;
-}
-
-/*****************************************************************************
- * Sepia: Calculates sepia of RGB values
- *****************************************************************************
- * This function calculates sepia values of RGB color space for a given sepia
- * intensity. Sepia algorithm is taken from here:
- * http://groups.google.com/group/comp.lang.java.programmer/browse_thread/
- * thread/9d20a72c40b119d0/18f12770ec6d9dd6
- *****************************************************************************/
-static void Sepia( int *p_r, int *p_g, int *p_b, int i_intensity )
-{
- int i_sepia_depth = 20;
- int16_t i_round;
- i_round = ( *p_r + *p_g + *p_b ) / 3;
- *p_r = vlc_uint8( i_round + ( i_sepia_depth * 2 ) );
- *p_g = vlc_uint8( i_round + i_sepia_depth );
- *p_b = vlc_uint8( i_round - i_intensity );
+#undef SCALEBITS
+#undef ONE_HALF
+#undef FIX
}
static int FilterCallback ( vlc_object_t *p_this, char const *psz_var,
filter_t *p_filter = (filter_t*)p_this;
filter_sys_t *p_sys = p_filter->p_sys;
- vlc_spin_lock( &p_sys->lock );
- p_sys->i_intensity = newval.i_int;
- vlc_spin_unlock( &p_sys->lock );
-
+ atomic_store( &p_sys->i_intensity, newval.i_int );
return VLC_SUCCESS;
}