📄 remoteosd.c
字号:
/***************************************************************************** * remoteosd.c: remote osd over vnc filter module ***************************************************************************** * Copyright (C) 2007-2008 Matthias Bauer * $Id: 6e4a5be941cf63a4d66185cf2636fe165bfa5575 $ * * Authors: Matthias Bauer <matthias dot bauer #_at_# gmx dot ch> * * 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 implid 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. *****************************************************************************//***************************************************************************** * RemoteOSD uses the RFB-Protocol of VNC to display an On-Screen-Display * menu generated by a streaming server as overlay for the streamed video. * * The streaming server that implements this is the ffnetdev plugin for VDR. * VDR (VideoDiskRecorder) is an Linux based OpenSource harddisk recorder * software. * The VDR ffnetdev plugin emulates the hardware MPEG decoder and streams the * video over the network instead of hardware video outputs. * The OSD menu of VDR is offered with the RFB protocol to a VNC client. * * In fact this video-filter is a simple VNC client that could be also used to * connect to a real VNC host. * Only 8-bit color is supported at the moment. * Using password protected VNC hosts is supported but not recommended, because * you need to insert the used password in the plugin configuration page of * VLC configuration in plain text and it's saved in plain text. *****************************************************************************///#define VNC_DEBUG/***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_plugin.h>#include <vlc_vout.h>#include "vlc_filter.h"#include "filter_common.h"#include "vlc_image.h"#include "vlc_osd.h"#include "vlc_keys.h"#include <vlc_network.h>#include <gcrypt.h> /* to encrypt password */#include <vlc_gcrypt.h>#include "remoteosd_rfbproto.h" /* type definitions of the RFB protocol for VNC *//***************************************************************************** * Module descriptor *****************************************************************************/#define READ_BUFFER_SIZE 1000000#define RMTOSD_HOST_TEXT N_("VNC Host")#define RMTOSD_HOST_LONGTEXT N_( \ "VNC hostname or IP address." )#define RMTOSD_PORT_TEXT N_("VNC Port")#define RMTOSD_PORT_LONGTEXT N_( \ "VNC portnumber." )#define RMTOSD_PASSWORD_TEXT N_("VNC Password")#define RMTOSD_PASSWORD_LONGTEXT N_( \ "VNC password." )#define RMTOSD_UPDATE_TEXT N_("VNC poll interval" )#define RMTOSD_UPDATE_LONGTEXT N_( \ "In this interval an update from VNC is requested, default every 300 ms. ")#define RMTOSD_POLL_TEXT N_("VNC polling")#define RMTOSD_POLL_LONGTEXT N_( \ "Activate VNC polling. Do NOT activate for use as VDR ffnetdev client." )#define RMTOSD_MOUSE_TEXT N_("Mouse events")#define RMTOSD_MOUSE_LONGTEXT N_( \ "Send mouse events to VNC host. Not needed for use as VDR ffnetdev client." )#define RMTOSD_KEYS_TEXT N_("Key events")#define RMTOSD_KEYS_LONGTEXT N_( \ "Send key events to VNC host." )#define RMTOSD_ALPHA_TEXT N_("Alpha transparency value (default 255)")#define RMTOSD_ALPHA_LONGTEXT N_( \ "The transparency of the OSD VNC can be changed by giving a value " \ "between 0 and 255. A lower value specifies more transparency a higher " \ "means less transparency. The default is being not transparent " \ "(value 255) the minimum is fully transparent (value 0)." )#define RMTOSD_CFG "rmtosd-"#define RMTOSD_UPDATE_MIN 200#define RMTOSD_UPDATE_DEFAULT 1000#define RMTOSD_UPDATE_MAX 300static 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 ); add_string( RMTOSD_CFG "host", "myvdr", NULL, RMTOSD_HOST_TEXT, RMTOSD_HOST_LONGTEXT, false ); add_integer_with_range( RMTOSD_CFG "port", 20001, 1, 0xFFFF, NULL, RMTOSD_PORT_TEXT, RMTOSD_PORT_LONGTEXT, false ); add_password( RMTOSD_CFG "password", "", NULL, RMTOSD_PASSWORD_TEXT, 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 ); add_bool( RMTOSD_CFG "vnc-polling", 0, NULL, RMTOSD_POLL_TEXT , RMTOSD_POLL_LONGTEXT, false ); add_bool( RMTOSD_CFG "mouse-events", 0, NULL, RMTOSD_MOUSE_TEXT , RMTOSD_MOUSE_LONGTEXT, false ); add_bool( RMTOSD_CFG "key-events", 0, NULL, 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 );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 );/***************************************************************************** * Sub filter code *****************************************************************************//***************************************************************************** * Local prototypes *****************************************************************************/struct filter_sys_t{ VLC_COMMON_MEMBERS bool b_need_update; /* VNC picture is updated, do update the OSD*/ mtime_t i_vnc_poll_interval; /* Update the OSD menu every n ms */ uint8_t i_alpha; /* alpha transparency value */ char *psz_host; /* VNC host */ int i_port; char *psz_passwd; /* VNC password */ bool b_vnc_poll; /* Activate VNC polling ? */ bool b_vnc_mouse_events; /* Send MouseEvents ? */ bool b_vnc_key_events; /* Send KeyEvents ? */ bool b_connection_active; /* Handshaking finished ? */ vlc_mutex_t lock; /* To lock for read/write on picture */ picture_t *p_pic; /* The picture with OSD data from VNC */ vout_thread_t *p_vout; /* Pointer to video-out thread */ int i_socket; /* Socket used for VNC */ uint16_t i_vnc_width; /* The with of the VNC screen */ uint16_t i_vnc_height; /* The height of the VNC screen */ uint32_t i_vnc_pixels; /* The pixels of the VNC screen */ bool b_alpha_from_vnc; /* Special ffnetdev alpha feature enabled ? */ char read_buffer[READ_BUFFER_SIZE]; bool b_continue; vlc_object_t* p_worker_thread; uint8_t ar_color_table_yuv[256][4];};/***************************************************************************** * CreateFilter: Create the filter and open the definition file *****************************************************************************/static int CreateFilter ( vlc_object_t *p_this ){ filter_t *p_filter = (filter_t *)p_this; filter_sys_t *p_sys = NULL; msg_Dbg( p_filter, "Creating vnc osd filter..." ); p_filter->p_sys = p_sys = malloc( sizeof(*p_sys) ); if( !p_filter->p_sys ) return VLC_ENOMEM; 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) ) { msg_Err( p_filter, "unable to get vnc host" ); goto error; } p_sys->psz_passwd = var_CreateGetString( p_this, RMTOSD_CFG "password" ); if( !p_sys->psz_passwd ) { msg_Err( p_filter, "unable to get vnc password" ); goto error; } p_sys->i_port = var_CreateGetIntegerCommand( p_this, RMTOSD_CFG "port" ); p_sys->i_alpha = var_CreateGetIntegerCommand( p_this, RMTOSD_CFG "alpha" ); /* in miliseconds, 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) { p_sys->i_vnc_poll_interval = 100; } for ( int i = 0; i < 256; i++ ) { p_sys->ar_color_table_yuv[i][0] = 255; p_sys->ar_color_table_yuv[i][1] = 255; p_sys->ar_color_table_yuv[i][2] = 255; p_sys->ar_color_table_yuv[i][3] = 255; } p_sys->b_vnc_poll = var_CreateGetBoolCommand( p_this, RMTOSD_CFG "vnc-polling" ); p_sys->b_vnc_mouse_events = var_CreateGetBoolCommand( p_this, RMTOSD_CFG "mouse-events" ); p_sys->b_vnc_key_events = var_CreateGetBoolCommand( p_this, RMTOSD_CFG "key-events" ); /* Keep track of OSD Events */ p_sys->b_need_update = false; /* Attach subpicture filter callback */ p_filter->pf_sub_filter = Filter; p_sys->p_vout = vlc_object_find( p_this, VLC_OBJECT_VOUT, FIND_PARENT ); if( p_sys->p_vout ) { var_AddCallback( p_sys->p_vout, "mouse-moved", MouseEvent, p_this ); var_AddCallback( p_sys->p_vout, "mouse-button-down", MouseEvent, p_this ); var_AddCallback( p_sys->p_vout->p_libvlc, "key-pressed", KeyEvent, p_this ); } es_format_Init( &p_filter->fmt_out, SPU_ES, VLC_FOURCC( 's','p','u',' ' ) ); p_filter->fmt_out.i_priority = 0; vlc_gcrypt_init(); /* create the vnc worker thread */ 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 ) ) { vlc_object_detach( p_sys->p_worker_thread ); vlc_object_release( p_sys->p_worker_thread ); msg_Err( p_filter, "cannot spawn vnc message reader thread" ); goto error; } msg_Dbg( p_filter, "osdvnc filter started" ); return VLC_SUCCESS;error: msg_Err( p_filter, "osdvnc filter discarded" ); stop_osdvnc( p_filter ); vlc_mutex_destroy( &p_sys->lock ); free( p_sys->psz_host ); free( p_sys->psz_passwd ); free( p_sys ); return VLC_EGENERIC;}/***************************************************************************** * DestroyFilter: Make a clean exit of this plugin *****************************************************************************/static void DestroyFilter( vlc_object_t *p_this ){ filter_t *p_filter = (filter_t*)p_this; filter_sys_t *p_sys = p_filter->p_sys; msg_Dbg( p_filter, "DestroyFilter called." ); stop_osdvnc( p_filter ); if( p_sys->p_vout ) { var_DelCallback( p_sys->p_vout, "mouse-moved", MouseEvent, p_this ); var_DelCallback( p_sys->p_vout, "mouse-button-down", MouseEvent, p_this );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -