00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdlib.h>
00028 #include <string.h>
00029
00030 #include <vlc/vlc.h>
00031 #include <vlc/vout.h>
00032
00033 #include "filter_common.h"
00034
00035
00036
00037
00038 static int Create ( vlc_object_t * );
00039 static void Destroy ( vlc_object_t * );
00040
00041 static int Init ( vout_thread_t * );
00042 static void End ( vout_thread_t * );
00043 static void Render ( vout_thread_t *, picture_t * );
00044
00045 static int SendEvents( vlc_object_t *, char const *,
00046 vlc_value_t, vlc_value_t, void * );
00047
00048
00049
00050
00051 vlc_module_begin();
00052 set_description( _("Invert video filter") );
00053 set_shortname( N_("Color inversion" ));
00054 set_category( CAT_VIDEO );
00055 set_subcategory( SUBCAT_VIDEO_VFILTER );
00056 set_capability( "video filter", 0 );
00057 add_shortcut( "invert" );
00058 set_callbacks( Create, Destroy );
00059 vlc_module_end();
00060
00061
00062
00063
00064
00065
00066
00067 struct vout_sys_t
00068 {
00069 vout_thread_t *p_vout;
00070 };
00071
00072
00073
00074
00075 static int Control( vout_thread_t *p_vout, int i_query, va_list args )
00076 {
00077 return vout_vaControl( p_vout->p_sys->p_vout, i_query, args );
00078 }
00079
00080
00081
00082
00083
00084
00085 static int Create( vlc_object_t *p_this )
00086 {
00087 vout_thread_t *p_vout = (vout_thread_t *)p_this;
00088
00089
00090 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
00091 if( p_vout->p_sys == NULL )
00092 {
00093 msg_Err( p_vout, "out of memory" );
00094 return VLC_ENOMEM;
00095 }
00096
00097 p_vout->pf_init = Init;
00098 p_vout->pf_end = End;
00099 p_vout->pf_manage = NULL;
00100 p_vout->pf_render = Render;
00101 p_vout->pf_display = NULL;
00102 p_vout->pf_control = Control;
00103
00104 return VLC_SUCCESS;
00105 }
00106
00107
00108
00109
00110 static int Init( vout_thread_t *p_vout )
00111 {
00112 int i_index;
00113 picture_t *p_pic;
00114 video_format_t fmt = {0};
00115
00116 I_OUTPUTPICTURES = 0;
00117
00118
00119 p_vout->output.i_chroma = p_vout->render.i_chroma;
00120 p_vout->output.i_width = p_vout->render.i_width;
00121 p_vout->output.i_height = p_vout->render.i_height;
00122 p_vout->output.i_aspect = p_vout->render.i_aspect;
00123 p_vout->fmt_out = p_vout->fmt_in;
00124 fmt = p_vout->fmt_out;
00125
00126
00127 msg_Dbg( p_vout, "spawning the real video output" );
00128
00129 p_vout->p_sys->p_vout = vout_Create( p_vout, &fmt );
00130
00131
00132 if( p_vout->p_sys->p_vout == NULL )
00133 {
00134 msg_Err( p_vout, "can't open vout, aborting" );
00135
00136 return VLC_EGENERIC;
00137 }
00138
00139 ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
00140
00141 ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
00142
00143 ADD_PARENT_CALLBACKS( SendEventsToChild );
00144
00145 return VLC_SUCCESS;
00146 }
00147
00148
00149
00150
00151 static void End( vout_thread_t *p_vout )
00152 {
00153 int i_index;
00154
00155
00156 for( i_index = I_OUTPUTPICTURES ; i_index ; )
00157 {
00158 i_index--;
00159 free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
00160 }
00161 }
00162
00163
00164
00165
00166
00167
00168 static void Destroy( vlc_object_t *p_this )
00169 {
00170 vout_thread_t *p_vout = (vout_thread_t *)p_this;
00171
00172 if( p_vout->p_sys->p_vout )
00173 {
00174 DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
00175 vlc_object_detach( p_vout->p_sys->p_vout );
00176 vout_Destroy( p_vout->p_sys->p_vout );
00177 }
00178
00179 DEL_PARENT_CALLBACKS( SendEventsToChild );
00180
00181 free( p_vout->p_sys );
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191 static void Render( vout_thread_t *p_vout, picture_t *p_pic )
00192 {
00193 picture_t *p_outpic;
00194 int i_index;
00195
00196
00197 while( ( p_outpic = vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 ) )
00198 == NULL )
00199 {
00200 if( p_vout->b_die || p_vout->b_error )
00201 {
00202 return;
00203 }
00204 msleep( VOUT_OUTMEM_SLEEP );
00205 }
00206
00207 vout_DatePicture( p_vout->p_sys->p_vout, p_outpic, p_pic->date );
00208 vout_LinkPicture( p_vout->p_sys->p_vout, p_outpic );
00209
00210 for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
00211 {
00212 uint8_t *p_in, *p_in_end, *p_line_end, *p_out;
00213
00214 p_in = p_pic->p[i_index].p_pixels;
00215 p_in_end = p_in + p_pic->p[i_index].i_visible_lines
00216 * p_pic->p[i_index].i_pitch;
00217
00218 p_out = p_outpic->p[i_index].p_pixels;
00219
00220 for( ; p_in < p_in_end ; )
00221 {
00222 uint64_t *p_in64, *p_out64;
00223
00224 p_line_end = p_in + p_pic->p[i_index].i_visible_pitch - 64;
00225
00226 p_in64 = (uint64_t*)p_in;
00227 p_out64 = (uint64_t*)p_out;
00228
00229 for( ; (ptrdiff_t)p_in64 < (ptrdiff_t)p_line_end ; )
00230 {
00231
00232 *p_out64++ = ~*p_in64++; *p_out64++ = ~*p_in64++;
00233 *p_out64++ = ~*p_in64++; *p_out64++ = ~*p_in64++;
00234 *p_out64++ = ~*p_in64++; *p_out64++ = ~*p_in64++;
00235 *p_out64++ = ~*p_in64++; *p_out64++ = ~*p_in64++;
00236 }
00237
00238 p_in = (uint8_t*)p_in64;
00239 p_out = (uint8_t*)p_out64;
00240 p_line_end += 64;
00241
00242 for( ; p_in < p_line_end ; )
00243 {
00244 *p_out++ = ~( *p_in++ );
00245 }
00246
00247 p_in += p_pic->p[i_index].i_pitch
00248 - p_pic->p[i_index].i_visible_pitch;
00249 p_out += p_outpic->p[i_index].i_pitch
00250 - p_outpic->p[i_index].i_visible_pitch;
00251 }
00252 }
00253
00254 vout_UnlinkPicture( p_vout->p_sys->p_vout, p_outpic );
00255
00256 vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic );
00257 }
00258
00259
00260
00261
00262 static int SendEvents( vlc_object_t *p_this, char const *psz_var,
00263 vlc_value_t oldval, vlc_value_t newval, void *p_data )
00264 {
00265 var_Set( (vlc_object_t *)p_data, psz_var, newval );
00266
00267 return VLC_SUCCESS;
00268 }
00269
00270
00271
00272
00273 static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
00274 vlc_value_t oldval, vlc_value_t newval, void *p_data )
00275 {
00276 vout_thread_t *p_vout = (vout_thread_t *)p_this;
00277 var_Set( p_vout->p_sys->p_vout, psz_var, newval );
00278 return VLC_SUCCESS;
00279 }