全部博文(1293)
分类: C/C++
2011-04-09 23:24:30
A typical VLC run course
This section describes what happens when you launch the vlc program. After the ELF dynamic loader blah blah blah, the main thread becomes the interface thread and starts up in src/interface/main.c . It passes through the following steps :
1. CPU detection : which CPU are we running on, what are its capabilities (MMX, MMXEXT, 3DNow, AltiVec...) ?
2. Message interface initialization ;
3. Command line options parsing ;
4. Playlist creation ;
5. Module bank initialization ;
6. Interface opening ;
7. Signal handler installation : SIGHUP, SIGINT and SIGQUIT are caught to manage a clean quit (please note that the SDL library also catches SIGSEGV) ;
8. Audio output thread spawning ;
9. Video output thread spawning ;
10. Main loop : events management ;
Following sections describe each of these steps in particular, and many more.
The message interfaceIt is a know fact that printf() functions are not necessarily thread-safe. As a result, one thread interrupted in a printf() call, followed by another calls to it, will leave the program in an undetermined state. So an API must be set up to print messages without crashing.
This API is implemented in two ways. If INTF_MSG_QUEUE is defined in config.h , every printf-like (see below) call will queue the message into a chained list. This list will be printed and flushed by the interface thread once upon an event loop. If INTF_MSG_QUEUE is undefined, the calling thread will acquire the print lock (which prevents two print operations to occur at the same time) and print the message directly (default behaviour).
Functions available to print messages are :
· intf_Msg ( char * psz_format, ... ) : Print a message to stdout , plain and stupid (for instance "vlc 0.2.72 (Apr 16 2001)").
· intf_ErrMsg ( char * psz_format, ... ) : Print an error message to stderr .
· intf_WarnMsg ( int i_level, char * psz_format, ... ) : Print a message to stderr if the warning level (determined by -v, -vv and -vvv) is low enough.
NotePlease note that the lower the level, the less important the message is (dayou spik ingliche ?).
· intf_DbgMsg ( char * psz_format, ... ) : This function is designed for optional checkpoint messages, such as "we are now entering function dvd_foo_thingy". It does nothing in non-trace mode. If the VLC is compiled with --enable-trace, the message is either written to the file vlc-trace.log (if TRACE_LOG is defined in config.h), or printed to stderr (otherwise用别的方法).
· intf_MsgImm, intf_ErrMsgImm, intf_WarnMsgImm, intf_DbgMsgImm : Same as above, except that the message queue, in case INTF_MSG_QUEUE is defined, will be flushed before the function returns.
· intf_WarnHexDump ( int i_level, void * p_data, int i_size ) : Dumps i_size bytes from p_data in hexadecimal. i_level works like intf_WarnMsg . This is useful for debugging purposes.
· intf_FlushMsg () : Flush the message queue, if it is in use.
Command line optionsVLC uses GNU getopt to parse command line options. getopt structures are defined in src/interface/main.c in the "Command line options constants" section. To add a new option This section needs to be changed, along with GetConfiguration and Usage.
Most configuration directives are exchanged via the environment array数组, using main_Put*Variable and main_Get*Variable. As a result, ./vlc --height 240 is strictly equivalent to : vlc_height=240 ./vlc. That way configuration variables are available everywhere, including plugins.
WarningPlease note that for thread-safety issues, you should not use main_Put*Variable once the second thread has been spawned.
Playlist managementThe playlist is created on startup from files given in the command line. An appropriate interface plugin can then add or remove files from it. Functions to be used are described in src/interface/intf_playlist.c. intf_PlaylistAdd and intf_PlaylistDelete are typically the most common used.
The main interface loop intf_Manage is then supposed to start and kill input threads when necessary.
Module bankOn startup, VLC creates a bank of all available .so files (plugins) in ., ./lib, /usr/local/lib/videolan/vlc (PLUGIN_PATH), and built-in plugins. Every plugin is checked with its capabilities, which are :
· MODULE_CAPABILITY_INTF : An interface plugin ;
· MODULE_CAPABILITY_ACCESS : A sam-ism, unused at present ;
· MODULE_CAPABILITY_INPUT : An input plugin, for instance PS or DVD ;
· MODULE_CAPABILITY_DECAPS : A sam-ism, unused at present ;
· MODULE_CAPABILITY_ADEC : An audio decoder ;
· MODULE_CAPABILITY_VDEC : A video decoder ;
· MODULE_CAPABILITY_MOTION : A motion compensation module (for the video decoder) ;
· MODULE_CAPABILITY_IDCT : An IDCT module (for the video decoder) ;
· MODULE_CAPABILITY_AOUT : An audio output module ;
· MODULE_CAPABILITY_VOUT : A video output module ;
· MODULE_CAPABILITY_YUV : A YUV module (for the video output) ;
· MODULE_CAPABILITY_AFX : An audio effect s plugin (for the audio output ; unimplemented) ;
· MODULE_CAPABILITY_VFX : A video effects plugin (for the video output ; unimplemented) ;
How to write a plugin is described in the latter sections. Other threads can request请求, 要求 a plugin descriptor with module_Need ( module_bank_t * p_bank, int i_capabilities, void * p_data ). p_data is an optional parameter (reserved for future use) for the pf_probe() function. The returned module_t structure contains pointers to the functions of the plug-in. See include/modules.h for more information.
The interface main loopThe interface thread will first look for a suitable interface plugin. Then it enters the main interface loop, with the plugin's pf_run function. This function will do what's appropriate, and every 100 ms will call (typically via a GUI timer callback) intf_Manage.
intf_Manage cleans up the module bank by unloading unnecessary modules, manages the playlist, and flushes waiting messages (if the message queue is in use).
How to write an interface plugin API for the ModuleHave a look the files in directories modules/misc/control, modules/misc/dummy仿制器, modules/misc/access, or modules/gui. However然而 the GUI interfaces are not very easy to understand, since they are quite big. I suggest to start digging into a non-graphical interface modules first. For example modules/control/hotkeys.c.
An interface module is made of 3 entry functions and a module description:
· The module description is made of macros that declares the capabilities of the module (interface, in this case既然这样) with their priority, the module description as it will appear in the preferences of GUI modules that implement them, some configuration variables specific to the module, shortcuts, sub-modules, etc.
· Open ( vlc_object_t* p_object ): This is called by VLC to initialize the module.
· Run ( vlc_object_t* p_object ): really does the job of the interface module (waiting for user input and displaying info). It should check periodically that p_intf->b_die is not VLC_TRUE.
· Close ( vcl_object_t * p_object ) function is called by VLC to uninitialize the module (basically, this consists in destroying whatever have been allocated by Open)
The above functions take a vlc_object_t* as argument, but that may need to be cast into a intf_thread_t* depending on your needs. This structure is often needed as a parameter for exported VLC functions, such as msg_Err(), msg_Warn(), ...
Define intf_sys_t to contain any variable you need (don't use static variables, they suck in a multi-threaded application :-).
If additional capabilities (such as Open button, playlist, menus, etc.) are needed, consult one of the GUI modules. One of the simpler GUI modules to consult might be modules/gui/ncurses/ncurses.c. It is a quite simple complete interface module with playlist interaction, and progress bar, among other things.
Arranging for your Module to get CompiledIf you create a new directory for your module, add a Modules.am file in it. In this file, put something like : SOURCES_yourmodule = myfile1.c myfile2.c
Then go to the main configure.ac file, and add in the AC_CONFIG_FILES section (towards the end of the file) a line similar to the others.
If you don't create a directory for your plugin (but instead just put it in an existing directory), you only have to add the two SOURCES_... lines to the existing Modules.am file
This declares your module; it does not arrange for it to be automatically compiled; automatic compilatoin is described further below.
You do not write a Makefile for your module. Instead this is done via the bootstrap and configuration process. So now run:
./bootstrap
./configure configure-options
make
To build the module manually, go to the directory it resides and type make libyourmodule_plugin.so (or .dll, or whatever the file type for a shared library is on your Operating System.)
To automatically have your module get built, you also set this in the configure.ac file; add your module name to the default modules section in one of the AX_ADD_PLUGINS directives.
Chapter 1. VLC Overview
Chapter 3. The complex multi-layer input