Commit 1a1ae383 authored by Vincent Seguin's avatar Vincent Seguin

A tout kass�.

parent 7929ae1b
......@@ -9,32 +9,71 @@
# Configuration
################################################################################
# Environment
#CC = gcc
#SHELL = /bin/sh
# Video output settings
VIDEO=X11
#VIDEO=DGA
#VIDEO=FB
#VIDEO=BEOS
# Target architecture and optimization
#ARCH=
ARCH=MMX
#ARCH=PPC
#----------------- do not change anything below this line ----------------------
################################################################################
# Settings and other variables
# Configuration pre-processing
################################################################################
# DEFINE will contain all the constants definitions decided in Makefile
DEFINE = -DVIDEO_$(VIDEO)
# video is a lowercase version of VIDEO used for filenames
video = $(shell echo $(VIDEO) | tr 'A-Z' 'a-z')
################################################################################
# Tunning and other variables
################################################################################
#
# Transformation for video decompression (Fourier or cosine)
#
TRANSFORM=vdec_idct
#TRANSFORM=vdec_idft
#
# C headers directories
#
INCLUDE += -Iinclude
ifeq ($(VIDEO),X11)
INCLUDE += -I/usr/X11R6/include/X11
endif
#
# Libraries
#
LIB += -lpthread
ifeq ($(VIDEO),X11)
LIB += -L/usr/X11R6/lib
LIB += -lX11
LIB += -lXext
LIB += -lpthread
LIB += -lXpm
endif
# System dependant libraries
#??LIB += -lXxf86dga
#
# C compiler flags: compilation
#
CCFLAGS += $(INCLUDE)
CCFLAGS += $(DEFINE) $(INCLUDE)
CCFLAGS += -Wall
CCFLAGS += -D_REENTRANT
CCFLAGS += -D_GNU_SOURCE
......@@ -44,21 +83,24 @@ CCFLAGS += -O6
CCFLAGS += -ffast-math -funroll-loops -fargument-noalias-global
CCFLAGS += -fomit-frame-pointer
#CCFLAGS += -fomit-frame-pointer -s
#LCFLAGS += -s
# Platform-specific optimizations
# Optimizations for x86 familiy :
# Optimizations for x86 familiy, without MMX
ifeq ($(ARCH),)
CCFLAGS += -malign-double
CCFLAGS += -march=pentiumpro
#CCFLAGS += -march=pentium
endif
# MMX support :
CFLAGS += -DHAVE_MMX
ASM_OBJ = video_decoder_ref/idctmmx.o \
video_decoder_ref/yuv12-rgb16.o
# Optimization for x86 with MMX support
ifeq ($(ARCH),MMX)
CCFLAGS += -malign-double
CCFLAGS += -march=pentiumpro
endif
#Optimizations for PowerPC :
#CCFLAGS += -mcpu=604e -mmultiple -mhard-float -mstring
# Optimizations for PowerPC
ifeq ($(ARCH),PPC)
CCFLAGS += -mcpu=604e -mmultiple -mhard-float -mstring
endif
#
# C compiler flags: dependancies
......@@ -71,31 +113,16 @@ DCFLAGS += -MM
#
LCFLAGS += $(LIB)
LCFLAGS += -Wall
#
# C compiler flags: functions flow
#
FCFLAGS += $(INCLUDE)
FCFLAGS += -A
FCFLAGS += -P
FCFLAGS += -v
FCFLAGS += -a
FCFLAGS += -X errno.h
FCFLAGS += -X fcntl.h
FCFLAGS += -X signal.h
FCFLAGS += -X stdio.h
FCFLAGS += -X stdlib.h
FCFLAGS += -X string.h
FCFLAGS += -X unistd.h
FCFLAGS += -X sys/ioctl.h
FCFLAGS += -X sys/stat.h
FCFLAGS += -X X11/Xlib.h
FFILTER = grep -v "intf_.*Msg.*\.\.\."
#LCFLAGS += -s
#
# C compiler flags: common flags
#
# CFLAGS
# Optimizations for x86 with MMX support
ifeq ($(ARCH),MMX)
CFLAGS += -DHAVE_MMX
endif
#
# Additionnal debugging flags
......@@ -122,7 +149,8 @@ interface_obj = interface/main.o \
interface/intf_cmd.o \
interface/intf_ctrl.o \
interface/control.o \
interface/xconsole.o
interface/intf_console.o \
interface/intf_$(video).o
input_obj = input/input_vlan.o \
input/input_file.o \
......@@ -136,14 +164,14 @@ input_obj = input/input_vlan.o \
audio_output_obj = audio_output/audio_output.o \
audio_output/audio_dsp.o
#video_output_obj = video_output/video_output.o \
# video_output/video_x11.o \
# video_output/video_graphics.o
video_output_obj = video_output/video_output.o \
video_output/video_$(video).o
audio_decoder_obj = audio_decoder/audio_decoder.o \
audio_decoder/audio_math.o
#generic_decoder_obj = generic_decoder/generic_decoder.o
#??generic_decoder_obj = generic_decoder/generic_decoder.o
# remeber to add it to OBJ
video_decoder_obj = video_decoder_ref/video_decoder.o \
video_decoder_ref/display.o \
......@@ -156,6 +184,7 @@ video_decoder_obj = video_decoder_ref/video_decoder.o \
video_decoder_ref/mpeg2dec.o \
video_decoder_ref/recon.o \
video_decoder_ref/spatscal.o
# video_decoder_ref/$(TRANSFORM).o
#video_parser_obj = video_parser/video_parser.o \
# video_parser/vpar_headers.o \
......@@ -173,6 +202,12 @@ misc_obj = misc/mtime.o \
misc/rsc_files.o \
misc/netutils.o
ifeq ($(ARCH),MMX)
ASM_OBJ = video_decoder_ref/idctmmx.o \
video_decoder_ref/yuv12-rgb16.o
endif
C_OBJ = $(interface_obj) \
$(input_obj) \
$(audio_output_obj) \
......@@ -182,7 +217,7 @@ C_OBJ = $(interface_obj) \
$(video_parser_obj) \
$(video_decoder_obj) \
$(vlan_obj) \
$(misc_obj) \
$(misc_obj)
#
# Other lists of files
......@@ -207,7 +242,7 @@ clean:
distclean: clean
rm -f **/*.o **/*~ *.log
rm -f vlc gmon.out core Documentation/cflow
rm -f vlc gmon.out core
rm -rf dep
FORCE:
......@@ -218,9 +253,6 @@ FORCE:
vlc: $(C_OBJ) $(ASM_OBJ)
$(CC) $(LCFLAGS) $(CFLAGS) -o $@ $(C_OBJ) $(ASM_OBJ)
Documentation/cflow: $(sources)
cflow $(FCFLAGS) $(CFLAGS) $(sources) | $(FFILTER) > $@
#
# Generic rules (see below)
#
......@@ -232,7 +264,7 @@ $(C_OBJ): %.o: dep/%.d
$(C_OBJ): %.o: %.c
$(CC) $(CCFLAGS) $(CFLAGS) -c -o $@ $<
$(ASM_OBJ): %.o: %.S
$(CC) -c -o $@ $<
$(CC) $(CFLAGS) -c -o $@ $<
################################################################################
# Note on generic rules and dependancies
......
......@@ -200,10 +200,9 @@ typedef struct aout_thread_s
/******************************************************************************
* Prototypes
******************************************************************************/
int aout_Open ( aout_thread_t *p_aout );
int aout_SpawnThread ( aout_thread_t *p_aout );
void aout_CancelThread ( aout_thread_t *p_aout );
void aout_Close ( aout_thread_t *p_aout );
aout_thread_t * aout_CreateThread ( int *pi_status );
void aout_DestroyThread ( aout_thread_t *p_aout, int *pi_status );
aout_fifo_t * aout_CreateFifo ( aout_thread_t *p_aout, aout_fifo_t *p_fifo );
void aout_DestroyFifo ( aout_fifo_t *p_fifo );
......@@ -9,7 +9,7 @@
*******************************************************************************/
/*******************************************************************************
* Types definitions
* Basic types definitions
*******************************************************************************/
/* Basic types definitions */
......@@ -30,6 +30,48 @@ typedef int boolean_t;
/* Counter for statistics and profiling */
typedef unsigned long count_t;
/*******************************************************************************
* Classes declaration
*******************************************************************************/
/* Interface */
struct intf_thread_s;
struct intf_sys_s;
struct intf_console_s;
struct intf_msg_s;
typedef struct intf_thread_s * p_intf_thread_t;
typedef struct intf_sys_s * p_intf_sys_t;
typedef struct intf_console_s * p_intf_console_t;
typedef struct intf_msg_s * p_intf_msg_t;
/* Input */
struct input_thread_s;
struct input_vlan_method_s;
struct input_cfg_s;
typedef struct input_thread_s * p_input_thread_t;
typedef struct input_vlan_method_s * p_input_vlan_method_t;
typedef struct input_cfg_s * p_input_cfg_t;
/* Audio */
struct aout_thread_s;
typedef struct aout_thread_s * p_aout_thread_t;
/* Video */
struct vout_thread_s;
struct vout_sys_s;
struct vdec_thread_s;
struct vpar_thread_s;
struct video_parser_s;
typedef struct vout_thread_s * p_vout_thread_t;
typedef struct vout_sys_s * p_vout_sys_t;
typedef struct vdec_thread_s * p_vdec_thread_t;
typedef struct vpar_thread_s * p_vpar_thread_t;
typedef struct video_parser_s * p_video_parser_t;
/*******************************************************************************
* Macros and inline functions
*******************************************************************************/
......
......@@ -3,17 +3,29 @@
* (c)1999 VideoLAN
*******************************************************************************
* Defines all compilation-time configuration constants and size limits
*******************************************************************************
* required headers:
* none
*******************************************************************************/
/* Conventions regarding names of symbols and variables
* ----------------------------------------------------
*
* - Symbols should begin with a prefix indicating in which module they are
* used, such as INTF_, VOUT_ or ADEC_.
*
* - Regarding environment variables, which are used as initialization parameters
* for threads :
* + variable names should end with '_VAR'
* + environment variable default value should end with '_DEFAULT'
* + values having a special meaning with '_VAL'
* + complete environment strings with '_ENV'
*
*/
/*******************************************************************************
* Program information
*******************************************************************************/
/* Program version and copyright message */
#define PROGRAM_VERSION "0.0.x"
#define PROGRAM_VERSION "DR 2.1"
#define COPYRIGHT_MESSAGE "VideoLAN Client v" PROGRAM_VERSION " (" __DATE__ ") - (c)1999 VideoLAN\n"
/*******************************************************************************
......@@ -45,6 +57,10 @@
/* General debugging support */
#define DEBUG
/* Extended debugging support - in this mode, debugging messages will have their
* date and context printed */
#define DEBUG_CONTEXT
/* Modules specific debugging */
#define DEBUG_INTF
#define DEBUG_INPUT
......@@ -54,10 +70,9 @@
/* Debugging log file - if defined, a file can be used to store all messages. If
* DEBUG_LOG_ONLY is defined, debug messages will only be printed to the log and
* will not appear on the screen */
//#define DEBUG_LOG "vlc-debug.log"
//#define DEBUG_LOG_ONLY
#define DEBUG_LOG "vlc-debug.log"
#define DEBUG_LOG_ONLY
/* ?? VOUT_DEBUG and co have changed ! */
/*******************************************************************************
* Common settings
......@@ -67,7 +82,8 @@
#define AUTO_SPAWN
/* Startup script */
#define INIT_SCRIPT "vlc.init"
#define INTF_INIT_SCRIPT_VAR "vlc_init"
#define INTF_INIT_SCRIPT_DEFAULT "vlc.init"
/* ?? */
#define THREAD_SLEEP 100000
......@@ -164,11 +180,23 @@
#define VLAN_DEFAULT_SERVER_PORT 6010
/*******************************************************************************
* Audio output thread configuration
* Audio configuration
*******************************************************************************/
/* Environment variable used to store dsp device name, and default value */
#define AOUT_DSP_VAR "vlc_dsp"
#define AOUT_DSP_DEFAULT "/dev/dsp"
/* Environment variable for stereo, and default value */
#define AOUT_STEREO_VAR "vlc_stereo"
#define AOUT_STEREO_DEFAULT 1
/* Environment variable for output rate, and default value */
#define AOUT_RATE_VAR "vlc_audio_rate"
#define AOUT_RATE_DEFAULT 44100
/*******************************************************************************
* Video output thread configuration
* Video configuration
*******************************************************************************/
/*
......@@ -176,34 +204,19 @@
*/
/* Title of the window */
#define VOUT_TITLE "VideoLAN Client: output"
#define VOUT_TITLE "VideoLAN Client"
/* Default use of XShm extension */
#define VOUT_SHM_EXT 1
/* Dimensions for display window */
/* Default dimensions for display window - these dimensions are the standard
* width and height for broadcasted MPEG-2 */
#define VOUT_WIDTH 544
#define VOUT_HEIGHT 576
/* Default heap size */
#define VOUT_HEAP_SIZE 100
/*
* Limitations
*/
/* Maximum number of video output threads - this value is used exclusively by
* interface, and is in fact an interface limitation */
#define VOUT_MAX_THREADS 10
/* Maximum number of video streams per video output thread */
#define VOUT_MAX_STREAMS 10
/* Maximum number of pictures which can be rendered in one loop, plus one */
/* Default video heap size - remember that a decompressed picture is big
* (~1 Mbyte) before using huge values */
#define VOUT_MAX_PICTURES 10
/*
* Other settings
* Time settings
*/
/* Time during which the thread will sleep if it has nothing to
......@@ -219,12 +232,12 @@
/* ?? this constant will probably evolve to a calculated value */
#define VOUT_DISPLAY_DELAY 150000
/* Maximum lap of time during which images are rendered in the same
* time. It should be greater than the maximum time between two succesive
* images to avoid useless renderings and calls to the display driver,
* but not to high to avoid desynchronization */
/* ?? this constant will probably evolve to a calculated value */
#define VOUT_DISPLAY_TOLERANCE 150000
/*
* Environment settings
*/
/* Allow use of X11 XShm (shared memory) extension if possible */
#define VOUT_XSHM 1
/*******************************************************************************
* Video parser configuration
......@@ -277,28 +290,12 @@
/* Maximal size of a command line in a script */
#define INTF_MAX_CMD_SIZE 240
/*
* Messages functions
* X11 interface properties
*/
/* Maximal size of the message queue - in case of overflow, all messages in the
* queue are printed by the calling thread */
#define INTF_MSG_QSIZE 32
/* Define to enable messages queues - disabling messages queue can be usefull
* when debugging, since it allows messages which would not otherwise be printed,
* due to a crash, to be printed anyway */
/*#define INTF_MSG_QUEUE*/
/* Format of the header for debug messages. The arguments following this header
* are the file (char *), the function (char *) and the line (int) in which the
* message function was called */
#define INTF_MSG_DBG_FORMAT "## %s:%s(),%i: "
/* Filename to log message
* Note that messages are only logged when debugging */
//#define INTF_MSG_LOGFILE "vlc.log"
#define INTF_APP_CLASS "vlc"
#define INTF_APP_NAME "vlc"
//??#define
/*
* X11 console properties
......@@ -323,15 +320,37 @@
#define INTF_XCONSOLE_FONT "-*-helvetica-medium-r-normal-*-18-*-*-*-*-*-iso8859-1"
/* Number of memorized lines in X11 console window text zone */
#define INTF_XCONSOLE_MAX_LINES 100
#define INTF_CONSOLE_MAX_TEXT 100
/* Maximal number of commands which can be saved in history list */
#define INTF_XCONSOLE_HISTORY_SIZE 20
#define INTF_CONSOLE_MAX_HISTORY 20
/* Maximum width of a line in an X11 console window. If a larger line is
* printed, it will be wrapped. */
#define INTF_XCONSOLE_MAX_LINE_WIDTH 120
#define ENV_VLC_DISPLAY "vlc_DISPLAY"
#define INTF_MAIN_WIDTH 600
#define INTF_MAIN_HEIGHT 600
/*******************************************************************************
* Interface messages functions
*******************************************************************************/
/* Maximal size of the message queue - in case of overflow, all messages in the
* queue are printed by the calling thread */
#define INTF_MSG_QSIZE 32
/* Define to enable messages queues - disabling messages queue can be usefull
* when debugging, since it allows messages which would not otherwise be printed,
* due to a crash, to be printed anyway */
//#define INTF_MSG_QUEUE
/* Format of the header for debug messages. The arguments following this header
* are the file (char *), the function (char *) and the line (int) in which the
* message function was called */
#define INTF_MSG_DBG_FORMAT "## %s:%s(),%i: "
/*******************************************************************************
* Network and VLAN management
......
......@@ -24,12 +24,6 @@
/*******************************************************************************
* Prototypes
*******************************************************************************/
int intf_CreateVoutThread ( intf_thread_t *p_intf, char *psz_title,
int i_width, int i_height );
void intf_DestroyVoutThread ( intf_thread_t *p_intf, int i_thread );
int intf_CreateInputThread ( intf_thread_t *p_intf, input_cfg_t* p_cfg );
void intf_DestroyInputThread ( intf_thread_t *p_intf, int i_thread );
int intf_SelectAudioStream ( intf_thread_t *p_intf, int i_input, int i_id );
void intf_DeselectAudioStream( intf_thread_t *p_intf, int i_input, int i_id );
int intf_SelectVideoStream ( intf_thread_t *p_intf, int i_input,
......
......@@ -310,7 +310,7 @@ typedef int (*f_read_t)( struct input_thread_struct *, const struct iovec *,
size_t );
typedef void (*f_clean_t)( struct input_thread_struct * );
typedef struct input_thread_struct
typedef struct input_thread_s
{
/* Thread properties and locks */
boolean_t b_die; /* 'die' flag */
......@@ -369,7 +369,7 @@ typedef struct input_thread_struct
* properties, asking the called function to use default settings for
* the other ones.
******************************************************************************/
typedef struct input_cfg_struct
typedef struct input_cfg_s
{
u64 i_properties;
......
......@@ -38,72 +38,11 @@
#define VLAN_ID_VLAN( vlan_id ) ( (vlan_id) & 0xff )
#define VLAN_ID( iface, vlan ) ( ((iface) << 8) | (vlan) )
/*******************************************************************************
* input_vlan_server_t: vlan server
*******************************************************************************
* This structure describes a vlan server.
*******************************************************************************/
typedef struct
{
struct sockaddr_in sa_in; /* server address */
int i_socket; /* socket descriptor */
/* Login informations */
char * psz_login; /* server login */
char * psz_passwd; /* server password */
} input_vlan_server_t;
/*******************************************************************************
* input_vlan_iface_t: vlan-capable network interface
*******************************************************************************
* This structure describes the abilities of a network interface capable of
* vlan management. Note that an interface could have several IP adresses, but
* since only the MAC address is used to change vlan, only one needs to be
* retrieved.
* ?? it could be interesting to send a port id on vlan request, to know if two
* interfaces are dependant regarding vlan changes.
*******************************************************************************/
typedef struct
{
char * psz_name; /* interface name */
struct sockaddr_in sa_in; /* interface IP */
char psz_mac[20]; /* interface MAC */
/* Hardware properties */
int i_master; /* master interface index */
int i_switch; /* switch number */
int i_port; /* port number */
int i_sharers; /* number of MACs on this port */
/* Vlan properties - these are only used if i_master is negative */
int i_refcount; /* locks counter */
int i_vlan; /* current vlan */
int i_default_vlan; /* default vlan */
} input_vlan_iface_t;
/*******************************************************************************
* vlan_method_data_t
*******************************************************************************
* Store global vlan library data.
*******************************************************************************/
typedef struct
{
vlc_mutex_t lock; /* library lock */
/* Server */
input_vlan_server_t server; /* vlan server */
/* Network interfaces */
int i_ifaces; /* number of vlan-compliant interfaces */
input_vlan_iface_t * p_iface; /* interfaces */
} input_vlan_method_t;
/*******************************************************************************
* Prototypes
*******************************************************************************/
int input_VlanMethodInit ( input_vlan_method_t *p_method,
char *psz_server, int i_port);
void input_VlanMethodFree ( input_vlan_method_t *p_method );
int input_VlanCreate ( void );
void input_VlanDestroy ( void );
int input_VlanId ( char *psz_iface, int i_vlan );
int input_VlanJoin ( int i_vlan_id );
......
......@@ -26,23 +26,25 @@
* This structe describes all interface-specific data of the main (interface)
* thread.
******************************************************************************/
typedef struct
typedef struct intf_thread_s
{
boolean_t b_die; /* `die' flag */
/* Threads control */
input_thread_t * pp_input[INPUT_MAX_THREADS]; /* input threads */
vout_thread_t * pp_vout[VOUT_MAX_THREADS]; /* vout threads */
aout_thread_t * p_aout; /* aout thread */
int i_input; /* default input thread */
int i_vout; /* default output thread */
/* Specific interfaces */
xconsole_t xconsole; /* X11 console */
p_intf_console_t p_console; /* console */
p_intf_sys_t p_sys; /* system interface */
/* Main threads - NULL if not active */
p_vout_thread_t p_vout;
p_input_thread_t p_input;
} intf_thread_t;
/******************************************************************************
* Prototypes
******************************************************************************/
int intf_Run( intf_thread_t * p_intf );
intf_thread_t * intf_Create ( void );
void intf_Run ( intf_thread_t * p_intf );
void intf_Destroy ( intf_thread_t * p_intf );
int intf_SelectInput ( intf_thread_t * p_intf, p_input_cfg_t p_cfg );
/*******************************************************************************
* intf_console.h: generic console methods for interface
* (c)1998 VideoLAN
*******************************************************************************/
/*******************************************************************************
* Prototypes
*******************************************************************************/
p_intf_console_t intf_ConsoleCreate ( void );
void intf_ConsoleDestroy ( p_intf_console_t p_console );
void intf_ConsoleClear ( p_intf_console_t p_console );
void intf_ConsolePrint ( p_intf_console_t p_console, char *psz_str );
void intf_ConsoleExec ( p_intf_console_t p_console, char *psz_str );
......@@ -3,75 +3,8 @@
* (c)1999 VideoLAN
*******************************************************************************
* This library provides basic functions for threads to interact with user
* interface, such as message output. If INTF_MSG_QUEUE is defined (which is the
* defaul), messages are not printed directly by threads, to bypass console
* limitations and slow printf() calls, but sent to a queue and printed later by
* interface thread.
* If INTF_MSG_QUEUE is not defined, output is directly performed on stderr.
*******************************************************************************
* required headers:
* "config.h"
* "mtime.h"
* "vlc_thread.h"
*******************************************************************************/
/*******************************************************************************
* interface_message_t
*******************************************************************************
* Store a single message. Messages have a maximal size of INTF_MSG_MSGSIZE.
* If DEBUG is defined, messages have a date field and debug messages are
* printed with a date to allow more precise profiling.
*******************************************************************************/
typedef struct
{
int i_type; /* message type, see below */
char * psz_msg; /* the message itself */
#ifdef DEBUG
/* Debugging informations - in DEBUG mode, all messages are dated and debug
* messages have calling location informations printed */
mtime_t date; /* date of the message (all messages) */
char * psz_file; /* file in which the function was called */
char * psz_function; /* function from which the function was called */
int i_line; /* line at which the function was called */
#endif
} interface_msg_message_t;
/* Message types */
#define INTF_MSG_STD 0 /* standard message */
#define INTF_MSG_ERR 1 /* error message */
#define INTF_MSG_INTF 2 /* interface message */
#define INTF_MSG_DBG 3 /* debug message */
/*******************************************************************************
* interface_msg_t
*******************************************************************************
* Store all data requiered by messages interfaces. It has a singe instance in
* program_data.
* interface, such as message output. See config.h for output configuration.
*******************************************************************************/
typedef struct
{
#ifdef INTF_MSG_QUEUE
/* Message queue */
vlc_mutex_t lock; /* message queue lock */
int i_count; /* number of messages stored */
interface_msg_message_t msg[INTF_MSG_QSIZE]; /* message queue */
#endif
#ifdef DEBUG_LOG
/* Log file */
FILE * p_log_file; /* log file */
#endif
#ifndef INTF_MSG_QUEUE
#ifndef DEBUG_LOG
/* If neither messages queue, neither log file is used, then the structure
* is empty. However, empty structures are not allowed in C. Therefore, a
* dummy integer is used to fill it. */
int i_dummy; /* unused filler */
#endif
#endif
} interface_msg_t;
/*******************************************************************************
* intf_DbgMsg macros and functions
......@@ -125,8 +58,8 @@ void intf_FlushMsg ( void );
/*******************************************************************************
* Prototypes
*******************************************************************************/
int intf_InitMsg ( interface_msg_t *p_intf_msg );
void intf_TerminateMsg ( interface_msg_t *p_intf_msg );
p_intf_msg_t intf_MsgCreate ( void );
void intf_MsgDestroy ( void );
void intf_Msg ( char *psz_format, ... );
void intf_ErrMsg ( char *psz_format, ... );
......@@ -134,5 +67,3 @@ void intf_IntfMsg ( char *psz_format, ... );
void intf_MsgImm ( char *psz_format, ... );
void intf_ErrMsgImm ( char *psz_format, ... );
/*******************************************************************************
* intf_sys.h: system dependant interface API
* (c)1999 VideoLAN
*******************************************************************************/
/*******************************************************************************
* Prototypes
*******************************************************************************/
int intf_SysCreate ( p_intf_thread_t p_intf );
void intf_SysDestroy( p_intf_thread_t p_intf );
void intf_SysManage ( p_intf_thread_t p_intf );
/*******************************************************************************
* pgm_data.h: access to all program variables
* main.h: access to all program variables
* (c)1999 VideoLAN
*******************************************************************************
* This header provides structures to access to all program variables. It should
* only be used by interface.
*******************************************************************************
* Required headers:
* <netinet/in.h>
* <sys/soundcard.h>
* <sys/uio.h>
* <X11/Xlib.h>
* <X11/extensions/XShm.h>
* "config.h"
* "common.h"
* "mtime.h"
* "vlc_thread.h"
* "input.h"
* "input_vlan.h"
* "audio_output.h"
* "video.h"
* "video_output.h"
* "xconsole.h"
* "interface.h"
* "intf_msg.h"
* Declaration and extern access to global program object.
*******************************************************************************/
/*******************************************************************************
* main_config_t
*******************************************************************************
* Store the main configuration (non thread-dependant configuration), such as
* parameters read from command line and name of configuration file
*******************************************************************************/
typedef struct
{
boolean_t b_audio; /* is audio output allowed ? */
boolean_t b_video; /* is video output allowed ? */
boolean_t b_vlans; /* are vlans supported ? */
/* Vlan input method configuration */
char * psz_input_vlan_server; /* vlan server */
int i_input_vlan_server_port; /* vlan server port */
} main_config_t;
/*******************************************************************************
* program_data_t, p_program_data (global variable)
* main_t, p_main (global variable)
*******************************************************************************
* This structure has an unique instance, declared in main and pointed by the
* only global variable of the program. It should allow access to any variable
......@@ -59,19 +22,27 @@ typedef struct
char ** ppsz_argv; /* command line arguments */
char ** ppsz_env; /* environment variables */
/* Configurations */
main_config_t cfg; /* general configuration */
video_cfg_t vout_cfg; /* video output configuration */
/* Generic settings */
boolean_t b_audio; /* is audio output allowed ? */
boolean_t b_video; /* is video output allowed ? */
boolean_t b_vlans; /* are vlans supported ? */
/* Unique threads */
p_aout_thread_t p_aout; /* audio output thread */
p_intf_thread_t p_intf; /* main interface thread */
/* Threads */
aout_thread_t aout_thread; /* audio output thread */
intf_thread_t intf_thread; /* interface thread */
/* Shared data - these structures are accessed directly from p_main by
* several modules */
p_intf_msg_t p_msg; /* messages interface data */
p_input_vlan_method_t p_input_vlan; /* vlan input method */
} main_t;
/* Shared data - these structures are accessed directly from p_program_data
* by several libraries */
interface_msg_t intf_msg; /* messages interface data */
input_vlan_method_t input_vlan_method; /* vlan input method */
} program_data_t;
extern main_t *p_main;
extern program_data_t *p_program_data;
/*******************************************************************************
* Prototypes - these methods are used to get default values for some threads
* and modules.
*******************************************************************************/
int main_GetIntVariable( char *psz_name, int i_default );
char * main_GetPszVariable( char *psz_name, char *psz_default );
/*******************************************************************************
* thread.h: threads status constants
* (c)1999 VideoLAN
*******************************************************************************
* These constants are used by all threads in *_CreateThread() and
* *_DestroyThreads() functions. Since those calls are non-blocking, an integer
* value is used as a shared flag to represent the status of the thread.
*******************************************************************************
* Requires:
* none
*******************************************************************************/
/* Void status - this value can be used to be sure, in an array of recorded
* threads, that no operation is currently in progress on the concerned thread */
#define THREAD_NOP 0 /* nothing happened */
/* Creation status */
#define THREAD_CREATE 10 /* thread is initializing */
#define THREAD_START 11 /* thread has forked */
#define THREAD_READY 19 /* thread is ready */
/* Destructions status */
#define THREAD_DESTROY 20 /* destruction order has been sent */
#define THREAD_END 21 /* destruction order has been received */
#define THREAD_OVER 29 /* thread does not exist any more */
/* Error status */
#define THREAD_ERROR 30 /* an error occured */
#define THREAD_FATAL 31 /* an fatal error occured - program must end */
......@@ -11,57 +11,28 @@
* "mtime.h"
*******************************************************************************/
/*******************************************************************************
* pixel_t: universal pixel value descriptor
*******************************************************************************
* This type and associated macros and functions are provided as an universal
* way of storing colors/pixels parameters. For pixels, it represents the
* actual value of the pixel. For RGB values, it is a 24 bits RGB encoded
* value. For masks, it is 0 or 1...
*******************************************************************************/
typedef u32 pixel_t;
#define RGBVALUE2RED( value ) ( (value) & 0x0000ff )
#define RGBVALUE2GREEN( value ) ( ((value) >> 8) & 0x0000ff )
#define RGBVALUE2BLUE( value ) ( ((value) >> 16) & 0x0000ff )
/*******************************************************************************
* picture_t: video picture
*******************************************************************************
* Any picture destined to be displayed by a video output thread should be
* stored in this structure from it's creation to it's effective display.
* Two forms of pictures exists: independant pictures, which can be manipulated
* freely, although usage of graphic library is recommanded, and heap pictures.
* Extreme care should be taken when manipulating heap pictures, since any error
* could cause a segmentation fault in the video output thread. The rule is:
* once a picture is in the video heap, only it's data can be written. All other
* fields should only be read or modified using interface functions.
* Note that for all pictures, some properties should never be modified, except
* by the video output thread itself, once the picture has been created !
* Picture type and flags should only be modified by the output thread. Note
* that an empty picture MUST have its flags set to 0.
*******************************************************************************/
typedef struct
{
/* Type and flags - should NOT be modified except by the vout thread */
int i_type; /* picture type */
int i_flags; /* picture flags */
int i_status; /* picture flags */
/* Picture properties - those properties are fixed at initialization and
* should NOT be modified */
* should NOT be modified. Note that for YUV pictures, i_bytes_per_line is
* the number of bytes for ONE of the Y, U or V pictures, and therefore the
* number of bytes in the picture is 3 * i_height * i_bytes_per_line */
int i_width; /* picture width */
int i_height; /* picture height */
int i_bpp; /* padded bits per pixel */
int i_bytes_per_line; /* total number of bytes per line */
/* Picture properties - those properties can be modified is the picture is
* independant, or in a heap but permanent or reserved */
int i_x; /* x position offset in output window */
int i_y; /* y position offset in output window */
int i_h_align; /* horizontal alignment */
int i_v_align; /* vertical alignment */
int i_h_ratio; /* horizontal display ratio */
int i_v_ratio; /* vertical display ratio */
int i_level; /* overlay hierarchical level */
/* Link reference counter - it can be modified using vout_Link and
* vout_Unlink functions, or directly if the picture is independant */
int i_refcount; /* link reference counter */
......@@ -69,120 +40,36 @@ typedef struct
/* Video properties - those properties should not be modified once
* the picture is in a heap, but can be freely modified if it is
* independant */
int i_stream; /* video stream id */
mtime_t date; /* display date */
mtime_t duration; /* duration for overlay pictures */
/* Picture data - data can always be freely modified, although special care
* should be taken for permanent pictures to avoid flickering - p_data
* itself (the pointer) should NEVER be modified */
pixel_t pixel; /* pixel value, for mask pictures */
/* Picture data - data can always be freely modified. p_data itself
* (the pointer) should NEVER be modified. In YUV format, the p_y, p_u and
* p_v data pointers refers to different areas of p_data, and should not
* be freed */
byte_t * p_data; /* picture data */
byte_t * p_y; /* pointer to beginning of Y image in p_data */
byte_t * p_u; /* pointer to beginning of U image in p_data */
byte_t * p_v; /* pointer to beginning of V image in p_data */
} picture_t;
/* Pictures types */
#define EMPTY_PICTURE 0 /* picture is waiting to be used */
#define RGB_BLANK_PICTURE 10 /* blank picture (rgb color, no data) */
#define PIXEL_BLANK_PICTURE 11 /* blank picture (pixel color, no data) */
#define RGB_PICTURE 20 /* picture is 24 bits rgb encoded */
#define PIXEL_PICTURE 30 /* picture is pixel encoded */
#define RGB_MASK_PICTURE 40 /* picture is a 1 bpp rgb mask */
#define PIXEL_MASK_PICTURE 41 /* picture is a 1 bpp pixel mask */
/* ?? */
#define YUV_444_PICTURE 100 /* chroma 444 YUV picture */
#define YUV_422_PICTURE 101 /* chroma 422 YUV picture */
#define YUV_420_PICTURE 102 /* chroma 420 YUV picture */
/* Pictures properties (flags) */
#define RESERVED_PICTURE (1 << 0) /* picture is not ready but reserved */
#define PERMANENT_PICTURE (1 << 1) /* picture is permanent */
#define DISPLAYED_PICTURE (1 << 2) /* picture has been displayed */
#define OWNER_PICTURE (1 << 3) /* picture owns its data */
#define DISPLAY_PICTURE (1 << 4) /* picture will be displayed */
#define DESTROY_PICTURE (1 << 5) /* picture will be destroyed */
#define TRANSPARENT_PICTURE (1 << 8) /* picture is transparent */
#define OVERLAY_PICTURE (1 << 9) /* picture overlays another one */
/* Alignments - this field describe how the position of the picture will
* be calculated */
#define ALIGN_LEFT -1 /* left-aligned */
#define ALIGN_TOP -1 /* up-aligned */
#define ALIGN_ENTER 0 /* centered */
#define ALIGN_RIGHT 1 /* right-aligned */
#define ALIGN_BOTTOM 1 /* bottom-aligned */
#define ALIGN_H_DEFAULT ALIGN_LEFT /* default horizontal alignment */
#define ALIGN_V_DEFAULT ALIGN_TOP /* default vertical alignment */
/* Display ratios - this field describe how the image will be resized before
* being displayed */
#define DISPLAY_RATIO_HALF -1 /* 1:2 half size */
#define DISPLAY_RATIO_NORMAL 0 /* 1:1 normal size */
#define DISPLAY_RATIO_DOUBLE 1 /* 2:1 double size */
/* ?? add other ratios (TRIPLE, THIRD), TV, automatic, ... */
#define EMPTY_PICTURE 0 /* picture slot is empty and available */
#define YUV_422_PICTURE 100 /* 4:2:2 YUV picture */
#define YUV_442_PICTURE 101 /* 4:4:2 YUV picture */
#define YUV_444_PICTURE 102 /* 4:4:4 YUV picture */
/* Pictures status */
#define FREE_PICTURE 0 /* picture is free and not allocated */
#define RESERVED_PICTURE 1 /* picture is allocated and reserved */
#define READY_PICTURE 2 /* picture is ready for display */
#define DISPLAYED_PICTURE 3 /* picture has been displayed but is linked */
#define DESTROYED_PICTURE 4 /* picture is allocated but no more used */
/*******************************************************************************
* video_cfg_t: video object configuration structure
*******************************************************************************
* This structure is passed as a parameter to many initialization function of
* the vout and vdec modules. It includes many fields describing potential
* properties of a new object. The 'i_properties' field allow to set only a
* subset of the required properties, asking the called function to use default
* settings for the other ones.
*******************************************************************************/
typedef struct video_cfg_s
{
u64 i_properties; /* used properties */
/* Size properties */
int i_width; /* image or window width */
int i_height; /* image or window height */
int i_size; /* heap size */
/* X11 properties */
char * psz_display; /* display name */
char * psz_title; /* window title */
boolean_t b_shm_ext; /* try to use XShm extension */
/* Pictures properties */
int i_type; /* picture type */
int i_flags; /* picture flags */
int i_bpp; /* padded bits per pixel */
int i_x; /* x position offset in output window */
int i_y; /* y position offset in output window */
int i_h_align; /* horizontal alignment */
int i_v_align; /* vertical alignment */
int i_h_ratio; /* horizontal display ratio */
int i_v_ratio; /* vertical display ratio */
int i_level; /* overlay hierarchical level */
int i_refcount; /* link reference counter */
int i_stream; /* video stream id */
mtime_t date; /* picture display date */
mtime_t duration; /* duration for overlay pictures */
pixel_t pixel; /* pixel value, for mask pictures */
byte_t * p_data; /* picture data */
} video_cfg_t;
/* Properties flags (see picture_t and other video structures for
* explanations) */
#define VIDEO_CFG_WIDTH (1 << 0)
#define VIDEO_CFG_HEIGHT (1 << 1)
#define VIDEO_CFG_SIZE (1 << 2)
#define VIDEO_CFG_DISPLAY (1 << 4)
#define VIDEO_CFG_TITLE (1 << 5)
#define VIDEO_CFG_SHM_EXT (1 << 6)
#define VIDEO_CFG_TYPE (1 << 8)
#define VIDEO_CFG_FLAGS (1 << 9)
#define VIDEO_CFG_BPP (1 << 10)
#define VIDEO_CFG_POSITION (1 << 11) /* both i_x and i_y */
#define VIDEO_CFG_ALIGN (1 << 12) /* both i_h_align and i_v_align */
#define VIDEO_CFG_RATIO (1 << 13) /* both i_h_ratio and i_y_ratio */
#define VIDEO_CFG_LEVEL (1 << 14)
#define VIDEO_CFG_REFCOUNT (1 << 15)
#define VIDEO_CFG_STREAM (1 << 16)
#define VIDEO_CFG_DATE (1 << 17)
#define VIDEO_CFG_DURATION (1 << 18)
#define VIDEO_CFG_PIXEL (1 << 19)
#define VIDEO_CFG_DATA (1 << 20)
......@@ -65,7 +65,7 @@ typedef struct vdec_thread_s
*******************************************************************************/
/* Thread management functions */
vdec_thread_t * vdec_CreateThread ( /* video_cfg_t *p_cfg, */ input_thread_t *p_input /*,
p_vdec_thread_t vdec_CreateThread ( /* video_cfg_t *p_cfg, */ input_thread_t *p_input /*,
vout_thread_t *p_vout, int *pi_status */ );
void vdec_DestroyThread ( vdec_thread_t *p_vdec /*, int *pi_status */ );
......
......@@ -16,38 +16,4 @@
* Prototypes
*******************************************************************************/
/* Pictures management functions */
picture_t * video_CreatePicture ( video_cfg_t *p_cfg );
picture_t * video_CopyPicture ( picture_t *p_pic );
picture_t * video_ReplicatePicture ( picture_t *p_pic );
void video_DestroyPicture ( picture_t *p_pic );
/* Files functions */
picture_t * video_ReadPicture ( int i_file );
/* Drawing functions */
void video_ClearPicture ( picture_t *p_pic );
void video_DrawPixel ( picture_t *p_pic, int i_x, int i_y, pixel_t value );
void video_DrawHLine ( picture_t *p_pic, int i_x, int i_y, int i_width, pixel_t value );
void video_DrawVLine ( picture_t *p_pic, int i_x, int i_y, int i_height, pixel_t value );
void video_DrawLine ( picture_t *p_pic, int i_x1, int i_y1,
int i_x2, int i_y2, pixel_t value );
void video_DrawBar ( picture_t *p_pic, int i_x, int i_y, int i_width,
int i_height, pixel_t value );
void video_DrawRectangle ( picture_t *p_pic, int i_x, int i_y,
int i_width, int i_height, pixel_t color );
void video_DrawPicture ( picture_t *p_pic, picture_t *p_insert, int i_x, int i_y );
void video_DrawText ( picture_t *p_pic, int i_x, int i_y, char *psz_text,
int i_size, pixel_t color );
/* Convertion functions */
/* ?? rgb->pixel, pixel->rgb */
/* Low-level shared functions */
void video_CopyPictureDescriptor ( picture_t *p_dest, picture_t *p_src );
int video_CreatePictureBody ( picture_t *p_pic, video_cfg_t *p_cfg );
#ifdef DEBUG
/* Debugging functions */
void video_PrintPicture ( picture_t *p_pic, char *psz_str );
#endif
......@@ -14,45 +14,6 @@
* "video.h"
*******************************************************************************/
/* ?? this over-complicated API and code should be re-designed, with a simple
* video-stream associated to a window (each window designed to be openned in
* a parent one and probably without border), and have an api looking like
* vout_CreateWindow
* vout_DestroyWindow
* vout_AddPicture
* vout_RemovePicture
* vout_ReservePicture
* vout_AddReservedPicture
* vout_Clear
* vout_Refresh
*
* the overlay/transparent, permanent and such stuff should disapear.
*/
/*******************************************************************************
* vout_stream_t: video stream descriptor
*******************************************************************************
* Each video stream has a set of properties, stored in this structure. It is
* part of vout_thread_t and is not supposed to be used anywhere else.
*******************************************************************************/
typedef struct
{
int i_status; /* is stream active ? */
picture_t * p_next_picture; /* next picture to be displayed */
#ifdef STATS
/* Statistics */
count_t c_pictures; /* total number of pictures added */
count_t c_rendered_pictures; /* number of rendered pictures */
#endif
} vout_stream_t;
/* Video stream status */
#define VOUT_INACTIVE_STREAM 0 /* stream is inactive (empty) */
#define VOUT_ACTIVE_STREAM 1 /* stream is active */
#define VOUT_ENDING_STREAM 2 /* stream will be destroyed when empty */
#define VOUT_DESTROYED_STREAM 3 /* stream must be destroyed */
/*******************************************************************************
* vout_thread_t: video output thread descriptor
*******************************************************************************
......@@ -65,9 +26,8 @@ typedef struct vout_thread_s
boolean_t b_die; /* `die' flag */
boolean_t b_error; /* `error' flag */
boolean_t b_active; /* `active' flag */
vlc_thread_t thread_id; /* id for thread functions */
vlc_mutex_t streams_lock; /* streams modification lock */
vlc_mutex_t pictures_lock; /* pictures modification lock */
pthread_t thread_id; /* id for pthread functions */
pthread_mutex_t lock; /* thread lock */
int * pi_status; /* temporary status flag */
/* Common display properties */
......@@ -75,30 +35,27 @@ typedef struct vout_thread_s
int i_height; /* current output method height */
int i_screen_depth; /* bits per pixel */
int i_bytes_per_pixel; /* real screen depth */
float f_x_ratio; /* horizontal display ratio */
float f_y_ratio; /* vertical display ratio */
/* Output method */
struct vout_x11_s * p_x11; /* X11 output method */
p_vout_sys_t p_sys; /* system output method */
/* Video heap */
int i_max_pictures; /* heap maximal size */
int i_pictures; /* current heap size */
picture_t * p_picture; /* pictures */
/* Streams data */
vout_stream_t p_stream[VOUT_MAX_STREAMS]; /* streams data */
picture_t p_picture[VOUT_MAX_PICTURES]; /* pictures */
#ifdef STATS
/* Statistics */
count_t c_loops; /* number of loops */
count_t c_idle_loops; /* number of idle loops */
count_t c_pictures; /* number of pictures added to heap */
count_t c_rendered_pictures; /* number of pictures rendered */
#endif
/* Rendering functions - these functions are of vout_render_blank_t and
* vout_render_line_t, but are not declared here using these types since
* they require vout_thread_t to be defined */
void (* RenderRGBBlank) ( struct vout_thread_s *p_vout, pixel_t pixel,
/* void (* RenderRGBBlank) ( struct vout_thread_s *p_vout, pixel_t pixel,
int i_x, int i_y, int i_width, int i_height );
void (* RenderPixelBlank) ( struct vout_thread_s *p_vout, pixel_t pixel,
int i_x, int i_y, int i_width, int i_height );
......@@ -114,64 +71,30 @@ typedef struct vout_thread_s
void (* RenderPixelMaskLine) ( struct vout_thread_s *p_vout, picture_t *p_pic,
int i_x, int i_y, int i_pic_x, int i_pic_y,
int i_width, int i_line_width, int i_ratio );
/* ?? add YUV types */
*/ /* ?? add YUV types */
} vout_thread_t;
/*******************************************************************************
* vout_render_blank_t: blank rendering function
* vout_render_line_t: rectangle rendering functions
*******************************************************************************
* All rendering functions should be of these types - for blank pictures
* (pictures with uniform color), blank rendering functions are called once. For
* other pictures, each function is called once for each picture line. Note that
* the part of the picture sent to the rendering functions is in the output
* window, since the clipping is done before.
* p_vout is the calling thread
* pixel is the color or pixel value of the rectange to be drawn
* p_pic is the picture to be rendered
* i_x, i_y is the absolute position in output window
* i_pic_x is the first pixel to be drawn in the picture
* i_pic_y is the line of the picture to be drawn
* i_width is the width of the area to be rendered in the picture (not in the
* output window), except for blank pictures, where it is the absolute size
* of the area to be rendered
* i_height is the height og the area to be rendered
* i_line_width is the number of time the line must be copied
* i_ratio is the horizontal display ratio
*******************************************************************************/
typedef void (vout_render_blank_t)( vout_thread_t *p_vout, pixel_t pixel,
int i_x, int i_y, int i_width, int i_height );
typedef void (vout_render_line_t) ( vout_thread_t *p_vout, picture_t *p_pic,
int i_x, int i_y, int i_pic_x, int i_pic_y,
int i_width, int i_line_width, int i_ratio );
/*******************************************************************************
* Prototypes
*******************************************************************************/
vout_thread_t * vout_CreateThread ( video_cfg_t *p_cfg, int *pi_status );
void vout_DestroyThread ( vout_thread_t *p_vout, int *pi_status );
picture_t * vout_DisplayPicture ( vout_thread_t *p_vout, picture_t *p_pic );
picture_t * vout_DisplayPictureCopy ( vout_thread_t *p_vout, picture_t *p_pic );
picture_t * vout_DisplayPictureReplicate ( vout_thread_t *p_vout, picture_t *p_pic );
picture_t * vout_DisplayReservedPicture ( vout_thread_t *p_vout, picture_t *p_pic );
picture_t * vout_CreateReservedPicture ( vout_thread_t *p_vout, video_cfg_t *p_cfg );
picture_t * vout_ReservePicture ( vout_thread_t *p_vout, picture_t *p_pic );
picture_t * vout_ReservePictureCopy ( vout_thread_t *p_vout, picture_t *p_pic );
picture_t * vout_ReservePictureReplicate ( vout_thread_t *p_vout, picture_t *p_pic );
void vout_RemovePicture ( vout_thread_t *p_vout, picture_t *p_pic );
vout_thread_t * vout_CreateThread (
#if defined(VIDEO_X11)
Display *p_display, Window root_window,
#elif defined(VIDEO_FB)
//??void
#endif
int i_width, int i_height, int *pi_status
);
void vout_RefreshPermanentPicture ( vout_thread_t *p_vout, picture_t *p_pic,
mtime_t displa_date );
void vout_DestroyThread ( vout_thread_t *p_vout, int *pi_status );
picture_t * vout_CreatePicture ( vout_thread_t *p_vout, int i_type,
int i_width, int i_height, int i_bytes_per_line );
void vout_DestroyPicture ( vout_thread_t *p_vout, picture_t *p_pic );
void vout_DisplayPicture ( vout_thread_t *p_vout, picture_t *p_pic );
void vout_LinkPicture ( vout_thread_t *p_vout, picture_t *p_pic );
void vout_UnlinkPicture ( vout_thread_t *p_vout, picture_t *p_pic );
int vout_CreateStream ( vout_thread_t *p_vout );
void vout_EndStream ( vout_thread_t *p_vout, int i_stream );
void vout_DestroyStream ( vout_thread_t *p_vout, int i_stream );
#ifdef DEBUG
void vout_PrintHeap ( vout_thread_t *p_vout, char *psz_str );
#endif
......@@ -182,3 +105,12 @@ void vout_PrintHeap ( vout_thread_t *p_vout, char *p
/*******************************************************************************
* video_sys.h: system dependant video output display method API
* (c)1999 VideoLAN
*******************************************************************************/
/*******************************************************************************
* Prototypes
*******************************************************************************/
#if defined(VIDEO_X11)
int vout_SysCreate ( p_vout_thread_t p_vout, Display *p_display, Window root_window );
#elif defined(VIDEO_FB)
int vout_SysCreate ( p_vout_thread_t p_vout );
#endif
int vout_SysInit ( p_vout_thread_t p_vout );
void vout_SysEnd ( p_vout_thread_t p_vout );
void vout_SysDestroy ( p_vout_thread_t p_vout );
int vout_SysManage ( p_vout_thread_t p_vout );
void vout_SysDisplay ( p_vout_thread_t p_vout );
/*******************************************************************************
* all.h: all headers
* vlc.h: all headers
* (c)1998 VideoLAN
*******************************************************************************
* This header includes all vlc .h headers and depending headers. A source file
......@@ -12,22 +12,54 @@
*******************************************************************************/
/* System headers */
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/shm.h>
#include <sys/soundcard.h>
#include <sys/uio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/XShm.h>
#include <X11/extensions/xf86dga.h>
/* Common headers */
#include "config.h"
#include "common.h"
#include "mtime.h"
#include "vlc_thread.h"
#include "netutils.h"
#include "debug.h"
#include "xutils.h"
#include "intf_msg.h"
/* Input */
#include "input.h"
#include "input_psi.h"
#include "input_pcr.h"
#include "input_netlist.h"
#include "input_vlan.h"
#include "decoder_fifo.h"
#include "input_file.h"
#include "input_network.h"
/* Audio */
#include "audio_output.h"
......@@ -35,16 +67,17 @@
/* Video */
#include "video.h"
#include "video_sys.h"
#include "video_output.h"
#include "video_decoder.h"
/* Interface */
#include "xconsole.h"
#include "intf_cmd.h"
#include "intf_ctrl.h"
#include "intf_sys.h"
#include "intf_console.h"
#include "interface.h"
#include "intf_msg.h"
/* Shared resources */
#include "pgm_data.h"
#include "main.h"
/*******************************************************************************
* vlc_thread.h : thread implementation for vieolan client
* (c)1999 VideoLAN
******************************************************************************/
*******************************************************************************
* This header is supposed to provide a portable threads implementation.
* Currently, it is a wrapper to the POSIX pthreads library.
*******************************************************************************/
#include <pthread.h>
/*******************************************************************************
* types definition
******************************************************************************/
/******************************************************************************
* Constants
******************************************************************************
* These constants are used by all threads in *_CreateThread() and
* *_DestroyThreads() functions. Since those calls are non-blocking, an integer
* value is used as a shared flag to represent the status of the thread.
*******************************************************************************/
/* Void status - this value can be used to be sure, in an array of recorded
* threads, that no operation is currently in progress on the concerned thread */
#define THREAD_NOP 0 /* nothing happened */
/* Creation status */
#define THREAD_CREATE 10 /* thread is initializing */
#define THREAD_START 11 /* thread has forked */
#define THREAD_READY 19 /* thread is ready */
/* Destructions status */
#define THREAD_DESTROY 20 /* destruction order has been sent */
#define THREAD_END 21 /* destruction order has been received */
#define THREAD_OVER 29 /* thread does not exist any more */
/* Error status */
#define THREAD_ERROR 30 /* an error occured */
#define THREAD_FATAL 31 /* an fatal error occured - program must end */
/******************************************************************************
* Types definition
******************************************************************************/
typedef pthread_t vlc_thread_t;
typedef pthread_mutex_t vlc_mutex_t;
typedef pthread_cond_t vlc_cond_t;
typedef void *(*vlc_thread_func)(void *data);
typedef void *(*vlc_thread_func_t)(void *p_data);
/******************************************************************************
* Prototypes
******************************************************************************/
static __inline__ int vlc_thread_create ( vlc_thread_t * thread, char * name,
vlc_thread_func func, void * data );
static __inline__ void vlc_thread_exit ( );
static __inline__ int vlc_thread_create( vlc_thread_t *p_thread, char *psz_name,
vlc_thread_func_t func, void *p_data );
static __inline__ void vlc_thread_exit ( void );
static __inline__ void vlc_thread_join ( vlc_thread_t thread );
static __inline__ int vlc_mutex_init ( vlc_mutex_t * mutex );
static __inline__ int vlc_mutex_lock ( vlc_mutex_t * mutex );
static __inline__ int vlc_mutex_unlock ( vlc_mutex_t * mtex );
static __inline__ int vlc_mutex_init ( vlc_mutex_t *p_mutex );
static __inline__ int vlc_mutex_lock ( vlc_mutex_t *p_mutex );
static __inline__ int vlc_mutex_unlock ( vlc_mutex_t *p_mutex );
static __inline__ int vlc_cond_init ( vlc_cond_t * condvar );
static __inline__ int vlc_cond_signal ( vlc_cond_t * condvar );
static __inline__ int vlc_cond_wait ( vlc_cond_t * condvar, vlc_mutex_t * mutex );
static __inline__ int vlc_cond_init ( vlc_cond_t *p_condvar );
static __inline__ int vlc_cond_signal ( vlc_cond_t *p_condvar );
static __inline__ int vlc_cond_wait ( vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex );
//static _inline__ int vlc_cond_timedwait ( vlc_cond_t * condvar, vlc_mutex_t * mutex,
// mtime_t absoute_timeout_time );
/*******************************************************************************
* vlc_thread_create
* vlc_thread_create: create a thread
******************************************************************************/
static __inline__ int vlc_thread_create(
vlc_thread_t * thread,
char * name,
vlc_thread_func func,
void * data)
static __inline__ int vlc_thread_create( vlc_thread_t *p_thread,
char *psz_name, vlc_thread_func_t func,
void *p_data)
{
return pthread_create( thread, NULL, func, data );
return pthread_create( p_thread, NULL, func, p_data );
}
/******************************************************************************
* vlc_thread_exit
* vlc_thread_exit: terminate a thread
*******************************************************************************/
static __inline__ void vlc_thread_exit()
static __inline__ void vlc_thread_exit( void )
{
pthread_exit( 0 );
}
/*******************************************************************************
* vlc_thread_exit
* vlc_thread_join: wait until a thread exits
******************************************************************************/
static __inline__ void vlc_thread_join( vlc_thread_t thread )
{
pthread_join( thread, NULL );
}
/*******************************************************************************
* vlc_mutex_init
* vlc_mutex_init: initialize a mutex
*******************************************************************************/
static __inline__ int vlc_mutex_init( vlc_mutex_t * mutex )
static __inline__ int vlc_mutex_init( vlc_mutex_t *p_mutex )
{
return pthread_mutex_init( mutex, NULL );
return pthread_mutex_init( p_mutex, NULL );
}
/*******************************************************************************
* vlc_mutex_lock
* vlc_mutex_lock: lock a mutex
*******************************************************************************/
static __inline__ int vlc_mutex_lock( vlc_mutex_t * mutex )
static __inline__ int vlc_mutex_lock( vlc_mutex_t *p_mutex )
{
return pthread_mutex_lock( mutex );
return pthread_mutex_lock( p_mutex );
}
/*******************************************************************************
* vlc_mutex_unlock
* vlc_mutex_unlock: unlock a mutex
*******************************************************************************/
static __inline__ int vlc_mutex_unlock( vlc_mutex_t * mutex )
static __inline__ int vlc_mutex_unlock( vlc_mutex_t *p_mutex )
{
return pthread_mutex_unlock( mutex );
return pthread_mutex_unlock( p_mutex );
}
/*******************************************************************************
* vlc_cond_init
* vlc_cond_init: initialize a condition
*******************************************************************************/
static __inline__ int vlc_cond_init( vlc_cond_t * condvar )
static __inline__ int vlc_cond_init( vlc_cond_t *p_condvar )
{
return pthread_cond_init( condvar, NULL );
return pthread_cond_init( p_condvar, NULL );
}
/*******************************************************************************
* vlc_cond_signal
* vlc_cond_signal: start a thread on condition completion
*******************************************************************************/
static __inline__ int vlc_cond_signal( vlc_cond_t * condvar )
static __inline__ int vlc_cond_signal( vlc_cond_t *p_condvar )
{
return pthread_cond_signal( condvar );
return pthread_cond_signal( p_condvar );
}
/*******************************************************************************
* vlc_cond_wait
* vlc_cond_wait: wait until condition completion
*******************************************************************************/
static __inline__ int vlc_cond_wait( vlc_cond_t * condvar, vlc_mutex_t * mutex )
static __inline__ int vlc_cond_wait( vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex )
{
return pthread_cond_wait( condvar, mutex );
return pthread_cond_wait( p_condvar, p_mutex );
}
/*******************************************************************************
* xconsole.h: X11 console for interface
* (c)1998 VideoLAN
*******************************************************************************
* The X11 console is a simple way to get interactive input from the user. It
* does not disturbs the standard terminal output. In theory, multiple consoles
* could be openned on different displays.
*?? will probably evolve
*******************************************************************************/
/*******************************************************************************
* xconsole_t: X11 console descriptor
*******************************************************************************
* The display pointer is specific to this structure since in theory, multiple
* console could be openned on different displays. A console is divided in two
* sections. The lower one is a single line edit control. Above, a multi-line
* output zone allow to send messages.
*******************************************************************************/
typedef struct
{
/* Initialization fields - those fields should be initialized before
* calling intf_OpenX11Console(). */
char * psz_display; /* display name */
char * psz_geometry; /* window geometry */
/* following fields are internal */
/* Settings and display properties */
Display * p_display; /* display pointer */
int i_screen; /* screen number */
XFontStruct * p_font; /* used font */
Window window; /* window instance handler */
/* Graphic contexts */
GC default_gc; /* graphic context for default text */
/* Pixmaps */
Pixmap background_pixmap; /* window background */
/* Window properties */
int i_width, i_height; /* window dimensions */
int i_text_offset; /* text zone placement from bottom */
int i_text_line_height;/* height of a single text line */
int i_edit_height; /* total edit zone height */
int i_edit_offset; /* edit zone placement from bottom */
/* Text array */
char * psz_text[INTF_XCONSOLE_MAX_LINES]; /* text */
int i_text_index; /* last line index */
/* Edit lines properties. The line has one more character than
* maximum width to allow adding a terminal '\0' when it is sent to
* execution or text zone. The size must stay between 0 (included) and
* INTF_X11_CONSOLE_MAX_LINE_WIDTH (included). The cursor position (index)
* can be between 0 (included) and size (included). */
char sz_edit[INTF_XCONSOLE_MAX_LINE_WIDTH + 1];
int i_edit_index; /* cursor position */
int i_edit_size; /* total size of edit text */
/* History. The history array (composed of asciiz strings) has a base,
* marking the *next* registered line, and an index, marking the actual
* line browsed. When an history browse is started, the current line is
* stored at base (but base isn't increased), and index is modified.
* When a command is executed, it is registered at base and base is
* increased. */
char * psz_history[INTF_XCONSOLE_HISTORY_SIZE + 1];
int i_history_index; /* index in history */
int i_history_base; /* history base */
} xconsole_t;
/*******************************************************************************
* Prototypes
*******************************************************************************/
int intf_OpenXConsole ( xconsole_t *p_console );
void intf_CloseXConsole ( xconsole_t *p_console );
void intf_ManageXConsole ( xconsole_t *p_console );
void intf_ClearXConsole ( xconsole_t *p_console );
void intf_PrintXConsole ( xconsole_t *p_console, char *psz_str );
......@@ -110,7 +110,7 @@ adec_thread_t * adec_CreateThread( input_thread_t * p_input )
p_adec->p_aout_fifo = NULL;
/* Spawn the audio decoder thread */
if ( vlc_thread_create(&p_adec->thread_id, "audio decoder", (vlc_thread_func)RunThread, (void *)p_adec) )
if ( vlc_thread_create(&p_adec->thread_id, "audio decoder", (vlc_thread_func_t)RunThread, (void *)p_adec) )
{
intf_ErrMsg("adec error: can't spawn audio decoder thread\n");
free( p_adec );
......
......@@ -34,11 +34,15 @@
#include "audio_output.h"
#include "audio_dsp.h"
#include "main.h"
/******************************************************************************
* Local prototypes
******************************************************************************/
static int aout_SpawnThread( aout_thread_t * p_aout );
/* Creating as much aout_Thread functions as configurations is one solution,
* examining the different cases in the Thread loop of an unique function is
* another. I chose the first solution. */
......@@ -55,51 +59,82 @@ static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long
static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo/*, mtime_t aout_date*/ );
/******************************************************************************
* aout_Open
* aout_CreateThread: initialize audio thread
******************************************************************************/
int aout_Open( aout_thread_t * p_aout )
aout_thread_t *aout_CreateThread( int *pi_status )
{
if ( aout_dspOpen( &p_aout->dsp ) )
aout_thread_t * p_aout; /* thread descriptor */
int i_status; /* thread status */
/* Allocate descriptor */
p_aout = (aout_thread_t *) malloc( sizeof(aout_thread_t) );
if( p_aout == NULL )
{
return( -1 );
return( NULL );
}
//???? kludge to initialize some audio parameters - place this section somewhere
//???? else
p_aout->dsp.i_format = AOUT_DEFAULT_FORMAT;
p_aout->dsp.psz_device = main_GetPszVariable( AOUT_DSP_VAR, AOUT_DSP_DEFAULT );
p_aout->dsp.b_stereo = main_GetIntVariable( AOUT_STEREO_VAR, AOUT_STEREO_DEFAULT );
p_aout->dsp.l_rate = main_GetIntVariable( AOUT_RATE_VAR, AOUT_RATE_DEFAULT );
// ???? end of kludge
/*
* Initialize DSP
*/
if ( aout_dspOpen( &p_aout->dsp ) )
{
free( p_aout );
return( NULL );
}
if ( aout_dspReset( &p_aout->dsp ) )
{
aout_dspClose( &p_aout->dsp );
return( -1 );
free( p_aout );
return( NULL );
}
if ( aout_dspSetFormat( &p_aout->dsp ) )
{
aout_dspClose( &p_aout->dsp );
return( -1 );
free( p_aout );
return( NULL );
}
if ( aout_dspSetChannels( &p_aout->dsp ) )
{
aout_dspClose( &p_aout->dsp );
return( -1 );
free( p_aout );
return( NULL );
}
if ( aout_dspSetRate( &p_aout->dsp ) )
{
aout_dspClose( &p_aout->dsp );
return( -1 );
free( p_aout );
return( NULL );
}
intf_DbgMsg("aout debug: audio device (%s) opened (format=%i, stereo=%i, rate=%li)\n",
p_aout->dsp.psz_device,
p_aout->dsp.i_format,
p_aout->dsp.b_stereo, p_aout->dsp.l_rate);
return( 0 );
//?? maybe it would be cleaner to change SpawnThread prototype
//?? see vout to handle status correctly - however, it is not critical since
//?? this thread is only called in main is all calls are blocking
if( aout_SpawnThread( p_aout ) )
{
aout_dspClose( &p_aout->dsp );
free( p_aout );
return( NULL );
}
return( p_aout );
}
/******************************************************************************
* aout_SpawnThread
******************************************************************************/
int aout_SpawnThread( aout_thread_t * p_aout )
static int aout_SpawnThread( aout_thread_t * p_aout )
{
int i_fifo;
long l_bytes;
......@@ -239,7 +274,7 @@ int aout_SpawnThread( aout_thread_t * p_aout )
p_aout->date = mdate();
/* Launch the thread */
if ( vlc_thread_create( &p_aout->thread_id, "audio output", (vlc_thread_func)aout_thread, p_aout ) )
if ( vlc_thread_create( &p_aout->thread_id, "audio output", (vlc_thread_func_t)aout_thread, p_aout ) )
{
intf_ErrMsg("aout error: can't spawn audio output thread (%p)\n", p_aout);
free( p_aout->buffer );
......@@ -252,28 +287,26 @@ int aout_SpawnThread( aout_thread_t * p_aout )
}
/******************************************************************************
* aout_CancelThread
* aout_DestroyThread
******************************************************************************/
void aout_CancelThread( aout_thread_t * p_aout )
void aout_DestroyThread( aout_thread_t * p_aout, int *pi_status )
{
//???? pi_status is not handled correctly: check vout how to do!
intf_DbgMsg("aout debug: requesting termination of audio output thread (%p)\n", p_aout);
/* Ask thread to kill itself and wait until it's done */
p_aout->b_die = 1;
vlc_thread_join( p_aout->thread_id );
vlc_thread_join( p_aout->thread_id ); // only if pi_status is NULL
/* Free the allocated memory */
free( p_aout->buffer );
free( p_aout->s32_buffer );
}
/******************************************************************************
* aout_Close
******************************************************************************/
void aout_Close( aout_thread_t * p_aout )
{
/* Free the structure */
aout_dspClose( &p_aout->dsp );
intf_DbgMsg("aout debug: audio device (%s) closed\n", p_aout->dsp.psz_device);
free( p_aout );
}
/******************************************************************************
......
......@@ -14,8 +14,10 @@
/******************************************************************************
* Preamble
******************************************************************************/
#include <errno.h>
*******************************************************************************/
#include "vlc.h"
/*#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
......@@ -31,8 +33,8 @@
#include "thread.h"
#include "intf_msg.h"
#include "debug.h" /* ?? temporaire, requis par netlist.h */
#include "debug.h" */
/*
#include "input.h"
#include "input_netlist.h"
#include "decoder_fifo.h"
......@@ -41,7 +43,7 @@
#include "video.h"
#include "video_output.h"
#include "video_decoder.h"
#include "video_decoder.h"*/
/*
* Local prototypes
......
......@@ -8,19 +8,22 @@
/*******************************************************************************
* Preamble
******************************************************************************/
*******************************************************************************/
#include "vlc.h"
/*
#include <errno.h>
#include <sys/uio.h> /* iovec */
#include <sys/uio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>
#include <sys/soundcard.h>
#include <stdlib.h> /* atoi(), malloc(), free() */
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h> /* ioctl() */
#include <net/if.h> /* ifreq */
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include "common.h"
......@@ -44,6 +47,7 @@
#include "video.h"
#include "video_output.h"
#include "video_decoder.h"
*/
/******************************************************************************
* Local prototypes
......@@ -192,7 +196,7 @@ input_thread_t *input_CreateThread( input_cfg_t *p_cfg )
#ifdef NO_THREAD
input_Thread( p_input );
#else
if( vlc_thread_create(&p_input->thread_id, "input", (vlc_thread_func)input_Thread,
if( vlc_thread_create(&p_input->thread_id, "input", (vlc_thread_func_t)input_Thread,
(void *) p_input) )
{
intf_ErrMsg("input error: can't spawn input thread (%s)\n",
......@@ -304,7 +308,7 @@ static void input_Thread( input_thread_t *p_input )
EndThread( p_input );
intf_DbgMsg("input debug: thread %p destroyed\n", p_input);
vlc_thread_exit( 0 );
vlc_thread_exit();
}
......
......@@ -9,9 +9,12 @@
/*******************************************************************************
* Preamble
*******************************************************************************/
#include "vlc.h"
/*
#include <errno.h>
#include <sys/uio.h> /* iovec */
#include <stdlib.h> /* atoi(), malloc(), free() */
#include <sys/uio.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
......@@ -19,7 +22,7 @@
#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>
#include <sys/soundcard.h>
#include <netinet/in.h> /* ntohs */
#include <netinet/in.h>
#include "common.h"
#include "config.h"
......@@ -39,8 +42,7 @@
#include "video.h"
#include "video_output.h"
#include "video_decoder.h"
#include "video_decoder.h" */
/******************************************************************************
* input_AddPgrmElem: Start the extraction and the decoding of a program element
......
......@@ -8,13 +8,18 @@
/*******************************************************************************
* Preamble
******************************************************************************/
*******************************************************************************/
#include "vlc.h"
/*
#include <errno.h>
#include <pthread.h>
#include <errno.h>
#include <stdio.h>
#include <sys/uio.h> /* iovec */
#include <stdlib.h> /* atoi(), malloc(), free() */
#include <sys/uio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h> /* ntohs */
#include <netinet/in.h>
#include <sys/soundcard.h>
#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>
......@@ -37,7 +42,7 @@
#include "xconsole.h"
#include "interface.h"
#include "pgm_data.h"
#include "pgm_data.h"*/
/*
* Precalculated 32-bits CRC table, shared by all instances of the PSI decoder
......@@ -50,7 +55,7 @@ u32 i_crc_32_table[256];
* the option (audio and video) passed to the VideoLAN client.
*/
#ifdef AUTO_SPAWN
extern program_data_t *p_program_data;
//??extern program_data_t *p_main;
#endif
/*
......@@ -627,7 +632,7 @@ static void DecodePgrmMapSection( u8* p_pms, input_thread_t* p_input )
{
case MPEG1_VIDEO_ES:
case MPEG2_VIDEO_ES:
if( p_program_data->cfg.b_video )
if( p_main->b_video )
{
/* Spawn a video thread */
input_AddPgrmElem( p_input,
......@@ -636,7 +641,7 @@ static void DecodePgrmMapSection( u8* p_pms, input_thread_t* p_input )
break;
case MPEG1_AUDIO_ES:
case MPEG2_AUDIO_ES:
if( p_program_data->cfg.b_audio )
if( p_main->b_audio )
{
/* Spawn an audio thread */
input_AddPgrmElem( p_input,
......
......@@ -28,6 +28,10 @@
/*******************************************************************************
* Preamble
*******************************************************************************/
#include "vlc.h"
/*#include <errno.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
......@@ -60,7 +64,67 @@
#include "interface.h"
#include "intf_msg.h"
#include "pgm_data.h"
#include "pgm_data.h"*/
/*******************************************************************************
* input_vlan_iface_t: vlan-capable network interface
*******************************************************************************
* This structure describes the abilities of a network interface capable of
* vlan management. Note that an interface could have several IP adresses, but
* since only the MAC address is used to change vlan, only one needs to be
* retrieved.
* ?? it could be interesting to send a port id on vlan request, to know if two
* interfaces are dependant regarding vlan changes.
*******************************************************************************/
typedef struct
{
char * psz_name; /* interface name */
struct sockaddr_in sa_in; /* interface IP */
char psz_mac[20]; /* interface MAC */
/* Hardware properties */
int i_master; /* master interface index */
int i_switch; /* switch number */
int i_port; /* port number */
int i_sharers; /* number of MACs on this port */
/* Vlan properties - these are only used if i_master is negative */
int i_refcount; /* locks counter */
int i_vlan; /* current vlan */
int i_default_vlan; /* default vlan */
} input_vlan_iface_t;
/*******************************************************************************
* input_vlan_server_t: vlan server
*******************************************************************************
* This structure describes a vlan server.
*******************************************************************************/
typedef struct
{
struct sockaddr_in sa_in; /* server address */
int i_socket; /* socket descriptor */
/* Login informations */
char * psz_login; /* server login */
char * psz_passwd; /* server password */
} input_vlan_server_t;
/*******************************************************************************
* vlan_method_data_t
*******************************************************************************
* Store global vlan library data.
*******************************************************************************/
typedef struct input_vlan_method_s
{
vlc_mutex_t lock; /* library lock */
/* Server */
input_vlan_server_t server; /* vlan server */
/* Network interfaces */
int i_ifaces; /* number of vlan-compliant interfaces */
input_vlan_iface_t * p_iface; /* interfaces */
} input_vlan_method_t;
/*
* Constants
......@@ -82,16 +146,19 @@ static int ServerRequestInfo ( input_vlan_server_t *p_server,
input_vlan_iface_t *p_iface );
/*******************************************************************************
* input_VlanMethodInit: initialize global vlan method data
* input_VlanCreate: initialize global vlan method data
*******************************************************************************
* Initialize vlan input method global data. This function should be called
* once before any input thread is created or any call to other input_Vlan*()
* function is attempted.
*******************************************************************************/
int input_VlanMethodInit( input_vlan_method_t *p_method, char *psz_server, int i_port )
int input_VlanCreate( void )
{
char * psz_server; // ??? get from environment
int i_port; // ??? get from environment
int i_index; /* interface/servers index */
input_vlan_iface_t * p_iface; /* interfaces */
input_vlan_method_t *p_method = p_main->p_input_vlan; //??
/* Build vlan server descriptor */
if( BuildInetAddr( &p_method->server.sa_in, psz_server, i_port ) )
......@@ -179,14 +246,15 @@ int input_VlanMethodInit( input_vlan_method_t *p_method, char *psz_server, int i
}
/*******************************************************************************
* input_VlanMethodFree: free global vlan method data
* input_VlanDestroy: free global vlan method data
*******************************************************************************
* Free resources allocated by input_VlanMethodInit. This function should be
* called at the end of the program.
*******************************************************************************/
void input_VlanMethodFree( input_vlan_method_t *p_method )
void input_VlanDestroy( void )
{
int i_index; /* server/interface index */
input_vlan_method_t *p_method = p_main->p_input_vlan; // ??
/* Leave all remaining vlans */
for( i_index = 0; i_index < p_method->i_ifaces; i_index++ )
......@@ -222,7 +290,7 @@ int input_VlanId( char *psz_iface, int i_vlan )
input_vlan_method_t * p_method; /* method global data */
int i_index; /* interface index */
p_method = &p_program_data->input_vlan_method;
p_method = p_main->p_input_vlan;
/* If psz_iface is NULL, use first (default) interface (if there is one) */
if( psz_iface == NULL )
......@@ -231,10 +299,10 @@ int input_VlanId( char *psz_iface, int i_vlan )
}
/* Browse all interfaces */
for( i_index = 0; i_index < p_program_data->input_vlan_method.i_ifaces ; i_index++ )
for( i_index = 0; i_index < p_main->p_input_vlan->i_ifaces ; i_index++ )
{
/* If interface has been found, return */
if( !strcmp( p_program_data->input_vlan_method.p_iface[i_index].psz_name, psz_iface ) )
if( !strcmp( p_main->p_input_vlan->p_iface[i_index].psz_name, psz_iface ) )
{
return( VLAN_ID( i_index, i_vlan ) );
}
......@@ -262,7 +330,7 @@ int input_VlanJoin( int i_vlan_id )
/* Initialize shortcuts, and use master if interface is dependant */
i_err = 0;
p_method = &p_program_data->input_vlan_method;
p_method = p_main->p_input_vlan;
p_iface = &p_method->p_iface[ VLAN_ID_IFACE( i_vlan_id ) ];
if( p_iface->i_master >= 0 )
{
......@@ -319,7 +387,7 @@ void input_VlanLeave( int i_vlan_id )
/* Initialize shortcuts, and use master if interface is dependant */
i_err = 0;
p_method = &p_program_data->input_vlan_method;
p_method = p_main->p_input_vlan;
p_iface = &p_method->p_iface[ VLAN_ID_IFACE( i_vlan_id ) ];
if( p_iface->i_master >= 0 )
{
......@@ -348,7 +416,7 @@ int input_VlanRequest( char *psz_iface )
input_vlan_method_t * p_method; /* method global data */
int i_index; /* interface index */
p_method = &p_program_data->input_vlan_method;
p_method = p_main->p_input_vlan;
/* If psz_iface is NULL, use first (default) interface (if there is one) -
* note that interface 0 can't be dependant, so dependance does not need
......@@ -390,8 +458,12 @@ int input_VlanSynchronize( void )
int i_vlan; /* vlan for current interface */
/* Get lock */
p_method = p_main->p_input_vlan;
pthread_mutex_lock( &p_method->lock );
/* ??
p_method = &p_program_data->input_vlan_method;
vlc_mutex_lock( &p_method->lock );
*/
for( i_index = 0; i_index < p_method->i_ifaces; i_index++ )
{
......
......@@ -10,6 +10,9 @@
/*******************************************************************************
* Preamble
*******************************************************************************/
#include "vlc.h"
/*??
#include <pthread.h>
#include <stdio.h>
#include <netinet/in.h>
#include <sys/soundcard.h>
......@@ -35,137 +38,6 @@
#include "intf_msg.h"
#include "control.h"
#include "pgm_data.h"
#include "pgm_data.h"*/
/*******************************************************************************
* intf_CreateVoutThread: create video output thread in interface
*******************************************************************************
* This function creates - if possible - a new video output thread in the
* interface registery, using interface default settings. It returns the
* thread number for the interface, or a negative number.
* If video is desactivated, nothing will be done. If psz_title is not NULL, it
* will be used as window's title, and width and height will also be used if
* they are positive.
*******************************************************************************/
int intf_CreateVoutThread( intf_thread_t *p_intf, char *psz_title, int i_width, int i_height )
{
#if 0
int i_thread; /* thread index */
video_cfg_t cfg; /* thread configuration */
/* Verify that video is enabled */
if( !p_program_data->cfg.b_video )
{
return( -1 );
}
/* Set configuration */
memcpy( &cfg, &p_program_data->vout_cfg, sizeof( cfg ) );
if( psz_title != NULL )
{
cfg.i_properties |= VIDEO_CFG_TITLE;
cfg.psz_title = psz_title;
}
if( i_width > 0 )
{
cfg.i_properties |= VIDEO_CFG_WIDTH;
cfg.i_width = i_width;
}
if( i_height > 0 )
{
cfg.i_properties |= VIDEO_CFG_HEIGHT;
cfg.i_height = i_height;
}
/* Find an empty place */
for( i_thread = 0; i_thread < VOUT_MAX_THREADS; i_thread++ )
{
if( p_intf->pp_vout[i_thread] == NULL )
{
/* The current place is empty: create a thread */
p_intf->pp_vout[i_thread] = vout_CreateThread( &cfg, NULL );
if( p_intf->pp_vout[i_thread] == NULL ) /* error */
{
return( -1 );
}
}
}
/* No empty place has been found */
return( -1 );
#endif
}
/*******************************************************************************
* intf_DestroyVoutThread: destroy video output thread in interface
*******************************************************************************
* This function destroy a video output thread created with
* intf_CreateVoutThread().
*******************************************************************************/
void intf_DestroyVoutThread( intf_thread_t *p_intf, int i_thread )
{
#if 0
#ifdef DEBUG
/* Check if thread still exists */
if( p_intf->pp_vout[i_thread] == NULL )
{
intf_DbgMsg("intf error: destruction of an inexistant vout thread\n");
return;
}
#endif
/* Destroy thread and marks its place as empty */
vout_DestroyThread( p_intf->pp_vout[i_thread], NULL );
p_intf->pp_vout[i_thread] = NULL;
#endif
}
/*******************************************************************************
* intf_CreateInputThread: create input thread in interface
*******************************************************************************
* This function creates - if possible - a new input thread in the
* interface registery, using interface default settings. It returns the
* thread number for the interface, or a negative number.
*******************************************************************************/
int intf_CreateInputThread( intf_thread_t *p_intf, input_cfg_t* p_cfg )
{
int i_thread; /* thread index */
/* Find an empty place */
for( i_thread = 0; i_thread < INPUT_MAX_THREADS; i_thread++ )
{
if( p_intf->pp_input[i_thread] == NULL )
{
/* The current place is empty: create a thread and return */
p_intf->pp_input[i_thread] = input_CreateThread( p_cfg );
return( (p_intf->pp_input[i_thread] != NULL) ? i_thread : -1 );
}
}
/* No empty place has been found */
return( -1 );
}
/*******************************************************************************
* intf_DestroyInputThread: destroy input thread in interface
*******************************************************************************
* This function destroy aa input thread created with
* intf_CreateInputThread().
*******************************************************************************/
void intf_DestroyInputThread( intf_thread_t *p_intf, int i_thread )
{
#ifdef DEBUG
/* Check if thread still exists */
if( p_intf->pp_input[i_thread] == NULL )
{
intf_DbgMsg("intf error: destruction of an inexistant input thread\n");
return;
}
#endif
/* Destroy thread and marks its place as empty */
input_DestroyThread( p_intf->pp_input[i_thread] );
p_intf->pp_input[i_thread] = NULL;
}
......@@ -9,69 +9,82 @@
/*******************************************************************************
* Preamble
*******************************************************************************/
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/soundcard.h>
#include <sys/uio.h>
#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/uio.h> /* for input.h */
#include "config.h"
#include "common.h"
#include "mtime.h"
#include "vlc_thread.h"
#include "thread.h"
#include "debug.h"
#include "input.h"
#include "intf_msg.h"
#include "interface.h"
#include "intf_cmd.h"
#include "intf_console.h"
#include "main.h"
#include "input.h"
#include "input_netlist.h"
#include "input_vlan.h"
#include "decoder_fifo.h"
#include "intf_sys.h"
#include "audio_output.h"
#include "audio_decoder.h"
#include "video.h"
#include "video_output.h"
#include "video_decoder.h"
/*******************************************************************************
* intf_Create: prepare interface before main loop
*******************************************************************************
* This function opens output devices and create specific interfaces. It send
* it's own error messages.
*******************************************************************************/
intf_thread_t* intf_Create( void )
{
intf_thread_t *p_intf;
#include "xconsole.h"
#include "interface.h"
#include "intf_cmd.h"
/* Allocate structure */
p_intf = malloc( sizeof( intf_thread_t ) );
if( !p_intf )
{
errno = ENOMEM;
return( NULL );
}
p_intf->b_die = 0;
intf_DbgMsg( "0x%x\n", p_intf );
#include "pgm_data.h"
/* ?? remove useless headers */
/* Initialize structure */
p_intf->p_vout = NULL;
p_intf->p_input = NULL;
/*
* Local prototypes
*/
static int StartInterface ( intf_thread_t *p_intf );
static void EndInterface ( intf_thread_t *p_intf );
/* Start interfaces */
p_intf->p_console = intf_ConsoleCreate();
if( p_intf->p_console == NULL )
{
intf_ErrMsg("intf error: can't create control console\n");
free( p_intf );
return( NULL );
}
if( intf_SysCreate( p_intf ) )
{
intf_ErrMsg("intf error: can't create interface\n");
intf_ConsoleDestroy( p_intf->p_console );
free( p_intf );
return( NULL );
}
return( p_intf );
}
/*******************************************************************************
* intf_Run
*******************************************************************************
* what it does:
* - Create an X11 console
* - wait for a command and try to execute it
* - interpret the order returned after the command execution
* - print the messages of the message queue (intf_FlushMsg)
* return value: 0 if successful, < 0 otherwise
* Initialization script and main interface loop.
*******************************************************************************/
int intf_Run( intf_thread_t *p_intf )
void intf_Run( intf_thread_t *p_intf )
{
/* When it is started, interface won't die immediatly */
p_intf->b_die = 0;
if( StartInterface( p_intf ) ) /* error */
intf_DbgMsg("0x%x begin\n", p_intf );
/* Execute the initialization script - if a positive number is returned,
* the script could be executed but failed */
if( intf_ExecScript( main_GetPszVariable( INTF_INIT_SCRIPT_VAR, INTF_INIT_SCRIPT_DEFAULT ) ) > 0 )
{
return( 1 );
intf_ErrMsg("intf error: error during initialization script\n");
}
/* Main loop */
......@@ -80,123 +93,58 @@ int intf_Run( intf_thread_t *p_intf )
/* Flush waiting messages */
intf_FlushMsg();
#ifndef FRAMEBUFFER
/* Manage specific interfaces */
intf_ManageXConsole( &p_intf->xconsole ); /* X11 console */
#endif
/* Manage specific interface */
intf_SysManage( p_intf );
/* Sleep to avoid using all CPU - since some interfaces needs to access
* keyboard events, a 100ms delay is a good compromise */
msleep( INTF_IDLE_SLEEP );
}
/* End of interface thread - the main() function will close all remaining
* output threads */
EndInterface( p_intf );
return ( 0 );
intf_DbgMsg("0x%x end\n", p_intf );
}
/* following functions are local */
/*******************************************************************************
* StartInterface: prepare interface before main loop
* intf_Destroy: clean interface after main loop
*******************************************************************************
* This function opens output devices and create specific interfaces. It send
* it's own error messages.
* This function destroys specific interfaces and close output devices.
*******************************************************************************/
static int StartInterface( intf_thread_t *p_intf )
void intf_Destroy( intf_thread_t *p_intf )
{
int i_thread; /* thread index */
#ifdef INIT_SCRIPT
int fd;
#endif
#if 0
/* Empty all threads array */
for( i_thread = 0; i_thread < VOUT_MAX_THREADS; i_thread++ )
{
p_intf->pp_vout[i_thread] = NULL;
}
#endif
for( i_thread = 0; i_thread < INPUT_MAX_THREADS; i_thread++ )
{
p_intf->pp_input[i_thread] = NULL;
}
#ifdef FRAMEBUFFER
intf_DbgMsg("intf debug: not opening X11 console\n");
#else
/* Start X11 Console*/
if( intf_OpenXConsole( &p_intf->xconsole ) )
{
intf_ErrMsg("intf error: can't open X11 console\n");
return( 1 );
}
#endif
intf_DbgMsg("0x%x\n", p_intf );
#ifdef INIT_SCRIPT
/* Execute the initialization script (typically spawn an input thread) */
if ( (fd = open( INIT_SCRIPT, O_RDONLY )) != -1 )
{
/* Startup script does exist */
close( fd );
intf_ExecScript( INIT_SCRIPT );
}
#endif
/* Destroy interfaces */
intf_SysDestroy( p_intf );
intf_ConsoleDestroy( p_intf->p_console );
return( 0 );
/* Free structure */
free( p_intf );
}
/*******************************************************************************
* EndInterface: clean interface after main loop
* intf_SelectInput: change input stream
*******************************************************************************
* This function destroys specific interfaces and close output devices.
* Kill existing input, if any, and try to open a new one. If p_cfg is NULL,
* no new input will be openned.
*******************************************************************************/
static void EndInterface( intf_thread_t *p_intf )
int intf_SelectInput( intf_thread_t * p_intf, input_cfg_t *p_cfg )
{
int i_thread; /* thread index */
boolean_t b_thread; /* flag for remaing threads */
int pi_vout_status[VOUT_MAX_THREADS]; /* vout threads status */
#ifndef FRAMEBUFFER
/* Close X11 console */
intf_CloseXConsole( &p_intf->xconsole );
#endif
intf_DbgMsg("0x%x\n", p_intf );
/* Destroy all remaining input threads */
for( i_thread = 0; i_thread < INPUT_MAX_THREADS; i_thread++ )
/* Kill existing input, if any */
if( p_intf->p_input != NULL )
{
if( p_intf->pp_input[i_thread] != NULL )
{
input_DestroyThread( p_intf->pp_input[i_thread] );
}
input_DestroyThread( p_intf->p_input /*??, NULL*/ );
p_intf->p_input = NULL;
}
#if 0
/* Destroy all remaining video output threads - all destruction orders are send,
* then all THREAD_OVER status are received */
for( i_thread = 0, b_thread = 0; i_thread < VOUT_MAX_THREADS; i_thread++ )
/* Open new one */
if( p_cfg != NULL )
{
if( p_intf->pp_vout[i_thread] != NULL )
{
vout_DestroyThread( p_intf->pp_vout[i_thread], &pi_vout_status[i_thread] );
b_thread = 1;
}
p_intf->p_input = input_CreateThread( p_cfg /*??, NULL*/ );
}
while( b_thread )
{
msleep( INTF_IDLE_SLEEP );
b_thread = 0;
for( i_thread = 0; i_thread < VOUT_MAX_THREADS; i_thread++ )
{
if( (p_intf->pp_vout[i_thread] != NULL)
&& (pi_vout_status[i_thread] != THREAD_OVER) )
{
b_thread = 1;
}
}
}
#endif
return( (p_cfg != NULL) && (p_intf->p_input == NULL) );
}
......@@ -10,6 +10,9 @@
/*******************************************************************************
* Preamble
*******************************************************************************/
#include "vlc.h"
/*
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
......@@ -38,8 +41,7 @@
#include "intf_msg.h"
#include "intf_cmd.h"
#include "intf_ctrl.h"
#include "pgm_data.h"
*/
/*
* Local prototypes
......@@ -111,7 +113,7 @@ int intf_ExecCommand( char *psz_cmd )
case INTF_FATAL_ERROR: /* fatal error */
/* Print message and terminates the interface thread */
intf_ErrMsg( "intf fatal: in command `%s'\n", psz_argv[0] );
p_program_data->intf_thread.b_die = 1;
p_main->p_intf->b_die = 1;
break;
case INTF_CRITICAL_ERROR: /* critical error */
......
/*******************************************************************************
* intf_console.c: generic console for interface
* (c)1998 VideoLAN
*******************************************************************************/
/*******************************************************************************
* Preamble
*******************************************************************************/
#include <stdlib.h>
#include "config.h"
/*******************************************************************************
* intf_console_t: console descriptor
*******************************************************************************
* Generic console object. This object will have a representation depending of
* the interface.
*******************************************************************************/
typedef struct intf_console_s
{
/* Text and history arrays - last line/command has indice 0 */
char * psz_text[INTF_CONSOLE_MAX_TEXT];
char * psz_history[INTF_CONSOLE_MAX_HISTORY];
} intf_console_t;
/*******************************************************************************
* Local prototypes
*******************************************************************************/
/*******************************************************************************
* intf_ConsoleCreate: create console
*******************************************************************************
* This function will initialize the console object.
* It returns NULL on error.
*******************************************************************************/
intf_console_t *intf_ConsoleCreate( void )
{
intf_console_t *p_console;
p_console = malloc( sizeof( intf_console_t ) );
return( p_console );
}
/*******************************************************************************
* intf_ConsoleDestroy
*******************************************************************************
* Destroy the console instance initialized by intf_ConsoleCreate.
*******************************************************************************/
void intf_ConsoleDestroy( intf_console_t *p_console )
{
free( p_console );
}
/*******************************************************************************
* intf_ConsoleClear: clear console
*******************************************************************************
* Empty all text.
*******************************************************************************/
void intf_ConsoleClear( intf_console_t *p_console )
{
//??
}
/*******************************************************************************
* intf_ConsolePrint: print a message to console
*******************************************************************************
* Print a message to the console.
*******************************************************************************/
void intf_ConsolePrint( intf_console_t *p_console, char *psz_str )
{
//??
}
/*******************************************************************************
* intf_ConsoleExec: execute a command in console
*******************************************************************************
* This function will run a command and print its result in console.
*******************************************************************************/
void intf_ConsoleExec( intf_console_t *p_console, char *psz_str )
{
//??
}
/* following functions are local */
......@@ -24,7 +24,8 @@
/*******************************************************************************
* Preamble
*******************************************************************************/
#include <errno.h>
#include "vlc.h"
/*??#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <stdio.h>
......@@ -67,6 +68,7 @@
#include "intf_ctrl.h"
#include "pgm_data.h"
*/
/*
* Local prototypes
......@@ -309,7 +311,7 @@ static int PlayAudio( int i_argc, intf_arg_t *p_argv )
struct stat stat_buffer; /* needed to find out the size of psz_file */
int i_arg; /* argument index */
if ( !p_program_data->cfg.b_audio ) /* audio is disabled */
if ( !p_main->b_audio ) /* audio is disabled */
{
intf_IntfMsg("play-audio error: audio is disabled");
return( INTF_NO_ERROR );
......@@ -383,10 +385,10 @@ static int PlayAudio( int i_argc, intf_arg_t *p_argv )
close( i_fd );
/* Now we can work out how many output units we can compute with the fifo */
fifo.l_units = (long)(((s64)fifo.l_units*(s64)p_program_data->aout_thread.dsp.l_rate)/(s64)fifo.l_rate);
fifo.l_units = (long)(((s64)fifo.l_units*(s64)p_main->p_aout->dsp.l_rate)/(s64)fifo.l_rate);
/* Create the fifo */
if ( aout_CreateFifo(&p_program_data->aout_thread, &fifo) == NULL )
if ( aout_CreateFifo(p_main->p_aout, &fifo) == NULL )
{
intf_IntfMsg("play-audio error: can't create audio fifo");
free( fifo.buffer );
......@@ -414,7 +416,7 @@ static int PlayVideo( int i_argc, intf_arg_t *p_argv )
*******************************************************************************/
static int Quit( int i_argc, intf_arg_t *p_argv )
{
p_program_data->intf_thread.b_die = 1;
p_main->p_intf->b_die = 1;
return( INTF_NO_ERROR );
}
......@@ -435,6 +437,7 @@ static int SelectPID( int i_argc, intf_arg_t *p_argv )
switch( p_argv[i_arg].i_index )
{
case 0:
// ?? useless
i_input = p_argv[i_arg].i_num;
break;
case 1:
......@@ -445,20 +448,10 @@ static int SelectPID( int i_argc, intf_arg_t *p_argv )
/* Find to which input this command is destinated */
if(i_input < INPUT_MAX_THREADS )
{
if( p_program_data->intf_thread.pp_input[i_input] )
{
intf_IntfMsg( "Adding PID %d to input %d\n", i_pid, i_input );
input_AddPgrmElem( p_program_data->intf_thread.pp_input[i_input],
i_pid );
//???? input_AddPgrmElem( p_main->p_intf->p_x11->p_input,
//???? i_pid );
return( INTF_NO_ERROR );
}
}
/* No such input was created */
intf_IntfMsg("No such input thread is currently running: %d\n", i_input);
return( INTF_OTHER_ERROR );
}
......@@ -528,10 +521,10 @@ static int SpawnInput( int i_argc, intf_arg_t *p_argv )
}
/* Default settings for the decoder threads */
cfg.p_aout = p_program_data->intf_thread.p_aout;
cfg.p_aout = p_main->p_aout;
/* Create the input thread */
if( intf_CreateInputThread( &p_program_data->intf_thread, &cfg ) == -1)
if( intf_SelectInput( p_main->p_intf, &cfg ) == -1)
{
return( INTF_OTHER_ERROR );
}
......@@ -551,15 +544,15 @@ static int Test( int i_argc, intf_arg_t *p_argv )
{
int i_thread;
if( i_argc == 1 )
/*?? if( i_argc == 1 )
{
i_thread = intf_CreateVoutThread( &p_program_data->intf_thread, NULL, -1, -1);
i_thread = intf_CreateVoutThread( &p_main->intf_thread, NULL, -1, -1);
intf_IntfMsg("return value: %d", i_thread );
}
else
else*/
{
i_thread = p_argv[1].i_num;
intf_DestroyVoutThread( &p_program_data->intf_thread, i_thread );
//?? intf_DestroyVoutThread( &p_main->intf_thread, i_thread );
}
return( INTF_NO_ERROR );
......@@ -576,7 +569,7 @@ static int Vlan( int i_argc, intf_arg_t *p_argv )
int i_command; /* command argument number */
/* Do not try anything if vlans are desactivated */
if( !p_program_data->cfg.b_vlans )
if( !p_main->b_vlans )
{
intf_IntfMsg("vlans are desactivated");
return( INTF_OTHER_ERROR );
......@@ -629,19 +622,7 @@ static int Psi( int i_argc, intf_arg_t *p_argv )
{
int i_index = p_argv[1].i_num;
if(i_index < INPUT_MAX_THREADS )
{
if(p_program_data->intf_thread.pp_input[i_index])
{
/* Read the Psi table for that thread */
intf_IntfMsg("Reading PSI table for input %d\n", i_index);
input_PsiRead(p_program_data->intf_thread.pp_input[i_index]);
//???? input_PsiRead(p_main->p_intf->p_x11->p_input );
return( INTF_NO_ERROR );
}
}
/* No such input was created */
intf_IntfMsg("No such input thread is currently running: %d\n", i_index);
return( INTF_OTHER_ERROR );
}
......@@ -3,74 +3,120 @@
* (c)1998 VideoLAN
*******************************************************************************
* This library provides basic functions for threads to interact with user
* interface, such as message output. If INTF_MSG_QUEUE is defined (which is the
* defaul), messages are not printed directly by threads, to bypass console
* limitations and slow printf() calls, but sent to a queue and printed later by
* interface thread.
* If INTF_MSG_QUEUE is not defined, output is directly performed on stderr.
* Exported symbols are declared in intf_msg.h.
* interface, such as message output. See config.h for output configuration.
*******************************************************************************/
/*******************************************************************************
* Preamble
*******************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/soundcard.h>
#include <sys/uio.h>
#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>
#include <unistd.h>
#include "config.h"
#include "common.h"
#include "mtime.h"
#include "vlc_thread.h"
#include "debug.h"
#include "intf_msg.h"
#include "interface.h"
#include "intf_console.h"
#include "main.h"
#include "input.h"
#include "input_vlan.h"
/*******************************************************************************
* intf_msg_item_t
*******************************************************************************
* Store a single message. Messages have a maximal size of INTF_MSG_MSGSIZE.
* If DEBUG is defined, messages have a date field and debug messages are
* printed with a date to allow more precise profiling.
*******************************************************************************/
typedef struct
{
int i_type; /* message type, see below */
char * psz_msg; /* the message itself */
#include "audio_output.h"
#ifdef DEBUG
/* Debugging informations - in DEBUG mode, debug messages have calling
* location informations printed */
mtime_t date; /* date of the message */
char * psz_file; /* file in which the function was called */
char * psz_function; /* function from which the function was called */
int i_line; /* line at which the function was called */
#endif
} intf_msg_item_t;
#include "video.h"
#include "video_output.h"
/* Message types */
#define INTF_MSG_STD 0 /* standard message */
#define INTF_MSG_ERR 1 /* error message */
#define INTF_MSG_INTF 2 /* interface message */
#define INTF_MSG_DBG 3 /* debug message */
#include "xconsole.h"
#include "interface.h"
#include "intf_msg.h"
/*******************************************************************************
* intf_msg_t
*******************************************************************************
* Store all data requiered by messages interfaces. It has a single reference
* int p_main.
*******************************************************************************/
typedef struct intf_msg_s
{
#ifdef INTF_MSG_QUEUE
/* Message queue */
vlc_mutex_t lock; /* message queue lock */
int i_count; /* number of messages stored */
intf_msg_item_t msg[INTF_MSG_QSIZE]; /* message queue */
#endif
#include "pgm_data.h"
#ifdef DEBUG_LOG
/* Log file */
int i_log_file; /* log file */
#endif
/*
#if !defined(INTF_MSG_QUEUE) && !defined(DEBUG_LOG)
/* If neither messages queue, neither log file is used, then the structure
* is empty. However, empty structures are not allowed in C. Therefore, a
* dummy integer is used to fill it. */
int i_dummy; /* unused filler */
#endif
} intf_msg_t;
/*****************************************************************************
* Local prototypes
*/
*****************************************************************************/
static void QueueMsg ( interface_msg_t *p_intf_msg, int i_type,
static void QueueMsg ( intf_msg_t *p_msg, int i_type,
char *psz_format, va_list ap );
static void PrintMsg ( interface_msg_message_t *p_msg );
static void PrintMsg ( intf_msg_item_t *p_msg );
#ifdef DEBUG
static void QueueDbgMsg ( interface_msg_t *p_intf_msg, char *psz_file,
static void QueueDbgMsg ( intf_msg_t *p_msg, char *psz_file,
char *psz_function, int i_line,
char *psz_format, va_list ap );
#endif
#ifdef INTF_MSG_QUEUE
static void FlushLockedMsg ( interface_msg_t *p_intf_msg );
static void FlushLockedMsg ( intf_msg_t *p_msg );
#endif
/*******************************************************************************
* intf_InitMsg: initialize messages interface (ok ?)
* intf_MsgCreate: initialize messages interface (ok ?)
*******************************************************************************
* This functions has to be called before any call to other intf_*Msg functions.
* It set up the locks and the message queue if it is used. On error,
* it returns errno (without printing its own error messages) and free all
* alocated resources.
* It set up the locks and the message queue if it is used.
*******************************************************************************/
int intf_InitMsg( interface_msg_t *p_intf_msg )
p_intf_msg_t intf_MsgCreate( void )
{
p_intf_msg_t p_msg;
/* Allocate structure */
p_msg = malloc( sizeof( intf_msg_t ) );
if( p_msg == NULL )
{
errno = ENOMEM;
}
else
{
#ifdef INTF_MSG_QUEUE
/* Message queue initialization */
vlc_mutex_init( &p_intf_msg->lock ); /* intialize lock */
......@@ -78,32 +124,36 @@ int intf_InitMsg( interface_msg_t *p_intf_msg )
#endif
#ifdef DEBUG_LOG
/* Log file initialization */
p_intf_msg->p_log_file = fopen( DEBUG_LOG, "w+" );
if ( !p_intf_msg->p_log_file )
{
return( errno );
}
/* Log file initialization - on failure, file pointer will be null,
* and no log will be issued, but this is not considered as an
* error */
p_msg->i_log_file = open( DEBUG_LOG, O_CREAT | O_APPEND | O_SYNC | O_WRONLY );
#endif
return( 0 );
}
return( p_msg );
}
/*******************************************************************************
* intf_TerminateMsg: free resources allocated by intf_InitMsg (ok ?)
* intf_MsgDestroy: free resources allocated by intf_InitMsg (ok ?)
*******************************************************************************
* This functions prints all messages remaining in queue, then free all the
* resources allocated by intf_InitMsg.
* No other messages interface functions should be called after this one.
*******************************************************************************/
void intf_TerminateMsg( interface_msg_t *p_intf_msg )
void intf_MsgDestroy( void )
{
intf_FlushMsg(); /* print all remaining messages */
#ifdef DEBUG_LOG
/* Close log file */
fclose( p_intf_msg->p_log_file );
/* Close log file if any */
if( p_main->p_msg->i_log_file >= 0 )
{
close( p_main->p_msg->i_log_file );
}
#endif
/* Free structure */
free( p_main->p_msg );
}
/*******************************************************************************
......@@ -117,7 +167,7 @@ void intf_Msg( char *psz_format, ... )
va_list ap;
va_start( ap, psz_format );
QueueMsg( &p_program_data->intf_msg, INTF_MSG_STD, psz_format, ap );
QueueMsg( p_main->p_msg, INTF_MSG_STD, psz_format, ap );
va_end( ap );
}
......@@ -127,12 +177,12 @@ void intf_Msg( char *psz_format, ... )
* This function is the same as intf_Msg, except that it prints its messages
* on stderr.
*******************************************************************************/
void intf_ErrMsg(char *psz_format, ...)
void intf_ErrMsg( char *psz_format, ...)
{
va_list ap;
va_start( ap, psz_format );
QueueMsg( &p_program_data->intf_msg, INTF_MSG_ERR, psz_format, ap );
QueueMsg( p_main->p_msg, INTF_MSG_ERR, psz_format, ap );
va_end( ap );
}
......@@ -152,7 +202,7 @@ void intf_IntfMsg(char *psz_format, ...)
va_list ap;
va_start( ap, psz_format );
QueueMsg( &p_program_data->intf_msg, INTF_MSG_INTF, psz_format, ap );
QueueMsg( p_main->p_msg, INTF_MSG_INTF, psz_format, ap );
va_end( ap );
}
......@@ -171,7 +221,7 @@ void _intf_DbgMsg( char *psz_file, char *psz_function, int i_line,
va_list ap;
va_start( ap, psz_format );
QueueDbgMsg( &p_program_data->intf_msg, psz_file, psz_function, i_line,
QueueDbgMsg( p_main->p_msg, psz_file, psz_function, i_line,
psz_format, ap );
va_end( ap );
}
......@@ -188,7 +238,7 @@ void intf_MsgImm( char *psz_format, ... )
va_list ap;
va_start( ap, psz_format );
QueueMsg( &p_program_data->intf_msg, INTF_MSG_STD, psz_format, ap );
QueueMsg( p_main->p_msg, INTF_MSG_STD, psz_format, ap );
va_end( ap );
intf_FlushMsg();
}
......@@ -204,7 +254,7 @@ void intf_ErrMsgImm(char *psz_format, ...)
va_list ap;
va_start( ap, psz_format );
QueueMsg( &p_program_data->intf_msg, INTF_MSG_ERR, psz_format, ap );
QueueMsg( p_main->p_msg, INTF_MSG_ERR, psz_format, ap );
va_end( ap );
intf_FlushMsg();
}
......@@ -223,7 +273,7 @@ void _intf_DbgMsgImm( char *psz_file, char *psz_function, int i_line,
va_list ap;
va_start( ap, psz_format );
QueueDbgMsg( &p_program_data->intf_msg, psz_file, psz_function, i_line,
QueueDbgMsg( p_main->p_msg, psz_file, psz_function, i_line,
psz_format, ap );
va_end( ap );
intf_FlushMsg();
......@@ -250,69 +300,59 @@ void intf_FlushMsg( void )
/* following functions are local */
/*******************************************************************************
* QueueMsg: add a message to a queue (ok ?)
* QueueMsg: add a message to a queue
*******************************************************************************
* This function provide basic functionnalities to other intf_*Msg functions.
* It add a message to a queue (after having printed all stored messages if it
* is full. If the message can't be converted to string in memory, it exit the
* program. If the queue is not used, it prints the message immediately.
*******************************************************************************/
static void QueueMsg(interface_msg_t *p_intf_msg, int i_type, char *psz_format, va_list ap)
static void QueueMsg( intf_msg_t *p_msg, int i_type, char *psz_format, va_list ap )
{
char * psz_str; /* formatted message string */
#ifndef INTF_MSG_QUEUE
interface_msg_message_t msg; /* message */
#endif
intf_msg_item_t * p_msg_item; /* pointer to message */
/* Convert message to string */
#ifndef INTF_MSG_QUEUE /*..................................... instant mode ...*/
intf_msg_item_t msg_item; /* message */
p_msg_item = &msg_item;
#endif /*......................................................................*/
/*
* Convert message to string
*/
vasprintf( &psz_str, psz_format, ap );
if( psz_str == NULL )
{
fprintf(stderr, "intf error: *** can not store message (%s) ***\n",
fprintf(stderr, "Warning: can't store following message (%s): ",
strerror(errno) );
vfprintf(stderr, psz_format, ap );
exit( errno );
}
#ifdef INTF_MSG_QUEUE
/*
* Queue mode: the queue is flushed if it is full, then the message is
* queued. A lock is required on queue to avoid indexes corruption
*/
vlc_mutex_lock( &p_intf_msg->lock ); /* get lock */
if( p_intf_msg->i_count == INTF_MSG_QSIZE ) /* flush queue if needed */
#ifdef INTF_MSG_QUEUE /*........................................ queue mode ...*/
vlc_mutex_lock( &p_msg->lock ); /* get lock */
if( p_msg->i_count == INTF_MSG_QSIZE ) /* flush queue if needed */
{
#ifdef DEBUG /* in debug mode, queue overflow causes a waring */
fprintf(stderr, "intf warning: *** message queue overflow ***\n" );
#ifdef DEBUG /* in debug mode, queue overflow causes a warning */
fprintf(stderr, "Warning: message queue overflow\n" );
#endif
FlushLockedMsg( p_intf_msg );
FlushLockedMsg( p_msg );
}
/* Queue message - if DEBUG if defined, the message is dated */
p_intf_msg->msg[ p_intf_msg->i_count ].i_type = i_type;
p_intf_msg->msg[ p_intf_msg->i_count++ ].psz_msg = psz_str;
#ifdef DEBUG
p_intf_msg->msg[ p_intf_msg->i_count ].date = mdate();
#endif
vlc_mutex_unlock( &p_intf_msg->lock ); /* give lock back */
#else
p_msg_item = p_msg->msg + p_msg->i_count++; /* select message */
#endif /*................................................ end of queue mode ...*/
/*
* Instant mode: the message is converted and printed immediately
* Fill message information fields
*/
msg.i_type = i_type;
msg.psz_msg = psz_str;
#ifdef DEBUG
msg.date = mdate();
#endif
PrintMsg( &msg ); /* print message */
free( psz_str ); /* free message data */
p_msg_item->i_type = i_type;
p_msg_item->psz_msg = psz_str;
#endif
#ifdef INTF_MSG_QUEUE /*........................................... queue mode */
vlc_mutex_unlock( &p_msg->lock ); /* give lock back */
#else /*......................................................... instant mode */
PrintMsg( p_msg_item ); /* print message */
free( psz_str ); /* free message data */
#endif /*......................................................................*/
}
/*******************************************************************************
......@@ -322,65 +362,58 @@ static void QueueMsg(interface_msg_t *p_intf_msg, int i_type, char *psz_format,
* DEBUG is define, and require additionnal debugging informations.
*******************************************************************************/
#ifdef DEBUG
static void QueueDbgMsg(interface_msg_t *p_intf_msg, char *psz_file, char *psz_function,
static void QueueDbgMsg(intf_msg_t *p_msg, char *psz_file, char *psz_function,
int i_line, char *psz_format, va_list ap)
{
char * psz_str; /* formatted message string */
#ifndef INTF_MSG_QUEUE
interface_msg_message_t msg; /* message */
#endif
intf_msg_item_t * p_msg_item; /* pointer to message */
#ifndef INTF_MSG_QUEUE /*..................................... instant mode ...*/
intf_msg_item_t msg_item; /* message */
p_msg_item = &msg_item;
#endif /*......................................................................*/
/* Convert message to string */
/*
* Convert message to string
*/
vasprintf( &psz_str, psz_format, ap );
if( psz_str == NULL )
{ /* critical error: not enough memory to store message */
fprintf(stderr, "intf error: *** can not store message (%s) ***\n", strerror(errno) );
{
fprintf(stderr, "Warning: can't store following message (%s): ",
strerror(errno) );
fprintf(stderr, INTF_MSG_DBG_FORMAT, psz_file, psz_function, i_line );
vfprintf(stderr, psz_format, ap );
exit( errno );
}
#ifdef INTF_MSG_QUEUE
/*
* Queue mode: the queue is flushed if it is full, then the message is
* queued. A lock is required on queue to avoid indexes corruption
*/
vlc_mutex_lock( &p_intf_msg->lock ); /* get lock */
if( p_intf_msg->i_count == INTF_MSG_QSIZE ) /* flush queue if needed */
#ifdef INTF_MSG_QUEUE /*........................................ queue mode ...*/
vlc_mutex_lock( &p_msg->lock ); /* get lock */
if( p_msg->i_count == INTF_MSG_QSIZE ) /* flush queue if needed */
{
fprintf(stderr, "intf warning: *** message queue overflow ***\n" );
FlushLockedMsg( p_intf_msg );
#ifdef DEBUG /* in debug mode, queue overflow causes a warning */
fprintf(stderr, "Warning: message queue overflow\n" );
#endif
FlushLockedMsg( p_msg );
}
/* Queue message */
p_intf_msg->msg[ p_intf_msg->i_count ].i_type = INTF_MSG_DBG;
p_intf_msg->msg[ p_intf_msg->i_count ].date = mdate();
p_intf_msg->msg[ p_intf_msg->i_count ].psz_file = psz_file;
p_intf_msg->msg[ p_intf_msg->i_count ].psz_function = psz_function;
p_intf_msg->msg[ p_intf_msg->i_count ].i_line = i_line;
p_intf_msg->msg[ p_intf_msg->i_count++ ].psz_msg = psz_str;
vlc_mutex_unlock( &p_intf_msg->lock ); /* give lock back */
#else
p_msg_item = p_msg->msg + p_msg->i_count++; /* select message */
#endif /*................................................ end of queue mode ...*/
/*
* Instant mode: the message is converted and printed immediately
* Fill message information fields
*/
msg.i_type = INTF_MSG_DBG;
msg.psz_file = psz_file;
msg.psz_function = psz_function;
msg.i_line = i_line;
#ifdef DEBUG
// msg.date = mdate();
#endif
msg.psz_msg = psz_str;
PrintMsg( &msg ); /* print message */
p_msg_item->i_type = INTF_MSG_DBG;
p_msg_item->psz_msg = psz_str;
p_msg_item->psz_file = psz_file;
p_msg_item->psz_function = psz_function;
p_msg_item->i_line = i_line;
p_msg_item->date = mdate();
#ifdef INTF_MSG_QUEUE /*........................................... queue mode */
vlc_mutex_unlock( &p_msg->lock ); /* give lock back */
#else /*......................................................... instant mode */
PrintMsg( p_msg_item ); /* print message */
free( psz_str ); /* free message data */
#endif
#endif /*......................................................................*/
}
#endif
......@@ -392,18 +425,18 @@ static void QueueDbgMsg(interface_msg_t *p_intf_msg, char *psz_file, char *psz_f
* INTF_MSG_QUEUE is defined.
*******************************************************************************/
#ifdef INTF_MSG_QUEUE
static void FlushLockedMsg ( interface_msg_t *p_intf_msg )
static void FlushLockedMsg ( intf_msg_t *p_msg )
{
int i_index;
for( i_index = 0; i_index < p_intf_msg->i_count; i_index++ )
for( i_index = 0; i_index < p_msg->i_count; i_index++ )
{
/* Print message and free message data */
PrintMsg( &p_intf_msg->msg[i_index] );
free( p_intf_msg->msg[i_index].psz_msg );
PrintMsg( &p_msg->msg[i_index] );
free( p_msg->msg[i_index].psz_msg );
}
p_intf_msg->i_count = 0;
p_msg->i_count = 0;
}
#endif
......@@ -417,35 +450,30 @@ static void FlushLockedMsg ( interface_msg_t *p_intf_msg )
*******************************************************************************/
#ifdef DEBUG
static void PrintMsg( interface_msg_message_t *p_msg )
static void PrintMsg( intf_msg_item_t *p_msg )
{
char psz_date[MSTRTIME_MAX_SIZE]; /* formatted time buffer */
char * psz_msg; /* message buffer */
/* Computes date */
mstrtime( psz_date, p_msg->date );
/* Format message - the message is formatted here because in case the log
* file is used, it avoids another format string parsing */
switch( p_msg->i_type )
{
case INTF_MSG_STD: /* regular messages */
case INTF_MSG_ERR:
asprintf( &psz_msg, "(%s) %s", psz_date, p_msg->psz_msg );
asprintf( &psz_msg, "%s", p_msg->psz_msg );
break;
case INTF_MSG_INTF: /* interface messages */
case INTF_MSG_DBG:
asprintf( &psz_msg, p_msg->psz_msg );
asprintf( &psz_msg, "%s", p_msg->psz_msg );
break;
#if 0
case INTF_MSG_DBG: /* debug messages */
mstrtime( psz_date, p_msg->date );
asprintf( &psz_msg, "(%s) " INTF_MSG_DBG_FORMAT "%s",
psz_date, p_msg->psz_file, p_msg->psz_function, p_msg->i_line,
p_msg->psz_msg );
break;
#endif
}
/* Check if formatting function suceeded */
......@@ -471,13 +499,16 @@ static void PrintMsg( interface_msg_message_t *p_msg )
fprintf( stderr, psz_msg );
break;
case INTF_MSG_INTF: /* interface messages */
intf_PrintXConsole( &p_program_data->intf_thread.xconsole, psz_msg );
intf_ConsolePrint( p_main->p_intf->p_console, psz_msg );
break;
}
#ifdef DEBUG_LOG
/* Append all messages to log file */
fprintf( p_program_data->intf_msg.p_log_file, psz_msg );
if( p_main->p_msg->i_log_file >= 0 )
{
write( p_main->p_msg->i_log_file, psz_msg, strlen( psz_msg ) );
}
#endif
/* Free formatted message */
......@@ -501,7 +532,7 @@ static void PrintMsg( interface_msg_message_t *p_msg )
fprintf( stderr, p_msg->psz_msg );
break;
case INTF_MSG_INTF: /* interface messages */
intf_PrintXConsole( &p_program_data->intf_thread.xconsole,
intf_PrintXConsole( &p_main->intf_thread.xconsole,
p_msg->psz_msg );
break;
}
......
......@@ -15,60 +15,36 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/soundcard.h>
#include <sys/uio.h>
#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>
#include <sys/soundcard.h> /* audio_output.h */
#include "config.h"
#include "common.h"
#include "mtime.h"
#include "vlc_thread.h"
#include "netutils.h"
#include "debug.h"
#include "intf_msg.h"
#include "input.h"
#include "input_vlan.h"
#include "input_netlist.h"
#include "decoder_fifo.h"
#include "audio_output.h"
#include "audio_decoder.h"
#include "video.h"
#include "video_output.h"
#include "video_decoder.h"
#include "xconsole.h"
#include "intf_msg.h"
#include "interface.h"
#include "audio_output.h"
#include "main.h"
#include "pgm_data.h"
/*
/*******************************************************************************
* Command line options constants. If something is changed here, be sure that
* GetConfiguration and Usage are also changed.
*/
*******************************************************************************/
/* Long options return values - note that values corresponding to short options
* chars, and in general any regular char, should be avoided */
#define OPT_DISPLAY 130
#define OPT_CONSOLE_DISPLAY 140
#define OPT_CONSOLE_GEOMETRY 141
#define OPT_NOAUDIO 150
#define OPT_STEREO 151
#define OPT_MONO 152
#define OPT_RATE 153
#define OPT_NOVIDEO 160
#define OPT_XSHM 161
#define OPT_NOXSHM 162
#define OPT_XDGA 161
#define OPT_XSHM 162
#define OPT_XNOSHM 163
#define OPT_XNODGA 164
#define OPT_NOVLANS 170
#define OPT_VLAN_SERVER 171
......@@ -80,26 +56,17 @@ static const struct option longopts[] =
/* General/common options */
{ "help", 0, 0, 'h' },
{ "display", 1, 0, OPT_DISPLAY },
/* Interface options */
{ "console-display", 1, 0, OPT_CONSOLE_DISPLAY },
{ "console-geometry", 1, 0, OPT_CONSOLE_GEOMETRY },
/* Audio options */
{ "noaudio", 0, 0, OPT_NOAUDIO },
{ "stereo", 0, 0, OPT_STEREO },
{ "mono", 0, 0, OPT_MONO },
{ "rate", 0, 0, OPT_RATE },
/* Video options */
{ "novideo", 0, 0, OPT_NOVIDEO },
{ "xshm", 0, 0, OPT_XSHM },
{ "noxshm", 0, 0, OPT_NOXSHM },
/* VLAN management options */
{ "novlans", 0, 0, OPT_NOVLANS },
{ "vlanserver", 1, 0, OPT_VLAN_SERVER },
{ 0, 0, 0, 0 }
};
......@@ -107,19 +74,18 @@ static const struct option longopts[] =
/* Short options */
static const char *psz_shortopts = "h";
/*
* Global variable program_data
*/
program_data_t *p_program_data; /* see pgm_data.h */
/*******************************************************************************
* Global variable program_data - this is the one and only, see main.h
*******************************************************************************/
main_t *p_main;
/*
/*******************************************************************************
* Local prototypes
*/
static void SetDefaultConfiguration ( program_data_t *p_data );
static int GetConfiguration ( program_data_t *p_config, int i_argc, char *ppsz_argv[],
char *ppsz_env[] );
*******************************************************************************/
static void SetDefaultConfiguration ( void );
static int GetConfiguration ( int i_argc, char *ppsz_argv[], char *ppsz_env[] );
static void Usage ( void );
static long GetIntParam ( const char *psz_param, long i_min, long i_max, int *pi_err );
static void InitSignalHandler ( void );
static void SignalHandler ( int i_signal );
......@@ -128,146 +94,174 @@ static void SignalHandler ( int i_signal );
*******************************************************************************
* Steps during program execution are:
* -configuration parsing and messages interface initialization
* -openning of audio output device
* -openning of audio output device and some global modules
* -execution of interface, which exit on error or on user request
* -closing of audio output device
* -closing of audio output device and some global modules
* On error, the spawned threads are cancelled, and the openned devices closed.
*******************************************************************************
* ?? Signal handlers should be restored to default once the interface has
* been closed, since they will cause a crash if the message interface is no
* more active.
*******************************************************************************/
int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
{
program_data_t program_data; /* root of all data - see pgm_data.h */
main_t main_data; /* root of all data - see main.h */
p_main = &main_data; /* set up the global variable */
/*
* Read configuration, initialize messages interface and set up program
*/
p_program_data = &program_data; /* set up the global variable */
if( intf_InitMsg( &program_data.intf_msg ) ) /* start messages interface */
p_main->p_msg = intf_MsgCreate();
if( !p_main->p_msg ) /* start messages interface */
{
fprintf(stderr, "intf critical: can't initialize messages interface (%s)\n",
fprintf(stderr, "critical error: can't initialize messages interface (%s)\n",
strerror(errno));
return(errno);
}
if( GetConfiguration( &program_data, /* parse command line */
i_argc, ppsz_argv, ppsz_env ) )
if( GetConfiguration( i_argc, ppsz_argv, ppsz_env ) )/* parse command line */
{
intf_TerminateMsg( &program_data.intf_msg );
intf_MsgDestroy();
return(errno);
}
intf_MsgImm( COPYRIGHT_MESSAGE ); /* print welcome message */
InitSignalHandler(); /* prepare signals for interception */
/*
* Initialize shared resources and libraries
*/
if( program_data.cfg.b_vlans
&& input_VlanMethodInit( &program_data.input_vlan_method,
program_data.cfg.psz_input_vlan_server,
program_data.cfg.i_input_vlan_server_port) )
if( main_data.b_vlans && input_VlanCreate() )
{
/* On error during vlans initialization, switch of vlans */
intf_Msg("intf: switching off vlans\n");
program_data.cfg.b_vlans = 0;
intf_Msg("Virtual LANs initialization failed : vlans management is desactivated\n");
main_data.b_vlans = 0;
}
/*
* Open audio device
* Open audio device and start aout thread
*/
if( program_data.cfg.b_audio )
if( main_data.b_audio )
{
if( aout_Open( &program_data.aout_thread ) )
main_data.p_aout = aout_CreateThread( NULL );
if( main_data.p_aout == NULL )
{
/* On error during audio initialization, switch of audio */
intf_Msg("intf: switching off audio\n");
program_data.cfg.b_audio = 0;
intf_Msg("Audio initialization failed : audio is desactivated\n");
main_data.b_audio = 0;
}
else if( aout_SpawnThread( &program_data.aout_thread ) )
{
aout_Close( &program_data.aout_thread );
input_VlanMethodFree( &program_data.input_vlan_method );
intf_TerminateMsg( &program_data.intf_msg );
return( -1 );
}
program_data.intf_thread.p_aout = &program_data.aout_thread;
}
/*
* Run interface
*/
intf_DbgMsg("intf debug: starting interface\n");
intf_Run( &program_data.intf_thread );
intf_DbgMsg("intf debug: interface terminated\n");
main_data.p_intf = intf_Create();
if( main_data.p_intf != NULL )
{
InitSignalHandler(); /* prepare signals for interception */
intf_Run( main_data.p_intf );
intf_Destroy( main_data.p_intf );
}
/*
* Close audio device
*/
if( program_data.cfg.b_audio )
if( main_data.b_audio )
{
aout_CancelThread( &program_data.aout_thread );
aout_Close( &program_data.aout_thread );
aout_DestroyThread( main_data.p_aout, NULL );
}
/*
* Free shared resources and libraries
*/
if( program_data.cfg.b_vlans )
if( main_data.b_vlans )
{
input_VlanMethodFree( &program_data.input_vlan_method );
input_VlanDestroy();
}
/*
* Terminate messages interface and program
*/
intf_Msg( "program terminated.\n" );
intf_TerminateMsg( &program_data.intf_msg );
intf_Msg( "Program terminated.\n" );
intf_MsgDestroy();
return( 0 );
}
/*******************************************************************************
* main_GetIntVariable: get the int value of an environment variable
*******************************************************************************
* This function is used to read some default parameters in modules.
*******************************************************************************/
int main_GetIntVariable( char *psz_name, int i_default )
{
char *psz_env;
psz_env = getenv( psz_name );
if( psz_env )
{
psz_env = strchr( psz_env, '=' );
if( psz_env )
{
return( atoi( psz_env + 1) );
}
}
return( i_default );
}
/*******************************************************************************
* main_GetPszVariable: get the string value of an environment variable
*******************************************************************************
* This function is used to read some default parameters in modules.
*******************************************************************************/
char * main_GetPszVariable( char *psz_name, char *psz_default )
{
char *psz_env;
psz_env = getenv( psz_name );
if( psz_env )
{
psz_env = strchr( psz_env, '=' );
if( psz_env )
{
return( psz_env + 1 );
}
}
return( psz_default );
}
/* following functions are local */
/*******************************************************************************
* SetDefaultConfiguration: set default options
*******************************************************************************
* This function is called by GetConfiguration before command line is parsed.
* It sets all the default values required later by the program. Note that
* all properties must be initialized, wether they are command-line dependant
* or not.
* It sets all the default values required later by the program. At this stage,
* most structure are not yet allocated, so initialization must be done using
* environment.
*******************************************************************************/
static void SetDefaultConfiguration( program_data_t *p_data )
static void SetDefaultConfiguration( void )
{
/*
* Audio output thread configuration
* All features are activated by default
*/
p_data->cfg.b_audio = 1; /* audio is activated by default */
p_data->aout_thread.dsp.psz_device = AOUT_DEFAULT_DEVICE;
/* je rajouterai la dtection des formats supports quand le reste
* marchera */
p_data->aout_thread.dsp.i_format = AOUT_DEFAULT_FORMAT;
p_data->aout_thread.dsp.b_stereo = AOUT_DEFAULT_STEREO;
p_data->aout_thread.dsp.l_rate = AOUT_DEFAULT_RATE;
p_main->b_audio = 1;
p_main->b_video = 1;
p_main->b_vlans = 1;
/*
* Interface thread configuration
* Audio output thread configuration
*/
/* X11 console */
p_data->intf_thread.xconsole.psz_display = NULL;
p_data->intf_thread.xconsole.psz_geometry = INTF_XCONSOLE_GEOMETRY;
/* --- ?? following are ok */
// ?? initialization using structures is no more available, use putenv/getenv
// instead.
/*
* Video output thread configuration
*/
p_data->cfg.b_video = 1;
p_data->vout_cfg.i_properties = 0;
// p_data->vout_cfg.i_properties = 0;
/* VLAN management */
p_data->cfg.b_vlans = 0;
/*??? p_data->cfg.b_vlans = 0;
p_data->cfg.psz_input_vlan_server = VLAN_DEFAULT_SERVER;
p_data->cfg.i_input_vlan_server_port = VLAN_DEFAULT_SERVER_PORT;
*/
}
/*******************************************************************************
......@@ -275,21 +269,21 @@ static void SetDefaultConfiguration( program_data_t *p_data )
*******************************************************************************
* Parse command line and configuration file for configuration. If the inline
* help is requested, the function Usage() is called and the function returns
* -1 (causing main() to exit). Note than messages interface is initialized at
* this stage.
* -1 (causing main() to exit). The messages interface is initialized at this
* stage, but most structures are not allocated, so only environment should
* be used.
*******************************************************************************/
static int GetConfiguration( program_data_t *p_data, int i_argc,
char *ppsz_argv[], char *ppsz_env[] )
static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
{
int c, i_err;
int c, i_opt;
/* Set default configuration and copy arguments */
p_data->i_argc = i_argc;
p_data->ppsz_argv = ppsz_argv;
p_data->ppsz_env = ppsz_env;
SetDefaultConfiguration( p_data );
p_main->i_argc = i_argc;
p_main->ppsz_argv = ppsz_argv;
p_main->ppsz_env = ppsz_env;
SetDefaultConfiguration();
/* Parse command line */
/* Parse command line options */
opterr = 0;
while( ( c = getopt_long( i_argc, ppsz_argv, psz_shortopts, longopts, 0 ) ) != EOF )
{
......@@ -300,58 +294,28 @@ static int GetConfiguration( program_data_t *p_data, int i_argc,
Usage();
return( -1 );
break;
case OPT_DISPLAY: /* --display */
p_data->vout_cfg.psz_display = optarg;
p_data->vout_cfg.i_properties |= VIDEO_CFG_DISPLAY;
p_data->intf_thread.xconsole.psz_display = optarg;
break;
/* Interface options */
case OPT_CONSOLE_DISPLAY: /* --console-display */
p_data->intf_thread.xconsole.psz_display = optarg;
break;
case OPT_CONSOLE_GEOMETRY: /* --console-geometry */
p_data->intf_thread.xconsole.psz_geometry = optarg;
break;
/* Audio options */
case OPT_NOAUDIO: /* --noaudio */
p_data->cfg.b_audio = 0;
p_main->b_audio = 0;
break;
case OPT_STEREO: /* --stereo */
p_data->aout_thread.dsp.b_stereo = 1;
// ?? should be replaced by a putenv
//p_main->p_aout->dsp.b_stereo = 1;
break;
case OPT_MONO: /* --mono */
p_data->aout_thread.dsp.b_stereo = 0;
break;
case OPT_RATE: /* --rate */
p_data->aout_thread.dsp.l_rate = GetIntParam(optarg, AOUT_MIN_RATE, AOUT_MAX_RATE, &i_err );
if( i_err )
{
return( EINVAL );
}
// ?? should be replaced by a putenv
//p_main->p_aout->dsp.b_stereo = 0;
break;
/* Video options */
case OPT_NOVIDEO: /* --novideo */
p_data->cfg.b_video = 0;
break;
case OPT_XSHM: /* --xshm */
p_data->vout_cfg.b_shm_ext = 1;
p_data->vout_cfg.i_properties |= VIDEO_CFG_SHM_EXT;
break;
case OPT_NOXSHM: /* --noxshm */
p_data->vout_cfg.b_shm_ext = 0;
p_data->vout_cfg.i_properties |= VIDEO_CFG_SHM_EXT;
p_main->b_video = 0;
break;
/* VLAN management options */
case OPT_NOVLANS: /* --novlans */
p_data->cfg.b_vlans = 0;
break;
case OPT_VLAN_SERVER: /* --vlanserver */
p_data->cfg.i_input_vlan_server_port = ServerPort( optarg );
p_data->cfg.psz_input_vlan_server = optarg;
p_main->b_vlans = 0;
break;
/* Internal error: unknown option */
......@@ -363,6 +327,11 @@ static int GetConfiguration( program_data_t *p_data, int i_argc,
}
}
/* Parse command line parameters - no check is made for these options */
for( i_opt = optind; i_opt < i_argc; i_opt++ )
{
putenv( ppsz_argv[ i_opt ] );
}
return( 0 );
}
......@@ -374,59 +343,44 @@ static int GetConfiguration( program_data_t *p_data, int i_argc,
static void Usage( void )
{
intf_Msg(COPYRIGHT_MESSAGE);
/* General options */
intf_Msg("usage: vlc [options...]\n" \
" -h, --help print usage\n" \
/* Usage */
intf_Msg("usage: vlc [options...] [parameters]\n" \
" parameters can be passed using environment variables\n" \
" example: vlan_server=vlan-server.via.ecp.fr:1234\n" \
);
/* Audio options */
intf_Msg(" --noaudio disable audio\n" \
/* Options */
intf_Msg("Options:" \
" -h, --help print usage\n" \
" --noaudio disable audio\n" \
" --stereo enable stereo\n" \
" --mono disable stereo\n"
" --rate <rate> audio output rate (kHz)\n" \
" --novideo disable video\n" \
" --novlans disable vlans\n" \
);
/* Video options */
intf_Msg(" --novideo disable video\n" \
" --xshm, --noxshm enable/disable use of XShm extension\n" \
" -d, --display <display> set display name\n" \
/* Interface parameters */
intf_Msg("Interface parameters:\n" \
" " INTF_INIT_SCRIPT_VAR "=<filename> initialization script\n" \
);
/* VLAN management options */
intf_Msg(" --novlans disable vlans\n" \
" --vlanserver <server[:port]> set vlan server address\n" \
/* Audio parameters */
intf_Msg("Audio parameters:\n" \
" " AOUT_DSP_VAR "=<filename> dsp device path\n" \
" " AOUT_STEREO_VAR "={1|0} stereo or mono output\n" \
" " AOUT_RATE_VAR "=<rate> output rate\n" \
);
}
/*******************************************************************************
* GetIntParam: convert a string to an integer
*******************************************************************************
* This function convert a string to an integer, check range of the value
* and that there is no error during convertion. pi_err is a pointer to an
* error flag, which contains non 0 on error. This function prints its own
* error messages.
*******************************************************************************/
static long GetIntParam( const char *psz_param, long i_min, long i_max, int *pi_err )
{
char *psz_endptr;
long int i_value;
/* Video parameters */
intf_Msg("Video parameters:\n" \
);
i_value = strtol( psz_param, &psz_endptr, 0 );
if( (psz_param[0] == '\0') && (*psz_endptr != '\0') ) /* conversion error */
{
intf_ErrMsg("intf error: conversion error ('%s' should be an integer between %ld and %ld)\n",
psz_param, i_min, i_max );
*pi_err = EINVAL;
return( 0 );
}
if( (i_value < i_min) || (i_value > i_max) ) /* range error */
{
intf_ErrMsg("intf error: range error ('%s' should be an integer between %ld and %ld)\n",
psz_param, i_min, i_max );
*pi_err = EINVAL;
return( 0 );
}
*pi_err = 0;
return( i_value );
/* Vlan parameters */
intf_Msg("VLANs (Virtual Local Aera Networks) parameters:\n" \
" vlan_server=<host>[:<port>] VLANs server address and port\n" \
);
}
/*******************************************************************************
* InitSignalHandler: system signal handler initialization
*******************************************************************************
......@@ -445,19 +399,25 @@ static void InitSignalHandler( void )
/*******************************************************************************
* SignalHandler: system signal handler
*******************************************************************************
* This function is called when a signal is received by the program. It ignores
* it or tries to terminate cleanly.
* This function is called when a signal is received by the program. It tries to
* end the program in a clean way.
*******************************************************************************/
static void SignalHandler( int i_signal )
{
/* Once a signal has been trapped, the signal handler needs to be re-armed on
* linux systems */
signal( i_signal, SignalHandler );
/* Once a signal has been trapped, the termination sequence will be armed and
* following signals will be ignored to avoid sending messages to an interface
* having been destroyed */
signal( SIGHUP, SIG_IGN );
signal( SIGINT, SIG_IGN );
signal( SIGQUIT, SIG_IGN );
/* Acknowledge the signal received */
intf_ErrMsgImm("intf: signal %d received\n", i_signal );
/* Try to terminate everything */
/* ?? this probably needs to be changed */
p_program_data->intf_thread.b_die = 1;
/* Try to terminate everything - this is done by requesting the end of the
* interface thread */
p_main->p_intf->b_die = 1;
}
/*******************************************************************************
* xconsole.c: X11 console for interface
* (c)1998 VideoLAN
*******************************************************************************
* The X11 console is a simple way to get interactive input from the user. It
* does not disturbs the standard terminal output. In theory, multiple consoles
* could be opened on different displays.
* The console has 2 parts: a multi-line display on top, able to display
* messages, and an input line at bottom.
*******************************************************************************/
/* ?? todo: background color, color lines, pixmaps in front of line,
* multiple fonts, control-like implementation, mouse management (copy/paste)...
* add a scroller to text zone
* It will probably be better to use something esier to use than plain xlib.
*
* There is no prompt yet since a pixmap would be sexier as a text prompt :)
* issue beeps (using audio_output, of course) on 'errors' (eol, end of history
* browse, ...)
* remove dups from history */
/*******************************************************************************
* Preamble
*******************************************************************************/
#include <errno.h>
#include <keysym.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/xpm.h>
#include "config.h"
#include "common.h"
#include "mtime.h"
#include "vlc_thread.h"
#include "xutils.h"
#include "xconsole.h"
#include "intf_msg.h"
#include "intf_cmd.h"
/*
* Local prototypes
*/
static int CreateXConsoleWindow ( xconsole_t *p_console );
static void DestroyXConsoleWindow ( xconsole_t *p_console );
static void PrintXConsoleLine ( xconsole_t *p_console, int i_line,
char *psz_str );
static void RedrawXConsoleText ( xconsole_t *p_console );
static void RedrawXConsoleEdit ( xconsole_t *p_console );
static void RegisterXConsoleHistory ( xconsole_t *p_console );
static void RecallXConsoleHistory ( xconsole_t *p_console, int i_index );
/*******************************************************************************
* intf_OpenXConsole: open console
*******************************************************************************
* This function try to open an X11 display and create a simple text window.
* It returns 0 on success.
*******************************************************************************/
int intf_OpenXConsole( xconsole_t *p_console )
{
int i_index; /* all purposes index */
/* Open display */
p_console->psz_display = XDisplayName( p_console->psz_display );
p_console->p_display = XOpenDisplay( p_console->psz_display );
if( !p_console->p_display ) /* error */
{
intf_ErrMsg("intf error: can't open display %s\n",
p_console->psz_display );
return( -1 );
}
/* Get the screen number */
p_console->i_screen = DefaultScreen( p_console->p_display );
/* Create window and set console attributes */
if( CreateXConsoleWindow( p_console ) ) /* error */
{
XFreeFont( p_console->p_display, p_console->p_font ); /* free font */
XCloseDisplay( p_console->p_display ); /* close display */
return( 1 ); /* return error code */
}
/* Set all text as empty */
for( i_index = 0; i_index < INTF_XCONSOLE_MAX_LINES; i_index++ )
{
p_console->psz_text[i_index] = 0; /* clear the line */
}
p_console->i_text_index = 0;
/* Clear edit line and history */
for( i_index = 0; i_index < INTF_XCONSOLE_HISTORY_SIZE; i_index++ )
{
p_console->psz_history[i_index] = 0; /* clear the line */
}
p_console->i_history_index = 0;
p_console->i_history_base = 0;
p_console->i_edit_index = 0;
p_console->i_edit_size = 0;
/* Print welcome message */
intf_PrintXConsole( p_console, INTF_XCONSOLE_WELCOME_MSG );
intf_DbgMsg("intf debug: X11 console %p opened\n", p_console );
return( 0 );
}
/*******************************************************************************
* intf_CloseXConsole: close console (ok ?)
*******************************************************************************
* Destroy a console window and close the display. This function should be
* called when the interface thread ends, and any further access to this console
* is vorbidden.
*******************************************************************************/
void intf_CloseXConsole( xconsole_t *p_console )
{
int i_index; /* all purposes index */
/* Destroy history */
for( i_index = 0; i_index < INTF_XCONSOLE_HISTORY_SIZE; i_index++ )
{
if( p_console->psz_history[i_index] ) /* history line isn't empty */
{
free( p_console->psz_history[i_index] ); /* free the line */
}
}
/* Destroy text */
for( i_index = 0; i_index < INTF_XCONSOLE_MAX_LINES; i_index++ )
{
if( p_console->psz_text[i_index] ) /* line isn't empty */
{
free( p_console->psz_text[i_index] ); /* free the line */
}
}
/* Destroy window and resources */
DestroyXConsoleWindow( p_console );
/* Close display */
XSetErrorHandler( NULL ); /* ?? reset non-fatal error handler */
XSetIOErrorHandler( NULL ); /* ?? reset IO error handler */
XCloseDisplay( p_console->p_display ); /* close display */
intf_DbgMsg("intf debug: X11 console %p closed\n", p_console );
}
/*******************************************************************************
* intf_ManageXConsole: manage X11 console events
*******************************************************************************
* This function manage events received in X11 console such as key pressed,
* messages received, and so on... It also run commands typed in the console.
*******************************************************************************/
void intf_ManageXConsole( xconsole_t *p_console )
{
XEvent x_event; /* generic event */
char x_char; /* keyboard event character */
KeySym keysym; /* keysym */
int i_index; /* multi purpose index */
int i_next_index; /* next history index */
/* If window has been resized, update attributes and redraw */
while( XCheckTypedEvent( p_console->p_display, ConfigureNotify, &x_event ) )
{
/* ?? check if move, expose or resize !!! */
p_console->i_width = ((XConfigureEvent *) &x_event)->width;
p_console->i_height = ((XConfigureEvent *) &x_event)->height;
RedrawXConsoleText( p_console );
RedrawXConsoleEdit( p_console );
XFlush( p_console->p_display );
}
/* Check keyboard events */
while( XCheckTypedEvent( p_console->p_display, KeyPress, &x_event ) )
{
/* If XLookupString returns a single character, the key is probably an
* ascii character and is added to the edit line, except if it is a
* control character (ascii < 32) or DEL (ascii = 127) */
if( (XLookupString( (XKeyEvent *) &x_event, &x_char, 1, &keysym, 0 ) == 1)
&& ( x_char >= 32 ) && ( x_char != 127 ) )
{
/* Increase line size, except if maximal size has been reached */
if( ++p_console->i_edit_size > INTF_XCONSOLE_MAX_LINE_WIDTH )
{
/* Maximal size reached */
p_console->i_edit_size = INTF_XCONSOLE_MAX_LINE_WIDTH;
}
/* Shift right line from cursor position to the end of line */
for( i_index = p_console->i_edit_size - 1; i_index > p_console->i_edit_index; i_index-- )
{
p_console->sz_edit[i_index] = p_console->sz_edit[i_index - 1];
}
/* Insert character at the cursor position and increase cursor position,
* except if the cursor reached the right of the line */
if( p_console->i_edit_index < INTF_XCONSOLE_MAX_LINE_WIDTH )
{
p_console->sz_edit[p_console->i_edit_index++] = x_char;
}
}
/* Else, the key is a control key, and keysym is used to process it. */
else
{
switch( keysym )
{
/* Cursor position modification */
case XK_Delete: /* Delete */
/* Delete has effect only if cursor is not at the end of the line */
if( p_console->i_edit_index < p_console->i_edit_size )
{
/* Shift left line from cursor position (excluded) to the end of line */
for( i_index = p_console->i_edit_index + 1; i_index < p_console->i_edit_size; i_index++ )
{
p_console->sz_edit[i_index - 1] = p_console->sz_edit[i_index];
}
/* Decrease line size */
p_console->i_edit_size--;
}
break;
case XK_BackSpace: /* BackSpace */
/* BackSpace has effect only if cursor is not at the beginning of the line */
if( p_console->i_edit_index > 0 )
{
/* Shift left line from cursor position (included) to the end of line */
for( i_index = p_console->i_edit_index; i_index < p_console->i_edit_size; i_index++ )
{
p_console->sz_edit[i_index - 1] = p_console->sz_edit[i_index];
}
/* Decrease line size and cursor position */
p_console->i_edit_size--;
p_console->i_edit_index--;
}
break;
case XK_Left: /* Left */
/* Move left */
if( --p_console->i_edit_index < 0 )
{
p_console->i_edit_index = 0;
}
break;
case XK_Right: /* Right */
/* Move right */
if( ++p_console->i_edit_index > p_console->i_edit_size )
{
p_console->i_edit_index = p_console->i_edit_size;
}
break;
case XK_Home: /* Home */
/* Go to beginning of line */
p_console->i_edit_index = 0;
break;
case XK_End: /* End */
/* Go to end of line */
p_console->i_edit_index = p_console->i_edit_size;
break;
/* Clear */
case XK_Escape:
/* Clear line and reset history index and record */
p_console->i_edit_index = 0;
p_console->i_edit_size = 0;
p_console->i_history_index = p_console->i_history_base;
break;
/* History */
case XK_Up:
/* If history index is history base, this marks the beginning of
* an history browse, and the current edited line needs to be
* registered */
if( p_console->i_history_index == p_console->i_history_base )
{
RegisterXConsoleHistory( p_console );
}
/* Calculate next index */
if( p_console->i_history_index )
{
i_next_index = p_console->i_history_index - 1;
}
else
{
i_next_index = INTF_XCONSOLE_HISTORY_SIZE - 1;
}
/* Go to previous record, if it not blank and a loop hasn't been made */
if( (i_next_index != p_console->i_history_base) && p_console->psz_history[i_next_index] )
{
RecallXConsoleHistory( p_console, i_next_index );
}
break;
case XK_Down:
/* If history index is not history base, Calculate next index */
if( p_console->i_history_index != p_console->i_history_base )
{
/* Calculate next index */
if( p_console->i_history_index == INTF_XCONSOLE_HISTORY_SIZE - 1 )
{
i_next_index = 0;
}
else
{
i_next_index = p_console->i_history_index + 1;
}
/* Go to previous record */
RecallXConsoleHistory( p_console, i_next_index );
}
break;
/* Command execution */
case XK_Return:
/* Command is executed only if line is not empty */
if( p_console->i_edit_size )
{
/* Add current line to history and increase history base. The
* called function also add a terminal '\0' to sz_edit, which
* allow to send it without furhter modification to execution. */
RegisterXConsoleHistory( p_console );
if( ++p_console->i_history_base > INTF_XCONSOLE_HISTORY_SIZE )
{
p_console->i_history_base = 0;
}
/* Execute command */
intf_ExecCommand( p_console->sz_edit );
/* Clear line and reset history index */
p_console->i_edit_index = 0;
p_console->i_edit_size = 0;
p_console->i_history_index = p_console->i_history_base;
}
break;
}
}
/* Redraw edit zone */
RedrawXConsoleEdit( p_console );
XFlush( p_console->p_display );
}
}
/*******************************************************************************
* intf_ClearXConsole: clear all lines in an X11 console (ok ?)
*******************************************************************************
* This function clears a X11 console, destroying all its text. The input
* line is not reset.
*******************************************************************************/
void intf_ClearXConsole( xconsole_t *p_console )
{
int i_index; /* all purposes index */
/* Clear all lines - once a line has been cleared, it's data pointer
* must be set to 0 to avoid clearing it again. */
for( i_index = 0; i_index < INTF_XCONSOLE_MAX_LINES; i_index++ )
{
if( p_console->psz_text[i_index] )
{
free( p_console->psz_text[i_index] );
p_console->psz_text[i_index] = 0;
}
}
/* Redraw the window */
RedrawXConsoleText( p_console );
XFlush( p_console->p_display );
}
/*******************************************************************************
* intf_PrintXConsole: print a message in a X11 console (ok ?)
*******************************************************************************
* This function print a message in an X11 console window. On error, it prints
* an error message and exit. The message is processed and copied and can be
* freed once the function has been called. During processing, the string can
* be splitted in several lines if '\n' are encountered or if a line is larger
* than INTF_XCONSOLE_MAX_LINE_WIDTH. A trailing '\n' will be ignored.
*******************************************************************************/
void intf_PrintXConsole( xconsole_t *p_console, char *psz_str )
{
char sz_line_buffer[INTF_XCONSOLE_MAX_LINE_WIDTH + 1]; /* buffer */
char * psz_index; /* string index */
int i_char_index; /* char index in line */
boolean_t b_eol; /* end of line flag */
/* Split the string in different lines. A line */
i_char_index = 0; /* character 0 */
b_eol = 0;
for( psz_index = psz_str; *psz_index; psz_index++ )
{
/* Check if we reached an end of line: if the current character is
* really an end of line or if the next one marks the end of the
* string. An end of line at then end of a string will be only
* processed once. */
if( (*psz_index == '\n') || ( psz_index[1] == '\0' ) )
{
b_eol = 1;
}
/* Else, the current character is added at the end of the line buffer */
{
sz_line_buffer[ i_char_index++ ] = *psz_index;
/* If we reached the maximal size for the line buffer, we also need
* to treat the end of line */
if( i_char_index == INTF_XCONSOLE_MAX_LINE_WIDTH )
{
b_eol = 1;
}
}
/* Check if an end of line has been detected */
if( b_eol )
{
/* Add a '\0' character at the end of the line buffer - note that
* i_char_index is now the line size + 1. */
sz_line_buffer[ i_char_index++ ] = '\0';
/* Increase line index */
if( p_console->i_text_index++ /* loop */
== INTF_XCONSOLE_MAX_LINES )
{
p_console->i_text_index = 0;
}
/* If there was a line in the current location, it needs to be
* erased. It will disappear from the console messages history. */
if( p_console->psz_text[ p_console->i_text_index] )
{
free( p_console->psz_text[ p_console->i_text_index] );
}
/* Allocate memory in lines array, and copy string - a memcpy is used
* since the size of the string is already known. On error during the
* allocation (ENOMEM), the line is set as blank and an error message
* is issued. */
p_console->psz_text[ p_console->i_text_index ]
= (char *) malloc( sizeof(char) * i_char_index );
if( !p_console->psz_text[ p_console->i_text_index] ) /* error */
{
intf_ErrMsg("intf error: can't copy `%s' (%s)\n",
sz_line_buffer, strerror(ENOMEM) );
p_console->psz_text[ p_console->i_text_index] = 0;
}
else /* success */
{
memcpy( p_console->psz_text[ p_console->i_text_index ],
sz_line_buffer, i_char_index );
}
/* Reset end of line indicator and char index */
b_eol = 0;
i_char_index = 0;
}
}
/* Display lines */
/* ?? now: redraw... would be better to scroll and draw only the good one */
RedrawXConsoleText( p_console );
XFlush( p_console->p_display );
}
/* following functions are local */
/*******************************************************************************
* RegisterXConsoleHistory: send current edit line to history (ok ?)
*******************************************************************************
* This function add a '\0' termination character at the end of the editing
* buffer, and copy it to the actual history base. If there is already a
* command registered at this place, it is removed.
* Note that the base index isn't updated.
* If there is not enough memory to allocate history record, the previous
* record is still cleared, and the new one is left blank. Note that this will
* probably cause problems when the history will be browsed, since the line
* won't be able to be recovered.
*******************************************************************************/
static void RegisterXConsoleHistory( xconsole_t *p_console )
{
/* Add a null character to mark the end of the edit line */
p_console->sz_edit[p_console->i_edit_size] = '\0';
/* Free current history record if required */
if( p_console->psz_history[p_console->i_history_base] )
{
free( p_console->psz_history[p_console->i_history_base] );
}
/* Allocate memory */
p_console->psz_history[p_console->i_history_base]
= (char *) malloc( sizeof(char) * ( p_console->i_edit_size + 1 ) );
/* On error, an error message is issued and the line is left blank */
if( !p_console->psz_history[p_console->i_history_base] ) /* error */
{
intf_ErrMsg("intf error: can't register `%s' in history\n", p_console->sz_edit );
p_console->psz_history[p_console->i_history_base] = 0;
}
/* If the allocation succeeded, the line is copied. Memcpy is used rather than
* strcpy because the line size is already known. */
else
{
memcpy( p_console->psz_history[p_console->i_history_base],
p_console->sz_edit, p_console->i_edit_size + 1 );
}
}
/*******************************************************************************
* RecallXConsoleHistory: copy an historic record to edit line (ok ?)
*******************************************************************************
* This function copy an historic record to edit line and update historic
* index.
*******************************************************************************/
static void RecallXConsoleHistory( xconsole_t *p_console, int i_index )
{
/* Calculate line size and copy it to edit line */
for( p_console->i_edit_size = 0;
p_console->psz_history[i_index][p_console->i_edit_size];
p_console->i_edit_size++ )
{
p_console->sz_edit[p_console->i_edit_size] = p_console->psz_history[i_index][p_console->i_edit_size];
}
/* Update indexes */
p_console->i_history_index = i_index;
p_console->i_edit_index = p_console->i_edit_size;
}
/*******************************************************************************
* CreateXConsoleWindow: open and set-up X11 console window (ok ?)
*******************************************************************************
* This function tries to create and set up a console window. This window is
* resizeable.
*******************************************************************************/
static int CreateXConsoleWindow( xconsole_t *p_console )
{
XSizeHints xsize_hints;
XSetWindowAttributes xwindow_attributes;
XGCValues xgcvalues;
int i_dummy; /* dummy for geometry */
/* Load first (edit) font - some of its properties are required to adapt
* window properties */
if( XTryLoadFont( p_console->p_display, INTF_XCONSOLE_FONT, &p_console->p_font ) )
{
return( 1 );
}
/* Set size related console properties */
p_console->i_edit_height = p_console->p_font->ascent + p_console->p_font->descent + 5;
p_console->i_edit_offset = p_console->p_font->descent + 2;
p_console->i_text_offset = p_console->i_edit_height + p_console->p_font->descent;
p_console->i_text_line_height = p_console->p_font->ascent + p_console->p_font->descent;
/* Read window geometry and prepare size hints */
XParseGeometry( p_console->psz_geometry,
&i_dummy, &i_dummy, &p_console->i_width, &p_console->i_height );
xsize_hints.base_width = p_console->i_height;
xsize_hints.base_height = p_console->i_width;
xsize_hints.min_width = p_console->i_text_line_height;
xsize_hints.min_height = p_console->i_text_line_height;
xsize_hints.flags = PSize | PMinSize;
/* Prepare the window attributes */
xwindow_attributes.backing_store = Always;
xwindow_attributes.background_pixel = WhitePixel( p_console->p_display, p_console->i_screen );
xwindow_attributes.event_mask = KeyPressMask | StructureNotifyMask;
/* Create the window */
p_console->window = XCreateWindow( p_console->p_display,
DefaultRootWindow( p_console->p_display ),
0, 0, p_console->i_width, p_console->i_height, 0,
CopyFromParent, InputOutput, CopyFromParent,
CWBackingStore | CWBackPixel | CWEventMask,
&xwindow_attributes );
XSetWMNormalHints( p_console->p_display, p_console->window, &xsize_hints );
XStoreName(p_console->p_display, p_console->window, INTF_XCONSOLE_TITLE);
/* Creation of a graphic contexts */
xgcvalues.background = WhitePixel( p_console->p_display, p_console->i_screen );
xgcvalues.foreground = BlackPixel( p_console->p_display, p_console->i_screen );
p_console->default_gc = XCreateGC( p_console->p_display, p_console->window,
GCForeground | GCBackground,
&xgcvalues);
/* ?? pixmap is always freed, etc... -> to be fixed ! */
#ifdef INTF_XCONSOLE_BACKGROUND_PIXMAP
/* Load background pixmap */
if( XpmReadFileToPixmap( p_console->p_display, /* error */
p_console->window, INTF_XCONSOLE_BACKGROUND_PIXMAP,
&p_console->background_pixmap, NULL, NULL) )
{
intf_ErrMsg("intf error: can't load background pixmap `%s'\n",
INTF_XCONSOLE_BACKGROUND_PIXMAP );
}
else /* success */
{
/* Set window background */
XSetWindowBackgroundPixmap(p_console->p_display, p_console->window,
p_console->background_pixmap );
}
#endif
/* Map the window */
XMapWindow( p_console->p_display, p_console->window ); /* map */
XFlush( p_console->p_display );
return( 0 );
}
/*******************************************************************************
* DestroyXConsoleWindow: destroy console window (ok ?)
*******************************************************************************
* Destroy a console window opened by CreateXConsoleWindow.
*******************************************************************************/
static void DestroyXConsoleWindow( xconsole_t *p_console )
{
/* Unmap window */
XUnmapWindow( p_console->p_display, p_console->window );
/* Destroy graphic contexts */
XFreeGC( p_console->p_display, p_console->default_gc );
/* Free pixmaps */
XFreePixmap( p_console->p_display, p_console->background_pixmap );
/* Free font */
XFreeFont( p_console->p_display, p_console->p_font );
/* Destroy window */
XDestroyWindow( p_console->p_display, p_console->window );
}
/*******************************************************************************
* PrintXConsoleLine: print a message in console (ok ?)
*******************************************************************************
* Print a message in console. Line 0 is just above the edit line, and line
* number increase while going up. The string is scanned for control
* characters.
*******************************************************************************/
static void PrintXConsoleLine( xconsole_t *p_console, int i_line, char *psz_str )
{
XTextItem textitem[INTF_XCONSOLE_MAX_LINE_WIDTH]; /* text */
int i_nb_textitems; /* total number of textitems */
int i_x; /* horizontal position */
int i_y; /* base vertical position */
/* If string is a null pointer, return */
if( !psz_str )
{
return;
}
/* Prepare array of textitems */
for( i_nb_textitems = 0;
*psz_str && (i_nb_textitems < INTF_XCONSOLE_MAX_LINE_WIDTH);
i_nb_textitems++ )
{
/* Check if first character is a control character - if a control
* character has been successfully processed, process next one */
while( *psz_str == '\033' )
{
psz_str++;
switch( *psz_str )
{
case 'g': /* bell */
/* ?? ring bell */
psz_str++;
break;
case '\0': /* error: end of string */
/* Print error message */
intf_ErrMsg("intf error: unauthorized control character `\\0'\n");
break;
default: /* error: unknown control character */
/* Print error message */
intf_ErrMsg("intf error: unknown control character `%c'\n", *psz_str );
break;
}
}
/* Prepare textitem */
textitem[i_nb_textitems].chars = psz_str;
textitem[i_nb_textitems].nchars = 0;
textitem[i_nb_textitems].delta = 0;
textitem[i_nb_textitems].font = p_console->p_font->fid;
/* Reach next control character or end of string */
do
{
psz_str++;
textitem[i_nb_textitems].nchars++;
}while( *psz_str && (*psz_str != '\033') );
}
/* Calulcate base position */
i_x = 0;
i_y = p_console->i_height - p_console->i_text_offset - i_line * p_console->i_text_line_height;
/* Print text */
XDrawText( p_console->p_display, p_console->window, p_console->default_gc, i_x, i_y,
textitem, i_nb_textitems );
}
/*******************************************************************************
* RedrawXConsoleEdit: redraw console edit zone (ok ?)
*******************************************************************************
* This function redraw just the edit zone of the console. It has to be called
* when the window is resized.
*******************************************************************************/
static void RedrawXConsoleEdit( xconsole_t *p_console )
{
XTextItem textitem; /* text */
int i_x; /* cursor position */
/* Clear window edit zone */
XClearArea( p_console->p_display, p_console->window, 0,
p_console->i_height - p_console->i_edit_height,
p_console->i_width, p_console->i_edit_height, False );
/* Draw separation line */
XDrawLine( p_console->p_display, p_console->window, p_console->default_gc,
0, p_console->i_height - p_console->i_edit_height,
p_console->i_width, p_console->i_height - p_console->i_edit_height );
/* Prepare text to be printed */
textitem.chars = p_console->sz_edit;
textitem.nchars = p_console->i_edit_size;
textitem.delta = 0;
textitem.font = p_console->p_font->fid;
/* Print text */
XDrawText( p_console->p_display, p_console->window, p_console->default_gc,
0, p_console->i_height - p_console->i_edit_offset,
&textitem, 1 );
/* Get cursor position */
i_x = XTextWidth( p_console->p_font, p_console->sz_edit, p_console->i_edit_index );
/* Print cursor. Cursor is placed at the beginning of the edited character,
* and it's size is calculated from maximal character size in the font. */
XDrawLine( p_console->p_display, p_console->window, p_console->default_gc,
i_x, p_console->i_height - p_console->i_edit_offset - p_console->p_font->ascent,
i_x, p_console->i_height - p_console->i_edit_offset + p_console->p_font->descent );
}
/*******************************************************************************
* RedrawXConsoleText: redraw console text zone (ok ?)
*******************************************************************************
* This function redraw all lines in the console. It has to be called when
* the window is resized.
*******************************************************************************/
static void RedrawXConsoleText( xconsole_t *p_console )
{
int i_line; /* current line */
int i_index; /* multi-purposes index */
int i_maxline; /* maximum line number */
/* Clear window text zone */
XClearArea( p_console->p_display, p_console->window, 0, 0, p_console->i_width,
p_console->i_height - p_console->i_edit_height, False );
/* Get maximum line number from window height */
i_maxline = (p_console->i_height - p_console->i_text_offset)
/ p_console->i_text_line_height;
/* Re-print messages zone: start from first message, line 0 and print
* messages until top of window is reached or all lines have been printed,
* which happens when i_index is the start index again */
i_line = 0;
i_index = p_console->i_text_index;
do
{
/* Print line */
PrintXConsoleLine( p_console, i_line, p_console->psz_text[i_index] );
/* Decrease i_index. Note that lines must be printed in reverse order
* since they are added in order. */
if( !i_index-- ) /* loop */
{
i_index = INTF_XCONSOLE_MAX_LINES - 1;
}
}
while( (i_line++ < i_maxline) && (i_index != p_console->i_text_index) );
}
......@@ -8,6 +8,10 @@
/*******************************************************************************
* Preamble
*******************************************************************************/
#include "vlc.h"
/*#include <errno.h>
#include <pthread.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
......@@ -23,13 +27,15 @@
#include "vlc_thread.h"
#include "intf_msg.h"
#include "debug.h" /* ?? temporaire, requis par netlist.h */
#include "debug.h"
#include "input.h"
#include "input_netlist.h"
#include "decoder_fifo.h"
#include "video.h"
#include "video_output.h"
#include "video_decoder.h"*/
#include "vdec_idct.h"
#include "video_decoder.h"
......
/*******************************************************************************
* vout_x11.c: X11 video output display method
* (c)1998 VideoLAN
*******************************************************************************
* The X11 method for video output thread. It's properties (and the vout_x11_t
* type) are defined in vout.h. The functions declared here should not be
* needed by any other module than vout.c.
*******************************************************************************/
/*******************************************************************************
* Preamble
*******************************************************************************/
#include "vlc.h"
/*
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/shm.h>
#include <sys/soundcard.h>
#include <sys/uio.h>
#include "config.h"
#include "common.h"
#include "mtime.h"
#include "vlc_thread.h"
#include "xutils.h"
#include "input.h"
#include "input_vlan.h"
#include "audio_output.h"
#include "video.h"
#include "video_output.h"
#include "video_sys.h"
#include "xconsole.h"
#include "interface.h"
#include "intf_msg.h"
*/
/*******************************************************************************
* vout_sys_t: video output framebuffer method descriptor
*******************************************************************************
* This structure is part of the video output thread descriptor.
* It describes the FB specific properties of an output thread. FB video
* output is performed through regular resizable windows. Windows can be
* dynamically resized to adapt to the size of the streams.
*******************************************************************************/
typedef struct vout_sys_s
{
int i_dummy;
} vout_sys_t;
/*******************************************************************************
* Local prototypes
*******************************************************************************/
/*******************************************************************************
* vout_SysCreate: allocate X11 video thread output method
*******************************************************************************
* This function allocate and initialize a X11 vout method.
*******************************************************************************/
int vout_SysCreate( vout_thread_t *p_vout )
{
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
if( p_vout->p_sys != NULL )
{
//??
return( 0 );
}
return( 1 );
}
/*******************************************************************************
* vout_SysInit: initialize Sys video thread output method
*******************************************************************************
* This function create a Sys window according to the user configuration.
*******************************************************************************/
int vout_SysInit( vout_thread_t *p_vout )
{
//??
intf_DbgMsg("%p -> success, depth=%d bpp",
p_vout, p_vout->i_screen_depth );
return( 0 );
}
/*******************************************************************************
* vout_SysEnd: terminate Sys video thread output method
*******************************************************************************
* Terminate an output method created by vout_SysCreateOutputMethod
*******************************************************************************/
void vout_SysEnd( vout_thread_t *p_vout )
{
intf_DbgMsg("%p\n", p_vout );
//??
}
/*******************************************************************************
* vout_SysDestroy: destroy Sys video thread output method
*******************************************************************************
* Terminate an output method created by vout_SysCreateOutputMethod
*******************************************************************************/
void vout_SysDestroy( vout_thread_t *p_vout )
{
//??
free( p_vout->p_sys );
}
/*******************************************************************************
* vout_SysManage: handle Sys events
*******************************************************************************
* This function should be called regularly by video output thread. It manages
* Sys events and allows window resizing. It returns a negative value if
* something happened which does not allow the thread to continue, and a
* positive one if the thread can go on, but the images have been modified and
* therefore it is useless to display them.
*******************************************************************************
* Messages type: vout, major code: 103
*******************************************************************************/
int vout_SysManage( vout_thread_t *p_vout )
{
//??
return( 0 );
}
/*******************************************************************************
* vout_SysDisplay: displays previously rendered output
*******************************************************************************
* This function send the currently rendered image to Sys server, wait until
* it is displayed and switch the two rendering buffer, preparing next frame.
*******************************************************************************/
void vout_SysDisplay( vout_thread_t *p_vout )
{
//??
/* Swap buffers */
//?? p_vout->p_sys->i_buffer_index = ++p_vout->p_sys->i_buffer_index & 1;
}
/*******************************************************************************
* video_graphics.c: pictures manipulation functions
* (c)1999 VideoLAN
*******************************************************************************
* Includes function to compose, convert and display pictures, and also basic
* functions to copy/convert pictures data or descriptors and read pictures
* from a file.
*******************************************************************************/
/*******************************************************************************
* Preamble
*******************************************************************************/
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include "common.h"
#include "config.h"
#include "mtime.h"
#include "video.h"
#include "video_graphics.h"
#include "intf_msg.h"
/*
* Local prototypes
*/
static int ReadPictureConfiguration ( int i_file, video_cfg_t *p_cfg );
/*******************************************************************************
* video_CreatePicture: create an empty picture
*******************************************************************************
* This function create an empty image. A null pointer is returned if the
* function fails.
* Following configuration properties are used:
* VIDEO_CFG_WIDTH picture width (required)
* VIDEO_CFG_HEIGHT picture height (required)
* VIDEO_CFG_TYPE picture type (required)
* VIDEO_CFG_FLAGS flags
* VIDEO_CFG_BPP padded bpp (required for pixel pictures)
* VIDEO_CFG_POSITION position in output window
* VIDEO_CFG_ALIGN base position in output window
* VIDEO_CFG_RATIO display ratio
* VIDEO_CFG_LEVEL overlay hierarchical level
* VIDEO_CFG_REFCOUNT links reference counter
* VIDEO_CFG_STREAM video stream id
* VIDEO_CFG_DATE display date
* VIDEO_CFG_DURATION duration for overlay pictures
* VIDEO_CFG_PIXEL pixel value for mask pictures
* VIDEO_CFG_DATA picture data (required if not owner and non blank)
*******************************************************************************/
picture_t *video_CreatePicture( video_cfg_t *p_cfg )
{
picture_t *p_newpic; /* new picture descriptor */
#ifdef DEBUG
/* Check base configuration */
if( (p_cfg->i_properties & (VIDEO_CFG_WIDTH | VIDEO_CFG_HEIGHT | VIDEO_CFG_TYPE))
!= (VIDEO_CFG_WIDTH | VIDEO_CFG_HEIGHT | VIDEO_CFG_TYPE) )
{
intf_DbgMsg("invalid picture configuration\n");
return( NULL );
}
/* Check flags validity */
if( (p_cfg->i_properties & VIDEO_CFG_FLAGS)
&& (p_cfg->i_flags & ( RESERVED_PICTURE | DISPLAYED_PICTURE
| DISPLAY_PICTURE | DESTROY_PICTURE )) )
{
intf_DbgMsg("invalid picture flags\n");
return( NULL );
}
#endif
/* Allocate descriptor */
p_newpic = malloc( sizeof(picture_t) );
if( !p_newpic ) /* error: malloc() failed */
{
return( NULL );
}
/* Create picture */
if( video_CreatePictureBody( p_newpic, p_cfg ) ) /* error */
{
free( p_newpic );
return( NULL );
}
/* Log and return */
#ifdef VOUT_DEBUG /* ?? -> video_debug ? */
video_PrintPicture( p_newpic, "video: created picture " );
#else
intf_DbgMsg("created picture %dx%d at %p\n", p_newpic->i_width, p_newpic->i_height, p_newpic);
#endif
return( p_newpic );
}
/*******************************************************************************
* video_CopyPicture: create a copy of a picture
*******************************************************************************
* This function creates a copy of a picture. It returns NULL on error.
*******************************************************************************
* Messages type: video, major code: 102
*******************************************************************************/
picture_t * video_CopyPicture( picture_t *p_pic )
{
picture_t * p_newpic; /* new picture descriptor */
p_newpic = malloc( sizeof(picture_t) );
if( p_newpic != NULL )
{
video_CopyPictureDescriptor( p_newpic, p_pic );
/* If source picture owns its data, make a copy */
if( p_pic->i_flags & OWNER_PICTURE )
{
p_newpic->p_data = malloc( p_pic->i_height * p_pic->i_bytes_per_line );
if( p_newpic->p_data == NULL ) /* error */
{
free( p_newpic );
return( NULL );
}
memcpy( p_newpic->p_data, p_pic->p_data,
p_pic->i_height * p_pic->i_bytes_per_line );
}
/* If source picture does not owns its data, copy the reference */
else
{
p_newpic->p_data = p_pic->p_data;
}
}
return( p_newpic );
}
/*******************************************************************************
* video_ReplicatePicture: creates a replica of a picture
*******************************************************************************
* This function creates a replica of the original picture. It returns NULL on
* error.
*******************************************************************************
* Messages type: video, major code: 103
*******************************************************************************/
picture_t * video_ReplicatePicture( picture_t *p_pic )
{
picture_t * p_newpic; /* new picture descrpitor */
p_newpic = malloc( sizeof(picture_t) );
if( p_newpic != NULL )
{
video_CopyPictureDescriptor( p_newpic, p_pic );
p_newpic->i_flags &= ~OWNER_PICTURE;
p_newpic->p_data = p_pic->p_data;
}
return( p_newpic );
}
/*******************************************************************************
* video_DestroyPicture: destroys a picture
*******************************************************************************
* This function destroy a picture created with any of the video_*Picture
* functions.
*******************************************************************************
* Messages type: video, major code: 104
*******************************************************************************/
void video_DestroyPicture( picture_t *p_pic )
{
intf_DbgMsg("video debug 104-1: destroying picture %p\n", p_pic );
/* Destroy data if picture owns it */
if( p_pic->i_flags & OWNER_PICTURE )
{
free( p_pic->p_data );
}
/* Destroy descriptor */
free( p_pic );
}
/*******************************************************************************
* video_ClearPicture: clear a picture
*******************************************************************************
* Set all pixel to 0 (black).
*******************************************************************************
* Messages type: video, major code: 105
*******************************************************************************/
void video_ClearPicture( picture_t *p_pic )
{
switch( p_pic->i_type )
{
case RGB_BLANK_PICTURE:
case PIXEL_BLANK_PICTURE:
/* Blank pictures will have their pixel value set to 0 */
p_pic->pixel = 0;
break;
default:
/* All pictures types except blank ones have a meaningfull i_bytes_per_line
* field, and blank ones don't need to be cleared. */
memset( p_pic->p_data, 0, p_pic->i_height * p_pic->i_bytes_per_line );
break;
}
}
/*******************************************************************************
* video_DrawPixel: set a pixel in a picture
*******************************************************************************
* This function set a pixel's value in an picture. It is an easy, but slow way
* to render an image, and should be avoided. Exact meaning of value depends of
* the picture type.
*******************************************************************************
* Messages type: video, major code: 106
*******************************************************************************/
void video_DrawPixel( picture_t *p_pic, int i_x, int i_y, pixel_t value )
{
switch( p_pic->i_type )
{
case RGB_PICTURE: /* 24 bits encoded RGB pictures */
p_pic->p_data[i_y * p_pic->i_bytes_per_line + i_x * 3 ] = RGBVALUE2RED( value );
p_pic->p_data[i_y * p_pic->i_bytes_per_line + i_x * 3 + 1] = RGBVALUE2GREEN( value );
p_pic->p_data[i_y * p_pic->i_bytes_per_line + i_x * 3 + 2] = RGBVALUE2BLUE( value );
break;
case PIXEL_PICTURE: /* pixel encoded pictures */
/* ?? */
break;
case RGB_MASK_PICTURE: /* 1 bpp rgb mask pictures */
case PIXEL_MASK_PICTURE: /* 1 bpp pixel mask pictures */
/* ?? */
break;
#ifdef DEBUG
default:
intf_DbgMsg("video debug 106-1: invalid picture %p type %d\n",
p_pic, p_pic->i_type);
break;
#endif
}
}
/*******************************************************************************
* video_DrawHLine: draw an horizontal line in a picture
*******************************************************************************
*
*******************************************************************************
* Messages type: video, major code: 107
*******************************************************************************/
void video_DrawHLine( picture_t *p_pic, int i_x, int i_y, int i_width, pixel_t value )
{
/* ?? */
}
/*******************************************************************************
* video_DrawVLine: draw a vertical line in a picture
*******************************************************************************
*
*******************************************************************************
* Messages type: video, major code: 108
*******************************************************************************/
void video_DrawVLine( picture_t *p_pic, int i_x, int i_y, int i_width, pixel_t value )
{
/* ?? */
}
/*******************************************************************************
* video_DrawLine: draw a line in a picture
*******************************************************************************
* video_DrawHLine() and video_DrawVLine() functions should be prefered if
* possible.
*******************************************************************************
* Messages type: video, major code: 109
*******************************************************************************/
void video_DrawLine( picture_t *p_pic, int i_x1, int i_y1, int i_x2, int i_y2, pixel_t value )
{
/* ?? */
}
/*******************************************************************************
* video_DrawBar: draw a bar in a picture
*******************************************************************************
* Draw a bar (filled rectangle) in a picture/
*******************************************************************************
* Messages type: video, major code: 110
*******************************************************************************/
void video_DrawBar( picture_t *p_pic, int i_x, int i_y, int i_width, int i_height,
pixel_t value )
{
/* ?? */
}
/*******************************************************************************
* video_DrawRectangle: draw a rectangle in a picture
*******************************************************************************
* Draw a rectangle (empty) in an image
*******************************************************************************
* Messages type: video, major code: 111
*******************************************************************************/
void video_DrawRectangle( picture_t *p_pic, int i_x, int i_y,
int i_width, int i_height, pixel_t value )
{
/* ?? */
}
/*******************************************************************************
* video_DrawImage: insert a picture in another one
*******************************************************************************
* ??
*******************************************************************************
* Messages type: video, major code: 112
*******************************************************************************/
void video_DrawPicture( picture_t *p_pic, picture_t *p_insert, int i_x, int i_y )
{
/* ?? */
}
/*******************************************************************************
* video_DrawText: insert text in a picture
*******************************************************************************
* This function prints a simple text in an image. It does not support
* different fonts, or complex text settings, but is designed to provide a
* simple way to display messages, counters and indications.
*******************************************************************************
* Messages type: video, major code: 113
*******************************************************************************/
void video_DrawText( picture_t *p_picture, int i_x, int i_y, char *psz_text,
int i_size, pixel_t value )
{
/* ?? */
}
/*******************************************************************************
* video_CopyPictureDescriptor: copy a picture descriptor
*******************************************************************************
* This function is used when a picture is added to the video heap. It does not
* copy the p_data field. Some post-treatment must obviously be done, especially
* concerning the OWNER_PICTURE flag, the i_refcount and p_data fields.
* Although it is exported, since it is used in several of the vout_* modules,
* it should not be used directly outside the video output module.
*******************************************************************************
* Messages type: video, major code 114
*******************************************************************************/
void video_CopyPictureDescriptor( picture_t *p_dest, picture_t *p_src )
{
p_dest->i_type = p_src->i_type;
p_dest->i_flags = p_src->i_flags;
p_dest->i_width = p_src->i_width;
p_dest->i_height = p_src->i_height;
p_dest->i_bpp = p_src->i_bpp;
p_dest->i_bytes_per_line = p_src->i_bytes_per_line;
p_dest->i_x = p_src->i_x;
p_dest->i_y = p_src->i_y;
p_dest->i_h_align = p_src->i_h_align;
p_dest->i_v_align = p_src->i_v_align;
p_dest->i_h_ratio = p_src->i_h_ratio;
p_dest->i_v_ratio = p_src->i_v_ratio;
p_dest->i_level = p_src->i_level;
p_dest->i_refcount = p_src->i_refcount;
p_dest->i_stream = p_src->i_stream;
p_dest->date = p_src->date;
p_dest->duration = p_src->duration;
p_dest->pixel = p_src->pixel;
}
/*******************************************************************************
* video_CreatePictureBody: create a picture in an descriptor
*******************************************************************************
* This function is used vy vout_CreateReservedPicture and vout_CreatePicture.
* It should not be called directly outside the video output module.
* It returns non 0 if the creation failed.
*******************************************************************************
* Messages type: video, major code 115
*******************************************************************************/
int video_CreatePictureBody( picture_t *p_pic, video_cfg_t *p_cfg )
{
#ifdef DEBUG
/* Check base configuration */
if( (p_cfg->i_properties & (VIDEO_CFG_WIDTH | VIDEO_CFG_HEIGHT | VIDEO_CFG_TYPE))
!= (VIDEO_CFG_WIDTH | VIDEO_CFG_HEIGHT | VIDEO_CFG_TYPE) )
{
intf_DbgMsg("video debug 115-1: invalid picture configuration\n");
return( 1 );
}
/* Check flags validity */
if( (p_cfg->i_properties & VIDEO_CFG_FLAGS)
&& (p_cfg->i_flags & ( RESERVED_PICTURE | DISPLAYED_PICTURE
| DISPLAY_PICTURE | DESTROY_PICTURE )) )
{
intf_DbgMsg("video debug 115-2: invalid picture flags\n");
return( 1 );
}
#endif
/* Initialize types, flags and dimensions */
p_pic->i_type = p_cfg->i_type;
p_pic->i_flags = ( p_cfg->i_properties & VIDEO_CFG_FLAGS ) ? p_cfg->i_flags : 0;
p_pic->i_width = p_cfg->i_width;
p_pic->i_height = p_cfg->i_height;
/* Initialize other pictures properties */
if( p_cfg->i_properties & VIDEO_CFG_POSITION )
{
p_pic->i_x = p_cfg->i_x;
p_pic->i_y = p_cfg->i_y;
}
else
{
p_pic->i_x = 0;
p_pic->i_y = 0;
}
if( p_cfg->i_properties & VIDEO_CFG_ALIGN )
{
p_pic->i_h_align = p_cfg->i_h_align;
p_pic->i_v_align = p_cfg->i_v_align;
}
else
{
p_pic->i_h_align = ALIGN_H_DEFAULT;
p_pic->i_v_align = ALIGN_V_DEFAULT;
}
if( p_cfg->i_properties & VIDEO_CFG_RATIO )
{
p_pic->i_h_ratio = p_cfg->i_h_ratio;
p_pic->i_v_ratio = p_cfg->i_v_ratio;
}
else
{
p_pic->i_h_ratio = DISPLAY_RATIO_NORMAL;
p_pic->i_v_ratio = DISPLAY_RATIO_NORMAL;
}
p_pic->i_level = ( p_cfg->i_properties & VIDEO_CFG_LEVEL )
? p_cfg->i_level : ( (p_pic->i_flags & OVERLAY_PICTURE) ? 1 : 0 );
p_pic->i_refcount = ( p_cfg->i_properties & VIDEO_CFG_REFCOUNT ) ? p_cfg->i_refcount : 0;
p_pic->i_stream = ( p_cfg->i_properties & VIDEO_CFG_STREAM ) ? p_cfg->i_stream : 0;
p_pic->date = ( p_cfg->i_properties & VIDEO_CFG_DATE ) ? p_cfg->date : 0;
p_pic->duration = ( p_cfg->i_properties & VIDEO_CFG_DURATION ) ? p_cfg->duration : 0;
/* Initialize type-dependant properties */
switch( p_pic->i_type )
{
case RGB_BLANK_PICTURE: /* rgb blank picture */
case PIXEL_BLANK_PICTURE: /* pixel blank picture */
#ifdef DEBUG
/* Check validity: blank pictures can't be transparent or owner */
if( p_pic->i_flags & ( OWNER_PICTURE | TRANSPARENT_PICTURE ) )
{
intf_DbgMsg("video debug 115-3: invalid blank picture flags\n");
return( 1 );
}
/* Set to 0 unused fields */
p_pic->i_bpp = 0;
p_pic->i_bytes_per_line = 0;
p_pic->p_data = NULL;
#endif
/* Set color */
p_pic->pixel = ( p_cfg->i_properties & VIDEO_CFG_PIXEL ) ? p_cfg->pixel : 0;
break;
case RGB_PICTURE: /* 24 bpp RGB */
#ifdef DEBUG
/* Set to 0 unused fields */
p_pic->pixel = 0;
#endif
/* Set fields */
p_pic->i_bpp = 24;
p_pic->i_bytes_per_line = PAD( p_pic->i_width * 3, sizeof(int) );
break;
case PIXEL_PICTURE: /* pixel encoded picture */
#ifdef DEBUG
/* Check validity: pixel pictures must have the bpp property defined,
* and it must be a multiple of 8 */
if( ! (p_cfg->i_properties & VIDEO_CFG_BPP) )
{
intf_DbgMsg("video debug 115-4: missing bpp for pixel picture\n");
return( 1 );
}
else if( p_cfg->i_bpp % 8 )
{
intf_DbgMsg("video debug 115-5: invalid bpp for pixel picture\n");
return( 1 );
}
/* Set to 0 unused fields */
p_pic->pixel = 0;
#endif
/* Set fields */
p_pic->i_bpp = p_cfg->i_bpp;
p_pic->i_bytes_per_line = PAD( p_pic->i_width * (p_cfg->i_bpp / 8), sizeof(int) );
break;
case RGB_MASK_PICTURE: /* 1 bpp rgb mask */
case PIXEL_MASK_PICTURE: /* 1 bpp pixel mask */
/* Set fields */
p_pic->i_bpp = 1;
p_pic->i_bytes_per_line = PAD( p_pic->i_width / 8, sizeof(int) );
p_pic->pixel = ( p_cfg->i_properties & VIDEO_CFG_PIXEL ) ? p_cfg->pixel : 0;
break;
#ifdef DEBUG
default: /* error: unknown picture type */
intf_DbgMsg("video debug 115-6: unknown picture type\n");
return( 1 );
break;
#endif
}
/* If picture is not blank, the p_data has some meaning */
if( (p_pic->i_type != RGB_BLANK_PICTURE)
&& (p_pic->i_type != PIXEL_BLANK_PICTURE) )
{
/* If picture owns its data, allocate p_data */
if( p_pic->i_flags & OWNER_PICTURE )
{
p_pic->p_data = malloc( p_pic->i_height * p_pic->i_bytes_per_line );
if( p_pic->p_data == NULL ) /* error */
{
return( 1 );
}
}
/* If picture is a reference, copy pointer */
else
{
#ifdef DEBUG
/* Check configuration */
if( !(p_cfg->i_properties & VIDEO_CFG_DATA) )
{
intf_DbgMsg("video debug 115-7: missing picture data\n");
return( 1 );
}
#endif
p_pic->p_data = p_cfg->p_data;
}
}
return( 0 );
}
/*******************************************************************************
* video_ReadPicture: read a picture from a file
*******************************************************************************
* This function reads a picture from an openned file. The picture must be
* stored in native format, ie: header, according to ReadPictureConfiguration
* function specifications, then raw data.
*******************************************************************************
* Messages type: video, major code 116
*******************************************************************************/
picture_t * video_ReadPicture( int i_file )
{
video_cfg_t p_cfg; /* new picture configuration */
picture_t * p_newpic; /* new picture descriptor */
/* Read picture configuration */
if( ReadPictureConfiguration( i_file, &p_cfg ) )
{
return( NULL );
}
/* Create picture and allocate data */
p_newpic = video_CreatePicture( &p_cfg );
if( p_newpic == NULL )
{
return( NULL );
}
/* Read data if required */
if( (p_newpic->i_type != RGB_BLANK_PICTURE) && (p_newpic->i_type != RGB_BLANK_PICTURE) )
{
if( read( i_file, p_newpic->p_data, p_newpic->i_height * p_newpic->i_bytes_per_line )
!= p_newpic->i_height * p_newpic->i_bytes_per_line )
{
intf_ErrMsg("video error 116-2: %s\n", strerror(errno));
video_DestroyPicture( p_newpic );
return( NULL );
}
}
/* Log and return */
#ifdef VOUT_DEBUG /* ?? -> video_debug ? */
video_PrintPicture( p_newpic, "video debug 116-1: read picture " );
#endif
return( p_newpic );
}
/* following functions are debugging functions */
/*******************************************************************************
* video_PrintPicture: display picture state (debugging function)
*******************************************************************************
* This function, which is only defined if DEBUG is defined, can be used for
* debugging purposes. It prints on debug stream the main characteristics of
* a picture. The second parameter is printed in front of data. Note that no
* header is printed by default.
*******************************************************************************
* Messages type: video, major code 141
*******************************************************************************/
#ifdef DEBUG
void video_PrintPicture( picture_t *p_pic, char *psz_str )
{
char * psz_type; /* type string */
char sz_flags[9]; /* flags string */
char sz_date[MSTRTIME_MAX_SIZE]; /* date buffer */
char sz_duration[MSTRTIME_MAX_SIZE]; /* duration buffer */
/* Non empty picture */
if( p_pic->i_type != EMPTY_PICTURE )
{
/* Build picture type information string */
switch( p_pic->i_type )
{
case RGB_BLANK_PICTURE:
psz_type = "rgb-blank";
break;
case PIXEL_BLANK_PICTURE:
psz_type = "pixel-blank";
break;
case RGB_PICTURE:
psz_type = "rgb";
break;
case PIXEL_PICTURE:
psz_type = "pixel";
break;
case RGB_MASK_PICTURE:
psz_type = "rgb mask";
break;
case PIXEL_MASK_PICTURE:
psz_type = "pixel mask";
break;
default:
psz_type = "?";
break;
}
/* Build flags information strings */
sz_flags[0] = ( p_pic->i_flags & RESERVED_PICTURE ) ? 'r' : '-';
sz_flags[1] = ( p_pic->i_flags & PERMANENT_PICTURE ) ? 'p' : '-';
sz_flags[2] = ( p_pic->i_flags & DISPLAYED_PICTURE ) ? 'D' : '-';
sz_flags[3] = ( p_pic->i_flags & OWNER_PICTURE ) ? 'O' : '-';
sz_flags[4] = ( p_pic->i_flags & DISPLAY_PICTURE ) ? 'd' : '-';
sz_flags[5] = ( p_pic->i_flags & DESTROY_PICTURE ) ? 'x' : '-';
sz_flags[6] = ( p_pic->i_flags & TRANSPARENT_PICTURE ) ? 't' : '-';
sz_flags[7] = ( p_pic->i_flags & OVERLAY_PICTURE ) ? 'o' : '-';
sz_flags[8] = '\0';
/* Print information strings */
intf_DbgMsg("%s%p: %s (%s) %dx%d-%d.%d s=%d rc=%d d=%s t=%s\n",
psz_str, p_pic,
psz_type, sz_flags,
p_pic->i_width, p_pic->i_height, p_pic->i_bpp, p_pic->i_bytes_per_line,
p_pic->i_stream,
p_pic->i_refcount,
mstrtime( sz_date, p_pic->date ), mstrtime( sz_duration, p_pic->duration) );
}
/* Empty picture */
else
{
intf_DbgMsg("%sempty\n", psz_str);
}
}
#endif
/* following functions are local */
/*******************************************************************************
* ReadPictureConfiguration: read a vout_cfg_t structure from a file
*******************************************************************************
* This function reads a picture configuration and properties from a file. Note
* that some fields of the vout_cft_t, which do not concern pictures, are
* ignored. Note that the file is in MSB (little-endian).
*******************************************************************************
* Messages type: video, major code 151
*******************************************************************************/
static int ReadPictureConfiguration( int i_file, video_cfg_t *p_cfg )
{
byte_t p_buffer[42]; /* buffer used to store the packed structure */
/* Read buffer */
if( read( i_file, p_buffer, 42 ) != 42 )
{
intf_ErrMsg("video error 151-1: %s\n", strerror(errno) );
return( errno );
}
/* Parse buffer */
p_cfg->i_properties = ntoh32( *(u32 *)( p_buffer ) );
p_cfg->i_type = *(u8 *)( p_buffer + 4 );
p_cfg->i_bpp= *(u8 *)( p_buffer + 5 );
p_cfg->i_width = ntoh16( *(u16 *)( p_buffer + 6 ) );
p_cfg->i_height = ntoh16( *(u16 *)( p_buffer + 8 ) );
p_cfg->i_flags = ntoh16( *(u16 *)( p_buffer + 10 ) );
p_cfg->i_x = ntoh16( *(s16 *)( p_buffer + 12 ) );
p_cfg->i_y = ntoh16( *(s16 *)( p_buffer + 14 ) );
p_cfg->i_h_align = *(s8 *)( p_buffer + 16 );
p_cfg->i_v_align = *(s8 *)( p_buffer + 17 );
p_cfg->i_h_ratio = *(s8 *)( p_buffer + 19 );
p_cfg->i_v_ratio = *(s8 *)( p_buffer + 19 );
p_cfg->i_level = *(s8 *)( p_buffer + 20 );
p_cfg->i_stream = *(u8 *)( p_buffer + 21 );
p_cfg->date = ntoh64( *(u64 *)( p_buffer + 22 ) );
p_cfg->duration = ntoh64( *(u64 *)( p_buffer + 30 ) );
p_cfg->pixel = ntoh32( *(u32 *)( p_buffer + 38 ) );
return( 0 );
}
......@@ -10,13 +10,13 @@
/*******************************************************************************
* Preamble
*******************************************************************************/
#include "vlc.h"
/*
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XShm.h>
#include "common.h"
#include "config.h"
......@@ -28,26 +28,17 @@
#include "video_graphics.h"
#include "video_output.h"
#include "video_x11.h"
#include "intf_msg.h"
*/
/*
* Local prototypes
*/
static int CheckConfiguration ( video_cfg_t *p_cfg );
static int InitThread ( vout_thread_t *p_vout );
static void RunThread ( vout_thread_t *p_vout );
static void ErrorThread ( vout_thread_t *p_vout );
static void EndThread ( vout_thread_t *p_vout );
static picture_t * FindPicture ( vout_thread_t *p_vout );
static void EmptyPicture ( vout_thread_t *p_vout, picture_t *p_pic );
static mtime_t FirstPass ( vout_thread_t *p_vout, mtime_t current_date );
static void SecondPass ( vout_thread_t *p_vout, mtime_t display_date );
static void SortPictures ( vout_thread_t *p_vout, picture_t **pp_picture );
static void RenderPicture ( vout_thread_t *p_vout, picture_t *p_pic );
static void ClipPicture ( int *pi_ofs, int i_size, int *pi_pic_ofs, int *pi_pic_size,
int i_ratio, int i_placement );
/*******************************************************************************
* vout_CreateThread: creates a new video output thread
......@@ -65,53 +56,53 @@ static void ClipPicture ( int *pi_ofs, int i_size, int *pi_pic_ofs,
* If pi_status is NULL, then the function will block until the thread is ready.
* If not, pi_error will be updated using one of the THREAD_* constants.
*******************************************************************************/
vout_thread_t *vout_CreateThread( video_cfg_t *p_cfg, int *pi_status )
vout_thread_t * vout_CreateThread (
#if defined(VIDEO_X11)
Display *p_display, Window root_window,
#elif defined(VIDEO_FB)
//??
#endif
int i_width, int i_height, int *pi_status
)
{
vout_thread_t * p_vout; /* thread descriptor */
int i_status; /* thread status */
/*
* Check configuration
*/
if( CheckConfiguration( p_cfg ) )
{
return( NULL );
}
/* Allocate descriptor and initialize flags */
/* Allocate descriptor and create method */
p_vout = (vout_thread_t *) malloc( sizeof(vout_thread_t) );
if( p_vout == NULL ) /* error */
{
return( NULL );
}
if( vout_X11AllocOutputMethod( p_vout, p_cfg ) )
intf_DbgMsg( "0x%x\n", p_vout );
if( vout_SysCreate( p_vout
#if defined(VIDEO_X11)
, p_display, root_window
#elif defined(VIDEO_FB)
//??
#endif
) )
{
free( p_vout );
return( NULL );
}
/* Copy configuration */
p_vout->i_max_pictures = p_cfg->i_size;
p_vout->i_width = p_cfg->i_width;
p_vout->i_height = p_cfg->i_height;
/* Set status */
/* Initialize */
p_vout->i_width = i_width;
p_vout->i_height = i_height;
p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status;
*p_vout->pi_status = THREAD_CREATE;
/* Initialize flags */
p_vout->b_die = 0;
p_vout->b_error = 0;
p_vout->b_active = 0;
/* Create thread and set locks */
vlc_mutex_init( &p_vout->streams_lock );
vlc_mutex_init( &p_vout->pictures_lock );
if( vlc_thread_create( &p_vout->thread_id, "video output", (vlc_thread_func)RunThread, (void *) p_vout) )
vlc_mutex_init( &p_vout->lock );
if( vlc_thread_create( &p_vout->thread_id, "video output",
(void *) RunThread, (void *) p_vout) )
{
intf_ErrMsg("vout error: %s\n", strerror(ENOMEM));
intf_DbgMsg("failed\n");
vout_X11FreeOutputMethod( p_vout );
vout_SysDestroy( p_vout );
free( p_vout );
return( NULL );
}
......@@ -126,12 +117,10 @@ vout_thread_t *vout_CreateThread( video_cfg_t *p_cfg, int *pi_status )
&& (i_status != THREAD_FATAL) );
if( i_status != THREAD_READY )
{
intf_DbgMsg("failed\n");
return( NULL );
}
}
intf_DbgMsg("succeeded -> %p\n", p_vout);
return( p_vout );
}
......@@ -147,6 +136,8 @@ void vout_DestroyThread( vout_thread_t *p_vout, int *pi_status )
{
int i_status; /* thread status */
intf_DbgMsg( "0x%x\n", p_vout );
/* Set status */
p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status;
*p_vout->pi_status = THREAD_DESTROY;
......@@ -163,355 +154,160 @@ void vout_DestroyThread( vout_thread_t *p_vout, int *pi_status )
}while( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
&& (i_status != THREAD_FATAL) );
}
intf_DbgMsg("%p -> succeeded\n", p_vout);
}
/*******************************************************************************
* vout_DisplayPicture: add a picture to a thread
* vout_DisplayPicture: display a picture
*******************************************************************************
* The picture will be placed in an empty place of the video heap of the thread.
* If this is impossible, NULL will be returned. Else, the original picture
* is destroyed.
* Remove the reservation flag of a picture, which will cause it to be ready for
* display.
*******************************************************************************/
picture_t * vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
picture_t * p_newpic; /* new picture index */
vlc_mutex_lock( &p_vout->lock );
p_newpic = FindPicture( p_vout );
if( p_newpic != NULL )
{
/* Copy picture information */
video_CopyPictureDescriptor( p_newpic, p_pic );
p_newpic->p_data = p_pic->p_data;
free( p_pic );
/* Remove reservation flag */
p_pic->i_status = READY_PICTURE;
/* Update heap size and stats */
p_vout->i_pictures++;
#ifdef STATS
/* Update stats */
p_vout->c_pictures++;
p_vout->p_stream[ p_newpic->i_stream ].c_pictures++;
#endif
}
/* Release lock and return */
vlc_mutex_unlock( &p_vout->pictures_lock );
return( p_newpic );
vlc_mutex_unlock( &p_vout->lock );
}
/*******************************************************************************
* vout_DisplayPictureCopy: copy a picture to a thread
* vout_CreatePicture: allocate a picture in the video output heap.
*******************************************************************************
* The picture will be copied in an empty place of the video heap of the thread.
* If this is impossible, NULL will be returned. The picture used is the copy
* of the picture passed as argument, which remains usable.
* The picture data are copied only if the original picture owns its own data.
* The link reference counter is set to 0.
* This function create a reserved image in the video output heap.
* A null pointer is returned if the function fails. This method provides an
* already allocated zone of memory in the picture data fields.
*******************************************************************************/
picture_t * vout_DisplayPictureCopy( vout_thread_t *p_vout, picture_t *p_pic )
picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
int i_width, int i_height, int i_bytes_per_line )
{
picture_t * p_newpic; /* new picture index */
int i_picture; /* picture index */
picture_t * p_free_picture = NULL; /* first free picture */
picture_t * p_destroyed_picture = NULL; /* first destroyed picture */
p_newpic = FindPicture( p_vout );
if( p_newpic != NULL )
{
/* Copy picture information */
video_CopyPictureDescriptor( p_newpic, p_pic );
/* Get lock */
vlc_mutex_lock( &p_vout->lock );
/* If source picture owns its data, make a copy */
if( p_pic->i_flags & OWNER_PICTURE )
/*
* Look for an empty place
*/
for( i_picture = 0;
i_picture < VOUT_MAX_PICTURES;
i_picture++ )
{
p_newpic->p_data = malloc( p_pic->i_height * p_pic->i_bytes_per_line );
if( p_newpic->p_data == NULL ) /* error */
if( p_vout->p_picture[i_picture].i_status == DESTROYED_PICTURE )
{
intf_ErrMsg("vout error: %s\n", strerror(ENOMEM) );
/* Restore type and flags */
p_newpic->i_type = EMPTY_PICTURE;
p_newpic->i_flags = 0;
vlc_mutex_unlock( &p_vout->pictures_lock );
return( NULL );
}
memcpy( p_newpic->p_data, p_pic->p_data,
p_pic->i_height * p_pic->i_bytes_per_line );
}
/* If source picture does not owns its data, copy the reference */
else
/* Picture is marked for destruction, but is still allocated */
if( (p_vout->p_picture[i_picture].i_type == i_type) &&
(p_vout->p_picture[i_picture].i_height == i_height) &&
(p_vout->p_picture[i_picture].i_bytes_per_line == i_bytes_per_line) )
{
p_newpic->p_data = p_pic->p_data;
}
p_newpic->i_refcount = 0;
/* Update heap size and stats */
p_vout->i_pictures++;
#ifdef STATS
p_vout->c_pictures++;
p_vout->p_stream[ p_newpic->i_stream ].c_pictures++;
#endif
/* Memory size do match : memory will not be reallocated, and function
* can end immediately - this is the best possible case, since no
* memory allocation needs to be done */
p_vout->p_picture[i_picture].i_width = i_width;
p_vout->p_picture[i_picture].i_status = RESERVED_PICTURE;
vlc_mutex_unlock( &p_vout->lock );
return( &p_vout->p_picture[i_picture] );
}
/* Release lock and return */
vlc_mutex_unlock( &p_vout->pictures_lock );
return( p_newpic );
}
/*******************************************************************************
* vout_DisplayPictureReplicate: copy a picture to a thread
*******************************************************************************
* The picture will be copied in an empty place of the video heap of the thread.
* If this is impossible, NULL will be returned. The picture used is the copy
* of the picture passed as argument, which remains usable.
* The picture data are a reference to original picture (the picture in the heap
* does not owns its data). Link reference counter is set to 0.
*******************************************************************************/
picture_t * vout_DisplayPictureReplicate( vout_thread_t *p_vout, picture_t *p_pic )
{
picture_t * p_newpic; /* new picture descrpitor */
p_newpic = FindPicture( p_vout );
if( p_newpic != NULL )
else if( p_destroyed_picture == NULL )
{
/* Copy picture information */
video_CopyPictureDescriptor( p_newpic, p_pic );
p_newpic->i_flags &= ~OWNER_PICTURE;
p_newpic->p_data = p_pic->p_data;
p_newpic->i_refcount = 0;
/* Update heap size and stats */
p_vout->i_pictures++;
#ifdef STATS
p_vout->c_pictures++;
p_vout->p_stream[ p_newpic->i_stream ].c_pictures++;
#endif
/* Memory size do not match, but picture index will be kept in
* case no other place are left */
p_destroyed_picture = &p_vout->p_picture[i_picture];
}
/* Release lock and return */
vlc_mutex_unlock( &p_vout->pictures_lock );
return( p_newpic );
}
/*******************************************************************************
* vout_DisplayReservedPicture: add a reserved picture to a thread
*******************************************************************************
* The picture will be placed in an empty place of the video heap of the thread.
* If the picture has been declared on reservation as permanent, it remains
* usable. Else, it will be destroyed by this call.
* This function can't fail, since it is the purpose of picture reservation to
* provide such a robust mechanism.
*******************************************************************************/
picture_t * vout_DisplayReservedPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
vlc_mutex_lock( &p_vout->pictures_lock );
/* Remove reservation flag */
p_pic->i_flags &= ~RESERVED_PICTURE;
#ifdef STATS
/* Update stats */
p_vout->c_pictures++;
p_vout->p_stream[ p_pic->i_stream ].c_pictures++;
#endif
vlc_mutex_unlock( &p_vout->pictures_lock );
return( p_pic );
}
/*******************************************************************************
* vout_CreateReservedPicture: reserve a place for a new picture in heap
*******************************************************************************
* This function create a reserved image in the video output heap.
* A null pointer is returned if the function fails.
* Following configuration properties are used:
* VIDEO_CFG_WIDTH picture width (required)
* VIDEO_CFG_HEIGHT picture height (required)
* VIDEO_CFG_TYPE picture type (required)
* VIDEO_CFG_FLAGS flags
* VIDEO_CFG_BPP padded bpp (required for pixel pictures)
* VIDEO_CFG_POSITION position in output window
* VIDEO_CFG_ALIGN base position in output window
* VIDEO_CFG_RATIO display ratio
* VIDEO_CFG_LEVEL overlay hierarchical level
* VIDEO_CFG_REFCOUNT links reference counter
* VIDEO_CFG_STREAM video stream id
* VIDEO_CFG_DATE display date
* VIDEO_CFG_DURATION duration for overlay pictures
* VIDEO_CFG_PIXEL pixel value for mask pictures
* VIDEO_CFG_DATA picture data (required if not owner and non blank)
* Pictures created using this function are always reserved, even if they did
* not had the RESERVED_PICTURE flag set.
* This function is very similar to the video_CreatePicture function.
*******************************************************************************/
picture_t *vout_CreateReservedPicture( vout_thread_t *p_vout, video_cfg_t *p_cfg )
{
picture_t * p_newpic; /* new picture index */
p_newpic = FindPicture( p_vout );
if( p_newpic != NULL )
{
/* Create new picture */
if( video_CreatePictureBody( p_newpic, p_cfg ) )
}
else if( (p_free_picture == NULL) &&
(p_vout->p_picture[i_picture].i_status == FREE_PICTURE ))
{
intf_ErrMsg("vout error: %s\n", strerror(ENOMEM));
/* Error: restore type and flags */
p_newpic->i_type = EMPTY_PICTURE;
p_newpic->i_flags = 0;
vlc_mutex_unlock( &p_vout->pictures_lock );
return( NULL );
/* Picture is empty and ready for allocation */
p_free_picture = &p_vout->p_picture[i_picture];
}
p_newpic->i_flags |= RESERVED_PICTURE;
/* Update heap size, release lock and return */
p_vout->i_pictures++;
}
/* Release lock and return */
vlc_mutex_unlock( &p_vout->pictures_lock );
return( p_newpic );
}
/*******************************************************************************
* vout_ReservePicture: reserve a place for a picture in heap
*******************************************************************************
* This function transforms an existing picture in a reserved picture in a
* video heap. The picture will be placed in an empty place of the video heap
* of the thread. If this is impossible, NULL will be returned. Else, the
* original picture is destroyed.
*******************************************************************************/
picture_t *vout_ReservePicture( vout_thread_t *p_vout, picture_t *p_pic )
{
picture_t * p_newpic; /* new picture index */
p_newpic = FindPicture( p_vout );
if( p_newpic != NULL )
/* If no free picture is available, use a destroyed picture */
if( (p_free_picture == NULL) && (p_destroyed_picture != NULL ) )
{
/* Copy picture information */
video_CopyPictureDescriptor( p_newpic, p_pic );
p_newpic->p_data = p_pic->p_data;
p_newpic->i_flags |= RESERVED_PICTURE;
free( p_pic );
/* Update heap size */
p_vout->i_pictures++;
/* No free picture or matching destroyed picture has been found, but
* a destroyed picture is still avalaible */
free( p_destroyed_picture->p_data );
p_free_picture = p_destroyed_picture;
}
/* Release lock and return */
vlc_mutex_unlock( &p_vout->pictures_lock );
return( p_newpic );
}
/*******************************************************************************
* vout_ReservePictureCopy: reserve a place for a picture in heap
*******************************************************************************
* This function returns a pointer to a picture which can be processed. The
* returned picture is a copy of the one passed as parameter.
* This function returns NULL if the reservation fails.
*******************************************************************************/
picture_t *vout_ReservePictureCopy( vout_thread_t *p_vout, picture_t *p_pic )
{
picture_t * p_newpic; /* new picture index */
p_newpic = FindPicture( p_vout );
if( p_newpic != NULL )
{
/* Copy picture information */
video_CopyPictureDescriptor( p_newpic, p_pic );
/*
* Prepare picture
*/
if( p_free_picture != NULL )
{
/* Allocate memory */
switch( i_type )
{
case YUV_422_PICTURE: /* YUV picture: 3*16 ?? bits per pixel */
case YUV_442_PICTURE:
case YUV_444_PICTURE:
p_free_picture->p_data = malloc( 3 * i_height * i_bytes_per_line );
p_free_picture->p_y = p_free_picture->p_data;
p_free_picture->p_u = (byte_t *)p_free_picture->p_data + i_height * i_bytes_per_line;
p_free_picture->p_v = (byte_t *)p_free_picture->p_data + i_height * i_bytes_per_line * 2;
break;
#ifdef DEBUG
default:
intf_DbgMsg("0x%x error: unknown picture type %d\n", p_vout, i_type );
p_free_picture->p_data = NULL;
#endif
}
/* If source picture owns its data, make a copy */
if( p_pic->i_flags & OWNER_PICTURE )
{
p_newpic->p_data = malloc( p_pic->i_height * p_pic->i_bytes_per_line );
if( p_newpic->p_data == NULL ) /* error */
if( p_free_picture->p_data != NULL )
{
intf_ErrMsg("vout error: %s\n", strerror(ENOMEM));
/* Restore type and flags */
p_newpic->i_type = EMPTY_PICTURE;
p_newpic->i_flags = 0;
vlc_mutex_unlock( &p_vout->pictures_lock );
return( NULL );
/* Copy picture informations */
p_free_picture->i_type = i_type;
p_free_picture->i_status = RESERVED_PICTURE;
p_free_picture->i_width = i_width;
p_free_picture->i_height = i_height;
p_free_picture->i_bytes_per_line = i_bytes_per_line;
p_free_picture->i_refcount = 0;
}
memcpy( p_newpic->p_data, p_pic->p_data,
p_pic->i_height * p_pic->i_bytes_per_line );
}
/* If source picture does not owns its data, copy the reference */
else
{
p_newpic->p_data = p_pic->p_data;
/* Memory allocation failed : set picture as empty */
p_free_picture->i_type = EMPTY_PICTURE;
p_free_picture->i_status = FREE_PICTURE;
p_free_picture = NULL;
intf_DbgMsg("0x%x malloc for new picture failed\n");
}
p_newpic->i_refcount = 0;
p_newpic->i_flags |= RESERVED_PICTURE;
/* Update heap size */
p_vout->i_pictures++;
vlc_mutex_unlock( &p_vout->lock );
return( p_free_picture );
}
/* Release lock and return */
vlc_mutex_unlock( &p_vout->pictures_lock );
return( p_newpic );
}
/*******************************************************************************
* vout_ReservePictureReplicate: reserve a place for a picture in heap
*******************************************************************************
* This function returns a pointer to a picture which can be processed. The
* returned picture is a copy of the one passed as parameter.
* This function returns NULL if the reservation fails.
*******************************************************************************/
picture_t *vout_ReservePictureReplicate( vout_thread_t *p_vout, picture_t *p_pic )
{
picture_t * p_newpic; /* new picture index */
p_newpic = FindPicture( p_vout );
if( p_newpic != NULL )
{
/* Copy picture information */
video_CopyPictureDescriptor( p_newpic, p_pic );
p_newpic->p_data = p_pic->p_data;
p_newpic->i_refcount = 0;
p_newpic->i_flags &= ~OWNER_PICTURE;
p_newpic->i_flags |= RESERVED_PICTURE;
/* Update heap size */
p_vout->i_pictures++;
}
/* Release lock and return */
vlc_mutex_unlock( &p_vout->pictures_lock );
return( p_newpic );
// No free or destroyed picture could be found
intf_DbgMsg("0x%x no picture available\n");
vlc_mutex_unlock( &p_vout->lock );
return( NULL );
}
/*******************************************************************************
* vout_RemovePicture: remove a permanent or reserved picture from the heap
*******************************************************************************
* This function frees a previously reserved picture or a permanent
* picture. The picture data is destroyed if required.
* picture. It is meant to be used when the construction of a picture aborted.
* Note that the picture will be destroyed even if it is linked !
*******************************************************************************/
void vout_RemovePicture( vout_thread_t *p_vout, picture_t *p_pic )
void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
vlc_mutex_lock( &p_vout->pictures_lock );
vlc_mutex_lock( &p_vout->lock );
/* Mark picture for destruction */
p_pic->i_flags |= DESTROY_PICTURE;
/* Since permanent pictures can normally not be destroyed by the vout thread,
* the permanent flag needs to be removed */
p_pic->i_flags &= ~PERMANENT_PICTURE;
intf_DbgMsg("%p -> picture %p removing requested\n", p_vout, p_pic );
p_pic->i_status = DESTROYED_PICTURE;
intf_DbgMsg("%p -> picture %p destroyed\n", p_vout, p_pic );
vlc_mutex_unlock( &p_vout->pictures_lock );
}
/*******************************************************************************
* vout_RefreshPermanentPicture:
*******************************************************************************
* Set the DISPLAYED_PICTURE flag of a permanent picture to 0, allowing to
* display it again if it not overlaid. The display date is also updated.
*******************************************************************************/
void vout_RefreshPermanentPicture( vout_thread_t *p_vout, picture_t *p_pic,
mtime_t display_date )
{
vlc_mutex_lock( &p_vout->pictures_lock );
p_pic->i_flags &= ~DISPLAYED_PICTURE;
p_pic->date = display_date;
vlc_mutex_lock( &p_vout->pictures_lock );
vlc_mutex_unlock( &p_vout->lock );
}
/*******************************************************************************
......@@ -522,9 +318,9 @@ void vout_RefreshPermanentPicture( vout_thread_t *p_vout, picture_t *p_pic,
*******************************************************************************/
void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
vlc_mutex_lock( &p_vout->pictures_lock );
vlc_mutex_lock( &p_vout->lock );
p_pic->i_refcount++;
vlc_mutex_unlock( &p_vout->pictures_lock );
vlc_mutex_unlock( &p_vout->lock );
}
/*******************************************************************************
......@@ -534,133 +330,17 @@ void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
*******************************************************************************/
void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
vlc_mutex_lock( &p_vout->pictures_lock );
vlc_mutex_lock( &p_vout->lock );
p_pic->i_refcount--;
#ifdef DEBUG
if( p_pic->i_refcount < 0 )
if( (p_pic->i_refcount == 0) && (p_pic->i_status == DISPLAYED_PICTURE) )
{
intf_DbgMsg("%p -> picture %p i_refcount < 0\n", p_vout, p_pic);
p_pic->i_status = DESTROYED_PICTURE;
}
#endif
vlc_mutex_unlock( &p_vout->pictures_lock );
vlc_mutex_unlock( &p_vout->lock );
}
/*******************************************************************************
* vout_CreateStream: get a new stream id
*******************************************************************************
* Stream ids are used to create list of pictures in a video output thread.
* The function returns an unused stream id, or a negative number on error.
* Stream id 0 is never returned, since it is not a stream descriptor but a set
* of independant images.
*******************************************************************************/
int vout_CreateStream( vout_thread_t *p_vout )
{
int i_index; /* stream index */
/* Find free (inactive) stream id */
vlc_mutex_lock( &p_vout->streams_lock ); /* get lock */
for( i_index = 1; i_index < VOUT_MAX_STREAMS; i_index++ ) /* find free id */
{
if( p_vout->p_stream[i_index].i_status == VOUT_INACTIVE_STREAM )
{
/* Initialize stream */
p_vout->p_stream[i_index].i_status = VOUT_ACTIVE_STREAM;
#ifdef STATS
p_vout->p_stream[i_index].c_pictures = 0;
p_vout->p_stream[i_index].c_rendered_pictures = 0;
#endif
/* Return stream id */
intf_DbgMsg("%p -> stream %i created\n", p_vout, i_index);
vlc_mutex_unlock( &p_vout->streams_lock ); /* release lock */
return( i_index ); /* return id */
}
}
/* Failure: all streams id are already active */
intf_DbgMsg("%p -> failed\n", p_vout);
vlc_mutex_unlock( &p_vout->streams_lock );
return( -1 );
}
/*******************************************************************************
* vout_EndStream: free a previously allocated stream
*******************************************************************************
* This function must be called once a stream is no more used. It can be called
* even if there are remaining pictures in the video heap, since the stream will
* only be destroyed once all pictures of the stream have been displayed.
*******************************************************************************/
void vout_EndStream( vout_thread_t *p_vout, int i_stream )
{
vlc_mutex_lock( &p_vout->streams_lock ); /* get lock */
p_vout->p_stream[i_stream].i_status = VOUT_ENDING_STREAM; /* mark stream */
vlc_mutex_unlock( &p_vout->streams_lock ); /* release lock */
intf_DbgMsg("%p -> stream %d\n", p_vout, i_stream);
}
/*******************************************************************************
* vout_DestroyStream: free a previously allocated stream
*******************************************************************************
* This function must be called once a stream is no more used. It can be called
* even if there are remaining pictures in the video heap, since all pictures
* will be removed before the stream is destroyed.
*******************************************************************************/
void vout_DestroyStream( vout_thread_t *p_vout, int i_stream )
{
vlc_mutex_lock( &p_vout->streams_lock ); /* get lock */
p_vout->p_stream[i_stream].i_status = VOUT_DESTROYED_STREAM;/* mark stream */
vlc_mutex_unlock( &p_vout->streams_lock ); /* release lock */
intf_DbgMsg("%p -> stream %d\n", p_vout, i_stream);
}
/* following functions are debugging functions */
/*******************************************************************************
* vout_PrintHeap: display heap state (debugging function)
*******************************************************************************
* This functions, which is only defined if DEBUG is defined, can be used
* for debugging purposes. It prints on debug stream the current state of the
* heap. The second parameter is used to identify the output.
*******************************************************************************/
#ifdef DEBUG
void vout_PrintHeap( vout_thread_t *p_vout, char *psz_str )
{
int i_picture; /* picture index */
intf_Msg("vout: --- thread %p heap status (%s) ---\n", p_vout, psz_str );
/* Browse all pictures in heap */
for( i_picture = 0; i_picture < p_vout->i_max_pictures; i_picture++ )
{
if( p_vout->p_picture[i_picture].i_type != EMPTY_PICTURE )
{
video_PrintPicture( &p_vout->p_picture[i_picture], "vout: ..." );
}
}
intf_Msg("vout: --- end ---\n");
}
#endif
/* following functions are local */
/*******************************************************************************
* CheckConfiguration: check vout_CreateThread() configuration
*******************************************************************************
* Set default parameters where required. In DEBUG mode, check if configuration
* is valid.
*******************************************************************************/
static int CheckConfiguration( video_cfg_t *p_cfg )
{
/* Heap size */
if( !( p_cfg->i_properties & VIDEO_CFG_SIZE ) )
{
p_cfg->i_size = VOUT_HEAP_SIZE;
}
return( 0 );
}
/*******************************************************************************
* InitThread: initialize video output thread
*******************************************************************************
......@@ -675,33 +355,11 @@ static int InitThread( vout_thread_t *p_vout )
/* Update status */
*p_vout->pi_status = THREAD_START;
/* Allocate video heap */
p_vout->p_picture =
(picture_t *) malloc( sizeof(picture_t) * p_vout->i_max_pictures );
if( !p_vout->p_picture ) /* error */
{
intf_ErrMsg("vout error: %s\n", strerror(ENOMEM));
intf_DbgMsg("%p -> failed\n", p_vout);
*p_vout->pi_status = THREAD_ERROR;
return( 1 );
}
/* Initialize pictures */
for( i_index = 0; i_index < p_vout->i_max_pictures; i_index++)
for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++)
{
p_vout->p_picture[i_index].i_type = EMPTY_PICTURE;
p_vout->p_picture[i_index].i_flags = 0;
}
/* Initialize video streams - note that stream 0 is always active */
p_vout->p_stream[0].i_status = VOUT_ACTIVE_STREAM;
#ifdef STATS
p_vout->p_stream[0].c_pictures = 0;
p_vout->p_stream[0].c_rendered_pictures = 0;
#endif
for( i_index = 1; i_index < VOUT_MAX_STREAMS; i_index++ )
{
p_vout->p_stream[i_index].i_status = VOUT_INACTIVE_STREAM;
p_vout->p_picture[i_index].i_status= FREE_PICTURE;
}
/* Initialize other properties */
......@@ -715,9 +373,8 @@ static int InitThread( vout_thread_t *p_vout )
/* Initialize output method - width, height, screen depth and bytes per
* pixel are initialized by this call. */
if( vout_X11CreateOutputMethod( p_vout ) ) /* error */
if( vout_SysInit( p_vout ) ) /* error */
{
free( p_vout->p_picture );
*p_vout->pi_status = THREAD_ERROR;
return( 1 );
}
......@@ -737,13 +394,10 @@ static int InitThread( vout_thread_t *p_vout )
*******************************************************************************/
static void RunThread( vout_thread_t *p_vout)
{
int i_stream; /* stream index */
int i_picture; /* picture index */
int i_active_streams; /* number of active streams */
int i_err; /* error code */
mtime_t display_date; /* display date */
mtime_t current_date; /* current date */
picture_t * pp_sorted_picture[VOUT_MAX_PICTURES]; /* sorted pictures */
picture_t * p_pic = NULL;
#ifdef VOUT_DEBUG
char sz_date[MSTRTIME_MAX_SIZE]; /* date buffer */
#endif
......@@ -751,6 +405,7 @@ static void RunThread( vout_thread_t *p_vout)
/*
* Initialize thread and free configuration
*/
intf_DbgMsg( "0x%x begin\n", p_vout );
p_vout->b_error = InitThread( p_vout );
if( p_vout->b_error )
{
......@@ -764,137 +419,109 @@ static void RunThread( vout_thread_t *p_vout)
*/
while( (!p_vout->b_die) && (!p_vout->b_error) )
{
/* Get locks on pictures and streams */
vlc_mutex_lock( &p_vout->streams_lock );
vlc_mutex_lock( &p_vout->pictures_lock );
/*
* Find the picture to display - this is the only operation requiring
* the lock on the picture, since once a READY_PICTURE has been found,
* it can't be modified by the other threads (except if it is unliked,
* but its data remains)
*/
vlc_mutex_lock( &p_vout->lock );
/* Initialise streams: clear images from all streams */
for( i_stream = 0; i_stream < VOUT_MAX_STREAMS; i_stream++ )
for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
{
if( (p_vout->p_picture[i_picture].i_status == READY_PICTURE) &&
( (p_pic == NULL) ||
(p_vout->p_picture[i_picture].date < p_pic->date) ) )
{
p_vout->p_stream[i_stream].p_next_picture = NULL;
p_pic = &p_vout->p_picture[i_picture];
}
}
/* First pass: a set of pictures is selected - all unselected pictures
* which should be removed are removed, and a display date is computed.
* If a stream has no next_picture after this step, then the heap does
* not include any picture from that stream. */
current_date = mdate();
display_date = FirstPass( p_vout, current_date );
vlc_mutex_unlock( &p_vout->lock );
/* Stream management: streams which are in ENDING or DESTROYED state and
* which have no more pictures are destroyed */
for( i_active_streams = i_stream = 1;
i_stream < VOUT_MAX_STREAMS;
i_stream++ )
/*
* Render picture if any
*/
if( p_pic )
{
switch( p_vout->p_stream[i_stream].i_status )
current_date = mdate();
if( p_pic->date < current_date )
{
case VOUT_ACTIVE_STREAM: /* active stream */
i_active_streams++;
break;
case VOUT_ENDING_STREAM: /* ending or destroyed streams */
case VOUT_DESTROYED_STREAM:
/* Those streams can be destroyed if there are no more picture
* remaining. This should always be the case for destroyed
* streams, except if it includes permanent pictures */
if( p_vout->p_stream[i_stream].p_next_picture == NULL )
/* Picture is late: it will be destroyed and the thread will go
* immediately to next picture */
vlc_mutex_lock( &p_vout->lock );
if( p_pic->i_refcount )
{
p_vout->p_stream[i_stream].i_status = VOUT_INACTIVE_STREAM;
#ifdef STATS
intf_DbgMsg("%p -> stream %d destroyed %d pictures, %d rendered pictures\n",
p_vout, i_stream, p_vout->p_stream[i_stream].c_pictures,
p_vout->p_stream[i_stream].c_rendered_pictures );
#else
intf_DbgMsg("%p -> stream %d destroyed\n", p_vout, i_stream );
#endif
p_pic->i_status = DISPLAYED_PICTURE;
}
/* If the stream can't be destroyed, it means it is still
* active - in that case, the next image pointer needs to be
* cleard */
else
{
i_active_streams++;
p_vout->p_stream[i_stream].p_next_picture = NULL;
}
break;
p_pic->i_status = DESTROYED_PICTURE;
}
vlc_mutex_unlock( &p_vout->lock );
intf_ErrMsg( "vout error: picture %p was late - skipped\n", p_pic );
p_pic = NULL;
}
/* From now until next loop, only next_picture field in streams
* will be used, and selected pictures structures won't modified.
* Therefore, locks can be released */
vlc_mutex_unlock( &p_vout->pictures_lock );
vlc_mutex_unlock( &p_vout->streams_lock );
/* If there are some pictures to display, then continue */
if( display_date != LAST_MDATE )
{
/* Increase display_date if it is too low */
if( display_date < current_date + VOUT_DISPLAY_DELAY )
else if( p_pic->date > current_date + VOUT_DISPLAY_DELAY )
{
intf_Msg("vout: late picture(s) detected\n");
display_date = current_date + VOUT_DISPLAY_DELAY;
/* A picture is ready to be rendered, but its rendering date is
* far from the current one so the thread will perform an empty loop
* as if no picture were found. The picture state is unchanged */
p_pic = NULL;
}
#ifdef VOUT_DEBUG
intf_DbgMsg("%p -> display_date is %s\n", p_vout,
mstrtime( sz_date, display_date ));
#endif
/* Second pass: a maximum of one picture per stream is selected
* (except for stream 0), and some previously selected pictures may
* be removed */
SecondPass( p_vout, display_date );
#ifdef VOUT_DEBUG
vout_PrintHeap( p_vout, "ready for rendering" );
#endif
/* Rendering: sort pictures and render them */
SortPictures( p_vout, pp_sorted_picture );
for( i_picture = 0; pp_sorted_picture[i_picture] != NULL; i_picture++ )
else
{
/* Render picture */
RenderPicture( p_vout, pp_sorted_picture[i_picture] );
/* Picture has not yet been displayed, and has a valid display
* date : render it */
RenderPicture( p_vout, p_pic );
}
/* Handle output method events - this function can return a negative
* value, which means a fatal error and the end of the display loop
* (i.e. the X11 window has been destroyed), a positive one, meaning
* a modification occured in the pictures and they do have need to
* be displayed, or 0 */
i_err = vout_X11ManageOutputMethod( p_vout );
if( !i_err )
{
/* Sleep and display */
mwait( display_date );
vout_X11DisplayOutput( p_vout );
}
else if( i_err < 0 )
/*
* Check events, sleep and display picture
*/
i_err = vout_SysManage( p_vout );
if( i_err < 0 )
{
/* An error occured, and the thread must terminate immediately,
/* A fatal error occured, and the thread must terminate immediately,
* without displaying anything - setting b_error to 1 cause the
* immediate end of the main while() loop. */
p_vout->b_error = 1;
}
}
/* If there is nothing to display, just handle events and sleep a while,
* hopping there will be something to do later */
else
{
if( vout_X11ManageOutputMethod( p_vout ) < 0)
if( p_pic )
{
p_vout->b_error = 1;
/* A picture is ready to be displayed : sleep until its display date */
mwait( p_pic->date );
if( !i_err )
{
vout_SysDisplay( p_vout );
}
/* Picture has been displayed : destroy it */
vlc_mutex_lock( &p_vout->lock );
if( p_pic->i_refcount )
{
p_pic->i_status = DISPLAYED_PICTURE;
}
else
{
msleep( VOUT_IDLE_SLEEP );
p_pic->i_status = DESTROYED_PICTURE;
}
vlc_mutex_unlock( &p_vout->lock );
}
else
{
/* Sleep to wait for new pictures */
msleep( VOUT_IDLE_SLEEP );
#ifdef STATS
/* Update counters */
p_vout->c_idle_loops++;
#endif
}
}
#ifdef STATS
/* Update counters */
......@@ -912,6 +539,7 @@ static void RunThread( vout_thread_t *p_vout)
/* End of thread */
EndThread( p_vout );
intf_DbgMsg( "0x%x end\n", p_vout );
}
/*******************************************************************************
......@@ -923,27 +551,9 @@ static void RunThread( vout_thread_t *p_vout)
*******************************************************************************/
static void ErrorThread( vout_thread_t *p_vout )
{
int i_picture; /* picture index */
/* Wait until a `die' order */
while( !p_vout->b_die )
{
/* Get lock on pictures */
vlc_mutex_lock( &p_vout->pictures_lock );
/* Try to remove all pictures - only removable pictures will be
* removed */
for( i_picture = 0; i_picture < p_vout->i_max_pictures; i_picture++ )
{
if( p_vout->p_picture[i_picture].i_type != EMPTY_PICTURE )
{
EmptyPicture( p_vout, &p_vout->p_picture[i_picture] );
}
}
/* Release locks on pictures */
vlc_mutex_unlock( &p_vout->pictures_lock );
/* Sleep a while */
msleep( VOUT_IDLE_SLEEP );
}
......@@ -958,35 +568,24 @@ static void ErrorThread( vout_thread_t *p_vout )
static void EndThread( vout_thread_t *p_vout )
{
int * pi_status; /* thread status */
#ifdef DEBUG
int i_stream; /* video stream index */
#endif
int i_picture;
/* Store status */
pi_status = p_vout->pi_status;
*pi_status = THREAD_END;
#ifdef DEBUG
/* Check for remaining pictures or video streams */
if( p_vout->i_pictures )
/* Destroy all remaining pictures */
for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
{
intf_DbgMsg("%p -> remaining pictures\n", p_vout);
}
for( i_stream = 1;
(i_stream < VOUT_MAX_STREAMS) && (p_vout->p_stream[i_stream].i_status == VOUT_INACTIVE_STREAM);
i_stream++ )
if( p_vout->p_picture[i_picture].i_status != FREE_PICTURE )
{
;
free( p_vout->p_picture[i_picture].p_data );
}
if( i_stream != VOUT_MAX_STREAMS )
{
intf_DbgMsg("%p -> remaining video streams\n", p_vout);
}
#endif
/* Destroy thread structures allocated by InitThread */
vout_X11DestroyOutputMethod( p_vout ); /* destroy output method */
free( p_vout->p_picture ); /* free heap */
vout_SysEnd( p_vout );
vout_SysDestroy( p_vout ); /* destroy output method */
free( p_vout );
/* Update status */
......@@ -994,643 +593,16 @@ static void EndThread( vout_thread_t *p_vout )
intf_DbgMsg("%p\n", p_vout);
}
/*******************************************************************************
* FindPicture: find an empty picture in a video heap
*******************************************************************************
* This function is used by most of the vout_*Picture*() functions. It locks the
* video heap, look for an empty picture in it and return a pointer to this
* picture, or NULL if the heap is full.
* Not that the heap is not unlocked when this function returns, and it needs
* to be donne by the calling function.
*******************************************************************************/
static picture_t *FindPicture( vout_thread_t *p_vout )
{
int i_picture; /* picture index */
/* Get lock */
vlc_mutex_lock( &p_vout->pictures_lock );
/* Look for an empty place */
for( i_picture = 0; i_picture < p_vout->i_max_pictures; i_picture++ )
{
/* An empty place has been found: return */
if( p_vout->p_picture[i_picture].i_type == EMPTY_PICTURE )
{
return( &p_vout->p_picture[i_picture] );
}
}
/* Nothing has been found */
return( NULL );
}
/*******************************************************************************
* EmptyPicture: empty a picture without destroying its descriptor
*******************************************************************************
* When a picture is no more used in video heap or must be destroyed, this
* function is called to destroy associated data and set picture type to empty.
* Only non permanent and unlinked pictures can be destroyed.
* Only non-empty pictures should be sent to this function.
* All picture flags are cleared, and the heap size is decreased.
*******************************************************************************
* Messages type: vout, major code 15
*******************************************************************************/
static void EmptyPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
#ifdef DEBUG
/* Check if picture is non-empty */
if( p_pic->i_type == EMPTY_PICTURE )
{
intf_DbgMsg("%p -> trying to remove empty picture %p\n",
p_vout, p_pic);
return;
}
#endif
/* Mark as ready for destruction */
p_pic->i_flags |= DESTROY_PICTURE;
p_pic->i_flags &= ~DISPLAY_PICTURE;
/* If picture is no more referenced and is not permanent, destroy */
if( (p_pic->i_refcount == 0) && !(p_pic->i_flags & PERMANENT_PICTURE) )
{
/* If picture owns its data, free them */
if( p_pic->i_flags & OWNER_PICTURE )
{
free( p_pic->p_data );
}
p_pic->i_type = EMPTY_PICTURE;
p_pic->i_flags = 0;
p_vout->i_pictures--;
intf_DbgMsg("%p -> picture %p removed\n", p_vout, p_pic);
}
}
/*******************************************************************************
* FirstPass: first pass of the vout thread on pictures
*******************************************************************************
* A set of pictures is selected according to the current date and their display
* date. Some unselected and already displayed pictures are removed, and the
* next display date is computed.
* The next_picture fields of all the streams are updated. Note that streams
* are initialized before this function is called.
*******************************************************************************
* Messages type: vout, major code 18
*******************************************************************************/
static mtime_t FirstPass( vout_thread_t *p_vout, mtime_t current_date )
{
mtime_t display_date; /* display date */
int i_picture; /* picture index */
picture_t * p_picture; /* picture pointer (shortcut) */
/* Set up date */
display_date = LAST_MDATE;
/* Browse all pictures */
for( i_picture = 0; i_picture < p_vout->i_max_pictures; i_picture++ )
{
p_picture = &p_vout->p_picture[i_picture];
/* Empty pictures are never selected */
if( p_picture->i_type == EMPTY_PICTURE )
{
;
}
/* Destroyed pictures are never selected, they can be emptied if needed */
else if( p_picture->i_flags & DESTROY_PICTURE )
{
EmptyPicture( p_vout, p_picture );
}
#ifdef DEBUG
/* Pictures in an inactive stream are submitted to a deletion attempt,
* and nether selected - this case should never happen */
else if( p_vout->p_stream[ p_picture->i_stream ].i_status == VOUT_INACTIVE_STREAM )
{
intf_DbgMsg("%p -> picture %p belongs to an inactive stream\n",
p_vout, p_picture);
EmptyPicture( p_vout, p_picture );
}
#endif
/* Pictures in a destroyed stream are submitted to a deletion attempt,
* and nether selected */
else if( p_vout->p_stream[ p_picture->i_stream ].i_status == VOUT_DESTROYED_STREAM )
{
EmptyPicture( p_vout, p_picture );
}
/* Reserved pictures are never selected */
else if( p_picture->i_flags & RESERVED_PICTURE )
{
p_picture->i_flags &= ~DISPLAY_PICTURE;
}
/* Overlay pictures */
else if( p_picture->i_flags & OVERLAY_PICTURE )
{
/* A picture is outdated if it is not permanent and if it's maximal
* date is passed */
if( !(p_picture->i_flags & PERMANENT_PICTURE )
&& (p_picture->date + p_picture->duration < current_date) )
{
p_picture->i_flags &= ~DISPLAY_PICTURE;
EmptyPicture( p_vout, p_picture );
}
/* Else if picture is in stream 0, it will always be selected */
else if( p_picture->i_stream == 0 )
{
p_picture->i_flags |= DISPLAY_PICTURE;
/* Update display_date if picture has never been displayed */
if( !(p_picture->i_flags & DISPLAYED_PICTURE) && (p_picture->date < display_date) )
{
display_date = p_picture->date;
}
}
/* The picture can be considered as a regular picture, because it
* has never been displayed */
else if( !(p_picture->i_flags & DISPLAYED_PICTURE) )
{
/* Select picture if can be updated */
if( (p_vout->p_stream[ p_picture->i_stream].p_next_picture == NULL)
|| (p_vout->p_stream[p_picture->i_stream].p_next_picture->date > p_picture->date))
{
p_picture->i_flags |= DISPLAY_PICTURE;
p_vout->p_stream[p_picture->i_stream].p_next_picture = p_picture;
/* Update display_date */
if( p_picture->date < display_date )
{
display_date = p_picture->date;
}
}
}
/* In other cases (overlay pictures which have already been displayed),
* the picture is always selected */
else
{
p_picture->i_flags |= DISPLAY_PICTURE;
/* The stream is only updated if there is no picture in that stream */
if( p_vout->p_stream[ p_picture->i_stream].p_next_picture == NULL )
{
p_vout->p_stream[p_picture->i_stream].p_next_picture = p_picture;
}
}
}
/* Non overlay pictures are deleted if they have been displayed, and
* selected if there date is valid */
else
{
/* Remove already displayed pictures */
if( p_picture->i_flags & DISPLAYED_PICTURE )
{
EmptyPicture( p_vout, p_picture );
}
/* Remove passed pictures, The picture is marked as displayed in case it
* could not be removed */
else if( p_picture->date < current_date )
{
intf_DbgMsg("%p -> picture %p detected late\n",
p_vout, p_picture );
p_picture->i_flags |= DISPLAYED_PICTURE;
EmptyPicture( p_vout, p_picture );
}
/* Update streams for other pictures */
else
{
p_picture->i_flags |= DISPLAY_PICTURE;
/* Update 'next picture' field in stream descriptor */
if( (p_vout->p_stream[ p_picture->i_stream].p_next_picture == NULL)
|| (p_vout->p_stream[p_picture->i_stream].p_next_picture->date > p_picture->date))
{
p_vout->p_stream[p_picture->i_stream].p_next_picture = p_picture;
/* Update display_date */
if( p_picture->date < display_date )
{
display_date = p_picture->date;
}
}
}
}
}
return( display_date );
}
/*******************************************************************************
* SecondPass: second pass of the vout thread on pictures
*******************************************************************************
* Select only one picture per stream other than stream 0, and remove pictures
* which should have been displayed.... but arrived too late. Note that nothing
* is locked when this function is called, and therefore pictures should not
* be removed here.
* Only previously selected pictures are processed.
*******************************************************************************
* Messages type: vout, major code 19
*******************************************************************************/
static void SecondPass( vout_thread_t *p_vout, mtime_t display_date )
{
int i_picture; /* picture index */
picture_t * p_picture; /* picture pointer (shortcut) */
for( i_picture = 0; i_picture < p_vout->i_max_pictures; i_picture++ )
{
p_picture = &p_vout->p_picture[i_picture];
/* Process only previously selected pictures */
if( p_picture->i_flags & DISPLAY_PICTURE )
{
/* Deselect picture if it is too youg */
if( p_picture->date > display_date + VOUT_DISPLAY_TOLERANCE )
{
p_picture->i_flags &= ~DISPLAY_PICTURE;
}
/* Pictures in stream 0 are selected depending only of their date */
else if( p_picture->i_stream == 0 )
{
/* Overlay pictures are not selected if they are
* outdated */
if( p_picture->i_flags & OVERLAY_PICTURE )
{
if( !(p_picture->i_flags & PERMANENT_PICTURE)
&& (display_date > p_picture->date + p_picture->duration) )
{
p_picture->i_flags |= DESTROY_PICTURE;
p_picture->i_flags &= ~DISPLAY_PICTURE;
}
}
/* Regular pictures are selected if they are not too late */
else if( p_picture->date < display_date - VOUT_DISPLAY_TOLERANCE )
{
intf_DbgMsg("%p -> picture %p detected late\n",
p_vout, p_picture );
p_picture->i_flags |= DISPLAYED_PICTURE | DESTROY_PICTURE;
p_picture->i_flags &= ~DISPLAY_PICTURE;
}
}
/* Overlay pictures which have been displayed have special
* processing */
else if( (p_picture->i_flags & OVERLAY_PICTURE)
&& (p_picture->i_flags & DISPLAYED_PICTURE) )
{
/* If the stream is not empty, or the picture has been
* outdated, de select */
if( (p_vout->p_stream[p_picture->i_stream].p_next_picture != NULL)
|| (!(p_picture->i_flags & PERMANENT_PICTURE)
&& (display_date > p_picture->date + p_picture->duration) ) )
{
p_picture->i_flags |= DESTROY_PICTURE;
p_picture->i_flags &= ~DISPLAY_PICTURE;
}
}
/* Other pictures are 'regular' pictures */
else
{
/* If the stream is empty, always select */
if( p_vout->p_stream[p_picture->i_stream].p_next_picture == NULL)
{
p_vout->p_stream[p_picture->i_stream].p_next_picture = p_picture;
}
/* Else, remove and mark as displayed (skip) if the picture is too old */
else if( p_picture->date < display_date - VOUT_DISPLAY_TOLERANCE )
{
intf_DbgMsg("%p -> picture %p detected late\n",
p_vout, p_picture );
p_picture->i_flags |= DISPLAYED_PICTURE | DESTROY_PICTURE;
p_picture->i_flags &= ~DISPLAY_PICTURE;
}
/* Else, select if the picture is younger than the current selected one */
else if( p_picture->date
< p_vout->p_stream[p_picture->i_stream].p_next_picture->date )
{
/* Deselect the previous picture */
p_vout->p_stream[p_picture->i_stream].p_next_picture->i_flags
&= ~DISPLAY_PICTURE;
/* Select the current one */
p_vout->p_stream[p_picture->i_stream].p_next_picture = p_picture;
}
/* Else, select if the current selected one is an already displayed overlay */
else if( (p_vout->p_stream[p_picture->i_stream].p_next_picture->i_flags
& ( OVERLAY_PICTURE | DISPLAYED_PICTURE ))
== (OVERLAY_PICTURE | DISPLAYED_PICTURE) )
{
/* Deselect and remove the previous picture */
p_picture->i_flags |= DESTROY_PICTURE;
p_picture->i_flags &= ~DISPLAY_PICTURE;
/* Select the current one */
p_vout->p_stream[p_picture->i_stream].p_next_picture = p_picture;
}
/* Else, deselect the picture */
else
{
p_picture->i_flags &= ~DISPLAY_PICTURE;
}
}
}
}
}
/*******************************************************************************
* SortPictures: sort pictures ready for display by hierarchical level
*******************************************************************************
* Build an array of pictures in rendering order, starting from minimal to
* level to maximal level. A NULL pointer always ends the array, which size is
* limited to VOUT_MAX_PICTURES.
*******************************************************************************
* Messages type: vout, major code 26
*******************************************************************************/
static void SortPictures( vout_thread_t *p_vout, picture_t **pp_picture )
{
int i_picture; /* picture index in sorted array */
int i_heap_picture; /* picture index in heap */
picture_t * p_previous_picture; /* first shift register */
picture_t * p_current_picture; /* second shift register */
/* Initialize array */
pp_picture[0] = NULL;
/* Copy and sort pictures */
for( i_heap_picture = 0; i_heap_picture < p_vout->i_max_pictures ; i_heap_picture++ )
{
/* Sort only selected pictures */
if( p_vout->p_picture[ i_heap_picture ].i_flags & DISPLAY_PICTURE )
{
/* Find picture position */
for( i_picture = 0; (pp_picture[i_picture] != NULL)
&& (pp_picture[i_picture]->i_level
<= p_vout->p_picture[ i_heap_picture ].i_level);
i_picture++ )
{
;
}
p_current_picture = &p_vout->p_picture[ i_heap_picture ];
/* Insert picture and shift end of array */
for( ; p_previous_picture != NULL; i_picture++ )
{
p_previous_picture = p_current_picture;
p_current_picture = pp_picture[i_picture];
if( i_picture == VOUT_MAX_PICTURES - 1 )
{
p_previous_picture = NULL;
}
pp_picture[i_picture] = p_previous_picture;
}
}
}
}
/*******************************************************************************
* RenderPicture: render a picture
*******************************************************************************
* This function convert a picture from a video heap to a pixel-encoded image
* and copy it to the current rendering buffer. No lock is required, since the
* rendered picture has been determined as existant, and will only be destroyed
* by the vout_Thread() later.
*******************************************************************************
* Messages types: vout, major code 27
* by the vout thread later.
*******************************************************************************/
static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
int i_x, i_y; /* position in display */
int i_pic_x; /* x offset in clipped picture */
int i_pic_y; /* y offset in clipped picture */
int i_height, i_width; /* clipped picture dimensions */
int i_line_width; /* line width */
void (*RenderLine)(vout_thread_t *p_vout, picture_t *p_pic, /* renderer */
int i_x, int i_y, int i_pic_x, int i_pic_y, int i_width,
int i_line_width, int i_ratio );
/* Update counters - this is done now since for blank pictures, the function
* may never reach it's regular end */
p_pic->i_flags |= DISPLAYED_PICTURE;
#ifdef STATS
p_vout->c_rendered_pictures++;
p_vout->p_stream[ p_pic->i_stream ].c_rendered_pictures++;
#endif
/* Computes position and size of the picture zone to render */
i_x = p_pic->i_x;
i_y = p_pic->i_y;
i_width = p_pic->i_width;
i_height = p_pic->i_height;
ClipPicture( &i_x, p_vout->i_width, &i_pic_x, &i_width, p_pic->i_h_ratio, p_pic->i_h_align );
ClipPicture( &i_y, p_vout->i_height, &i_pic_y, &i_height, p_pic->i_v_ratio, p_pic->i_v_align );
#ifdef VOUT_DEBUG
intf_DbgMsg("%p -> picture %p, (%d-%d:%d-%d, %dx%d)\n",
p_vout, p_pic, i_x, i_pic_x, i_y, i_pic_y, i_width, i_height );
#endif
/* If there is noting to display, returns immediately */
if( (i_pic_x >= i_width) || (i_pic_y >= i_height) )
{
return;
}
/* Determine method used to render line. This function is choosed here to
* avoid multiple conditions tests later */
switch( p_pic->i_type )
{
case RGB_BLANK_PICTURE: /* picture is blank, RGB encoded (no data) */
case PIXEL_BLANK_PICTURE: /* picture is blank, pixel encoded (no data) */
/* Blank pictures are displayed immediately - dimensions are real ones,
* and should be recalculated */
switch( p_pic->i_h_ratio )
{
case DISPLAY_RATIO_HALF: /* 1:2 half size */
i_width = (i_width - i_pic_x) / 2;
break;
case DISPLAY_RATIO_NORMAL: /* 1:1 normal size */
i_width -= i_pic_x;
break;
case DISPLAY_RATIO_DOUBLE: /* 2:1 double size */
i_width = (i_width - i_pic_x) * 2;
break;
/* ?? add others display ratio */
}
switch( p_pic->i_v_ratio )
{
case DISPLAY_RATIO_HALF: /* 1:2 half size */
i_height = (i_height - i_pic_y) / 2;
break;
case DISPLAY_RATIO_NORMAL: /* 1:1 normal size */
i_height -= i_pic_y;
break;
case DISPLAY_RATIO_DOUBLE: /* 2:1 double size */
i_height = (i_height - i_pic_y) * 2;
break;
/* ?? add others display ratio */
}
if( p_pic->i_type == RGB_BLANK_PICTURE ) /* RGB blank picture */
{
p_vout->RenderRGBBlank( p_vout, p_pic->pixel, i_x, i_y, i_width, i_height );
}
else /* pixel blank picture */
{
p_vout->RenderPixelBlank( p_vout, p_pic->pixel, i_x, i_y, i_width, i_height );
}
return;
break;
case RGB_PICTURE: /* picture is 24 bits rgb encoded */
RenderLine = p_vout->RenderRGBLine;
break;
case PIXEL_PICTURE: /* picture is pixel encoded */
RenderLine = p_vout->RenderPixelLine;
break;
case RGB_MASK_PICTURE: /* picture is a 1 rgb bpp mask */
RenderLine = p_vout->RenderRGBMaskLine;
break;
case PIXEL_MASK_PICTURE: /* picture is a 1 pixel bpp mask */
RenderLine = p_vout->RenderPixelMaskLine;
break;
/* ?? add YUV types */
#ifdef DEBUG
default: /* internal error, which should never happen */
intf_DbgMsg("%p -> unknown type for picture %p\n", p_vout, p_pic);
break;
#endif
}
/* For non blank pictures, loop on lines */
for( ; i_pic_y < i_height; i_pic_y++ )
{
/* First step: check if line has to be rendered. This is not obvious since
* if display ratio is less than 1:1, some of the lines don't need to
* be displayed, and therefore do not need to be rendered. */
switch( p_pic->i_v_ratio )
{
case DISPLAY_RATIO_HALF: /* 1:2 half size */
/* Only even lines are rendered, and copied once */
i_line_width = i_pic_y % 2;
break;
case DISPLAY_RATIO_NORMAL: /* 1:1 normal size */
/* All lines are rendered and copied once */
i_line_width = 1;
break;
case DISPLAY_RATIO_DOUBLE: /* 2:1 double size */
/* All lines are rendered and copied twice */
i_line_width = 2;
break;
}
if( i_line_width )
{
/* Computed line width can be reduced if it would cause to render
* outside the display */
if( i_y + i_line_width > p_vout->i_height )
{
i_line_width = p_vout->i_height - i_y;
}
/* Second step: render line. Since direct access to the rendering
* buffer is required, functions in charge of rendering the line
* are part of the display driver. Because this step is critical
* and require high optimization, different methods are used
* depending of the horizontal display ratio, the image type and
* the screen depth. */
RenderLine( p_vout, p_pic, i_x, i_y, i_pic_x, i_pic_y,
i_width, i_line_width, p_pic->i_h_ratio );
/* Increment display line index */
i_y += i_line_width;
}
}
}
/*******************************************************************************
* ClipPicture: clip a picture in display window
*******************************************************************************
* This function computes picture placement in display window and rendering
* zone, according to wished picture placement and display ratio. It must be
* called twice, once and with the x coordinates and once with the y
* coordinates.
* The pi_pic_ofs parameter is only written, but pi_ofs and pi_pic_size must
* be valid arguments. Note that *pi_pic_size is still the rendering zone size,
* starting from picture offset 0 and not the size starting from *pi_pic_ofs
* (same thing for i_size).
*******************************************************************************
* Messages types: vout, major code 28
*******************************************************************************/
static void ClipPicture( int *pi_ofs, int i_size, int *pi_pic_ofs, int *pi_pic_size,
int i_ratio, int i_placement )
{
int i_ofs; /* temporary picture position */
/* Computes base picture position */
switch( i_placement )
{
case -1: /* left/top aligned */
i_ofs = *pi_ofs;
break;
case 0: /* centered */
i_ofs = *pi_ofs + (i_size - *pi_pic_size) / 2;
break;
case 1: /* right/bottom aligned */
i_ofs = *pi_ofs + i_size - *pi_pic_size;
break;
#ifdef DEBUG
default: /* internal error, which should never happen */
intf_DbgMsg("invalid placement\n");
break;
#endif
}
/* Computes base rendering position and update picture position - i_ofs is
* the picture position, and can be negative */
if( i_ofs < 0 ) /* picture starts outside the screen */
{
switch( i_ratio )
{
case DISPLAY_RATIO_HALF: /* 1:2 half size */
*pi_pic_ofs = - *pi_ofs * 2;
break;
case DISPLAY_RATIO_NORMAL: /* 1:1 normal size */
*pi_pic_ofs = -*pi_ofs;
break;
case DISPLAY_RATIO_DOUBLE: /* 2:1 double size */
*pi_pic_ofs = -CEIL(*pi_ofs, 2);
break;
#ifdef DEBUG
default: /* internal error, which should never happen */
intf_DbgMsg("unsupported ratio\n");
break;
#endif
}
*pi_ofs = 0;
}
else /* picture starts inside the screen */
{
*pi_pic_ofs = 0;
*pi_ofs = i_ofs;
}
/* Computes rendering size - i_ofs is the picture position, and can be
* negative, *pi_ofs is the real picture position, and is always positive */
switch( i_ratio )
{
case DISPLAY_RATIO_HALF: /* 1:2 half size */
if( i_ofs + CEIL(*pi_pic_size, 2) > i_size )
{
*pi_pic_size = ( i_size - i_ofs ) * 2;
}
break;
case DISPLAY_RATIO_NORMAL: /* 1:1 normal size */
if( i_ofs + *pi_pic_size > i_size )
{
*pi_pic_size = i_size - i_ofs;
}
break;
case DISPLAY_RATIO_DOUBLE: /* 2:1 double size */
if( *pi_ofs + *pi_pic_size * 2 > i_size )
{
*pi_pic_size = ( i_size - i_ofs ) / 2;
}
break;
#ifdef DEBUG
default: /* internal error, which should never happen */
intf_DbgMsg("unsupported ratio\n");
break;
#endif
}
/*???*/
}
......@@ -10,6 +10,9 @@
/*******************************************************************************
* Preamble
*******************************************************************************/
#include "vlc.h"
/*
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
......@@ -41,20 +44,50 @@
#include "xconsole.h"
#include "interface.h"
#include "intf_msg.h"
*/
#include "pgm_data.h"
/*******************************************************************************
* vout_sys_t: video output X11 method descriptor
*******************************************************************************
* This structure is part of the video output thread descriptor.
* It describes the X11 specific properties of an output thread. X11 video
* output is performed through regular resizable windows. Windows can be
* dynamically resized to adapt to the size of the streams.
*******************************************************************************/
typedef struct vout_sys_s
{
/* User settings */
boolean_t b_shm; /* shared memory extension flag */
/*
* Local prototypes
*/
static int X11CheckConfiguration ( video_cfg_t *p_cfg );
/* Internal settings and properties */
Display * p_display; /* display pointer */
int i_screen; /* screen number */
Window root_window; /* root window */
Window window; /* window instance handler */
GC gc; /* graphic context instance handler */
/* Color maps and translation tables - some of those tables are shifted,
* see x11.c for more informations. */
u8 * trans_16bpp_red; /* red (16 bpp) (SHIFTED !) */
u8 * trans_16bpp_green; /* green (16 bpp) (SHIFTED !) */
u8 * trans_16bpp_blue; /* blue (16 bpp) (SHIFTED !) */
/* Display buffers and shared memory information */
int i_buffer_index; /* buffer index */
XImage * p_ximage[2]; /* XImage pointer */
XShmSegmentInfo shm_info[2]; /* shared memory zone information */
int i_completion_type; /* ?? */
} vout_sys_t;
static int X11OpenDisplay ( vout_thread_t *p_vout );
/*******************************************************************************
* Local prototypes
*******************************************************************************/
static int X11GetProperties ( vout_thread_t *p_vout );
static int X11CreateWindow ( vout_thread_t *p_vout );
static int X11CreateImages ( vout_thread_t *p_vout );
static void X11DestroyImages ( vout_thread_t *p_vout );
static void X11DestroyWindow ( vout_thread_t *p_vout );
static void X11CloseDisplay ( vout_thread_t *p_vout );
static int X11CreateImage ( vout_thread_t *p_vout, XImage **pp_ximage );
static void X11DestroyImage ( XImage *p_ximage );
static int X11CreateShmImage ( vout_thread_t *p_vout, XImage **pp_ximage,
......@@ -62,146 +95,74 @@ static int X11CreateShmImage ( vout_thread_t *p_vout, XImage **pp_ximage,
static void X11DestroyShmImage ( vout_thread_t *p_vout, XImage *p_ximage,
XShmSegmentInfo *p_shm_info );
static vout_render_blank_t X11RenderRGBBlank;
static vout_render_blank_t X11RenderPixelBlank8bpp;
static vout_render_blank_t X11RenderPixelBlank16bpp;
static vout_render_blank_t X11RenderPixelBlank24bpp;
static vout_render_blank_t X11RenderPixelBlank32bpp;
static vout_render_line_t X11RenderRGBLine8bpp;
static vout_render_line_t X11RenderRGBLine16bpp;
static vout_render_line_t X11RenderRGBLine24bpp;
static vout_render_line_t X11RenderRGBLine32bpp;
static vout_render_line_t X11RenderPixelLine8bpp;
static vout_render_line_t X11RenderPixelLine16bpp;
static vout_render_line_t X11RenderPixelLine24bpp;
static vout_render_line_t X11RenderPixelLine32bpp;
static vout_render_line_t X11RenderRGBMaskLine;
static vout_render_line_t X11RenderPixelMaskLine8bpp;
static vout_render_line_t X11RenderPixelMaskLine16bpp;
static vout_render_line_t X11RenderPixelMaskLine24bpp;
static vout_render_line_t X11RenderPixelMaskLine32bpp;
/* ?? YUV types */
/*******************************************************************************
* vout_X11AllocOutputMethod: allocate X11 video thread output method
* vout_SysCreate: allocate X11 video thread output method
*******************************************************************************
* This function creates a X11 output method descriptor in the vout_thread_t
* desriptor and initialize it.
* Following configuration properties are used:
* VIDEO_CFG_DISPLAY display used
* VIDEO_CFG_TITLE window title
* VIDEO_CFG_SHM_EXT try to use XShm extension
* This function allocate and initialize a X11 vout method.
*******************************************************************************/
int vout_X11AllocOutputMethod( vout_thread_t *p_vout, video_cfg_t *p_cfg )
int vout_SysCreate( vout_thread_t *p_vout, Display *p_display, Window root_window )
{
/* Check configuration */
if( X11CheckConfiguration(p_cfg) )
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
if( p_vout->p_sys != NULL )
{
return( 1 );
}
/* Allocate descriptor */
p_vout->p_x11 = (vout_x11_t *) malloc( sizeof( vout_x11_t ) );
if( p_vout->p_x11 == NULL )
{
intf_ErrMsg("vout error 101-1: cannot allocate X11 method descriptor: %s\n",
strerror(errno));
return( 1 );
p_vout->p_sys->p_display = p_display;
p_vout->p_sys->root_window = root_window;
return( 0 );
}
/* Initialize fields - string passed in configuration structure are copied
* since they can be destroyed at any moment - remember that NULL is a valid
* value for psz_display */
p_vout->p_x11->psz_title = (char *) malloc( strlen(p_cfg->psz_title) + 1);
if( p_vout->p_x11->psz_title == NULL )
{
free( p_vout->p_x11 );
return( 1 );
}
strcpy( p_vout->p_x11->psz_title, p_cfg->psz_title );
if( p_cfg->psz_display != NULL )
{
p_vout->p_x11->psz_display = (char *) malloc( strlen(p_cfg->psz_display) + 1);
if( p_vout->p_x11->psz_display == NULL )
{
free( p_vout->p_x11->psz_title );
free( p_vout->p_x11 );
return( 1 );
}
strcpy( p_vout->p_x11->psz_display, p_cfg->psz_display );
}
else
{
p_vout->p_x11->psz_display = NULL;
}
p_vout->p_x11->b_shm_ext = p_cfg->b_shm_ext;
return( 0 );
}
/*******************************************************************************
* vout_X11FreeOutputMethod: free X11 video thread output method
*******************************************************************************
* Free an X11 video thread output method allocated by
* vout_X11AllocOutputMethod()
*******************************************************************************/
void vout_X11FreeOutputMethod( vout_thread_t *p_vout )
{
if( p_vout->p_x11->psz_display != NULL )
{
free( p_vout->p_x11->psz_display );
}
free( p_vout->p_x11->psz_title );
free( p_vout->p_x11 );
}
/*******************************************************************************
* vout_X11CreateOutputMethod: create X11 video thread output method
* vout_SysInit: initialize X11 video thread output method
*******************************************************************************
* This function opens a display and create a X11 window according to the user
* configuration.
* This function create a X11 window according to the user configuration.
*******************************************************************************/
int vout_X11CreateOutputMethod( vout_thread_t *p_vout )
int vout_SysInit( vout_thread_t *p_vout )
{
if( X11OpenDisplay( p_vout ) ) /* open display */
if( X11GetProperties( p_vout ) ) /* get display properties */
{
free( p_vout->p_x11 );
return( 1 );
}
if( X11CreateWindow( p_vout ) ) /* create window */
{
X11CloseDisplay( p_vout );
free( p_vout->p_x11 );
return( 1 );
}
if( X11CreateImages( p_vout ) ) /* create images */
{
X11DestroyWindow( p_vout );
X11CloseDisplay( p_vout );
free( p_vout->p_x11 );
return( 1 );
}
intf_DbgMsg("%p -> success, depth=%d bpp, XShm=%d\n",
p_vout, p_vout->i_screen_depth, p_vout->p_x11->b_shm_ext);
intf_DbgMsg("%p -> success, depth=%d bpp, Shm=%d\n",
p_vout, p_vout->i_screen_depth, p_vout->p_sys->b_shm );
return( 0 );
}
/*******************************************************************************
* vout_X11DestroyOutputMethod: destroy X11 video thread output method
*******************************************************************************
* Destroys an output method created by vout_X11CreateOutputMethod
* vout_SysEnd: terminate X11 video thread output method
*******************************************************************************
* Messages type: vout, major code: 102
* Terminate an output method created by vout_X11CreateOutputMethod
*******************************************************************************/
void vout_X11DestroyOutputMethod( vout_thread_t *p_vout )
void vout_SysEnd( vout_thread_t *p_vout )
{
X11DestroyImages( p_vout );
X11DestroyWindow( p_vout );
X11CloseDisplay( p_vout );
intf_DbgMsg("%p\n", p_vout );
}
/*******************************************************************************
* vout_X11ManageOutputMethod: handle X11 events
* vout_SysDestroy: destroy X11 video thread output method
*******************************************************************************
* Terminate an output method created by vout_X11CreateOutputMethod
*******************************************************************************/
void vout_SysDestroy( vout_thread_t *p_vout )
{
free( p_vout->p_sys );
}
/*******************************************************************************
* vout_SysManage: handle X11 events
*******************************************************************************
* This function should be called regularly by video output thread. It manages
* X11 events and allows window resizing. It returns a negative value if
......@@ -211,61 +172,15 @@ void vout_X11DestroyOutputMethod( vout_thread_t *p_vout )
*******************************************************************************
* Messages type: vout, major code: 103
*******************************************************************************/
int vout_X11ManageOutputMethod( vout_thread_t *p_vout )
int vout_SysManage( vout_thread_t *p_vout )
{
XEvent xevent; /* X11 event */
boolean_t b_resized; /* window has been resized */
/* Handle X11 events: ConfigureNotify events are parsed to know if the
* output window's size changed, MapNotify and UnmapNotify to know if the
* window is mapped (and if the display is usefull), and ClientMessages
* to intercept window destruction requests */
b_resized = 0;
while( XCheckWindowEvent( p_vout->p_x11->p_display, p_vout->p_x11->window,
StructureNotifyMask, &xevent ) == True )
{
/* ConfigureNotify event: prepare */
if( (xevent.type == ConfigureNotify)
&& ((xevent.xconfigure.width != p_vout->i_width)
|| (xevent.xconfigure.height != p_vout->i_height)) )
{
/* Update dimensions */
b_resized = 1;
p_vout->i_width = xevent.xconfigure.width;
p_vout->i_height = xevent.xconfigure.height;
}
/* MapNotify event: change window status and disable screen saver */
else if( (xevent.type == MapNotify) && !p_vout->b_active )
{
XDisableScreenSaver( p_vout->p_x11->p_display );
p_vout->b_active = 1;
}
/* UnmapNotify event: change window status and enable screen saver */
else if( (xevent.type == UnmapNotify) && p_vout->b_active )
{
XEnableScreenSaver( p_vout->p_x11->p_display );
p_vout->b_active = 0;
}
/* ClientMessage event - only WM_PROTOCOLS with WM_DELETE_WINDOW data
* are handled - according to the man pages, the format is always 32
* in this case */
else if( (xevent.type == ClientMessage)
/* && (xevent.xclient.message_type == p_vout->p_x11->wm_protocols)
&& (xevent.xclient.data.l[0] == p_vout->p_x11->wm_delete_window )*/ )
{
intf_DbgMsg("******* ClientMessage ******\n");
boolean_t b_resized;
//??
/* ?? this function should not receive any usefull X11 messages, since they
* have tobe treated by the main interface window - check it. */
return 0; //??
/* ?? this never happens :( */
return( -1 );
}
#ifdef DEBUG
/* Other event */
else
{
intf_DbgMsg("%p -> unhandled event type %d received\n", p_vout, xevent.type );
}
#endif
}
/* If window has been resized, re-create images */
if( b_resized )
......@@ -286,26 +201,24 @@ int vout_X11ManageOutputMethod( vout_thread_t *p_vout )
}
/*******************************************************************************
* vout_X11DisplayOutput: displays previously rendered output
* vout_SysDisplay: displays previously rendered output
*******************************************************************************
* This function send the currently rendered image to X11 server, wait until
* it is displayed and switch the two rendering buffer, preparing next frame.
*******************************************************************************
* Messages type: vout, major code: 105
*******************************************************************************/
void vout_X11DisplayOutput( vout_thread_t *p_vout )
void vout_SysDisplay( vout_thread_t *p_vout )
{
if( p_vout->p_x11->b_shm_ext) /* XShm is used */
if( p_vout->p_sys->b_shm) /* XShm is used */
{
/* Display rendered image using shared memory extension */
XShmPutImage(p_vout->p_x11->p_display, p_vout->p_x11->window, p_vout->p_x11->gc,
p_vout->p_x11->p_ximage[ p_vout->p_x11->i_buffer_index ],
XShmPutImage(p_vout->p_sys->p_display, p_vout->p_sys->window, p_vout->p_sys->gc,
p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ],
0, 0, 0, 0,
p_vout->p_x11->p_ximage[ p_vout->p_x11->i_buffer_index ]->width,
p_vout->p_x11->p_ximage[ p_vout->p_x11->i_buffer_index ]->height, True);
p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->width,
p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->height, True);
/* Send the order to the X server */
XFlush(p_vout->p_x11->p_display);
XFlush(p_vout->p_sys->p_display);
/* ?? wait until effective display ? */
/* do XNextEvent(Display_Ptr, &xev);
......@@ -313,145 +226,49 @@ void vout_X11DisplayOutput( vout_thread_t *p_vout )
}
else /* regular X11 capabilities are used */
{
XPutImage(p_vout->p_x11->p_display, p_vout->p_x11->window, p_vout->p_x11->gc,
p_vout->p_x11->p_ximage[ p_vout->p_x11->i_buffer_index ],
XPutImage(p_vout->p_sys->p_display, p_vout->p_sys->window, p_vout->p_sys->gc,
p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ],
0, 0, 0, 0,
p_vout->p_x11->p_ximage[ p_vout->p_x11->i_buffer_index ]->width,
p_vout->p_x11->p_ximage[ p_vout->p_x11->i_buffer_index ]->height);
p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->width,
p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->height);
/* Send the order to the X server */
XFlush(p_vout->p_x11->p_display); /* ?? not needed ? */
XFlush(p_vout->p_sys->p_display); /* ?? not needed ? */
}
/* Swap buffers */
p_vout->p_x11->i_buffer_index = ++p_vout->p_x11->i_buffer_index & 1;
p_vout->p_sys->i_buffer_index = ++p_vout->p_sys->i_buffer_index & 1;
}
/* following functions are local */
/*******************************************************************************
* X11CheckConfiguration: check configuration.
*******************************************************************************
* Set default parameters where required. In DEBUG mode, check if configuration
* is valid.
* X11GetProperties: get properties of a given display
*******************************************************************************
* Messages type: vout, major code: 116
* Opens an X11 display and try to detect usable X extensions.
*******************************************************************************/
static int X11CheckConfiguration( video_cfg_t *p_cfg )
static int X11GetProperties( vout_thread_t *p_vout )
{
/* Window dimensions */
if( !( p_cfg->i_properties & VIDEO_CFG_WIDTH ) )
{
p_cfg->i_width = VOUT_WIDTH;
}
if( !( p_cfg->i_properties & VIDEO_CFG_HEIGHT ) )
{
p_cfg->i_height = VOUT_HEIGHT;
}
/* Display */
if( !( p_cfg->i_properties & VIDEO_CFG_DISPLAY ) )
{
p_cfg->psz_display = NULL;
}
/* Window title */
if( !( p_cfg->i_properties & VIDEO_CFG_TITLE ) )
{
p_cfg->psz_title = VOUT_TITLE;
}
/* Use of XShm extension */
if( !( p_cfg->i_properties & VIDEO_CFG_SHM_EXT ) )
{
p_cfg->b_shm_ext = VOUT_SHM_EXT;
}
return( 0 );
}
/*******************************************************************************
* X11OpenDisplay: open X11 display
*******************************************************************************
* Opens an X11 display and set up pictures rendering functions according to
* screen depth.
* Following configuration properties are used:
* VIDEO_CFG_DISPLAY display used
* VIDEO_CFG_SHM_EXT try to use XShm extension
*******************************************************************************
* Messages type: vout, major code: 106
*******************************************************************************/
static int X11OpenDisplay( vout_thread_t *p_vout )
{
char *psz_display;
/* Open display, using display name provided or default one */
psz_display = XDisplayName( p_vout->p_x11->psz_display );
p_vout->p_x11->p_display = XOpenDisplay( psz_display );
if( !p_vout->p_x11->p_display ) /* error */
{
intf_ErrMsg("vout error 106-1: can't open display %s\n", psz_display );
return( 1 );
}
/* Check if XShm extension is wished and supported */
/* ?? in old client, we checked if display was local or not - is it really
* needed ? */
if( p_vout->p_x11->b_shm_ext )
{
p_vout->p_x11->b_shm_ext = (XShmQueryExtension(p_vout->p_x11->p_display) == True);
}
else
{
p_vout->p_x11->b_shm_ext = 0;
}
/* Check if extensions are supported */
p_vout->p_sys->b_shm = VOUT_XSHM && (XShmQueryExtension(p_vout->p_sys->p_display) == True);
/* Get the screen number and depth (bpp) - select functions depending
* of this value. i_bytes_per_pixel is required since on some hardware,
* depth as 15bpp are used, which can cause problems with later memory
* allocation. */
p_vout->p_x11->i_screen = DefaultScreen( p_vout->p_x11->p_display );
p_vout->i_screen_depth = DefaultDepth( p_vout->p_x11->p_display,
p_vout->p_x11->i_screen );
p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
p_vout->i_screen_depth = DefaultDepth( p_vout->p_sys->p_display,
p_vout->p_sys->i_screen );
switch( p_vout->i_screen_depth )
{
case 8: /* 8 bpp (256 colors) */
p_vout->i_bytes_per_pixel = 1;
p_vout->RenderRGBBlank = X11RenderRGBBlank;
p_vout->RenderPixelBlank = X11RenderPixelBlank8bpp;
p_vout->RenderRGBLine = X11RenderRGBLine8bpp;
p_vout->RenderPixelLine = X11RenderPixelLine8bpp;
p_vout->RenderRGBMaskLine = X11RenderRGBMaskLine;
p_vout->RenderPixelMaskLine = X11RenderPixelMaskLine8bpp;
/*
Process_Frame=Dither_Frame;
Process_Top_Field=Dither_Top_Field;
Process_Bottom_Field=Dither_Bottom_Field;
Process_Top_Field420=Dither_Top_Field420;
Process_Bottom_Field420=Dither_Bottom_Field420; ?? */
break;
case 15: /* 15 bpp (16bpp with a missing green bit) */
p_vout->i_bytes_per_pixel = 2;
/*
?? */
p_vout->RenderRGBBlank = X11RenderRGBBlank;
p_vout->RenderPixelBlank = X11RenderPixelBlank16bpp;
p_vout->RenderRGBLine = X11RenderRGBLine16bpp;
p_vout->RenderPixelLine = X11RenderPixelLine16bpp;
p_vout->RenderRGBMaskLine = X11RenderRGBMaskLine;
p_vout->RenderPixelMaskLine = X11RenderPixelMaskLine16bpp;
/* ?? probably a 16bpp with differenr convertion functions - just map
* functions, then switch to 16bpp */
break;
case 16: /* 16 bpp (65536 colors) */
p_vout->i_bytes_per_pixel = 2;
p_vout->RenderRGBBlank = X11RenderRGBBlank;
p_vout->RenderPixelBlank = X11RenderPixelBlank16bpp;
p_vout->RenderRGBLine = X11RenderRGBLine16bpp;
p_vout->RenderPixelLine = X11RenderPixelLine16bpp;
p_vout->RenderRGBMaskLine = X11RenderRGBMaskLine;
p_vout->RenderPixelMaskLine = X11RenderPixelMaskLine16bpp;
/*
Process_Frame=Translate_Frame;
Process_Top_Field=Translate_Top_Field;
......@@ -462,12 +279,7 @@ static int X11OpenDisplay( vout_thread_t *p_vout )
case 24: /* 24 bpp (millions of colors) */
p_vout->i_bytes_per_pixel = 3;
p_vout->RenderRGBBlank = X11RenderRGBBlank;
p_vout->RenderPixelBlank = X11RenderPixelBlank24bpp;
p_vout->RenderRGBLine = X11RenderRGBLine24bpp;
p_vout->RenderPixelLine = X11RenderPixelLine24bpp;
p_vout->RenderRGBMaskLine = X11RenderRGBMaskLine;
p_vout->RenderPixelMaskLine = X11RenderPixelMaskLine24bpp;
/*
Process_Frame=Translate_Frame;
Process_Top_Field=Translate_Top_Field;
......@@ -478,12 +290,6 @@ static int X11OpenDisplay( vout_thread_t *p_vout )
case 32: /* 32 bpp (millions of colors) */
p_vout->i_bytes_per_pixel = 4;
p_vout->RenderRGBBlank = X11RenderRGBBlank;
p_vout->RenderPixelBlank = X11RenderPixelBlank32bpp;
p_vout->RenderRGBLine = X11RenderRGBLine32bpp;
p_vout->RenderPixelLine = X11RenderPixelLine32bpp;
p_vout->RenderRGBMaskLine = X11RenderRGBMaskLine;
p_vout->RenderPixelMaskLine = X11RenderPixelMaskLine32bpp;
/*
Process_Frame=Translate_Frame;
Process_Top_Field=Translate_Top_Field;
......@@ -495,7 +301,6 @@ static int X11OpenDisplay( vout_thread_t *p_vout )
default: /* unsupported screen depth */
intf_ErrMsg("vout error 106-2: screen depth %i is not supported\n",
p_vout->i_screen_depth);
XCloseDisplay( p_vout->p_x11->p_display );
return( 1 );
break;
}
......@@ -503,109 +308,64 @@ static int X11OpenDisplay( vout_thread_t *p_vout )
}
/*******************************************************************************
* X11CreateWindow: create X11 window
*******************************************************************************
* Create and set-up the output window.
* Following configuration properties are used:
* VIDEO_CFG_WIDTH window width
* VIDEO_CFG_HEIGHT window height
* VIDEO_CFG_TITLE window title
* X11CreateWindow: create X11 vout window
*******************************************************************************
* Messages type: vout, major code: 107
* The video output window will be created. Normally, this window is wether
* full screen or part of a parent window. Therefore, it does not need a
* title or other hints. Thery are still supplied in case the window would be
* spawned as a standalone one by the interface.
*******************************************************************************/
static int X11CreateWindow( vout_thread_t *p_vout )
{
XSizeHints xsize_hints;
XSetWindowAttributes xwindow_attributes;
XGCValues xgcvalues;
XEvent xevent;
boolean_t b_expose;
boolean_t b_configure_notify;
boolean_t b_map_notify;
/* Prepare window manager hints and properties */
xsize_hints.base_width = p_vout->i_width;
xsize_hints.base_height = p_vout->i_height;
xsize_hints.flags = PSize;
p_vout->p_x11->wm_protocols = XInternAtom( p_vout->p_x11->p_display, "WM_PROTOCOLS", True );
p_vout->p_x11->wm_delete_window = XInternAtom( p_vout->p_x11->p_display, "WM_DELETE_WINDOW", True );
/* ?? add icons and placement hints ? */
/* Prepare window attributes */
xwindow_attributes.backing_store = Always; /* save the hidden part */
/* Create the window and set hints - the window must receive ConfigureNotify
* events, and, until it is displayed, Expose and MapNotify events. */
p_vout->p_x11->window = XCreateSimpleWindow( p_vout->p_x11->p_display,
DefaultRootWindow( p_vout->p_x11->p_display ),
p_vout->p_sys->window = XCreateSimpleWindow( p_vout->p_sys->p_display,
p_vout->p_sys->root_window,
0, 0,
p_vout->i_width, p_vout->i_height,
0, 0, 0);
XSelectInput( p_vout->p_x11->p_display, p_vout->p_x11->window,
XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window,
ExposureMask | StructureNotifyMask );
XChangeWindowAttributes( p_vout->p_x11->p_display, p_vout->p_x11->window,
XChangeWindowAttributes( p_vout->p_sys->p_display, p_vout->p_sys->window,
CWBackingStore, &xwindow_attributes);
/* Set window manager hints and properties: size hints, command, window's name,
* and accepted protocols */
XSetWMNormalHints( p_vout->p_x11->p_display, p_vout->p_x11->window, &xsize_hints );
XSetCommand( p_vout->p_x11->p_display, p_vout->p_x11->window,
p_program_data->ppsz_argv, p_program_data->i_argc );
XStoreName( p_vout->p_x11->p_display, p_vout->p_x11->window, p_vout->p_x11->psz_title );
if( (p_vout->p_x11->wm_protocols == None) /* use WM_DELETE_WINDOW */
|| (p_vout->p_x11->wm_delete_window == None)
|| !XSetWMProtocols( p_vout->p_x11->p_display, p_vout->p_x11->window,
&p_vout->p_x11->wm_delete_window, 1 ) )
{
/* WM_DELETE_WINDOW is not supported by window manager */
intf_Msg("vout: missing or bad window manager - please exit program kindly.\n");
}
/* Creation of a graphic context that doesn't generate a GraphicsExpose event
when using functions like XCopyArea */
xgcvalues.graphics_exposures = False;
p_vout->p_x11->gc = XCreateGC( p_vout->p_x11->p_display, p_vout->p_x11->window,
p_vout->p_sys->gc = XCreateGC( p_vout->p_sys->p_display, p_vout->p_sys->window,
GCGraphicsExposures, &xgcvalues);
/* Create color system */
/*?? if( CreateX11Colors( p_vout ) )
{
intf_ErrMsg("vout error 107-1: can't initialize color system\n");
XCloseDisplay( p_vout->p_x11->p_display );
return( - 1 );
}*/
/* Send orders to server, and wait until window is displayed - three events
/* Send orders to server, and wait until window is displayed - two events
* must be received: a MapNotify event, an Expose event allowing drawing in the
* window, and a ConfigureNotify to get the window dimensions. Once those events
* have been received, only ConfigureNotify events need to be received. */
* window */
b_expose = 0;
b_configure_notify = 0;
b_map_notify = 0;
XMapWindow( p_vout->p_x11->p_display, p_vout->p_x11->window);
XMapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window);
do
{
XNextEvent( p_vout->p_x11->p_display, &xevent);
XNextEvent( p_vout->p_sys->p_display, &xevent);
if( (xevent.type == Expose)
&& (xevent.xexpose.window == p_vout->p_x11->window) )
&& (xevent.xexpose.window == p_vout->p_sys->window) )
{
b_expose = 1;
}
else if( (xevent.type == MapNotify)
&& (xevent.xmap.window == p_vout->p_x11->window) )
&& (xevent.xmap.window == p_vout->p_sys->window) )
{
b_map_notify = 1;
}
else if( (xevent.type == ConfigureNotify)
&& (xevent.xconfigure.window == p_vout->p_x11->window) )
{
b_configure_notify = 1;
p_vout->i_width = xevent.xconfigure.width;
p_vout->i_height = xevent.xconfigure.height;
}
}
while( !( b_expose && b_configure_notify && b_map_notify ) );
XSelectInput( p_vout->p_x11->p_display, p_vout->p_x11->window, StructureNotifyMask );
while( !( b_expose && b_map_notify ) );
XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window, 0 );
/* At this stage, the window is openned, displayed, and ready to receive data */
p_vout->b_active = 1;
......@@ -627,51 +387,51 @@ static int X11CreateImages( vout_thread_t *p_vout )
/* Create XImages using XShm extension - on failure, fall back to regular
* way (and destroy the first image if it was created successfully) */
if( p_vout->p_x11->b_shm_ext )
if( p_vout->p_sys->b_shm )
{
/* Create first image */
i_err = X11CreateShmImage( p_vout, &p_vout->p_x11->p_ximage[0],
&p_vout->p_x11->shm_info[0] );
i_err = X11CreateShmImage( p_vout, &p_vout->p_sys->p_ximage[0],
&p_vout->p_sys->shm_info[0] );
if( !i_err ) /* first image has been created */
{
/* Create second image */
if( X11CreateShmImage( p_vout, &p_vout->p_x11->p_ximage[1],
&p_vout->p_x11->shm_info[1] ) )
if( X11CreateShmImage( p_vout, &p_vout->p_sys->p_ximage[1],
&p_vout->p_sys->shm_info[1] ) )
{ /* error creating the second image */
X11DestroyShmImage( p_vout, p_vout->p_x11->p_ximage[0],
&p_vout->p_x11->shm_info[0] );
X11DestroyShmImage( p_vout, p_vout->p_sys->p_ximage[0],
&p_vout->p_sys->shm_info[0] );
i_err = 1;
}
}
if( i_err ) /* an error occured */
{
intf_Msg("vout: XShm extension desactivated\n" );
p_vout->p_x11->b_shm_ext = 0;
p_vout->p_sys->b_shm = 0;
}
}
/* Create XImages without XShm extension */
if( !p_vout->p_x11->b_shm_ext )
if( !p_vout->p_sys->b_shm )
{
if( X11CreateImage( p_vout, &p_vout->p_x11->p_ximage[0] ) )
if( X11CreateImage( p_vout, &p_vout->p_sys->p_ximage[0] ) )
{
intf_Msg("vout error 108-1: can't create images\n");
p_vout->p_x11->p_ximage[0] = NULL;
p_vout->p_x11->p_ximage[1] = NULL;
p_vout->p_sys->p_ximage[0] = NULL;
p_vout->p_sys->p_ximage[1] = NULL;
return( -1 );
}
if( X11CreateImage( p_vout, &p_vout->p_x11->p_ximage[1] ) )
if( X11CreateImage( p_vout, &p_vout->p_sys->p_ximage[1] ) )
{
intf_Msg("vout error 108-2: can't create images\n");
X11DestroyImage( p_vout->p_x11->p_ximage[0] );
p_vout->p_x11->p_ximage[0] = NULL;
p_vout->p_x11->p_ximage[1] = NULL;
X11DestroyImage( p_vout->p_sys->p_ximage[0] );
p_vout->p_sys->p_ximage[0] = NULL;
p_vout->p_sys->p_ximage[1] = NULL;
return( -1 );
}
}
/* Set buffer index to 0 */
p_vout->p_x11->i_buffer_index = 0;
p_vout->p_sys->i_buffer_index = 0;
return( 0 );
}
......@@ -685,17 +445,17 @@ static int X11CreateImages( vout_thread_t *p_vout )
*******************************************************************************/
static void X11DestroyImages( vout_thread_t *p_vout )
{
if( p_vout->p_x11->b_shm_ext ) /* Shm XImages... */
if( p_vout->p_sys->b_shm ) /* Shm XImages... */
{
X11DestroyShmImage( p_vout, p_vout->p_x11->p_ximage[0],
&p_vout->p_x11->shm_info[0] );
X11DestroyShmImage( p_vout, p_vout->p_x11->p_ximage[1],
&p_vout->p_x11->shm_info[1] );
X11DestroyShmImage( p_vout, p_vout->p_sys->p_ximage[0],
&p_vout->p_sys->shm_info[0] );
X11DestroyShmImage( p_vout, p_vout->p_sys->p_ximage[1],
&p_vout->p_sys->shm_info[1] );
}
else /* ...or regular XImages */
{
X11DestroyImage( p_vout->p_x11->p_ximage[0] );
X11DestroyImage( p_vout->p_x11->p_ximage[1] );
X11DestroyImage( p_vout->p_sys->p_ximage[0] );
X11DestroyImage( p_vout->p_sys->p_ximage[1] );
}
}
......@@ -708,27 +468,10 @@ static void X11DestroyImages( vout_thread_t *p_vout )
*******************************************************************************/
static void X11DestroyWindow( vout_thread_t *p_vout )
{
XUnmapWindow( p_vout->p_x11->p_display, p_vout->p_x11->window );
/* ?? DestroyX11Colors( p_vout ); */
/* ?? no more valid: colormap */
/* if( p_vout->p_x11->b_private_colormap )
{
XFreeColormap( p_vout->p_x11->p_display, p_vout->p_x11->private_colormap);
} */
XFreeGC( p_vout->p_x11->p_display, p_vout->p_x11->gc );
XDestroyWindow( p_vout->p_x11->p_display, p_vout->p_x11->window );
}
/*******************************************************************************
* X11CloseDisplay: close X11 display
*******************************************************************************
* Close an X11 display openned by vout_X11OpenDisplay().
*******************************************************************************
* Messages type: vout, major code: 111
*******************************************************************************/
static void X11CloseDisplay( vout_thread_t *p_vout )
{
XCloseDisplay( p_vout->p_x11->p_display ); /* close display */
intf_DbgMsg("vout window: 0x%x\n", p_vout->p_sys->window );
XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
XFreeGC( p_vout->p_sys->p_display, p_vout->p_sys->gc );
XDestroyWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
}
/*******************************************************************************
......@@ -770,8 +513,8 @@ static int X11CreateImage( vout_thread_t *p_vout, XImage **pp_ximage )
}
/* Create XImage */
*pp_ximage = XCreateImage( p_vout->p_x11->p_display,
DefaultVisual(p_vout->p_x11->p_display, p_vout->p_x11->i_screen),
*pp_ximage = XCreateImage( p_vout->p_sys->p_display,
DefaultVisual(p_vout->p_sys->p_display, p_vout->p_sys->i_screen),
p_vout->i_screen_depth, ZPixmap, 0, pb_data,
p_vout->i_width, p_vout->i_height, i_quantum, 0);
if(! *pp_ximage ) /* error */
......@@ -804,8 +547,8 @@ static int X11CreateShmImage( vout_thread_t *p_vout, XImage **pp_ximage,
XShmSegmentInfo *p_shm_info)
{
/* Create XImage */
*pp_ximage = XShmCreateImage( p_vout->p_x11->p_display,
DefaultVisual(p_vout->p_x11->p_display, p_vout->p_x11->i_screen),
*pp_ximage = XShmCreateImage( p_vout->p_sys->p_display,
DefaultVisual(p_vout->p_sys->p_display, p_vout->p_sys->i_screen),
p_vout->i_screen_depth, ZPixmap, 0,
p_shm_info, p_vout->i_width, p_vout->i_height );
if(! *pp_ximage ) /* error */
......@@ -844,7 +587,7 @@ static int X11CreateShmImage( vout_thread_t *p_vout, XImage **pp_ximage,
/* Attach shared memory segment to X server (read only) */
p_shm_info->readOnly = True;
if( XShmAttach( p_vout->p_x11->p_display, p_shm_info ) == False ) /* error */
if( XShmAttach( p_vout->p_sys->p_display, p_shm_info ) == False ) /* error */
{
intf_ErrMsg("vout error 113-4: can't attach shared memory to server\n");
shmdt( p_shm_info->shmaddr ); /* detach shared memory from process
......@@ -855,7 +598,7 @@ static int X11CreateShmImage( vout_thread_t *p_vout, XImage **pp_ximage,
/* ?? don't know what it is. Function XShmGetEventBase prototype is defined
* in mit-shm document, but does not appears in any header. */
p_vout->p_x11->i_completion_type = XShmGetEventBase(p_vout->p_x11->p_display) + ShmCompletion;
p_vout->p_sys->i_completion_type = XShmGetEventBase(p_vout->p_sys->p_display) + ShmCompletion;
return( 0 );
}
......@@ -894,7 +637,7 @@ static void X11DestroyShmImage( vout_thread_t *p_vout, XImage *p_ximage,
return;
}
XShmDetach( p_vout->p_x11->p_display, p_shm_info ); /* detach from server */
XShmDetach( p_vout->p_sys->p_display, p_shm_info ); /* detach from server */
XDestroyImage( p_ximage );
if( shmdt( p_shm_info->shmaddr ) ) /* detach shared memory from process */
{ /* also automatic freeing... */
......@@ -905,224 +648,3 @@ static void X11DestroyShmImage( vout_thread_t *p_vout, XImage *p_ximage,
/* following functions are local rendering functions */
/*******************************************************************************
* X11RenderRGBBlank: RGB blank picture rendering function
*******************************************************************************
* Render a blank picture. Opposed to other rendering function, this one is
* picture-based and not line-based. Dimensions sent as parameters are effective
* dimensions of the rectangle to draw.
*******************************************************************************
* Messages type: vout, major code: ???
*******************************************************************************/
static void X11RenderRGBBlank( vout_thread_t *p_vout, pixel_t pixel,
int i_x, int i_y, int i_width, int i_height )
{
/* ?? convert rgb->pixel */
/* ?? call p_vout->RenderPixelBlank */
}
/*******************************************************************************
* X11RenderPixelBlank*: pixel blank picture rendering functions
*******************************************************************************
* Render a blank picture. Opposed to other rendering function, this one is
* picture-based and not line-based. Dimensions sent as parameters are effective
* dimensions of the rectangle to draw.
*******************************************************************************
* Messages type: vout, major code: 117
*******************************************************************************/
static void X11RenderPixelBlank8bpp( vout_thread_t *p_vout, pixel_t pixel,
int i_x, int i_y, int i_width, int i_height )
{
int i_line; /* current line */
int i_bytes_per_line; /* XImage bytes per line */
byte_t * p_data; /* XImage data */
i_bytes_per_line = p_vout->p_x11->p_ximage[ p_vout->p_x11->i_buffer_index ]->bytes_per_line;
p_data = p_vout->p_x11->p_ximage[ p_vout->p_x11->i_buffer_index ]->data + i_bytes_per_line * i_y;
for( i_line = i_y; i_line < i_y + i_height; i_line++, p_data += i_bytes_per_line )
{
memset( p_data + i_x, pixel, i_width - i_x );
}
}
static void X11RenderPixelBlank16bpp( vout_thread_t *p_vout, pixel_t pixel,
int i_x, int i_y, int i_width, int i_height )
{
int i_line; /* current line */
int i_pixel; /* pixel offset */
int i_bytes_per_line; /* XImage bytes per line */
byte_t * p_data; /* XImage data */
i_bytes_per_line = p_vout->p_x11->p_ximage[ p_vout->p_x11->i_buffer_index ]->bytes_per_line;
p_data = p_vout->p_x11->p_ximage[ p_vout->p_x11->i_buffer_index ]->data + i_bytes_per_line * i_y;
for( i_line = i_y; i_line < i_y + i_height; i_line++, p_data += i_bytes_per_line )
{
for( i_pixel = 0; i_pixel < i_width; i_pixel++ )
{
((u16 *)p_data)[ i_x + i_pixel ] = pixel;
}
break;
}
}
static void X11RenderPixelBlank24bpp( vout_thread_t *p_vout, pixel_t pixel,
int i_x, int i_y, int i_width, int i_height )
{
int i_line; /* current line */
int i_pixel; /* pixel offset */
int i_bytes_per_line; /* XImage bytes per line */
byte_t * p_data; /* XImage data */
i_bytes_per_line = p_vout->p_x11->p_ximage[ p_vout->p_x11->i_buffer_index ]->bytes_per_line;
p_data = p_vout->p_x11->p_ximage[ p_vout->p_x11->i_buffer_index ]->data + i_bytes_per_line * i_y;
for( i_line = i_y; i_line < i_y + i_height; i_line++, p_data += i_bytes_per_line )
{
for( i_pixel = 0; i_pixel < i_width; i_pixel++ )
{
*(u32 *)(p_data + (i_x + i_pixel) * 3) |= pixel;
}
}
}
static void X11RenderPixelBlank32bpp( vout_thread_t *p_vout, pixel_t pixel,
int i_x, int i_y, int i_width, int i_height )
{
int i_line; /* current line */
int i_pixel; /* pixel offset */
int i_bytes_per_line; /* XImage bytes per line */
byte_t * p_data; /* XImage data */
i_bytes_per_line = p_vout->p_x11->p_ximage[ p_vout->p_x11->i_buffer_index ]->bytes_per_line;
p_data = p_vout->p_x11->p_ximage[ p_vout->p_x11->i_buffer_index ]->data + i_bytes_per_line * i_y;
for( i_line = i_y; i_line < i_y + i_height; i_line++, p_data += i_bytes_per_line )
{
for( i_pixel = 0; i_pixel < i_width; i_pixel++ )
{
((u32 *)p_data)[ i_x + i_pixel ] = pixel;
}
break;
}
}
/*******************************************************************************
* X11RenderRGBLine*: RGB picture rendering functions
*******************************************************************************
* Render a 24bpp RGB-encoded picture line.
*******************************************************************************
* Messages type: vout, major code: 118
*******************************************************************************/
static void X11RenderRGBLine8bpp( vout_thread_t *p_vout, picture_t *p_pic,
int i_x, int i_y, int i_pic_x, int i_pic_y,
int i_width, int i_line_width, int i_ratio )
{
/* ?? */
}
static void X11RenderRGBLine16bpp( vout_thread_t *p_vout, picture_t *p_pic,
int i_x, int i_y, int i_pic_x, int i_pic_y,
int i_width, int i_line_width, int i_ratio )
{
/* ?? */
}
static void X11RenderRGBLine24bpp( vout_thread_t *p_vout, picture_t *p_pic,
int i_x, int i_y, int i_pic_x, int i_pic_y,
int i_width, int i_line_width, int i_ratio )
{
/* ?? */
}
static void X11RenderRGBLine32bpp( vout_thread_t *p_vout, picture_t *p_pic,
int i_x, int i_y, int i_pic_x, int i_pic_y,
int i_width, int i_line_width, int i_ratio )
{
/* ?? */
}
/*******************************************************************************
* X11RenderPixelLine*: pixel picture rendering functions
*******************************************************************************
* Render a pixel-encoded picture line.
*******************************************************************************
* Messages type: vout, major code: 119
*******************************************************************************/
static void X11RenderPixelLine8bpp( vout_thread_t *p_vout, picture_t *p_pic,
int i_x, int i_y, int i_pic_x, int i_pic_y,
int i_width, int i_line_width, int i_ratio )
{
/* ?? */
}
static void X11RenderPixelLine16bpp( vout_thread_t *p_vout, picture_t *p_pic,
int i_x, int i_y, int i_pic_x, int i_pic_y,
int i_width, int i_line_width, int i_ratio )
{
/* ?? */
}
static void X11RenderPixelLine24bpp( vout_thread_t *p_vout, picture_t *p_pic,
int i_x, int i_y, int i_pic_x, int i_pic_y,
int i_width, int i_line_width, int i_ratio )
{
/* ?? */
}
static void X11RenderPixelLine32bpp( vout_thread_t *p_vout, picture_t *p_pic,
int i_x, int i_y, int i_pic_x, int i_pic_y,
int i_width, int i_line_width, int i_ratio )
{
/* ?? */
}
/*******************************************************************************
* X11RenderRGBMaskLine: mask picture rendering function
*******************************************************************************
* Render a 1bpp RGB mask-encoded picture line.
*******************************************************************************
* Messages type: vout, major code: 120
*******************************************************************************/
static void X11RenderRGBMaskLine( vout_thread_t *p_vout, picture_t *p_pic,
int i_x, int i_y, int i_pic_x, int i_pic_y,
int i_width, int i_line_width, int i_ratio )
{
/* ?? */
}
/*******************************************************************************
* X11RenderPixelMaskLine: mask picture rendering functions
*******************************************************************************
* Render a 1bpp pixel mask-encoded picture line.
*******************************************************************************
* Messages type: vout, major code: 121
*******************************************************************************/
static void X11RenderPixelMaskLine8bpp( vout_thread_t *p_vout, picture_t *p_pic,
int i_x, int i_y, int i_pic_x, int i_pic_y,
int i_width, int i_line_width, int i_ratio )
{
/* ?? */
}
static void X11RenderPixelMaskLine16bpp( vout_thread_t *p_vout, picture_t *p_pic,
int i_x, int i_y, int i_pic_x, int i_pic_y,
int i_width, int i_line_width, int i_ratio )
{
/* ?? */
}
static void X11RenderPixelMaskLine24bpp( vout_thread_t *p_vout, picture_t *p_pic,
int i_x, int i_y, int i_pic_x, int i_pic_y,
int i_width, int i_line_width, int i_ratio )
{
/* ?? */
}
static void X11RenderPixelMaskLine32bpp( vout_thread_t *p_vout, picture_t *p_pic,
int i_x, int i_y, int i_pic_x, int i_pic_y,
int i_width, int i_line_width, int i_ratio )
{
/* ?? */
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment