From: Antoine Cellerier Date: Fri, 10 Nov 2006 20:59:15 +0000 (+0000) Subject: Puzzle vout filter. (vlc --vout-filter puzzle ) X-Git-Tag: 0.9.0-test0~9576 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=0cd336b3fb3407d960382dd46f21112bc41be130;p=vlc Puzzle vout filter. (vlc --vout-filter puzzle ) --- diff --git a/configure.ac b/configure.ac index 21d69ad8d4..8782cac7b5 100644 --- a/configure.ac +++ b/configure.ac @@ -1091,7 +1091,7 @@ VLC_ADD_PLUGINS([fixed32tos16 s16tofixed32 u8tofixed32 mono]) VLC_ADD_PLUGINS([trivial_resampler ugly_resampler]) VLC_ADD_PLUGINS([trivial_channel_mixer trivial_mixer]) VLC_ADD_PLUGINS([playlist export sgimb nsc xtag]) -VLC_ADD_PLUGINS([i420_rgb rawvideo blend scale image logo magnify]) +VLC_ADD_PLUGINS([i420_rgb rawvideo blend scale image logo magnify puzzle]) VLC_ADD_PLUGINS([wav araw subtitle vobsub adpcm a52sys dtssys au ty voc xa nuv]) VLC_ADD_PLUGINS([access_directory access_file access_udp access_tcp]) VLC_ADD_PLUGINS([access_http access_mms access_ftp ipv4]) diff --git a/modules/video_filter/Modules.am b/modules/video_filter/Modules.am index 9ed5c8a10f..5439b3f134 100644 --- a/modules/video_filter/Modules.am +++ b/modules/video_filter/Modules.am @@ -25,4 +25,5 @@ SOURCES_opencv_wrapper = opencv_wrapper.c SOURCES_opencv_example = opencv_example.cpp filter_event_info.h SOURCES_rotate = rotate.c SOURCES_noise = noise.c +SOURCES_puzzle = puzzle.c noinst_HEADERS = filter_common.h diff --git a/modules/video_filter/puzzle.c b/modules/video_filter/puzzle.c new file mode 100644 index 0000000000..77baa157a8 --- /dev/null +++ b/modules/video_filter/puzzle.c @@ -0,0 +1,427 @@ +/***************************************************************************** + * puzzle.c : Puzzle game + ***************************************************************************** + * Copyright (C) 2005-2006 the VideoLAN team + * $Id$ + * + * Authors: Antoine Cellerier + * + * 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 + * (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. + * + * 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. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include /* malloc(), free() */ +#include + +#include +#include + +#include + +#include "filter_common.h" +#include "vlc_image.h" +#include "vlc_input.h" +#include "vlc_playlist.h" + +/***************************************************************************** + * Local prototypes + *****************************************************************************/ +static int Create ( vlc_object_t * ); +static void Destroy ( vlc_object_t * ); + +static int Init ( vout_thread_t * ); +static void End ( vout_thread_t * ); +static void Render ( vout_thread_t *, picture_t * ); + +static int SendEvents ( vlc_object_t *, char const *, + vlc_value_t, vlc_value_t, void * ); +static int MouseEvent ( vlc_object_t *, char const *, + vlc_value_t, vlc_value_t, void * ); + +/***************************************************************************** + * Module descriptor + *****************************************************************************/ + +#define ROWS_TEXT N_("Number of puzzle rows") +#define ROWS_LONGTEXT N_("Number of puzzle rows") +#define COLS_TEXT N_("Number of puzzle columns") +#define COLS_LONGTEXT N_("Number of puzzle columns") + +vlc_module_begin(); + set_description( _("Puzzle interactive game video filter") ); + set_shortname( _( "Puzzle" )); + set_capability( "video filter", 0 ); + set_category( CAT_VIDEO ); + set_subcategory( SUBCAT_VIDEO_VFILTER ); + + add_integer_with_range( "puzzle-rows", 4, 1, 128, NULL, + ROWS_TEXT, ROWS_LONGTEXT, VLC_FALSE ); + add_integer_with_range( "puzzle-cols", 4, 1, 128, NULL, + COLS_TEXT, COLS_LONGTEXT, VLC_FALSE ); + + set_callbacks( Create, Destroy ); +vlc_module_end(); + +/***************************************************************************** + * vout_sys_t: Magnify video output method descriptor + *****************************************************************************/ +struct vout_sys_t +{ + vout_thread_t *p_vout; + + image_handler_t *p_image; + + int i_cols; + int i_rows; + int *pi_order; + int i_selected; + vlc_bool_t b_finished; +}; + +/***************************************************************************** + * Control: control facility for the vout (forwards to child vout) + *****************************************************************************/ +static int Control( vout_thread_t *p_vout, int i_query, va_list args ) +{ + return vout_vaControl( p_vout->p_sys->p_vout, i_query, args ); +} + +/***************************************************************************** + * Misc stuff... + *****************************************************************************/ +static vlc_bool_t finished( vout_sys_t *p_sys ) +{ + int i; + for( i = 0; i < p_sys->i_cols * p_sys->i_rows; i++ ) + { + if( i != p_sys->pi_order[i] ) return VLC_FALSE; + } + return VLC_TRUE; +} +static void shuffle( vout_sys_t *p_sys ) +{ + int i, c; + free( p_sys->pi_order ); + p_sys->pi_order = malloc( p_sys->i_cols * p_sys->i_rows * sizeof( int ) ); + do + { + for( i = 0; i < p_sys->i_cols * p_sys->i_rows; i++ ) + { + p_sys->pi_order[i] = -1; + } + i = 0; + for( c = 0; c < p_sys->i_cols * p_sys->i_rows; ) + { + i = rand()%( p_sys->i_cols * p_sys->i_rows ); + if( p_sys->pi_order[i] == -1 ) + { + p_sys->pi_order[i] = c; + c++; + } + } + p_sys->b_finished = finished( p_sys ); + } while( p_sys->b_finished == VLC_TRUE ); +} + +/***************************************************************************** + * Create: allocates Magnify video thread output method + *****************************************************************************/ +static int Create( vlc_object_t *p_this ) +{ + vout_thread_t *p_vout = (vout_thread_t *)p_this; + + /* Allocate structure */ + p_vout->p_sys = malloc( sizeof( vout_sys_t ) ); + if( p_vout->p_sys == NULL ) + { + msg_Err( p_vout, "out of memory" ); + return VLC_ENOMEM; + } + + p_vout->p_sys->p_image = image_HandlerCreate( p_vout ); + + p_vout->p_sys->i_rows = config_GetInt( p_vout, "puzzle-rows" ); + p_vout->p_sys->i_cols = config_GetInt( p_vout, "puzzle-cols" ); + p_vout->p_sys->i_selected = -1; + + p_vout->p_sys->pi_order = NULL; + shuffle( p_vout->p_sys ); + + p_vout->pf_init = Init; + p_vout->pf_end = End; + p_vout->pf_manage = NULL; + p_vout->pf_render = Render; + p_vout->pf_display = NULL; + p_vout->pf_control = Control; + + return VLC_SUCCESS; +} + +/***************************************************************************** + * Init: initialize Magnify video thread output method + *****************************************************************************/ +static int Init( vout_thread_t *p_vout ) +{ + int i_index; + picture_t *p_pic; + video_format_t fmt = {0}; + + I_OUTPUTPICTURES = 0; + + /* Initialize the output structure */ + p_vout->output.i_chroma = p_vout->render.i_chroma; + p_vout->output.i_width = p_vout->render.i_width; + p_vout->output.i_height = p_vout->render.i_height; + p_vout->output.i_aspect = p_vout->render.i_aspect; + + p_vout->fmt_out = p_vout->fmt_in; + fmt = p_vout->fmt_out; + + /* Try to open the real video output */ + msg_Dbg( p_vout, "spawning the real video output" ); + + p_vout->p_sys->p_vout = vout_Create( p_vout, &fmt ); + + /* Everything failed */ + if( p_vout->p_sys->p_vout == NULL ) + { + msg_Err( p_vout, "cannot open vout, aborting" ); + return VLC_EGENERIC; + } + + var_AddCallback( p_vout->p_sys->p_vout, "mouse-x", MouseEvent, p_vout ); + var_AddCallback( p_vout->p_sys->p_vout, "mouse-y", MouseEvent, p_vout ); + var_AddCallback( p_vout->p_sys->p_vout, "mouse-clicked", + MouseEvent, p_vout); + + ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES ); + ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents ); + ADD_PARENT_CALLBACKS( SendEventsToChild ); + + return VLC_SUCCESS; +} + +/***************************************************************************** + * End: terminate Magnify video thread output method + *****************************************************************************/ +static void End( vout_thread_t *p_vout ) +{ + int i_index; + + /* Free the fake output buffers we allocated */ + for( i_index = I_OUTPUTPICTURES ; i_index ; ) + { + i_index--; + free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig ); + } + + var_DelCallback( p_vout->p_sys->p_vout, "mouse-x", MouseEvent, p_vout); + var_DelCallback( p_vout->p_sys->p_vout, "mouse-y", MouseEvent, p_vout); + var_DelCallback( p_vout->p_sys->p_vout, "mouse-clicked", MouseEvent, p_vout); +} + +/***************************************************************************** + * Destroy: destroy Magnify video thread output method + *****************************************************************************/ +static void Destroy( vlc_object_t *p_this ) +{ + vout_thread_t *p_vout = (vout_thread_t *)p_this; + + if( p_vout->p_sys->p_vout ) + { + DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents ); + vlc_object_detach( p_vout->p_sys->p_vout ); + vout_Destroy( p_vout->p_sys->p_vout ); + } + + image_HandlerDelete( p_vout->p_sys->p_image ); + free( p_vout->p_sys->pi_order ); + + DEL_PARENT_CALLBACKS( SendEventsToChild ); + + free( p_vout->p_sys ); +} + +/***************************************************************************** + * Render: displays previously rendered output + *****************************************************************************/ +static void Render( vout_thread_t *p_vout, picture_t *p_pic ) +{ + picture_t *p_outpic; + + //video_format_t fmt_out = {0}; + //picture_t *p_converted; + + int i_plane; + + int i_rows = p_vout->p_sys->i_rows; + int i_cols = p_vout->p_sys->i_cols; + + /* This is a new frame. Get a structure from the video_output. */ + while( ( p_outpic = vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 ) ) + == NULL ) + { + if( p_vout->b_die || p_vout->b_error ) + { + return; + } + msleep( VOUT_OUTMEM_SLEEP ); + } + + vout_DatePicture( p_vout->p_sys->p_vout, p_outpic, p_pic->date ); + + for( i_plane = 0; i_plane < p_outpic->i_planes; i_plane++ ) + { + plane_t *p_in = p_pic->p+i_plane; + plane_t *p_out = p_outpic->p+i_plane; + int i_pitch = p_in->i_pitch; + int i; + + for( i = 0; i < i_cols * i_rows; i++ ) + { + int i_col = i % i_cols; + int i_row = i / i_cols; + int i_ocol = p_vout->p_sys->pi_order[i] % i_cols; + int i_orow = p_vout->p_sys->pi_order[i] / i_cols; + int i_last_row = i_row + 1; + i_orow *= p_in->i_lines / i_rows; + i_row *= p_in->i_lines / i_rows; + i_last_row *= p_in->i_lines / i_rows; + + for( ; i_row < i_last_row; i_row++, i_orow++ ) + { + memcpy( p_out->p_pixels + i_row * i_pitch + + i_col * i_pitch / i_cols, + p_in->p_pixels + i_orow * i_pitch + + i_ocol * i_pitch / i_cols, + i_pitch / i_cols ); + } + } + } + + if( p_vout->p_sys->i_selected != -1 ) + { + plane_t *p_in = p_pic->p+Y_PLANE; + plane_t *p_out = p_outpic->p+Y_PLANE; + int i_pitch = p_in->i_pitch; + int i_col = p_vout->p_sys->i_selected % i_cols; + int i_row = p_vout->p_sys->i_selected / i_cols; + int i_last_row = i_row + 1; + i_row *= p_in->i_lines / i_rows; + i_last_row *= p_in->i_lines / i_rows; + memset( p_out->p_pixels + i_row * i_pitch + + i_col * i_pitch / i_cols, + 0xff, i_pitch / i_cols ); + for( ; i_row < i_last_row; i_row++ ) + { + p_out->p_pixels[ i_row * i_pitch + + i_col * i_pitch / i_cols ] = 0xff; + p_out->p_pixels[ i_row * i_pitch + + (i_col+1) * i_pitch / i_cols - 1 ] = 0xff; + } + i_row--; + memset( p_out->p_pixels + i_row * i_pitch + + i_col * i_pitch / i_cols, + 0xff, i_pitch / i_cols ); + } + + vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic ); +} + +/***************************************************************************** + * SendEvents: forward mouse and keyboard events to the parent p_vout + *****************************************************************************/ +static int SendEvents( vlc_object_t *p_this, char const *psz_var, + vlc_value_t oldval, vlc_value_t newval, void *p_data ) +{ + var_Set( (vlc_object_t *)p_data, psz_var, newval ); + + return VLC_SUCCESS; +} + +/***************************************************************************** + * SendEventsToChild: forward events to the child/children vout + *****************************************************************************/ +static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var, + vlc_value_t oldval, vlc_value_t newval, void *p_data ) +{ + vout_thread_t *p_vout = (vout_thread_t *)p_this; + var_Set( p_vout->p_sys->p_vout, psz_var, newval ); + return VLC_SUCCESS; +} + +/***************************************************************************** + * MouseEvent: callback for mouse events + *****************************************************************************/ +static int MouseEvent( vlc_object_t *p_this, char const *psz_var, + vlc_value_t oldval, vlc_value_t newval, void *p_data ) +{ + vout_thread_t *p_vout = (vout_thread_t*)p_data; + int i_x, i_y; + int i_v; + +#define MOUSE_DOWN 1 +#define MOUSE_CLICKED 2 +#define MOUSE_MOVE_X 4 +#define MOUSE_MOVE_Y 8 +#define MOUSE_MOVE 12 + uint8_t mouse= 0; + + int v_h = p_vout->output.i_height; + int v_w = p_vout->output.i_width; + int i_pos; + + if( psz_var[6] == 'x' ) mouse |= MOUSE_MOVE_X; + if( psz_var[6] == 'y' ) mouse |= MOUSE_MOVE_Y; + if( psz_var[6] == 'c' ) mouse |= MOUSE_CLICKED; + + i_v = var_GetInteger( p_vout->p_sys->p_vout, "mouse-button-down" ); + if( i_v & 0x1 ) mouse |= MOUSE_DOWN; + i_y = var_GetInteger( p_vout->p_sys->p_vout, "mouse-y" ); + i_x = var_GetInteger( p_vout->p_sys->p_vout, "mouse-x" ); + + if( mouse & MOUSE_CLICKED ) + { + i_pos = p_vout->p_sys->i_cols * ( ( p_vout->p_sys->i_rows * i_y ) / v_h ) + (p_vout->p_sys->i_cols * i_x ) / v_w; + if( p_vout->p_sys->b_finished == VLC_TRUE ) + { + shuffle( p_vout->p_sys ); + } + else if( p_vout->p_sys->i_selected == -1 ) + { + p_vout->p_sys->i_selected = i_pos; + } + else if( p_vout->p_sys->i_selected == i_pos ) + { + p_vout->p_sys->i_selected = -1; + } + else if( p_vout->p_sys->i_selected == i_pos + 1 + || p_vout->p_sys->i_selected == i_pos - 1 + || p_vout->p_sys->i_selected == i_pos + p_vout->p_sys->i_cols + || p_vout->p_sys->i_selected == i_pos - p_vout->p_sys->i_cols ) + { + int a = p_vout->p_sys->pi_order[ p_vout->p_sys->i_selected ]; + p_vout->p_sys->pi_order[ p_vout->p_sys->i_selected ] = + p_vout->p_sys->pi_order[ i_pos ]; + p_vout->p_sys->pi_order[ i_pos ] = a; + p_vout->p_sys->i_selected = -1; + + p_vout->p_sys->b_finished = finished( p_vout->p_sys ); + } + } + return VLC_SUCCESS; +}