X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_filter%2Fremoteosd.c;h=8b0e02ece326754b86991c75306cf4f11c192ec7;hb=0ff3d294f534eb45b0a62cbca90b9878d3b34c60;hp=1b84c18938ae2baf9f8aa2f6369c3c77a46bd04f;hpb=42bb236284b09355d8bfde47fb4915dd1f07aa68;p=vlc diff --git a/modules/video_filter/remoteosd.c b/modules/video_filter/remoteosd.c index 1b84c18938..8b0e02ece3 100644 --- a/modules/video_filter/remoteosd.c +++ b/modules/video_filter/remoteosd.c @@ -64,63 +64,8 @@ #include /* to encrypt password */ #include -#define CHALLENGESIZE 16 -#define MAX_VNC_SERVER_NAME_LENGTH 255 - #include "remoteosd_rfbproto.h" /* type definitions of the RFB protocol for VNC */ -/***************************************************************************** - * Local prototypes - *****************************************************************************/ -/* subfilter functions */ -static int CreateFilter ( vlc_object_t * ); -static void DestroyFilter( vlc_object_t * ); -static subpicture_t *Filter( filter_t *, mtime_t ); - -static int MouseEvent ( vlc_object_t *p_this, char const *psz_var, - vlc_value_t oldval, vlc_value_t newval, void *p_data ); - -static int KeyEvent( vlc_object_t *p_this, char const *psz_var, - vlc_value_t oldval, vlc_value_t newval, void *p_data ); - -static void stop_osdvnc ( filter_t *p_filter ); - -static void vnc_worker_thread ( vlc_object_t *p_thread_obj ); - -static void update_request_thread( vlc_object_t *p_thread_obj ); - -static bool open_vnc_connection ( filter_t *p_filter ); - -static bool handshaking ( filter_t *p_filter ); - -static bool process_server_message ( filter_t *p_filter, - rfbServerToClientMsg *msg ); - -static bool read_exact( filter_t *p_filter, - int i_socket, - char* p_readbuf, - int i_bytes ); - -static bool write_exact( filter_t *p_filter, - int i_socket, - char* p_writebuf, - int i_bytes ); - -static inline void rgb_to_yuv( uint8_t *y, uint8_t *u, uint8_t *v, - int r, int g, int b ); - -static inline bool fill_rect( filter_sys_t* p_sys, - uint16_t i_x, uint16_t i_y, - uint16_t i_w, uint16_t i_h, - uint8_t i_color ); - -static inline bool raw_line( filter_sys_t* p_sys, - uint16_t i_x, uint16_t i_y, - uint16_t i_w ); - -static void vnc_encrypt_bytes( unsigned char *bytes, char *passwd ); - - /***************************************************************************** * Module descriptor *****************************************************************************/ @@ -167,35 +112,86 @@ static void vnc_encrypt_bytes( unsigned char *bytes, char *passwd ); #define RMTOSD_UPDATE_DEFAULT 1000 #define RMTOSD_UPDATE_MAX 300 +static int CreateFilter ( vlc_object_t * ); +static void DestroyFilter( vlc_object_t * ); -vlc_module_begin(); - set_description( N_("Remote-OSD over VNC") ); - set_capability( "sub filter", 100 ); - set_shortname( N_("Remote-OSD") ); - set_category( CAT_VIDEO ); - set_subcategory( SUBCAT_VIDEO_SUBPIC ); - add_shortcut( "rmtosd" ); - set_callbacks( CreateFilter, DestroyFilter ); +vlc_module_begin () + set_description( N_("Remote-OSD over VNC") ) + set_capability( "sub filter", 100 ) + set_shortname( N_("Remote-OSD") ) + set_category( CAT_VIDEO ) + set_subcategory( SUBCAT_VIDEO_SUBPIC ) + add_shortcut( "rmtosd" ) + set_callbacks( CreateFilter, DestroyFilter ) add_string( RMTOSD_CFG "host", "myvdr", NULL, RMTOSD_HOST_TEXT, - RMTOSD_HOST_LONGTEXT, false ); + RMTOSD_HOST_LONGTEXT, false ) add_integer_with_range( RMTOSD_CFG "port", 20001, 1, 0xFFFF, NULL, - RMTOSD_PORT_TEXT, RMTOSD_PORT_LONGTEXT, false ); + RMTOSD_PORT_TEXT, RMTOSD_PORT_LONGTEXT, false ) add_password( RMTOSD_CFG "password", "", NULL, RMTOSD_PASSWORD_TEXT, - RMTOSD_PASSWORD_LONGTEXT, false ); + RMTOSD_PASSWORD_LONGTEXT, false ) add_integer_with_range( RMTOSD_CFG "update", RMTOSD_UPDATE_DEFAULT, RMTOSD_UPDATE_MIN, RMTOSD_UPDATE_MAX, NULL, RMTOSD_UPDATE_TEXT, - RMTOSD_UPDATE_LONGTEXT, true ); + RMTOSD_UPDATE_LONGTEXT, true ) add_bool( RMTOSD_CFG "vnc-polling", 0, NULL, - RMTOSD_POLL_TEXT , RMTOSD_POLL_LONGTEXT, false ); + RMTOSD_POLL_TEXT , RMTOSD_POLL_LONGTEXT, false ) add_bool( RMTOSD_CFG "mouse-events", 0, NULL, - RMTOSD_MOUSE_TEXT , RMTOSD_MOUSE_LONGTEXT, false ); + RMTOSD_MOUSE_TEXT , RMTOSD_MOUSE_LONGTEXT, false ) add_bool( RMTOSD_CFG "key-events", 0, NULL, - RMTOSD_KEYS_TEXT , RMTOSD_KEYS_LONGTEXT, false ); + RMTOSD_KEYS_TEXT , RMTOSD_KEYS_LONGTEXT, false ) add_integer_with_range( RMTOSD_CFG "alpha", 255, 0, 255, NULL, - RMTOSD_ALPHA_TEXT, RMTOSD_ALPHA_LONGTEXT, true ); + RMTOSD_ALPHA_TEXT, RMTOSD_ALPHA_LONGTEXT, true ) + +vlc_module_end () + + +/***************************************************************************** + * Local prototypes + *****************************************************************************/ +#define CHALLENGESIZE 16 +#define MAX_VNC_SERVER_NAME_LENGTH 255 + +/* subfilter functions */ +static subpicture_t *Filter( filter_t *, mtime_t ); + +static int MouseEvent ( vlc_object_t *p_this, char const *psz_var, + vlc_value_t oldval, vlc_value_t newval, void *p_data ); + +static int KeyEvent( vlc_object_t *p_this, char const *psz_var, + vlc_value_t oldval, vlc_value_t newval, void *p_data ); + +static void stop_osdvnc ( filter_t *p_filter ); + +static void* vnc_worker_thread ( vlc_object_t *p_thread_obj ); + +static void* update_request_thread( vlc_object_t *p_thread_obj ); + +static bool open_vnc_connection ( filter_t *p_filter ); + +static bool handshaking ( filter_t *p_filter ); + +static bool process_server_message ( filter_t *p_filter, + rfbServerToClientMsg *msg ); + +static inline void rgb_to_yuv( uint8_t *y, uint8_t *u, uint8_t *v, + int r, int g, int b ); + +static inline bool fill_rect( filter_sys_t* p_sys, + uint16_t i_x, uint16_t i_y, + uint16_t i_w, uint16_t i_h, + uint8_t i_color ); +static inline bool copy_rect( filter_sys_t* p_sys, + uint16_t i_x, uint16_t i_y, + uint16_t i_w, uint16_t i_h, + uint16_t i_sx, uint16_t i_sy ); + + +static inline bool raw_line( filter_sys_t* p_sys, + uint16_t i_x, uint16_t i_y, + uint16_t i_w ); + +static void vnc_encrypt_bytes( unsigned char *bytes, char *passwd ); -vlc_module_end(); /***************************************************************************** * Sub filter code @@ -243,7 +239,6 @@ struct filter_sys_t bool b_continue; vlc_object_t* p_worker_thread; - vlc_object_t* p_update_request_thread; uint8_t ar_color_table_yuv[256][4]; }; @@ -258,15 +253,16 @@ static int CreateFilter ( vlc_object_t *p_this ) msg_Dbg( p_filter, "Creating vnc osd filter..." ); - p_filter->p_sys = p_sys = (filter_sys_t *) malloc( sizeof(filter_sys_t) ); + p_filter->p_sys = p_sys = malloc( sizeof(*p_sys) ); if( !p_filter->p_sys ) return VLC_ENOMEM; - memset( p_sys, 0, sizeof(filter_sys_t) ); + memset( p_sys, 0, sizeof(*p_sys) ); /* Populating struct */ vlc_mutex_init( &p_sys->lock ); p_sys->b_continue = true; p_sys->i_socket = -1; + p_sys->p_pic = NULL; p_sys->psz_host = var_CreateGetString( p_this, RMTOSD_CFG "host" ); if( EMPTY_STR(p_sys->psz_host) ) @@ -286,7 +282,7 @@ static int CreateFilter ( vlc_object_t *p_this ) p_sys->i_alpha = var_CreateGetIntegerCommand( p_this, RMTOSD_CFG "alpha" ); - /* in miliseconds, 0 disables polling, should not be lower than 100 */ + /* in milliseconds, 0 disables polling, should not be lower than 100 */ p_sys->i_vnc_poll_interval = var_CreateGetIntegerCommand( p_this, RMTOSD_CFG "update" ); if ( p_sys->i_vnc_poll_interval < 100) @@ -333,15 +329,14 @@ static int CreateFilter ( vlc_object_t *p_this ) vlc_gcrypt_init(); /* create the vnc worker thread */ - p_sys->p_worker_thread = vlc_object_create( p_this, VLC_OBJECT_GENERIC ); + p_sys->p_worker_thread = vlc_object_create( p_this, + sizeof( vlc_object_t ) ); vlc_object_attach( p_sys->p_worker_thread, p_this ); if( vlc_thread_create( p_sys->p_worker_thread, "vnc worker thread", - vnc_worker_thread, - VLC_THREAD_PRIORITY_LOW, false ) ) + vnc_worker_thread, VLC_THREAD_PRIORITY_LOW ) ) { vlc_object_detach( p_sys->p_worker_thread ); vlc_object_release( p_sys->p_worker_thread ); - p_sys->p_worker_thread = NULL; msg_Err( p_filter, "cannot spawn vnc message reader thread" ); goto error; } @@ -353,10 +348,9 @@ static int CreateFilter ( vlc_object_t *p_this ) error: msg_Err( p_filter, "osdvnc filter discarded" ); - p_sys->b_continue = false; - stop_osdvnc( p_filter ); + vlc_mutex_destroy( &p_sys->lock ); free( p_sys->psz_host ); free( p_sys->psz_passwd ); free( p_sys ); @@ -386,7 +380,6 @@ static void DestroyFilter( vlc_object_t *p_this ) KeyEvent, p_this ); vlc_object_release( p_sys->p_vout ); - p_sys->p_vout = NULL; } var_Destroy( p_this, RMTOSD_CFG "host" ); @@ -398,6 +391,7 @@ static void DestroyFilter( vlc_object_t *p_this ) var_Destroy( p_this, RMTOSD_CFG "key-events" ); var_Destroy( p_this, RMTOSD_CFG "alpha" ); + vlc_mutex_destroy( &p_sys->lock ); free( p_sys->psz_host ); free( p_sys->psz_passwd ); free( p_sys ); @@ -407,30 +401,20 @@ static void stop_osdvnc ( filter_t *p_filter ) { filter_sys_t *p_sys = p_filter->p_sys; - if (p_sys->i_socket >= 0) - { - net_Close(p_sys->i_socket); - } - p_sys->b_continue = false; /* this causes the threads to stop */ + /* It will unlock socket reading */ + vlc_object_kill( p_filter ); - if ( p_sys->p_worker_thread ) + /* */ + if( p_sys->p_worker_thread ) { msg_Dbg( p_filter, "joining worker_thread" ); + vlc_object_kill( p_sys->p_worker_thread ); vlc_thread_join( p_sys->p_worker_thread ); vlc_object_detach( p_sys->p_worker_thread ); vlc_object_release( p_sys->p_worker_thread ); msg_Dbg( p_filter, "released worker_thread" ); } - if ( p_sys->p_update_request_thread ) - { - msg_Dbg( p_filter, "joining update_request_thread" ); - vlc_thread_join( p_sys->p_update_request_thread ); - vlc_object_detach( p_sys->p_update_request_thread ); - vlc_object_release( p_sys->p_update_request_thread ); - msg_Dbg( p_filter, "released update_request_thread" ); - } - msg_Dbg( p_filter, "osdvnc stopped" ); } @@ -620,6 +604,7 @@ static bool handshaking ( filter_t *p_filter ) rfbSetPixelFormatMsg sp; sp.type = rfbSetPixelFormat; + sp.pad1 = sp.pad2 = 0; sp.format.bitsPerPixel = 8; sp.format.depth = 8 ; sp.format.bigEndian = 1; @@ -630,6 +615,7 @@ static bool handshaking ( filter_t *p_filter ) sp.format.redShift = 10; sp.format.greenShift = 5; sp.format.blueShift = 0; + sp.format.pad1 = sp.format.pad2 = 0; if( !write_exact( p_filter, p_sys->i_socket, (char*)&sp, sz_rfbSetPixelFormatMsg) ) @@ -642,6 +628,7 @@ static bool handshaking ( filter_t *p_filter ) rfbSetEncodingsMsg se; se.type = rfbSetEncodings; + se.pad = 0; se.nEncodings = htons( p_sys->b_alpha_from_vnc ? 3 : 2 ); if( !write_exact( p_filter, p_sys->i_socket, @@ -684,23 +671,25 @@ static bool handshaking ( filter_t *p_filter ) } -static void vnc_worker_thread( vlc_object_t *p_thread_obj ) +static void* vnc_worker_thread( vlc_object_t *p_thread_obj ) { filter_t* p_filter = (filter_t*)(p_thread_obj->p_parent); filter_sys_t *p_sys = p_filter->p_sys; + vlc_object_t *p_update_request_thread; + int canc = vlc_savecancel (); msg_Dbg( p_filter, "VNC worker thread started" ); - if ( open_vnc_connection ( p_filter ) == false ) + if( !open_vnc_connection ( p_filter ) ) { msg_Err( p_filter, "Could not connect to vnc host" ); - return; + goto exit; } - if ( handshaking ( p_filter ) == false ) + if( !handshaking ( p_filter ) ) { msg_Err( p_filter, "Error occured while handshaking vnc host" ); - return; + goto exit; } p_sys->b_connection_active = true; /* to enable sending key @@ -708,122 +697,116 @@ static void vnc_worker_thread( vlc_object_t *p_thread_obj ) /* Create an empty picture for VNC the data */ vlc_mutex_lock( &p_sys->lock ); - p_sys->p_pic = malloc( sizeof(picture_t) ); + p_sys->p_pic = picture_New( VLC_FOURCC('Y','U','V','A'), + p_sys->i_vnc_width, p_sys->i_vnc_height, VOUT_ASPECT_FACTOR ); if( !p_sys->p_pic ) { vlc_mutex_unlock( &p_sys->lock ); - return; - } - vout_AllocatePicture( VLC_OBJECT(p_filter), p_sys->p_pic, - VLC_FOURCC('Y','U','V','A'), - p_sys->i_vnc_width, - p_sys->i_vnc_height, - VOUT_ASPECT_FACTOR ); - if( !p_sys->p_pic->i_planes ) - { - free( p_sys->p_pic ); - p_sys->p_pic = NULL; - vlc_mutex_unlock( &p_sys->lock ); - return; + goto exit; } p_sys->i_vnc_pixels = p_sys->i_vnc_width * p_sys->i_vnc_height; vlc_mutex_unlock( &p_sys->lock ); /* create the update request thread */ - p_sys->p_update_request_thread = vlc_object_create( p_filter, - VLC_OBJECT_GENERIC ); - vlc_object_attach( p_sys->p_update_request_thread, p_filter ); - if( vlc_thread_create( p_sys->p_update_request_thread, + p_update_request_thread = vlc_object_create( p_filter, + sizeof( vlc_object_t ) ); + vlc_object_attach( p_update_request_thread, p_filter ); + if( vlc_thread_create( p_update_request_thread, "vnc update request thread", - update_request_thread, - VLC_THREAD_PRIORITY_LOW, false ) ) + update_request_thread, VLC_THREAD_PRIORITY_LOW ) ) { - vlc_object_detach( p_sys->p_update_request_thread ); - vlc_object_release( p_sys->p_update_request_thread ); - p_sys->p_update_request_thread = NULL; + vlc_object_detach( p_update_request_thread ); + vlc_object_release( p_update_request_thread ); msg_Err( p_filter, "cannot spawn vnc update request thread" ); - return; + goto exit; } /* connection is initialized, now read and handle server messages */ + while( vlc_object_alive( p_thread_obj ) ) + { + rfbServerToClientMsg msg; + int i_msgSize; - int i_msgSize; + memset( &msg, 0, sizeof(msg) ); - rfbServerToClientMsg msg; + if( !read_exact(p_filter, p_sys->i_socket, (char*)&msg, 1 ) ) + { + msg_Err( p_filter, "Error while waiting for next server message"); + break; + } + switch (msg.type) + { + case rfbFramebufferUpdate: + i_msgSize = sz_rfbFramebufferUpdateMsg; + break; + case rfbSetColourMapEntries: + i_msgSize = sz_rfbSetColourMapEntriesMsg; + break; + case rfbBell: + i_msgSize = sz_rfbBellMsg; + break; + case rfbServerCutText: + i_msgSize = sz_rfbServerCutTextMsg; + break; + case rfbReSizeFrameBuffer: + i_msgSize = sz_rfbReSizeFrameBufferMsg; + break; + default: + i_msgSize = 0; + msg_Err( p_filter, "Invalid message %u received", msg.type ); + break; + } - while (p_sys->b_continue) - { - msg.type = 0; - if ( !read_exact(p_filter, p_sys->i_socket, (char*)&msg, 1 ) ) - { - msg_Err( p_filter, "Error while waiting for next server message"); - p_sys->b_continue = false; - } - else - { - switch (msg.type) - { - case rfbFramebufferUpdate: - i_msgSize = sz_rfbFramebufferUpdateMsg; - break; - case rfbSetColourMapEntries: - i_msgSize = sz_rfbSetColourMapEntriesMsg; - break; - case rfbBell: - i_msgSize = sz_rfbBellMsg; - break; - case rfbServerCutText: - i_msgSize = sz_rfbServerCutTextMsg; - break; - case rfbReSizeFrameBuffer: - i_msgSize = sz_rfbReSizeFrameBufferMsg; - break; - default: - i_msgSize = 0; - msg_Err( p_filter, "Invalid message %u received", msg.type ); - p_sys->b_continue = false; - } - if (p_sys->b_continue == true) - { - if (--i_msgSize > 0) - { - if ( !read_exact( p_filter, p_sys->i_socket, - ((char*)&msg)+1, i_msgSize ) ) - { - msg_Err( p_filter, "Error while reading message of type %u", - msg.type ); - p_sys->b_continue = false; - } - else - { - process_server_message( p_filter, &msg); - } - } - else - { - process_server_message( p_filter, &msg); - } - } - - } - - if (p_sys->p_worker_thread->b_die || - p_sys->p_worker_thread->b_error) - { - p_sys->b_continue = false; - } + if( i_msgSize <= 0 ) + break; + if( --i_msgSize > 0 ) + { + if ( !read_exact( p_filter, p_sys->i_socket, + ((char*)&msg)+1, i_msgSize ) ) + { + msg_Err( p_filter, "Error while reading message of type %u", + msg.type ); + break; + } + } + process_server_message( p_filter, &msg); } - msg_Dbg( p_filter, "VNC message reader thread ended" ); + msg_Dbg( p_filter, "joining update_request_thread" ); + vlc_object_kill( p_update_request_thread ); + vlc_thread_join( p_update_request_thread ); + vlc_object_detach( p_update_request_thread ); + vlc_object_release( p_update_request_thread ); + msg_Dbg( p_filter, "released update_request_thread" ); + +exit: + + vlc_mutex_lock( &p_sys->lock ); + p_sys->b_connection_active = false; + + if (p_sys->i_socket >= 0) + net_Close(p_sys->i_socket); + if( p_sys->p_pic ) + picture_Release( p_sys->p_pic ); + + /* It will hide the subtitle */ + p_sys->b_continue = false; + p_sys->b_need_update = true; + vlc_mutex_unlock( &p_sys->lock ); + + msg_Dbg( p_filter, "VNC message reader thread ended" ); + vlc_restorecancel (canc); + return NULL; } -static void update_request_thread( vlc_object_t *p_thread_obj ) +static void* update_request_thread( vlc_object_t *p_thread_obj ) { filter_t* p_filter = (filter_t*)(p_thread_obj->p_parent); filter_sys_t *p_sys = p_filter->p_sys; + int canc = vlc_savecancel (); msg_Dbg( p_filter, "VNC update request thread started" ); @@ -840,34 +823,34 @@ static void update_request_thread( vlc_object_t *p_thread_obj ) { msg_Err( p_filter, "Could not write rfbFramebufferUpdateRequestMsg." ); p_sys->b_continue = false; + return NULL; } udr.incremental = 1; mtime_t i_poll_interval_microsec = p_sys->i_vnc_poll_interval * 1000; - if (p_sys->b_vnc_poll) + if( p_sys->b_vnc_poll) { - while ( p_sys->b_continue == true ) + while( vlc_object_alive( p_thread_obj ) ) { msleep( i_poll_interval_microsec ); if( write_exact(p_filter, p_sys->i_socket, (char*)&udr, sz_rfbFramebufferUpdateRequestMsg) == false) { msg_Err( p_filter, "Could not write rfbFramebufferUpdateRequestMsg." ); - p_sys->b_continue = false; - } - if (p_sys->p_update_request_thread->b_die || - p_sys->p_update_request_thread->b_error) - { - p_sys->b_continue = false; + break; } } + p_sys->b_continue = false; } else { msg_Dbg( p_filter, "VNC polling disabled." ); } + msg_Dbg( p_filter, "VNC update request thread ended" ); + vlc_restorecancel (canc); + return NULL; } static bool process_server_message ( filter_t *p_filter, @@ -926,10 +909,31 @@ static bool process_server_message ( filter_t *p_filter, case rfbEncodingCopyRect: { - msg_Err( p_filter, - "Rect in unsupported encoding rfbEncodingCopyRect" ); - return false; + rfbCopyRect rect; + + if ( !read_exact( p_filter, p_sys->i_socket, + (char*)&rect, + sz_rfbCopyRect ) ) + { + msg_Err( p_filter, "Could not read rfbCopyRect" ); + return false; + } + rect.srcX = htons( rect.srcX ); + rect.srcY = htons( rect.srcY ); + + vlc_mutex_lock( &p_sys->lock ); + if ( !copy_rect( p_sys, + hdr.r.x, hdr.r.y, + hdr.r.w, hdr.r.h, + rect.srcX, rect.srcY ) ) + { + msg_Err( p_filter, "copy_rect failed." ); + vlc_mutex_unlock( &p_sys->lock ); + return false; + } + vlc_mutex_unlock( &p_sys->lock ); } + break; case rfbEncodingRRE: { @@ -1133,7 +1137,7 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) } /* Allocate the subpicture internal data. */ - p_spu = p_filter->pf_sub_buffer_new( p_filter ); + p_spu = filter_NewSubpicture( p_filter ); if( !p_spu ) { vlc_mutex_unlock( &p_sys->lock ); @@ -1145,6 +1149,9 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) p_spu->i_stop = 0; p_spu->b_ephemer = true; + if( !p_sys->b_continue ) + p_spu->i_stop = p_spu->i_start + 1; + /* Create new SPU region */ memset( &fmt, 0, sizeof(video_format_t) ); fmt.i_chroma = VLC_FOURCC('Y','U','V','A'); @@ -1153,7 +1160,7 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) fmt.i_width = fmt.i_visible_width = p_pic->p[Y_PLANE].i_visible_pitch; fmt.i_height = fmt.i_visible_height = p_pic->p[Y_PLANE].i_visible_lines; fmt.i_x_offset = fmt.i_y_offset = 0; - p_region = p_spu->pf_create_region( VLC_OBJECT(p_filter), &fmt ); + p_region = subpicture_region_New( &fmt ); if( !p_region ) { msg_Err( p_filter, "cannot allocate SPU region" ); @@ -1162,19 +1169,20 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) return NULL; } - vout_CopyPicture( p_filter, &p_region->picture, p_pic ); + /* FIXME the copy is probably not needed anymore */ + picture_Copy( p_region->p_picture, p_pic ); p_sys->b_need_update = false; vlc_mutex_unlock( &p_sys->lock ); /* set to one of the 9 relative locations */ - p_region->i_align = 0; //=CENTER + p_region->i_align = 0; /* Center */ p_spu->b_absolute = false; - p_spu->i_x = 0; - p_spu->i_y = 0; + p_spu->i_original_picture_width = 0; /*Let vout core do the horizontal scaling */ + p_spu->i_original_picture_height = fmt.i_height; p_spu->p_region = p_region; @@ -1227,6 +1235,65 @@ static inline bool fill_rect( filter_sys_t* p_sys, return true; } +static inline bool copy_rect( filter_sys_t* p_sys, + uint16_t i_x, uint16_t i_y, + uint16_t i_w, uint16_t i_h, + uint16_t i_sx, uint16_t i_sy ) +{ + plane_t *p_Y = p_sys->p_pic->p+Y_PLANE; + plane_t *p_U = p_sys->p_pic->p+U_PLANE; + plane_t *p_V = p_sys->p_pic->p+V_PLANE; + plane_t *p_A = p_sys->p_pic->p+A_PLANE; + + int i_pitch = p_Y->i_pitch; + int i_lines = p_Y->i_lines; + + fprintf( stderr, "copy_rect: (%d,%d)+(%d,%d) -> (%d,%d)\n", i_x, i_y, i_w, i_h, i_sx, i_sy ); + + if( i_x + i_w > i_pitch || i_sx + i_w > i_pitch ) + return false; + if( i_y + i_h > i_lines || i_sy + i_h > i_lines) + return false; + + if( i_w <= 0 || i_h <= 0 ) + return true; + + uint8_t *pb_buffer = calloc( i_w * i_h, 4 ); + if( !pb_buffer ) + return false; + + for( int i_line = 0; i_line < i_h; i_line++ ) + { + for( int i_column = 0; i_column < i_w; i_column++ ) + { + const int i_src_offset = ( i_sy + i_line ) * i_pitch + i_sx + i_column; + const int i_tmp_offset = ( 0 + i_line ) * i_w + 0 + i_column; + + pb_buffer[4*i_tmp_offset + 0] = p_Y->p_pixels[i_src_offset]; + pb_buffer[4*i_tmp_offset + 1] = p_U->p_pixels[i_src_offset]; + pb_buffer[4*i_tmp_offset + 2] = p_V->p_pixels[i_src_offset]; + pb_buffer[4*i_tmp_offset + 3] = p_A->p_pixels[i_src_offset]; + } + } + + for( int i_line = 0; i_line < i_h; i_line++ ) + { + for( int i_column = 0; i_column < i_w; i_column++ ) + { + const int i_tmp_offset = ( 0 + i_line ) * i_w + 0 + i_column; + const int i_dst_offset = ( i_y + i_line ) * i_pitch + i_x + i_column; + + p_Y->p_pixels[i_dst_offset] = pb_buffer[4*i_tmp_offset + 0]; + p_U->p_pixels[i_dst_offset] = pb_buffer[4*i_tmp_offset + 1]; + p_V->p_pixels[i_dst_offset] = pb_buffer[4*i_tmp_offset + 2]; + p_A->p_pixels[i_dst_offset] = pb_buffer[4*i_tmp_offset + 3]; + } + } + free( pb_buffer ); + return true; + +} + static inline bool raw_line( filter_sys_t* p_sys, uint16_t i_x, uint16_t i_y, uint16_t i_w ) @@ -1269,9 +1336,6 @@ static int MouseEvent( vlc_object_t *p_this, char const *psz_var, filter_t *p_filter = (filter_t *)p_data; filter_sys_t *p_sys = p_filter->p_sys; - if( !p_sys->b_connection_active ) - return VLC_SUCCESS; - if( !p_sys->b_vnc_mouse_events ) return VLC_SUCCESS; @@ -1279,23 +1343,38 @@ static int MouseEvent( vlc_object_t *p_this, char const *psz_var, int i_x, i_y; int i_v; - int v_h = p_vout->output.i_height; - int v_w = p_vout->output.i_width; i_v = var_GetInteger( p_sys->p_vout, "mouse-button-down" ); i_y = var_GetInteger( p_sys->p_vout, "mouse-y" ); i_x = var_GetInteger( p_sys->p_vout, "mouse-x" ); + vlc_mutex_lock( &p_sys->lock ); + + const int v_h = p_vout->fmt_in.i_visible_height; + const int v_w = p_sys->i_vnc_width * v_h / p_sys->i_vnc_height; + const int v_x = (p_vout->fmt_in.i_visible_width-v_w)/2; + + i_x -= v_x; + if( i_y < 0 || i_x < 0 || i_y >= v_h || i_x >= v_w ) { - msg_Dbg( p_this, "invalid mouse event? x=%d y=%d btn=%x", i_x, i_y, i_v ); - return VLC_SUCCESS; + vlc_mutex_unlock( &p_sys->lock ); + msg_Dbg( p_this, "invalid mouse event? x=%d y=%d btn=%x", i_x, i_y, i_v ); + return VLC_SUCCESS; + } + if( !p_sys->b_connection_active ) + { + vlc_mutex_unlock( &p_sys->lock ); + return VLC_SUCCESS; } + #ifdef VNC_DEBUG msg_Dbg( p_this, "mouse event x=%d y=%d btn=%x", i_x, i_y, i_v ); #endif - /* FIXME: calculate x and y coordinates for scaled output */ + /* */ + i_x = i_x * p_sys->i_vnc_width / v_w; + i_y = i_y * p_sys->i_vnc_height / v_h; /* buttonMask bits 0-7 are buttons 1-8, 0=up, 1=down */ rfbPointerEventMsg ev; @@ -1307,6 +1386,8 @@ static int MouseEvent( vlc_object_t *p_this, char const *psz_var, write_exact( p_filter, p_sys->i_socket, (char*)&ev, sz_rfbPointerEventMsg); + vlc_mutex_unlock( &p_sys->lock ); + return VLC_SUCCESS; } @@ -1321,9 +1402,6 @@ static int KeyEvent( vlc_object_t *p_this, char const *psz_var, filter_t *p_filter = (filter_t *)p_data; filter_sys_t *p_sys = p_filter->p_sys; - if( !p_sys->b_connection_active ) - return VLC_SUCCESS; - if( !p_sys->b_vnc_key_events ) return VLC_SUCCESS; @@ -1335,11 +1413,20 @@ static int KeyEvent( vlc_object_t *p_this, char const *psz_var, return VLC_EGENERIC; } + vlc_mutex_lock( &p_sys->lock ); + if( !p_sys->b_connection_active ) + { + vlc_mutex_unlock( &p_sys->lock ); + return VLC_SUCCESS; + } + uint32_t i_key32 = newval.i_int; i_key32 = htonl(i_key32); rfbKeyEventMsg ev; + ev.type = rfbKeyEvent; ev.down = 1; + ev.pad = 0; /* first key-down for modifier-keys */ if (newval.i_int & KEY_MODIFIER_CTRL) @@ -1391,6 +1478,7 @@ static int KeyEvent( vlc_object_t *p_this, char const *psz_var, write_exact( p_filter, p_sys->i_socket, (char*)&ev, sz_rfbKeyEventMsg); } + vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS; } @@ -1422,3 +1510,4 @@ static void vnc_encrypt_bytes( unsigned char *bytes, char *passwd ) gcry_cipher_encrypt( ctx, bytes, CHALLENGESIZE, bytes, CHALLENGESIZE ); gcry_cipher_close( ctx ); } +