24
24
/*****************************************************************************
26
26
*****************************************************************************/
27
#include <stdlib.h> /* malloc(), free() */
32
#include <vlc_common.h>
33
#include <vlc_plugin.h>
35
38
#include "filter_common.h"
39
#include "filter_picture.h"
36
41
#include "vlc_image.h"
37
#include "vlc_input.h"
38
#include "vlc_playlist.h"
40
43
/*****************************************************************************
42
45
*****************************************************************************/
43
46
static int Create ( vlc_object_t * );
44
47
static void Destroy ( vlc_object_t * );
46
static int Init ( vout_thread_t * );
47
static void End ( vout_thread_t * );
48
static void Render ( vout_thread_t *, picture_t * );
50
static int SendEvents ( vlc_object_t *, char const *,
51
vlc_value_t, vlc_value_t, void * );
52
static int MouseEvent ( vlc_object_t *, char const *,
53
vlc_value_t, vlc_value_t, void * );
55
/*****************************************************************************
57
*****************************************************************************/
58
49
vlc_module_begin();
59
set_description( _("Magnify/Zoom interactive video filter") );
60
set_shortname( _( "Magnify" ));
50
set_description( N_("Magnify/Zoom interactive video filter") );
51
set_shortname( N_( "Magnify" ));
61
52
set_capability( "video filter", 0 );
62
53
set_category( CAT_VIDEO );
63
54
set_subcategory( SUBCAT_VIDEO_VFILTER );
65
56
set_callbacks( Create, Destroy );
60
/*****************************************************************************
62
*****************************************************************************/
63
static int Init ( vout_thread_t * );
64
static void End ( vout_thread_t * );
65
static void Render ( vout_thread_t *, picture_t * );
67
static int SendEvents ( vlc_object_t *, char const *,
68
vlc_value_t, vlc_value_t, void * );
69
static int MouseEvent ( vlc_object_t *, char const *,
70
vlc_value_t, vlc_value_t, void * );
72
static void DrawZoomStatus( uint8_t *, int i_pitch, int i_width, int i_height,
73
int i_offset_x, int i_offset_y, bool b_visible );
74
static void DrawRectangle( uint8_t *, int i_pitch, int i_width, int i_height,
75
int x, int y, int i_w, int i_h );
68
77
/*****************************************************************************
69
78
* vout_sys_t: Magnify video output method descriptor
70
79
*****************************************************************************/
210
237
*****************************************************************************/
211
238
static void Render( vout_thread_t *p_vout, picture_t *p_pic )
240
vout_sys_t *p_sys = p_vout->p_sys;
213
241
picture_t *p_outpic;
215
int o_x = p_vout->p_sys->i_x;
216
int o_y = p_vout->p_sys->i_y;
217
int o_zoom = p_vout->p_sys->i_zoom;
220
video_format_t fmt_out = {0};
221
244
picture_t *p_converted;
224
248
/* This is a new frame. Get a structure from the video_output. */
225
while( ( p_outpic = vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 ) )
249
while( ( p_outpic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) )
228
if( p_vout->b_die || p_vout->b_error )
252
if( !vlc_object_alive (p_vout) || p_vout->b_error )
232
256
msleep( VOUT_OUTMEM_SLEEP );
235
vout_DatePicture( p_vout->p_sys->p_vout, p_outpic, p_pic->date );
237
p_oyp = &(p_outpic->p[Y_PLANE]);
259
vout_DatePicture( p_sys->p_vout, p_outpic, p_pic->date );
262
vlc_mutex_lock( &p_sys->lock );
263
const bool b_visible = p_sys->b_visible;
264
const int o_x = p_sys->i_x;
265
const int o_y = p_sys->i_y;
266
const int o_zoom = p_sys->i_zoom;
267
const int64_t i_last_activity = p_sys->i_last_activity;
268
vlc_mutex_unlock( &p_sys->lock );
239
270
/* background magnified image */
240
271
if( o_zoom != ZOOM_FACTOR )
242
#define magnify( plane ) \
243
o_yp = o_y*p_outpic->p[plane].i_lines/p_outpic->p[Y_PLANE].i_lines; \
244
o_xp = o_x*p_outpic->p[plane].i_pitch/p_outpic->p[Y_PLANE].i_pitch; \
245
for( y=0; y<p_outpic->p[plane].i_visible_lines; y++ ) \
247
for( x=0; x<p_outpic->p[plane].i_visible_pitch; x++ ) \
249
p_outpic->p[plane].p_pixels[y*p_outpic->p[plane].i_pitch+x] = \
250
p_pic->p[plane].p_pixels[ \
251
( o_yp + y*ZOOM_FACTOR/o_zoom )*p_outpic->p[plane].i_pitch \
252
+ o_xp + x*ZOOM_FACTOR/o_zoom \
273
video_format_t fmt_in;
274
video_format_t fmt_out;
278
for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
280
const int o_yp = o_y * p_outpic->p[i_plane].i_lines / p_outpic->p[Y_PLANE].i_lines;
281
const int o_xp = o_x * p_outpic->p[i_plane].i_pitch / p_outpic->p[Y_PLANE].i_pitch;
283
crop.p[i_plane].p_pixels += o_yp * p_outpic->p[i_plane].i_pitch + o_xp;
287
fmt_in = p_vout->fmt_out;
288
fmt_in.i_width = (fmt_in.i_width * ZOOM_FACTOR / o_zoom) & ~1;
289
fmt_in.i_height = (fmt_in.i_height * ZOOM_FACTOR / o_zoom) & ~1;
292
fmt_out = p_vout->fmt_out;
294
p_converted = image_Convert( p_sys->p_image, &crop, &fmt_in, &fmt_out );
296
picture_CopyPixels( p_outpic, p_converted );
298
picture_Release( p_converted );
263
#define copy( plane ) \
264
memcpy( p_outpic->p[plane].p_pixels, p_pic->p[plane].p_pixels, \
265
p_outpic->p[plane].i_lines * p_outpic->p[plane].i_pitch );
302
picture_CopyPixels( p_outpic, p_pic );
272
if( p_vout->p_sys->b_visible )
306
p_oyp = &p_outpic->p[Y_PLANE];
309
video_format_t fmt_out;
274
311
/* image visualization */
275
312
fmt_out = p_vout->fmt_out;
276
fmt_out.i_width = p_vout->render.i_width/VIS_ZOOM;
277
fmt_out.i_height = p_vout->render.i_height/VIS_ZOOM;
278
p_converted = image_Convert( p_vout->p_sys->p_image, p_pic,
279
&(p_pic->format), &fmt_out );
280
#define copyimage( plane ) \
281
for( y=0; y<p_converted->p[plane].i_visible_lines; y++) \
283
memcpy( p_outpic->p[plane].p_pixels+y*p_outpic->p[plane].i_pitch, \
284
p_converted->p[plane].p_pixels+y*p_converted->p[plane].i_pitch, \
285
p_converted->p[plane].i_visible_pitch ); \
313
fmt_out.i_width = (p_vout->render.i_width/VIS_ZOOM ) & ~1;
314
fmt_out.i_height = (p_vout->render.i_height/VIS_ZOOM) & ~1;
315
p_converted = image_Convert( p_sys->p_image, p_pic,
316
&p_pic->format, &fmt_out );
317
for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
320
for( y = 0; y < p_converted->p[i_plane].i_visible_lines; y++)
323
&p_outpic->p[i_plane].p_pixels[y*p_outpic->p[i_plane].i_pitch],
324
p_converted->p[i_plane].p_pixels+y*p_converted->p[i_plane].i_pitch,
325
p_converted->p[i_plane].i_visible_pitch );
287
copyimage( Y_PLANE );
288
copyimage( U_PLANE );
289
copyimage( V_PLANE );
291
if( p_converted->pf_release )
292
p_converted->pf_release( p_converted );
328
picture_Release( p_converted );
294
330
/* white rectangle on visualization */
295
v_w = p_oyp->i_pitch*ZOOM_FACTOR/(VIS_ZOOM*o_zoom);
296
v_h = (o_y+p_oyp->i_lines*ZOOM_FACTOR/o_zoom)/VIS_ZOOM;
298
memset( p_oyp->p_pixels
299
+ o_y/VIS_ZOOM*p_oyp->i_pitch
300
+ o_x/VIS_ZOOM, 0xff, v_w+1 );
331
v_w = __MIN( fmt_out.i_width * ZOOM_FACTOR / o_zoom, fmt_out.i_width - 1 );
332
v_h = __MIN( fmt_out.i_height * ZOOM_FACTOR / o_zoom, fmt_out.i_height - 1 );
302
for( y = o_y/VIS_ZOOM+1; y < v_h; y++ )
306
y*p_oyp->i_pitch+o_x/VIS_ZOOM
310
y*p_oyp->i_pitch+o_x/VIS_ZOOM + v_w
314
memset( p_oyp->p_pixels
316
+ o_x/VIS_ZOOM, 0xff, v_w+1 );
334
DrawRectangle( p_oyp->p_pixels, p_oyp->i_pitch,
335
p_oyp->i_pitch, p_oyp->i_lines,
336
o_x/VIS_ZOOM, o_y/VIS_ZOOM,
319
v_h = p_oyp->i_lines/VIS_ZOOM;
340
v_h = fmt_out.i_height + 1;
326
/* print a small "VLC ZOOM" ... gruikkkkkkkkk */
327
#define DRAW(a) {int c,l=1;L a;}
329
#define X ;draw(l,c);c+=1
331
#define draw(y,x) p_oyp->p_pixels[(v_h+y)*p_oyp->i_pitch+x] = 0xff;
332
if( p_vout->p_sys->b_visible )
334
X o o o X o X o o o o o o X X X X o o o X X X X X o o X X X o o o X X X o o X X o X X o o o X o o o X o X X X X X o X X X X o o X X X X X L
335
X o o o X o X o o o o o X o o o o o o o o o o X o o X o o o X o X o o o X o X o X o X o o o X o o o X o o o X o o o X o o o X o X o o o o L
336
o X o X o o X o o o o o X o o o o o o o o o X o o o X o o o X o X o o o X o X o o o X o o o X X X X X o o o X o o o X o o o X o X X X X o L
337
o X o X o o X o o o o o X o o o o o o o o X o o o o X o o o X o X o o o X o X o o o X o o o X o o o X o o o X o o o X o o o X o X o o o o L
338
o o X o o o X X X X X o o X X X X o o o X X X X X o o X X X o o o X X X o o X o o o X o o o X o o o X o X X X X X o X X X X o o X X X X X L
342
X o o o X o X o o o o o o X X X X o o o X X X X X o o X X X o o o X X X o o X X o X X o o o o X X X X o X o o o X o o X X X o o X o o o X L
343
X o o o X o X o o o o o X o o o o o o o o o o X o o X o o o X o X o o o X o X o X o X o o o X o o o o o X o o o X o X o o o X o X o o o X L
344
o X o X o o X o o o o o X o o o o o o o o o X o o o X o o o X o X o o o X o X o o o X o o o o X X X o o X X X X X o X o o o X o X o X o X L
345
o X o X o o X o o o o o X o o o o o o o o X o o o o X o o o X o X o o o X o X o o o X o o o o o o o X o X o o o X o X o o o X o X o X o X L
346
o o X o o o X X X X X o o X X X X o o o X X X X X o o X X X o o o X X X o o X o o o X o o o X X X X o o X o o o X o o X X X o o o X o X o L
347
/* print a small "VLC ZOOM" */
348
if( b_visible || i_last_activity + p_sys->i_hide_timeout > mdate() )
349
DrawZoomStatus( p_oyp->p_pixels, p_oyp->i_pitch, p_oyp->i_pitch, p_oyp->i_lines,
354
if( p_vout->p_sys->b_visible )
357
memset( p_oyp->p_pixels
358
+ (v_h+9)*p_oyp->i_pitch,
357
vlc_memset( p_oyp->p_pixels + (v_h+9)*p_oyp->i_pitch, 0xff, 41 );
360
358
for( y = v_h + 10; y < v_h + 90; y++ )
362
360
int width = v_h + 90 - y;
363
361
width = (width*width)/160;
364
if( (80 - y + v_h)*10 < o_zoom )
362
if( (80 - y + v_h)*ZOOM_FACTOR/10 < o_zoom )
366
memset( p_oyp->p_pixels
364
vlc_memset( p_oyp->p_pixels + y*p_oyp->i_pitch, 0xff, width );
378
vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic );
374
vout_DisplayPicture( p_sys->p_vout, p_outpic );
377
static void DrawZoomStatus( uint8_t *pb_dst, int i_pitch, int i_width, int i_height,
378
int i_offset_x, int i_offset_y, bool b_visible )
380
static const char *p_hide =
381
"X X X XXXX XXXXX XXX XXX XX XX X X XXXXX XXXX XXXXXL"
382
"X X X X X X X X X X X X X X X X X X L"
383
" X X X X X X X X X X X XXXXX X X X XXXX L"
384
" X X X X X X X X X X X X X X X X X L"
385
" X XXXXX XXXX XXXXX XXX XXX X X X X XXXXX XXXX XXXXXL";
386
static const char *p_show =
387
"X X X XXXX XXXXX XXX XXX XX XX XXXX X X XXX X XL"
388
"X X X X X X X X X X X X X X X X X X XL"
389
" X X X X X X X X X X X XXX XXXXX X X X X XL"
390
" X X X X X X X X X X X X X X X X X X XL"
391
" X XXXXX XXXX XXXXX XXX XXX X X XXXX X X XXX X X L";
392
const char *p_draw = b_visible ? p_hide : p_show;
395
for( i = 0, x = i_offset_x, y = i_offset_y; p_draw[i] != '\0'; i++ )
397
if( p_draw[i] == 'X' )
399
if( x < i_width && y < i_height )
400
pb_dst[y*i_pitch + x] = 0xff;
403
else if( p_draw[i] == ' ' )
407
else if( p_draw[i] == 'L' )
414
static void DrawRectangle( uint8_t *pb_dst, int i_pitch, int i_width, int i_height,
415
int x, int y, int i_w, int i_h )
419
if( x + i_w > i_width || y + i_h > i_height )
423
vlc_memset( &pb_dst[y * i_pitch + x], 0xff, i_w );
426
for( dy = 1; dy < i_h-1; dy++ )
428
pb_dst[(y+dy) * i_pitch + x + 0] = 0xff;
429
pb_dst[(y+dy) * i_pitch + x + i_w-1] = 0xff;
433
vlc_memset( &pb_dst[(y+i_h-1) * i_pitch + x], 0xff, i_w );
381
436
/*****************************************************************************