mirror of https://code.videolan.org/videolan/vlc
248 lines
9.7 KiB
XML
248 lines
9.7 KiB
XML
<chapter> <title> VLC Overview </title>
|
|
|
|
<sect1> <title> LibVLC </title>
|
|
|
|
<para> LibVLC is the core part of VLC. It is a library providing an
|
|
interface for programs such as VLC to a lot of functionalities such as
|
|
stream access, audio and video output, plugin handling, a thread system.
|
|
All the LibVLC source files are located in the <filename>src/</filename>
|
|
directory and its subdirectories: </para>
|
|
|
|
<itemizedlist>
|
|
|
|
<listitem> <para> <filename>interface/</filename>: contains code for
|
|
user interaction such as key presses and device ejection. </para>
|
|
</listitem>
|
|
|
|
<listitem> <para> <filename>playlist/</filename>: manages playlist
|
|
interaction such as stop, play, next, or random playback. </para>
|
|
</listitem>
|
|
|
|
<listitem> <para> <filename>input/</filename>: opens an input module,
|
|
reads packets, parses them and passes reconstituted elementary streams
|
|
to the decoder(s). </para> </listitem>
|
|
|
|
<listitem> <para> <filename>video_output/</filename>: initializes the
|
|
video display, gets all pictures and subpictures (ie. subtitles) from
|
|
the decoder(s), optionally converts them to another format (such as YUV
|
|
to RGB), and displays them. </para></listitem>
|
|
|
|
<listitem> <para> <filename>audio_output/</filename>: initializes the
|
|
audio mixer, ie. finds the right playing frequency, and then resamples
|
|
audio frames received from the decoder(s). </para> </listitem>
|
|
|
|
<listitem> <para> <filename>stream_output/</filename>: TODO </para>
|
|
</listitem>
|
|
|
|
<listitem> <para> <filename>misc/</filename>: miscellaneous utilities
|
|
used in other parts of libvlc, such as the thread system, the message
|
|
queue, CPU detection, the object lookup system, or platform-specific
|
|
code. </para> </listitem>
|
|
|
|
</itemizedlist>
|
|
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata fileref="modules.png" format="PNG" scalefit="1" scale="80"/>
|
|
</imageobject>
|
|
<imageobject>
|
|
<imagedata fileref="modules.gif" format="GIF" />
|
|
</imageobject>
|
|
<textobject>
|
|
<phrase> Data flow between modules </phrase>
|
|
</textobject>
|
|
</mediaobject>
|
|
|
|
</sect1>
|
|
|
|
<sect1> <title> VLC </title>
|
|
|
|
<para> VLC is a simple program written around LibVLC. It is very small,
|
|
but is a fully featured multimedia player thanks to LibVLC's support for
|
|
dynamic modules. </para>
|
|
|
|
</sect1>
|
|
|
|
<sect1> <title> Modules </title>
|
|
|
|
<para> Modules are located in the <filename>modules/</filename>
|
|
subdirectory and are loaded at runtime. Every module may offer different
|
|
features that will best suit a particular file or a particular
|
|
environment. Besides, most portability works result in the writing of an
|
|
audio_output/video_output/interface module to support a new platform (eg.
|
|
BeOS or MacOS X). </para>
|
|
|
|
<para> Plugin modules are loaded and unloaded dynamically
|
|
by functions in <filename>src/misc/modules.c</filename> and
|
|
<filename>include/modules*.h</filename>. The API for writing modules will
|
|
be discussed in a following chapter. </para>
|
|
|
|
<para> Modules can also be built directly into the application which uses
|
|
LibVLC, for instance on an operating system that does not have support for
|
|
dynamically loadable code. Modules statically built into the application
|
|
are called builtins. </para>
|
|
|
|
</sect1>
|
|
|
|
<sect1> <title> Threads </title>
|
|
|
|
<sect2> <title> Thread management </title>
|
|
|
|
<para> VLC is heavily multi-threaded. We chose against a single-thread
|
|
approach because decoder preemptibility and scheduling would be a
|
|
mastermind (for instance decoders and outputs have to be separated,
|
|
otherwise it cannot be warrantied that a frame will be played at the
|
|
exact presentation time), and we currently have no plan to support a
|
|
single-threaded client. Multi-process decoders usually imply more overhead
|
|
(problems of shared memory) and communication between processes is harder.
|
|
</para>
|
|
|
|
<para> Our threading structure is modeled on pthreads.
|
|
However, for portability reasons, we don't call
|
|
<function>pthread_*</function> functions directly, but use a
|
|
similar wrapper, made of <function>vlc_thread_create</function>,
|
|
<function>vlc_thread_exit</function>,
|
|
<function>vlc_thread_join</function>,
|
|
<function>vlc_mutex_init</function>, <function>vlc_mutex_lock</function>,
|
|
<function>vlc_mutex_unlock</function>,
|
|
<function>vlc_mutex_destroy</function>,
|
|
<function>vlc_cond_init</function>, <function>vlc_cond_signal</function>,
|
|
<function>vlc_cond_broadcast</function>,
|
|
<function>vlc_cond_wait</function>, <function>vlc_cond_destroy</function>,
|
|
and structures <type>vlc_thread_t</type>, <type>vlc_mutex_t</type>, and
|
|
<type>vlc_cond_t</type>. </para>
|
|
|
|
</sect2>
|
|
|
|
<sect2> <title> Synchronization </title>
|
|
|
|
<para> Another key feature of VLC is that decoding and playing are
|
|
asynchronous: decoding is done by a decoder thread, playing is done by
|
|
audio_output or video_output thread. The design goal is to ensure that
|
|
an audio or video frame is played exactly at the right time, without
|
|
blocking any of the decoder threads. This leads to a complex communication
|
|
structure between the interface, the input, the decoders and the outputs.
|
|
</para>
|
|
|
|
<para> Having several input and video_output threads reading multiple
|
|
files at the same time is permitted, despite the fact that the current
|
|
interface doesn't allow any way to do it [this is subject to change in the
|
|
near future]. Anyway the client has been written from the ground up with
|
|
this in mind. This also implies that a non-reentrant library (including in
|
|
particular liba52) cannot be used without using a global lock. </para>
|
|
|
|
<para> Presentation Time Stamps located in the system layer of the
|
|
stream are passed to the decoders, and all resulting samples are dated
|
|
accordingly. The output layers are supposed to play them at the right
|
|
time. Dates are converted to microseconds ; an absolute date is the number
|
|
of microseconds since Epoch (Jan 1st, 1970). The <type>mtime_t</type> type
|
|
is a signed 64-bit integer. </para>
|
|
|
|
<para> The current date can be retrieved with
|
|
<function>mdate()</function>. The execution of a thread can be suspended
|
|
until a certain <parameter>date</parameter> via <function>mwait</function>
|
|
<parameter>( mtime_t date )</parameter>. You can sleep for a fixed number
|
|
of microseconds with <function>msleep</function> <parameter>( mtime_t
|
|
delay )</parameter>. </para>
|
|
|
|
<warning> <para> Please remember to wake up slightly
|
|
<emphasis>before</emphasis> the presentation date, if some particular
|
|
treatment needs to be done (e.g. a chroma transformation). For instance
|
|
in <filename>modules/codec/mpeg_video/synchro.c</filename>, track of the
|
|
average decoding times is kept to ensure pictures are not decoded too
|
|
late. </para> </warning>
|
|
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
<sect1> <title> Code conventions </title>
|
|
|
|
<sect2> <title> Function naming </title>
|
|
|
|
<para>
|
|
All functions are named accordingly : module name (in lower case) + _ +
|
|
function name (in mixed case, <emphasis> without underscores</emphasis>).
|
|
For instance : <function>intf_FooFunction</function>. Static functions
|
|
don't need usage of the module name.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2> <title> Variable naming </title>
|
|
|
|
<para>
|
|
Hungarian notations are used, that means we have the following prefixes :
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem> <para> i_ for integers (sometimes l_ for long integers) ;
|
|
</para> </listitem>
|
|
<listitem> <para> b_ for booleans ; </para> </listitem>
|
|
<listitem> <para> d_ for doubles (sometimes f_ for floats) ;
|
|
</para> </listitem>
|
|
<listitem> <para> pf_ for function pointers ; </para> </listitem>
|
|
<listitem> <para> psz_ for a Pointer to a String terminated by a
|
|
Zero (C-string) ;
|
|
</para> </listitem>
|
|
<listitem> <para> More generally, we add a p when the variable is
|
|
a pointer to a type. </para> </listitem>
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
If one variable has no basic type (for instance a complex structure), don't
|
|
put any prefix (except p_* if it's a pointer). After one prefix, put
|
|
an <emphasis> explicit </emphasis> variable name <emphasis> in lower
|
|
case</emphasis>. If several words are required, join them with an
|
|
underscore (no mixed case). Examples :
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem> <para>
|
|
<type> data_packet_t * </type> <varname> p_buffer; </varname>
|
|
</para> </listitem> <listitem> <para>
|
|
<type> char </type> <varname> psz_msg_date[42]; </varname>
|
|
</para> </listitem> <listitem> <para>
|
|
<type> int </type> <varname> pi_es_refcount[MAX_ES]; </varname>
|
|
</para> </listitem> <listitem> <para>
|
|
<type> void </type> <varname> (* pf_next_data_packet)( int * ); </varname>
|
|
</para> </listitem>
|
|
</itemizedlist>
|
|
|
|
</sect2>
|
|
|
|
<sect2> <title> A few words about white spaces </title>
|
|
|
|
<para>
|
|
First, never use tabs in the source (you're entitled to use them in the
|
|
Makefile :-). Use <command> set expandtab </command> under <application>
|
|
vim </application> or the equivalent under <application>
|
|
emacs</application>. Indents are 4 spaces long.
|
|
</para>
|
|
|
|
<para>
|
|
Second, put spaces <emphasis> before and after </emphasis> operators, and
|
|
inside brackets. For instance :
|
|
<programlisting> for( i = 0; i < 12; i++, j += 42 ); </programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
Third, leave braces alone on their lines (GNU style). For instance :
|
|
<programlisting>
|
|
if( i_es == 42 )
|
|
{
|
|
p_buffer[0] = 0x12;
|
|
}
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
We write C, so use C-style comments /* ... */.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
</chapter>
|