Remove developer documentation, almost untouched in over 7 years
2
doc/developer/.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
!Makefile
|
||||
!Makefile.in
|
@ -1,41 +0,0 @@
|
||||
# Makefile for VideoLAN Doc
|
||||
# Clément Stenac
|
||||
# Anil Daoud
|
||||
|
||||
XSLTPROC=xsltproc
|
||||
LYNX=lynx
|
||||
JADE=jade
|
||||
|
||||
XML_DECL := /usr/share/sgml/declaration/xml.decl
|
||||
XSL_CHUNK = videolan-doc-chunk.xsl
|
||||
XSL = videolan-doc.xsl
|
||||
XSL_TXT = /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/xhtml/html.xsl
|
||||
|
||||
all: manual
|
||||
|
||||
manual: manual.html all-html manual.pdf manual.txt
|
||||
|
||||
# HTML
|
||||
all-html: *.xml
|
||||
xsltproc $(XSL_CHUNK) manual.xml
|
||||
mv *.html html
|
||||
|
||||
manual.html: *.xml
|
||||
xsltproc $(XSL) manual.xml > manual.html
|
||||
|
||||
# PDF
|
||||
manual.pdf: *.xml
|
||||
jade -t tex -d stylesheet-print-noicones.dsl -o manual.tex $(XML_DECL) manual.xml
|
||||
pdfjadetex manual.tex
|
||||
pdfjadetex manual.tex
|
||||
pdfjadetex manual.tex
|
||||
rm -f *.tex *.out *.aux *.log
|
||||
|
||||
# TXT
|
||||
manual.txt: *.xml
|
||||
xsltproc $(XSL_TXT) manual.xml > manual.txt
|
||||
|
||||
clean:
|
||||
rm -f manual.txt manual.pdf
|
||||
rm -f *.html *.aux *.log *.tex *.out
|
||||
rm -f html/*.html
|
@ -1,63 +0,0 @@
|
||||
# Extract from the Debian SGML/XML HOWTO by Stéphane Bortzmeyer
|
||||
|
||||
MAX_TEX_RECURSION=4
|
||||
|
||||
# For Debian :
|
||||
#XML_DECL=/usr/lib/sgml/declaration/xml.decl
|
||||
#HTML_SS=/usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/html/docbook.dsl
|
||||
#PRINT_SS=/usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/print/docbook.dsl
|
||||
|
||||
# For RedHat :
|
||||
# XML_DECL=/usr/share/sgml/docbook/dsssl-stylesheets-1.76/dtds/decls/xml.dcl
|
||||
# HTML_SS=/usr/share/sgml/docbook/dsssl-stylesheets-1.76/html/docbook.dsl
|
||||
# PRINT_SS=/usr/share/sgml/docbook/dsssl-stylesheets-1.76/print/docbook.dsl
|
||||
|
||||
# For Mac OS X :
|
||||
#XML_DECL=/sw/share/sgml/dsssl/docbook-dsssl-nwalsh/dtds/decls/xml.dcl
|
||||
#HTML_SS=/sw/share/sgml/dsssl/docbook-dsssl-nwalsh/html/docbook.dsl
|
||||
#PRINT_SS=/sw/share/sgml/dsssl/docbook-dsssl-nwalsh/print/docbook.dsl
|
||||
#JADE=openjade
|
||||
|
||||
JADE=@JADE@
|
||||
LYNX=@LYNX@
|
||||
DVIPS=@DVIPS@
|
||||
JADETEX=@JADETEX@
|
||||
|
||||
XML_DECL=@XML_DECL@
|
||||
HTML_SS=@HTML_SS@
|
||||
PRINT_SS=@PRINT_SS@
|
||||
|
||||
DOCS=@DOCS@
|
||||
|
||||
all: manual
|
||||
|
||||
|
||||
manual: manual.txt manual.ps manual.html
|
||||
|
||||
manual.tex: audio_output.xml debugging.xml decoders.xml gfdl.xml glossary.xml history.xml input.xml interface.xml manual.xml overview.xml ports.xml video_output.xml
|
||||
$(JADE) -t tex -V %section-autolabel% -d $(PRINT_SS) $(XML_DECL) manual.xml
|
||||
perl -i.bak -pe 's/\000//g' $@ && rm $*.tex.bak
|
||||
# No it's not a joke
|
||||
|
||||
manual.html: audio_output.xml debugging.xml decoders.xml gfdl.xml glossary.xml history.xml input.xml interface.xml manual.xml overview.xml ports.xml video_output.xml
|
||||
$(JADE) -t sgml -V %section-autolabel% -V nochunks \
|
||||
-d $(HTML_SS) $(XML_DECL) manual.xml > $@
|
||||
|
||||
manual.dvi: manual.tex modules.eps ps.eps stream.eps ts.eps
|
||||
$(JADETEX) manual.tex
|
||||
$(JADETEX) manual.tex
|
||||
$(JADETEX) manual.tex
|
||||
|
||||
manual.ps: manual.dvi
|
||||
$(DVIPS) -f $< > $@
|
||||
|
||||
manual.txt: audio_output.xml debugging.xml decoders.xml gfdl.xml glossary.xml history.xml input.xml interface.xml manual.xml overview.xml ports.xml video_output.xml
|
||||
$(JADE) -t sgml -V nochunks -d $(HTML_SS) $(XML_DECL) manual.xml > dump.html
|
||||
$(LYNX) -force_html -dump dump.html > $@
|
||||
-rm -f dump.html
|
||||
|
||||
clean:
|
||||
rm -f manual.txt
|
||||
rm -f *.html *.aux *.log *.dvi *.ps *.tex
|
||||
rm -f *.bck *~ .\#* \#*
|
||||
|
@ -1,376 +0,0 @@
|
||||
<chapter> <title> The audio output layer </title>
|
||||
|
||||
<sect1> <title> Audio output overview </title>
|
||||
|
||||
<para>
|
||||
This chapter documents the audio output layer known under the "audio output 3" codename. It has first been released with VLC version 0.5.0. Previous versions use an antic API, which is no longer documented nor supported. You definitely should write new code only for aout3 and later.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The audio output's main purpose is to take sound samples from one or several decoders (called "input streams" in this chapter), to mix them and write them to an output device (called "output stream"). During this process, transformations may be needed or asked by the user, and they will be performed by audio filters.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
(insert here a schematic of the data flow in aout3)
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Terminology </title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> <emphasis> Sample </emphasis> : A sample is an elementary piece of audio information, containing the value for all channels. For instance, a stream at 44100 Hz features 44100 samples per second, no matter how many channels are coded, nor the coding type of the coefficients. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> Frame </emphasis> : A set of samples of arbitrary size. Codecs usually have a fixed frame size (for instance an A/52 frame contains 1536 samples). Frames do not have much importance in the audio output, since it can manage buffers of arbitrary sizes. However, for undecoded formats, the developer must indicate the number of bytes required to carry a frame of n samples, since it depends on the compression ratio of the stream. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> Coefficient </emphasis> : A sample contains one coefficient per channel. For instance a stereo stream features 2 coefficients per sample. Many audio items (such as the float32 audio mixer) deal directly with the coefficients. Of course, an undecoded sample format doesn't have the notion of "coefficient", since a sample cannot be materialized independantly in the stream. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> Resampling </emphasis> : Changing the number of samples per second of an audio stream. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> Downmixing/upmixing </emphasis> : Changing the configuration of the channels (see below). </para> </listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Audio sample formats </title>
|
||||
|
||||
<para>
|
||||
The whole audio output can viewed as a pipeline transforming one audio format to another in successive steps. Consequently, it is essential to understand what an audio sample format is.
|
||||
</para>
|
||||
|
||||
<para> The audio_sample_format_t structure is defined in include/audio_output.h. It contains the following members : </para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> <emphasis> i_format </emphasis> : Define the format of the coefficients. This is a FOURCC field. For instance 'fl32' (float32), 'fi32' (fixed32), 's16b' (signed 16-bit big endian), 's16l' (signed 16-bit little endian), AOUT_FMT_S16_NE (shortcut to either 's16b' or 's16l'), 'u16b', 'u16l','s8 ', 'u8 ', 'ac3 ', 'spdi' (S/PDIF). Undecoded sample formats include 'a52 ', 'dts ', 'spdi', 'mpga' (MPEG audio layer I and II), 'mpg3' (MPEG audio layer III). An audio filter allowing to go from one format to another is called, by definition, a "converter". Some converters play the role of a decoder (for instance a52tofloat32.c), but are in fact "audio filters". </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> i_rate </emphasis> : Define the number of samples per second the audio output will have to deal with. Common values are 22050, 24000, 44100, 48000. i_rate is in Hz. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> i_physical_channels </emphasis> : Define the channels which are physically encoded in the buffer. This field is a bitmask of values defined in audio_output.h, for instance AOUT_CHAN_CENTER, AOUT_CHAN_LEFT, etc. Beware : the numeric value doesn't represent the number of coefficients per sample, see aout_FormatNbChannels() for that. The coefficients for each channel are always stored interleaved, because it is much easier for the mixer to deal with interleaved coefficients. Consequently, decoders which output planar data must implement an interleaving function. Coefficients must be output in the following order (WG-4 specification) : left, right, left surround, right surround, center, LFE.</para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> i_original_channels </emphasis> : Define the channels from the original stream which have been used to constitute a buffer. For instance, imagine your output plug-ins only has mono output (AOUT_CHAN_CENTER), and your stream is stereo. You can either use both channels of the stream (i_original_channels == AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT), or select one of them. i_original_channels uses the same bitmask as i_physical_channels, and also features special bits AOUT_CHAN_DOLBYSTEREO, which indicates whether the input stream is downmixed to Dolby surround sound, and AOUT_CHAN_DUALMONO, which indicates that the stereo stream is actually constituted of two mono streams, and only one of them should be selected (for instance, two languages on one VCD).</para> </listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
<note> <para>
|
||||
For 16-bit integer format types, we make a distinction between big-endian and little-endian storage types. However, floats are also stored in either big endian or little endian formats, and we didn't make a difference. The reason is, samples are hardly stored in float32 format in a file, and transferred from one machine to another ; so we assume float32 always use the native endianness.
|
||||
</para> <para>
|
||||
Yet, samples are quite often stored as big-endian signed 16-bit integers, such as in DVD's LPCM format. So the LPCM decoder allocates an 's16b' input stream, and on little-endian machines, an 's16b'->'s16l' converter is automatically invoked by the input pipeline.
|
||||
</para> <para>
|
||||
In most cases though, AOUT_FMT_S16_NE and AOUT_FMT_U16_NE should be used.
|
||||
</para> </note>
|
||||
|
||||
<para>
|
||||
The aout core provides macros to compare two audio sample formats. AOUT_FMTS_IDENTICAL() tests if i_format, i_rate, i_physical_channels and i_original_channels are identical. AOUT_FMTS_SIMILAR tests if i_rate and i_channels are identical (useful to write a pure converter filter).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The audio_sample_format_t structure then contains two additional parameters, which you are not supposed to write directly, except if you're dealing with undecoded formats. For PCM formats they are automatically filled in by aout_FormatPrepare(), which is called by the core functions when necessary.
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> <emphasis> i_frame_length </emphasis> : Define the number of samples of the "natural" frame. For instance for A/52 it is 1536, since 1536 samples are compressed in an undecoded buffer. For PCM formats, the frame size is 1, because every sample in the buffer can be independantly accessed. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> i_bytes_per_frame </emphasis> : Define the size (in bytes) of a frame. For A/52 it depends on the bitrate of the input stream (read in the sync info). For instance for stereo float32 samples, i_bytes_per_frame == 8 (i_frame_length == 1). </para> </listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
These last two fields (which are <emphasis> always </emphasis> meaningful as soon as aout_FormatPrepare() has been called) make it easy to calculate the size of an audio buffer : i_nb_samples * i_bytes_per_frame / i_frame_length.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Typical runcourse </title>
|
||||
|
||||
<para>
|
||||
The input spawns a new audio decoder, say for instance an A/52 decoder. The A/52 decoder parses the sync info for format information (eg. it finds 48 kHz, 5.1, 196 kbi/s), and creates a new aout "input stream" with aout_InputNew(). The sample format is :
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> i_format = 'a52 ' </para> </listitem>
|
||||
<listitem> <para> i_rate = 48000 </para> </listitem>
|
||||
<listitem> <para> i_physical_channels = i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE </para> </listitem>
|
||||
<listitem> <para> i_frame_length = 1536 </para> </listitem>
|
||||
<listitem> <para> i_bytes_per_frame = 24000 </para> </listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
This input format won't be modified, and will be stored in the aout_input_t structure corresponding to this input stream : p_aout->pp_inputs[0]->input. Since it is our first input stream, the aout core will try to configure the output device with this audio sample format (p_aout->output.output), to avoid unnecessary transformations.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The core will probe for an output module in the usual fashion, and its behavior will depend. Either the output device has the S/PDIF capability, and then it will set p_aout->output.output.i_format to 'spdi', or it's a PCM-only device. It will thus ask for the native sample format, such as 'fl32' (for Darwin CoreAudio) or AOUT_FMT_S16_NE (for OSS). The output device may also have constraints on the number of channels or the rate. For instance, the p_aout->output.output structure may look like :
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> i_format = AOUT_FMT_S16_NE </para> </listitem>
|
||||
<listitem> <para> i_rate = 44100 </para> </listitem>
|
||||
<listitem> <para> i_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT </para> </listitem>
|
||||
<listitem> <para> i_frame_length = 1 </para> </listitem>
|
||||
<listitem> <para> i_bytes_per_frame = 4 </para> </listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
Once we have an output format, we deduce the mixer format. It is strictly forbidden to change the audio sample format between the mixer and the output (because all transformations happen in the input pipeline), except for i_format. The reason is that we have only developed three mixers (float32 and S/PDIF, plus fixed32 for embedded devices which do not feature an FPU), so all other types must be cast into one of those. Still with our example, the p_aout->mixer.mixer structure looks like :
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> i_format = 'fl32' </para> </listitem>
|
||||
<listitem> <para> i_rate = 44100 </para> </listitem>
|
||||
<listitem> <para> i_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT </para> </listitem>
|
||||
<listitem> <para> i_frame_length = 1 </para> </listitem>
|
||||
<listitem> <para> i_bytes_per_frame = 8 </para> </listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
The aout core will thus allocate an audio filter to convert 'fl32' to AOUT_FMT_S16_NE. This is the only audio filter in the output pipeline. It will also allocate a float32 mixer. Since only one input stream is present, the trivial mixer will be used (only copies samples from the first input stream). Otherwise it would have used a more precise float32 mixer.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The last step of the initialization is to build an input pipeline. When several properties have to be changed, the aout core searches first for an audio filter capable of changing :
|
||||
</para>
|
||||
|
||||
<orderedlist>
|
||||
<listitem> <para> All parameters ; </para> </listitem>
|
||||
<listitem> <para> i_format and i_physical_channels/i_original_channels ; </para> </listitem>
|
||||
<listitem> <para> i_format ; </para> </listitem>
|
||||
</orderedlist>
|
||||
|
||||
<para>
|
||||
If the whole transformation cannot be done by only one audio filter, it will allocate a second and maybe a third filter to deal with the rest. To follow up on our example, we will allocate two filters : a52tofloat32 (which will deal with the conversion and the downmixing), and a resampler. Quite often, for undecoded formats, the converter will also deal with the downmixing, for efficiency reasons.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When this initialization is over, the "decoder" plug-in can run its main loop. Typically the decoder requests a buffer of length i_nb_samples, and copies the undecoded samples there (using GetChunk()). The buffer then goes along the input pipeline, which will do the decoding (to 'fl32'), and downmixing and resampling. Additional resampling will occur if complex latency issues in the output layer impose us to go temporarily faster or slower to achieve perfect lipsync (this is decided on a per-buffer basis). At the end of the input pipeline, the buffer is placed in a FIFO, and the decoder thread runs the audio mixer.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The audio mixer then calculates whether it has enough samples to build a new output buffer. If it does, it mixes the input streams, and passes the buffer to the output layer. The buffer goes along the output pipeline (which in our case only contains a converter filter), and then it is put in the output FIFO for the device.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Regularly, the output device will fetch the next buffer from the output FIFO, either through a callback of the audio subsystem (Mac OS X' CoreAudio, SDL), or thanks to a dedicated audio output thread (OSS, ALSA...). This mechanism uses aout_OutputNextBuffer(), and gives the estimated playing date of the buffer. If the computed playing date isn't equal to the estimated playing date (with a small tolerance), the output layer changes the date of all buffers in the audio output module, triggering some resampling at the beginning of the input pipeline when the next buffer will come from the decoder. That way, we shall resynchronize audio and video streams. When the buffer is played, it is finally released.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Mutual exclusion mechanism </title>
|
||||
|
||||
<para>
|
||||
The access to the internal structures must be carefully protected, because contrary to other objects in the VLC framework (input, video output, decoders...), the audio output doesn't have an associated thread. It means that parts of the audio output run in different threads (decoders, audio output IO thread, interface), and we do not control when the functions are called. Thus, much care must be taken to avoid concurrent access on the same part of the audio output, without creating a bottleneck which would cause latency problems at the output layer.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Consequently, we have set up a locking mechanism in five parts :
|
||||
</para>
|
||||
|
||||
<orderedlist>
|
||||
<listitem> <para> <emphasis> p_aout->mixer_lock </emphasis> : This lock is taken when the audio mixer is entered. The decoder thread in which the mixer runs must hold the mutex during the mixing, until the buffer comes out of the output pipeline. Without holding this mutex, the interface thread cannot change the output pipeline, and a decoder cannot add a new input stream. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> p_input->lock </emphasis> : This lock is taken when a decoder calls aout_BufferPlay(), as long as the buffer is in the input pipeline. The interface thread cannot change the input pipeline without holding this lock. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> p_aout->output_fifo_lock </emphasis> : This lock must be taken to add or remove a packet from the output FIFO, or change its dates. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> p_aout->input_fifos_lock </emphasis> : This lock must be taken to add or remove a packet from one of the input FIFOs, or change its dates. </para> </listitem>
|
||||
</orderedlist>
|
||||
|
||||
<para>
|
||||
Having so many mutexes makes it easy to fall into deadlocks (ie. when a thread has the mixer lock and wants the input fifos lock, and the other has the input fifos lock and wants the mixer lock). We could have worked with fewer locks (and even one global_lock), but for instance when the mixer is running, we do not want to block the audio output IO thread from picking up the next buffer. So for efficiency reasons we want to keep that many locks.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
So we have set up a strong discipline in taking the locks. If you need several of the locks, you <emphasis> must </emphasis> take them in the order indicated above. For instance if you already the hold input fifos lock, it is <emphasis> strictly forbidden </emphasis> to try and take the mixer lock. You must first release the input fifos lock, then take the mixer lock, and finally take again the input fifos lock.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It might seem a big constraint, but the order has been chosen so that in most cases, it is the most natural order to take the locks.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Internal structures </title>
|
||||
|
||||
<sect2> <title> Buffers </title>
|
||||
|
||||
<para>
|
||||
The aout_buffer_t structure is only allocated by the aout core functions, and goes from the decoder to the output device. A new aout buffer is allocated in these circumstances :
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> Whenever the decoder calls aout_BufferNew(). </para> </listitem>
|
||||
<listitem> <para> In the input and output pipeline, when an audio filter requests a new output buffer (ie. when b_in_place == 0, see below). </para> </listitem>
|
||||
<listitem> <para> In the audio mixer, when a new output buffer is being prepared. </para> </listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<note> <para>
|
||||
Most audio filters are able to place the output result in the same buffer as the input data, so most buffers can be reused that way, and we avoid massive allocations. However, some filters require the allocation of an output buffer.
|
||||
</para> <para>
|
||||
The core functions are smart enough to determine if the buffer is ephemer (for instance if it will only be used between two audio filters, and disposed of immediately therafter), or if it will need to be shared among several threads (as soon as it will need to stay in an input or output FIFO).
|
||||
</para> <para>
|
||||
In the first case, the aout_buffer_t structure and its associated buffer will be allocated in the thread's stack (via the alloca() system call), whereas in the latter in the process's heap (via malloc()). You, codec or filter developer, don't have to deal with the allocation or deallocation of the buffers.
|
||||
</para> </note>
|
||||
|
||||
<para>
|
||||
The fields you'll probably need to use are : p_buffer (pointer to the raw data), i_nb_bytes (size of the significative portion of the data), i_nb_samples, start_date and end_date.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2> <title> Date management </title>
|
||||
|
||||
<para>
|
||||
On the first impression, you might be tempted to think that to calculate the starting date of a buffer, it might be enough to regularly fetch the PTS i_pts from the input, and then : i_pts += i_nb_past_samples * 1000000 / i_rate. Well, I'm sorry to deceive you, but you'll end up with rounding problems, resulting in a crack every few seconds.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Indeed, if you have 1536 samples per buffer (as is often the case for A/52) at 44.1 kHz, it gives : 1536 * 1000000 / 44100 = 34829.9319727891. The decimal part of this figure will drive you mad (note that with 48 kHz samples it is an integral digit, so it will work well in many cases).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
One solution could have been to work in nanoseconds instead of milliseconds, but you'd only be making the problem 1000 times less frequent. The only exact solution is to add 34829 for every buffer, and keep the remainder of the division somewhere. For every buffer you add the remainders, and when it's greater than 44100, you add 34830 instead of 34829. That way you don't have the rounding error which would occur in the long run (this is called the Bresenham algorithm).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The good news is, the audio output core provides a structure (audio_date_t) and functions to deal with it :
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> <emphasis> aout_DateInit( audio_date_t * p_date, u32 i_divider ) </emphasis> : Initialize the Bresenham algorithm with the divider i_divider. Usually, i_divider will be the rate of the stream. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> aout_DateSet( audio_date_t * p_date, mtime_t new_date ) </emphasis> : Initialize the date, and set the remainder to 0. You will usually need this whenever you get a new PTS from the input. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> aout_DateMove( audio_date_t * p_date, mtime_t difference ) </emphasis> : Add or subtract microseconds from the stored date (used by the aout core when the output layer reports a lipsync problem). </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> aout_DateGet( audio_date_t * p_date ) </emphasis> : Return the current stored date. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> aout_DateIncrement( audio_date_t * p_date, u32 i_nb_samples ) </emphasis> : Add i_nb_samples * 1000000 to the stored date, taking into account rounding errors, and return the result. </para> </listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2> <title> FIFOs </title>
|
||||
|
||||
<para>
|
||||
FIFOs are used at two places in the audio output : at the end of the input pipeline, before entering the audio mixer, to store the buffers which haven't been mixed yet ; and at the end of the output pipeline, to queue the buffers for the output device.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
FIFOs store a chained list of buffers. They also keep the ending date of the last buffer, and whenever you pass a new buffer, they will enforce the time continuity of the stream by changing its start_date and end_date to match the FIFO's end_date (in case of stream discontinuity, the aout core will have to reset the date). The aout core provides functions to access the FIFO. Please understand than none of these functions use mutexes to protect exclusive access, so you must deal with race conditions yourself if you want to use them directly !
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> <emphasis> aout_FifoInit( aout_instance_t * p_aout, aout_fifo_t * p_fifo, u32 i_rate ) </emphasis> : Initialize the FIFO pointers, and the aout_date_t with the appropriate rate of the stream (see above for an explanation of aout dates). </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> aout_FifoPush( aout_instance_t * p_aout, aout_fifo_t * p_fifo, aout_buffer_t * p_buffer ) </emphasis> : Add p_buffer at the end of the chained list, update its start_date and end_date according to the FIFO's end_date, and update the internal end_date. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> aout_FifoSet( aout_instance_t * p_aout, aout_fifo_t * p_fifo, mtime_t date ) </emphasis> : Trash all buffers, and set a new end_date. Used when a stream discontinuity has been detected. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> aout_FifoMoveDates( aout_instance_t * p_aout, aout_fifo_t * p_fifo, mtime_t difference ) </emphasis> : Add or subtract microseconds from end_date and from start_date and end_date of all buffers in the FIFO. The aout core will use this function to force resampling, after lipsync issues. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> aout_FifoNextStart( aout_instance_t * p_aout, aout_fifo_t * p_fifo ) </emphasis> : Return the start_date which will be given to the next buffer passed to aout_FifoPush(). </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> aout_FifoPop( aout_instance_t * p_aout, aout_fifo_t * p_fifo ) </emphasis> : Return the first buffer of the FIFO, and remove it from the chained list. </para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> aout_FifoDestroy( aout_instance_t * p_aout, aout_fifo_t * p_fifo ) </emphasis> : Free all buffers in the FIFO. </para> </listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</sect2>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> API for the decoders </title>
|
||||
|
||||
<para>
|
||||
The API between the audio output and the decoders is quite simple. As soon as the decoder has the required information to fill in an audio_sample_format_t, it can call : p_dec->p_aout_input = aout_InputNew( p_dec->p_fifo, &p_dec->p_aout, &p_dec->output_format ).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In the next operations, the decoder will need both p_aout and p_aout_input. To retrieve a buffer, it calls : p_buffer = aout_BufferNew( p_dec->p_aout, p_dec->p_aout_input, i_nb_frames ).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The decoder must at least fill in start_date (using an audio_date_t is recommended), and then it can play the buffer : aout_BufferPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer ). In case of error, the buffer can be deleted (without being played) with aout_BufferDelete( p_dec->p_aout, p_dec->p_aout_input, p_buffer ).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When the decoder dies, or the sample format changes, the input stream must be destroyed with : aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input ).
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> API for the output module </title>
|
||||
|
||||
<para>
|
||||
An output module must implement a constructor, an optional destructor, and a p_aout->output.pf_play function. The constructor is the function which will be called when the module is loaded, and returns 0 if, and only if the output device could be open. The function may perform specific allocation in p_aout->output.p_sys, provided the structure is deallocated in the destructor.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In most cases, the p_aout->output.pf_play function does nothing (the only exception is when the samples can be processed immediately, without caring about dates, as in the file output). The job is then done by the IO callback which you are supposed to provide.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
On modern sound architectures (such as Mac OS X CoreAudio or SDL), when the audio buffer starves, the operating system automatically calls a function from your application. On outdated sound architectures (such as OSS), you have to emulate this behavior. Then your constructor must spawn a new audio IO thread, which periodically calls the IO callback to transfer the data.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When it is called, the first job of the IO callback will be determine the date at which the next samples will be played. Again, on modern platforms this information is given by the operating system, whereas on others you have to deduce it from the state of the internal buffer. Then you call aout_OutputNextBuffer( p_aout, next_date, b_can_sleek ), which will return a pointer to the next buffer to write, or NULL if none was available. In the latter case, it is advised to write zeros to the DSP.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The value of the last parameter (b_can_sleek) changes the behavior of the function. When it is set to 0, aout_OutputNextBuffer() will run an internal machinery to compensate for possible drift. For instance if the PTS of the next buffer is 40 ms earlier than the date you ask, it means we are very late. So it will ask the input stage to downsample the incoming buffers, so that we can come back in sync. No specific behavior is thus expected from your module.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
On the contrary, when b_can_sleek is set to 1, you tell the output layer not to take any actions to compensate a drift. You will typically use this when you've just played silence, and you can deal with buffers which are too early by inserting zeros (zeros in this case will not break the audio continuity, since you were playing nothing before). Another case of use is with S/PDIF output. S/PDIF packets cannot be resampled for obvious reasons, so you <emphasis> must </emphasis> use b_can_sleek = 1.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Once you have a buffer, you just have to transfer it to the DSP, for instance : memcpy( dsp_buffer, p_buffer->p_buffer, p_buffer->i_nb_bytes ).
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Writing an audio filter </title>
|
||||
|
||||
<para>
|
||||
An audio filter module is constituted of a constructor, a destructor, and a p_filter->pf_do_work function. The constructor is passed a p_filter structure, and it returns 0 if it is able to do the <emphasis> whole </emphasis> transformation between p_filter->input and p_filter->output. If you can do only part of the transformation, say you can't do it (if the aout core doesn't find a fitting filter, it will split the transformation and ask you again).
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Audio filters can be of three types :
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> Converters : change i_format (for instance from float32 to s16). </para> </listitem>
|
||||
<listitem> <para> Resamplers : change i_rate (for instance from 48 kHz to 44.1 kHz). </para> </listitem>
|
||||
<listitem> <para> Channel mixers : change i_physical_channels/i_original_channels (for instance from 5.1 to stereo). </para> </listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
Audio filters can also combine any of these types. For instance you can have an audio filter which transforms A/52 5.1 to float32 stereo.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
The constructor must also set p_filter->b_in_place. If it's 0, the aout core will allocate a new buffer for the output. If it's 1, when you write a byte in the output buffer, it destroys the same byte in the input buffer (they share the same memory area). Some filters can work in place because they just do a linear transformation (like float32->s16), but most filters will want b_in_place = 0. The filter can allocate private data in p_filter->p_sys. Do not forget to deallocate it in the destructor.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The p_filter->pf_do_work gets an input and an output buffer as arguments, and process them. At the end of the processing, do not forget to set p_out_buf->i_nb_samples and p_out_buf->i_nb_bytes, since they aren't inited by the aout core (their values can change between input and output and it's not quite predictible).
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Writing an audio mixer </title>
|
||||
|
||||
<para>
|
||||
Writing an audio mixer is very similar to writing an audio filter. The only difference is that you have to deal with the input buffers yourself, and request for new buffers when you need to. Between two calls to pf_do_work, the position in the buffer is remembered in p_input->p_first_byte_to_mix (it isn't always the start of the buffer, since input and output buffers can be of different length). It is your job to set this pointer at the end of pf_do_work.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For more details, please have a look at the float32 mixer. It's much more understandable than lines of documentation.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
@ -1,112 +0,0 @@
|
||||
dnl $Id$
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT(manual.xml.in,0.0.1)
|
||||
|
||||
AC_CHECK_PROGS(JADE, openjade jade, [nogood])
|
||||
|
||||
if test "$JADE" = nogood ; then
|
||||
AC_MSG_ERROR(You need jade to build the documentation.
|
||||
Get it from http://openjade.sourceforge.net/)
|
||||
else
|
||||
DOCS="manual.html"
|
||||
fi
|
||||
|
||||
AC_PATH_PROG(LYNX, lynx, [nope])
|
||||
|
||||
if test "$LYNX" = nope ; then
|
||||
AC_MSG_WARN(Can not create text version of manual)
|
||||
else
|
||||
DOCS="$DOCS manual.txt"
|
||||
fi
|
||||
|
||||
AC_PATH_PROG(DVIPS, dvips, [nodvips])
|
||||
AC_PATH_PROG(JADETEX, jadetex, [nojadetex])
|
||||
|
||||
if test "$DVIPS" = nodvips -o "$JADETEX" = nojadetex ; then
|
||||
AC_MSG_WARN(Can not create PostScript version of manual)
|
||||
else
|
||||
DOCS="$DOCS manual.ps"
|
||||
fi
|
||||
|
||||
AC_CANONICAL_SYSTEM
|
||||
dnl ========================================================================
|
||||
case "$host_os" in
|
||||
linux* )
|
||||
if test -f /etc/redhat-release ; then
|
||||
XML_DECL=/usr/share/sgml/docbook/dsssl-stylesheets-1.76/dtds/decls/xml.dcl
|
||||
HTML_SS=/usr/share/sgml/docbook/dsssl-stylesheets-1.76/html/docbook.dsl
|
||||
PRINT_SS=/usr/share/sgml/docbook/dsssl-stylesheets-1.76/print/docbook.dsl
|
||||
DOCBOOKX_DTD=/usr/share/sgml/docbook/xml-dtd-4.1.2/docbookx.dtd
|
||||
else
|
||||
# Assume Debian
|
||||
XML_DECL=/usr/lib/sgml/declaration/xml.decl
|
||||
HTML_SS=/usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/html/docbook.dsl
|
||||
PRINT_SS=/usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/print/docbook.dsl
|
||||
DOCBOOKX_DTS=/usr/share/sgml/docbook/dtd/xml/4.1/docbookx.dtd
|
||||
fi
|
||||
;;
|
||||
darwin5* | darwin6* )
|
||||
XML_DECL=/sw/share/sgml/dsssl/docbook-dsssl-nwalsh/dtds/decls/xml.dcl
|
||||
HTML_SS=/sw/share/sgml/dsssl/docbook-dsssl-nwalsh/html/docbook.dsl
|
||||
PRINT_SS=/sw/share/sgml/dsssl/docbook-dsssl-nwalsh/print/docbook.dsl
|
||||
DOCBOOKX_DTD=/sw/share/xml/dtd/docbookx/4.1.2/docbookx.dtd
|
||||
;;
|
||||
* )
|
||||
echo "Don't know $host_os. Picking up from environment."
|
||||
XML_DECL=$XML_DECL
|
||||
HTML_SS=$HTML_SS
|
||||
PRINT_SS=$PRINT_SS
|
||||
esac
|
||||
|
||||
AC_ARG_WITH(xml_decl,
|
||||
[ --with-xml-dcl=PATH place to find xml.dcl file])
|
||||
if test -n "${xml_decl}"; then
|
||||
XML_DECL=$xml_decl
|
||||
fi
|
||||
|
||||
if test ! -f $XML_DECL ; then
|
||||
AC_MSG_ERROR(Can't find xml.dcl file. Set with --with-xml-dcl.)
|
||||
fi
|
||||
|
||||
|
||||
AC_ARG_WITH(html_ss,
|
||||
[ --with-html-ss=PATH place to find html/docbook.dsl file])
|
||||
if test -n "${html_ss}"; then
|
||||
HTML_SS=$html_ss
|
||||
fi
|
||||
|
||||
if test ! -f $HTML_SS ; then
|
||||
AC_MSG_ERROR(Can't find html/docbook.dsl file. Set with --with-html-ss.)
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(print_ss,
|
||||
[ --with-print-ss=PATH place to find print/docbook.dsl file])
|
||||
if test -n "${print_ss}"; then
|
||||
PRINT_SS=$print_ss
|
||||
fi
|
||||
|
||||
if test ! -f $PRINT_SS ; then
|
||||
AC_MSG_ERROR(Can't find print/docbook.dsl file. Set with --with-print-ss.)
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(docbook_dtd,
|
||||
[ --with-dockbook-dtd=PATH place to find docbookx.dtd file])
|
||||
if test -n "${docbook_dtd}"; then
|
||||
DOCBOOKX_DTD=$docbook_dtd
|
||||
fi
|
||||
|
||||
if test ! -f $DOCBOOKX_DTD ; then
|
||||
AC_MSG_ERROR(Can't find docbook.dsl file. Set with --with-docbook_dtd.)
|
||||
fi
|
||||
|
||||
AC_SUBST(XML_DECL)
|
||||
AC_SUBST(HTML_SS)
|
||||
AC_SUBST(PRINT_SS)
|
||||
AC_SUBST(DOCBOOKX_DTD)
|
||||
AC_SUBST(JADE)
|
||||
AC_SUBST(LYNX)
|
||||
AC_SUBST(DOCS)
|
||||
|
||||
AC_CONFIG_FILES([manual.xml Makefile])
|
||||
AC_OUTPUT
|
@ -1,55 +0,0 @@
|
||||
<appendix> <title> Advanced debugging </title>
|
||||
|
||||
<para>
|
||||
We never debug our code, because we don't put bugs in. Okay, you want
|
||||
some real stuff. Sam still uses <function> printf() </function> to
|
||||
find out where it crashes. For real programmers, here is a summary
|
||||
of what you can do if you have problems.
|
||||
</para>
|
||||
|
||||
<sect1> <title> Where does it crash ? </title>
|
||||
|
||||
<para>
|
||||
The best way to know that is to use gdb. You can start using it with
|
||||
good chances by configuring with <parameter> --enable-debug </parameter>.
|
||||
It will add <parameter> -g </parameter> to the compiler <parameter>
|
||||
CFLAGS</parameter>, and activate some additional safety checks. Just
|
||||
run <command> gdb vlc</command>, type <command> run myfile.vob</command>,
|
||||
and wait until it crashes. You can view where it stopped with
|
||||
<command>bt</command>, and print variables with <command>print
|
||||
<C-style></command>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you run into troubles, you may want to turn the optimizations off.
|
||||
Optimizations (especially inline functions) may confuse the debugger.
|
||||
Use <parameter> --disable-optimizations </parameter> in that case.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Other problems </title>
|
||||
|
||||
<para>
|
||||
It may be more complicated than that, for instance unpredictable
|
||||
behaviour, random bug or performance issue. You have several options
|
||||
to deal with this. If you experience unpredictable behaviour, I hope
|
||||
you don't have a heap or stack corruption (eg. writing in an unallocated
|
||||
space), because they are hard to find. If you are really desperate, have
|
||||
a look at something like ElectricFence or dmalloc. Under GNU/Linux, an
|
||||
easy check is to type <command> export MALLOC_CHECK_=2 </command> before
|
||||
launching vlc (see <command> malloc(3) </command> for more information).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
VLC offers a "trace-mode". It can create a log file with very accurate dates
|
||||
and messages of what it does, so it is useful to detect performance
|
||||
issues or lock-ups. Compile with <parameter> --enable-trace </parameter>
|
||||
and tune the <parameter> TRACE_* </parameter> flags in <filename>
|
||||
include/config.h </filename> to enable certain types of messages (log
|
||||
file writing can take up a lot of time, and will have side effects).
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
</appendix>
|
@ -1,460 +0,0 @@
|
||||
<chapter> <title> How to write a decoder </title>
|
||||
|
||||
<sect1> <title> What is precisely a decoder in the VLC scheme ? </title>
|
||||
|
||||
<para>
|
||||
The decoder does the mathematical part of the process of playing a
|
||||
stream. It is separated from the demultiplexers (in the input module),
|
||||
which manage packets to rebuild a continuous elementary stream, and from
|
||||
the output thread, which takes samples reconstituted by the decoder
|
||||
and plays them. Basically, a decoder has no interaction with devices,
|
||||
it is purely algorithmic.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In the next section we will describe how the decoder retrieves the
|
||||
stream from the input. The output API (how to say "this sample is
|
||||
decoded and can be played at xx") will be talked about in the next
|
||||
chapters.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Decoder configuration </title>
|
||||
|
||||
<para>
|
||||
The input thread spawns the appropriate decoder modules from <filename>
|
||||
src/input/input_dec.c</filename>. The <function>Dec_CreateThread</function>
|
||||
function selects the more accurate decoder module. Each decoder module
|
||||
looks at decoder_config.i_type and returns a score [ see the modules
|
||||
section ]. It then launches <function> module.pf_run()</function>,
|
||||
with a <type>decoder_config_t</type>, described in <filename>
|
||||
include/input_ext-dec.h</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The generic <type>decoder_config_t</type> structure, gives the decoder
|
||||
the ES ID and type, and pointers to a <type> stream_control_t </type>
|
||||
structure (gives information on the play status), a <type> decoder_fifo_t
|
||||
</type> and <parameter> pf_init_bit_stream</parameter>, which will be
|
||||
described in the next two sections.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Packet structures </title>
|
||||
|
||||
<para>
|
||||
The input module provides an advanced API for delivering stream data
|
||||
to the decoders. First let's have a look at the packet structures.
|
||||
They are defined in <filename> include/input_ext-dec.h</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<type>data_packet_t</type> contains a pointer to the physical location
|
||||
of data. Decoders should only start to read them at <parameter>
|
||||
p_payload_start </parameter> until <parameter> p_payload_end</parameter>.
|
||||
Thereafter, it will switch to the next packet, <parameter> p_next
|
||||
</parameter> if it is not <constant>NULL</constant>. If the
|
||||
<parameter> b_discard_payload
|
||||
</parameter> flag is up, the content of the packet is messed up and it
|
||||
should be discarded.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<type>data_packet_t</type> are contained into <type>pes_packet_t</type>.
|
||||
<type>pes_packet_t</type> features a chained list
|
||||
(<parameter>p_first</parameter>) of <type>data_packet_t
|
||||
</type> representing (in the MPEG paradigm) a complete PES packet. For
|
||||
PS streams, a <type> pes_packet_t </type> usually only contains one
|
||||
<type>data_packet_t</type>. In TS streams though, one PES can be split
|
||||
among dozens of TS packets. A PES packet has PTS dates (see your
|
||||
MPEG specification for more information) and the current pace of reading
|
||||
that should be applied for interpolating dates (<parameter>i_rate</parameter>).
|
||||
<parameter> b_data_alignment </parameter> (if available in the system
|
||||
layer) indicates if the packet is a random access point, and <parameter>
|
||||
b_discontinuity </parameter> tells whether previous packets have been
|
||||
dropped.
|
||||
</para>
|
||||
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="ps.png" format="PNG" scalefit="1" scale="95" />
|
||||
</imageobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="ps.gif" format="GIF" />
|
||||
</imageobject>
|
||||
<textobject>
|
||||
<phrase> A PES packet in a Program Stream </phrase>
|
||||
</textobject>
|
||||
<caption>
|
||||
<para> In a Program Stream, a PES packet features only one
|
||||
data packet, whose buffer contains the PS header, the PES
|
||||
header, and the data payload.
|
||||
</para>
|
||||
</caption>
|
||||
</mediaobject>
|
||||
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="ts.png" format="PNG" scalefit="1" scale="95" />
|
||||
</imageobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="ts.gif" format="GIF" />
|
||||
</imageobject>
|
||||
<textobject>
|
||||
<phrase> A PES packet in a Transport Stream </phrase>
|
||||
</textobject>
|
||||
<caption>
|
||||
<para> In a Transport Stream, a PES packet can feature an
|
||||
unlimited number of data packets (three on the figure)
|
||||
whose buffers contains the PS header, the PES
|
||||
header, and the data payload.
|
||||
</para>
|
||||
</caption>
|
||||
</mediaobject>
|
||||
|
||||
<para>
|
||||
The structure shared by both the input and the decoder is <type>
|
||||
decoder_fifo_t</type>. It features a rotative FIFO of PES packets to
|
||||
be decoded. The input provides macros to manipulate it : <function>
|
||||
DECODER_FIFO_ISEMPTY, DECODER_FIFO_ISFULL, DECODER_FIFO_START,
|
||||
DECODER_FIFO_INCSTART, DECODER_FIFO_END, DECODER_FIFO_INCEND</function>.
|
||||
Please remember to take <parameter>p_decoder_fifo->data_lock
|
||||
</parameter> before any operation on the FIFO.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The next packet to be decoded is DECODER_FIFO_START( *p_decoder_fifo ).
|
||||
When it is finished, you need to call <function>
|
||||
p_decoder_fifo->pf_delete_pes( p_decoder_fifo->p_packets_mgt,
|
||||
DECODER_FIFO_START( *p_decoder_fifo ) ) </function> and then
|
||||
<function> DECODER_FIFO_INCSTART( *p_decoder_fifo )</function> to
|
||||
return the PES to the <link linkend="input_buff">buffer manager</link>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If the FIFO is empty (<function>DECODER_FIFO_ISEMPTY</function>), you
|
||||
can block until a new packet is received with a cond signal :
|
||||
<function> vlc_cond_wait( &p_fifo->data_wait,
|
||||
&p_fifo->data_lock )</function>. You have to hold the lock before
|
||||
entering this function. If the file is over or the user quits,
|
||||
<parameter>p_fifo->b_die</parameter> will be set to 1. It indicates
|
||||
that you must free all your data structures and call <function>
|
||||
vlc_thread_exit() </function> as soon as possible.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> The bit stream (input module) </title>
|
||||
|
||||
<para>
|
||||
This classical way of reading packets is not convenient, though, since
|
||||
the elementary stream can be split up arbitrarily. The input module
|
||||
provides primitives which make reading a bit stream much easier.
|
||||
Whether you use it or not is at your option, though if you use it you
|
||||
shouldn't access the packet buffer any longer.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The bit stream allows you to just call <function> GetBits()</function>,
|
||||
and this functions will transparently read the packet buffers, change
|
||||
data packets and pes packets when necessary, without any intervention
|
||||
from you. So it is much more convenient for you to read a continuous
|
||||
Elementary Stream, you don't have to deal with packet boundaries
|
||||
and the FIFO, the bit stream will do it for you.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The central idea is to introduce a buffer of 32 bits [normally
|
||||
<type> WORD_TYPE</type>, but 64-bit version doesn't work yet], <type>
|
||||
bit_fifo_t</type>. It contains the word buffer and the number of
|
||||
significant bits (higher part). The input module provides five
|
||||
inline functions to manage it :
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> <type> u32 </type> <function> GetBits </function>
|
||||
<parameter>( bit_stream_t * p_bit_stream, unsigned int i_bits )
|
||||
</parameter> :
|
||||
Returns the next <parameter> i_bits </parameter> bits from the
|
||||
bit buffer. If there are not enough bits, it fetches the following
|
||||
word from the <type>decoder_fifo_t</type>. This function is only
|
||||
guaranteed to work with up to 24 bits. For the moment it works until
|
||||
31 bits, but it is a side effect. We were obliged to write a different
|
||||
function, <function>GetBits32</function>, for 32-bit reading,
|
||||
because of the << operator.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> RemoveBits </function> <parameter>
|
||||
( bit_stream_t * p_bit_stream, unsigned int i_bits ) </parameter> :
|
||||
The same as <function> GetBits()</function>, except that the bits
|
||||
aren't returned (we spare a few CPU cycles). It has the same
|
||||
limitations, and we also wrote <function> RemoveBits32</function>.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <type> u32 </type> <function> ShowBits </function>
|
||||
<parameter>( bit_stream_t * p_bit_stream, unsigned int i_bits )
|
||||
</parameter> :
|
||||
The same as <function> GetBits()</function>, except that the bits
|
||||
don't get flushed after reading, so that you need to call
|
||||
<function> RemoveBits() </function> by hand afterwards. Beware,
|
||||
this function won't work above 24 bits, except if you're aligned
|
||||
on a byte boundary (see next function).
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> RealignBits </function> <parameter>
|
||||
( bit_stream_t * p_bit_stream ) </parameter> :
|
||||
Drops the n higher bits (n < 8), so that the first bit of
|
||||
the buffer be aligned an a byte boundary. It is useful when
|
||||
looking for an aligned startcode (MPEG for instance).
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> GetChunk </function> <parameter>
|
||||
( bit_stream_t * p_bit_stream, byte_t * p_buffer, size_t i_buf_len )
|
||||
</parameter> :
|
||||
It is an analog of <function> memcpy()</function>, but taking
|
||||
a bit stream as first argument. <parameter> p_buffer </parameter>
|
||||
must be allocated and at least <parameter> i_buf_len </parameter>
|
||||
long. It is useful to copy data you want to keep track of.
|
||||
</para> </listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
All these functions recreate a continuous elementary stream paradigm.
|
||||
When the bit buffer is empty, they take the following word in the
|
||||
current packet. When the packet is empty, it switches to the next
|
||||
<type>data_packet_t</type>, or if unapplicable to the next <type>
|
||||
pes_packet_t</type> (see <function>
|
||||
p_bit_stream->pf_next_data_packet</function>). All this is
|
||||
completely transparent.
|
||||
</para>
|
||||
|
||||
<note> <title> Packet changes and alignment issues </title>
|
||||
<para>
|
||||
We have to study the conjunction of two problems. First, a
|
||||
<type> data_packet_t </type> can have an even number of bytes,
|
||||
for instance 177, so the last word will be truncated. Second,
|
||||
many CPU (sparc, alpha...) can only read words aligned on a
|
||||
word boundary (that is, 32 bits for a 32-bit word). So packet
|
||||
changes are a lot more complicated than you can imagine, because
|
||||
we have to read truncated words and get aligned.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For instance <function> GetBits() </function> will call
|
||||
<function> UnalignedGetBits() </function> from <filename>
|
||||
src/input/input_ext-dec.c</filename>. Basically it will
|
||||
read byte after byte until the stream gets realigned. <function>
|
||||
UnalignedShowBits() </function> is a bit more complicated
|
||||
and may require a temporary packet
|
||||
(<parameter>p_bit_stream->showbits_data</parameter>).
|
||||
</para> </note>
|
||||
|
||||
<para>
|
||||
To use the bit stream, you have to call <parameter>
|
||||
p_decoder_config->pf_init_bit_stream( bit_stream_t * p_bit_stream,
|
||||
decoder_fifo_t * p_fifo )</parameter> to set up all variables. You will
|
||||
probably need to regularly fetch specific information from the packet,
|
||||
for instance the PTS. If <parameter> p_bit_stream->pf_bit_stream_callback
|
||||
</parameter> is not <constant> NULL</constant>, it will be called
|
||||
on a packet change. See <filename> src/video_parser/video_parser.c
|
||||
</filename> for an example. The second argument
|
||||
indicates whether it is just a new <type>data_packet_t</type> or
|
||||
also a new <type>pes_packet_t</type>. You can store your own structure in
|
||||
<parameter> p_bit_stream->p_callback_arg</parameter>.
|
||||
</para>
|
||||
|
||||
<warning> <para>
|
||||
When you call <function>pf_init_bit_stream</function>, the
|
||||
<function>pf_bitstream_callback</function> is not defined yet,
|
||||
but it jumps to the first packet, though. You will probably
|
||||
want to call your bitstream callback by hand just after
|
||||
<function> pf_init_bit_stream</function>.
|
||||
</para> </warning>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Built-in decoders </title>
|
||||
|
||||
<para>
|
||||
VLC already features an MPEG layer 1 and 2 audio decoder, an MPEG MP@ML
|
||||
video decoder, an AC3 decoder (borrowed from LiViD), a DVD SPU decoder,
|
||||
and an LPCM decoder. You can write your own decoder, just mimic the
|
||||
video parser.
|
||||
</para>
|
||||
|
||||
<note> <title> Limitations in the current design </title>
|
||||
<para>
|
||||
To add a new decoder, you'll still have to add the stream type as there's
|
||||
still a a hard-wired piece of code in <filename> src/input/input_programs.c
|
||||
</filename>.
|
||||
</para> </note>
|
||||
|
||||
<para>
|
||||
The MPEG audio decoder is native, but doesn't support layer 3 decoding
|
||||
[too much trouble], the AC3 decoder is a port from Aaron
|
||||
Holtzman's libac3 (the original libac3 isn't reentrant), and the
|
||||
SPU decoder is native. You may want to have a look at <function>
|
||||
BitstreamCallback </function> in the AC3 decoder. In that case we have
|
||||
to jump the first 3 bytes of a PES packet, which are not part of the
|
||||
elementary stream. The video decoder is a bit special and will
|
||||
be described in the following section.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> The MPEG video decoder </title>
|
||||
|
||||
<para>
|
||||
VLC media player provides an MPEG-1, and an MPEG-2 Main Profile @
|
||||
Main Level decoder. It has been natively written for VLC, and is quite
|
||||
mature. Its status is a bit special, since it is splitted between two
|
||||
logicial entities : video parser and video decoder.
|
||||
The initial goal is to separate bit stream parsing functions from
|
||||
highly parallelizable mathematical algorithms. In theory, there can be
|
||||
one video parser thread (and only one, otherwise we would have race
|
||||
conditions reading the bit stream), along with a pool of video decoder
|
||||
threads, which do IDCT and motion compensation on several blocks
|
||||
at once.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It doesn't (and won't) support MPEG-4 or DivX decoding. It is not an
|
||||
encoder. It should support the whole MPEG-2 MP@ML specification, though
|
||||
some features are still left untested, like Differential Motion Vectors.
|
||||
Please bear in mind before complaining that the input elementary stream
|
||||
must be valid (for instance this is not the case when you directly read
|
||||
a DVD multi-angle .vob file).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The most interesting file is <filename> vpar_synchro.c</filename>, it is
|
||||
really worth the shot. It explains the whole frame dropping algorithm.
|
||||
In a nutshell, if the machine is powerful enough, we decoder all IPBs,
|
||||
otherwise we decode all IPs and Bs if we have enough time (this is
|
||||
based on on-the-fly decoding time statistics). Another interesting file
|
||||
is <filename>vpar_blocks.c</filename>, which describes all block
|
||||
(including coefficients and motion vectors) parsing algorithms. Look
|
||||
at the bottom of the file, we indeed generate one optimized function
|
||||
for every common picture type, and one slow generic function. There
|
||||
are also several levels of optimization (which makes compilation slower
|
||||
but certain types of files faster decoded) called <constant>
|
||||
VPAR_OPTIM_LEVEL</constant>, level 0 means no optimization, level 1
|
||||
means optimizations for MPEG-1 and MPEG-2 frame pictures, level 2
|
||||
means optimizations for MPEG-1 and MPEG-2 field and frame pictures.
|
||||
</para>
|
||||
|
||||
<sect2> <title> Motion compensation plug-ins </title>
|
||||
|
||||
<para>
|
||||
Motion compensation (i.e. copy of regions from a reference picture) is
|
||||
very platform-dependant (for instance with MMX or AltiVec versions), so
|
||||
we moved it to the <filename> plugins/motion </filename> directory. It
|
||||
is more convenient for the video decoder, and resulting plug-ins may
|
||||
be used by other video decoders (MPEG-4 ?). A motion plugin must
|
||||
define 6 functions, coming straight from the specification :
|
||||
<function> vdec_MotionFieldField420, vdec_MotionField16x8420,
|
||||
vdec_MotionFieldDMV420, vdec_MotionFrameFrame420, vdec_MotionFrameField420,
|
||||
vdec_MotionFrameDMV420</function>. The equivalent 4:2:2 and 4:4:4
|
||||
functions are unused, since these formats are forbidden in MP@ML (it
|
||||
would only take longer compilation time).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Look at the C version of the algorithms if you want more information.
|
||||
Note also that the DMV algorithm is untested and is probably buggy.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2> <title> IDCT plug-ins </title>
|
||||
|
||||
<para>
|
||||
Just like motion compensation, IDCT is platform-specific. So we moved it
|
||||
to <filename> plugins/idct</filename>. This module does the IDCT
|
||||
calculation, and copies the data to the final picture. You need to define
|
||||
seven methods :
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> <function> vdec_IDCT </function> <parameter>
|
||||
( decoder_config_t * p_config, dctelem_t * p_block, int )
|
||||
</parameter> :
|
||||
Does the complete 2-D IDCT. 64 coefficients are in <parameter>
|
||||
p_block</parameter>.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> vdec_SparseIDCT </function>
|
||||
<parameter> ( vdec_thread_t * p_vdec, dctelem_t * p_block,
|
||||
int i_sparse_pos ) </parameter> :
|
||||
Does an IDCT on a block with only one non-NULL coefficient
|
||||
(designated by <parameter> i_sparse_pos</parameter>). You can
|
||||
use the function defined in <filename> plugins/idct/idct_common.c
|
||||
</filename> which precalculates these 64 matrices at
|
||||
initialization time.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> vdec_InitIDCT </function>
|
||||
<parameter> ( vdec_thread_t * p_vdec ) </parameter> :
|
||||
Does the initialization stuff needed by <function>
|
||||
vdec_SparseIDCT</function>.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> vdec_NormScan </function>
|
||||
<parameter> ( u8 ppi_scan[2][64] ) </parameter> :
|
||||
Normally, this function does nothing. For minor optimizations,
|
||||
some IDCT (MMX) need to invert certain coefficients in the
|
||||
MPEG scan matrices (see ISO/IEC 13818-2).
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> vdec_InitDecode </function>
|
||||
<parameter> ( struct vdec_thread_s * p_vdec ) </parameter> :
|
||||
Initializes the IDCT and optional crop tables.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> vdec_DecodeMacroblockC </function>
|
||||
<parameter> ( struct vdec_thread_s *p_vdec,
|
||||
struct macroblock_s * p_mb ); </parameter> :
|
||||
Decodes an entire macroblock and copies its data to the final
|
||||
picture, including chromatic information.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> vdec_DecodeMacroblockBW </function>
|
||||
<parameter> ( struct vdec_thread_s *p_vdec,
|
||||
struct macroblock_s * p_mb ); </parameter> :
|
||||
Decodes an entire macroblock and copies its data to the final
|
||||
picture, except chromatic information (used in grayscale mode).
|
||||
</para> </listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
Currently we have implemented optimized versions for : MMX, MMXEXT, and
|
||||
AltiVec [doesn't work]. We have two plain C versions, the normal
|
||||
(supposedly optimized) Berkeley version (<filename>idct.c</filename>),
|
||||
and the simple 1-D separation IDCT from the ISO reference decoder
|
||||
(<filename>idctclassic.c</filename>).
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2> <title> Symmetrical Multiprocessing </title>
|
||||
|
||||
<para>
|
||||
The MPEG video decoder of VLC can take advantage of several processors if
|
||||
necessary. The idea is to launch a pool of decoders, which will do
|
||||
IDCT/motion compensation on several macroblocks at once.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The functions managing the pool are in <filename>
|
||||
src/video_decoder/vpar_pool.c</filename>. Its use on non-SMP machines is
|
||||
not recommanded, since it is actually slower than the monothread version.
|
||||
Even on SMP machines sometimes...
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
@ -1,436 +0,0 @@
|
||||
<appendix id="gfdl">
|
||||
<title>GNU Free Documentation License</title>
|
||||
<!-- - GNU Project - Free Software Foundation (FSF) -->
|
||||
<!-- LINK REV="made" HREF="mailto:webmasters@gnu.org" -->
|
||||
|
||||
|
||||
<!-- sect1>
|
||||
<title>GNU Free Documentation License</title -->
|
||||
|
||||
<para>Version 1.1, March 2000</para>
|
||||
|
||||
<blockquote>
|
||||
<para>Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.</para>
|
||||
</blockquote>
|
||||
|
||||
<sect1 label="0">
|
||||
<title>PREAMBLE</title>
|
||||
|
||||
<para>The purpose of this License is to make a manual, textbook,
|
||||
or other written document "free" in the sense of freedom: to
|
||||
assure everyone the effective freedom to copy and redistribute it,
|
||||
with or without modifying it, either commercially or
|
||||
noncommercially. Secondarily, this License preserves for the
|
||||
author and publisher a way to get credit for their work, while not
|
||||
being considered responsible for modifications made by
|
||||
others.</para>
|
||||
|
||||
<para>This License is a kind of "copyleft", which means that
|
||||
derivative works of the document must themselves be free in the
|
||||
same sense. It complements the GNU General Public License, which
|
||||
is a copyleft license designed for free software.</para>
|
||||
|
||||
<para>We have designed this License in order to use it for manuals
|
||||
for free software, because free software needs free documentation:
|
||||
a free program should come with manuals providing the same
|
||||
freedoms that the software does. But this License is not limited
|
||||
to software manuals; it can be used for any textual work,
|
||||
regardless of subject matter or whether it is published as a
|
||||
printed book. We recommend this License principally for works
|
||||
whose purpose is instruction or reference.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 label="1">
|
||||
<title>APPLICABILITY AND DEFINITIONS</title>
|
||||
|
||||
<para>This License applies to any manual or other work that
|
||||
contains a notice placed by the copyright holder saying it can be
|
||||
distributed under the terms of this License. The "Document",
|
||||
below, refers to any such manual or work. Any member of the
|
||||
public is a licensee, and is addressed as "you".</para>
|
||||
|
||||
<para>A "Modified Version" of the Document means any work
|
||||
containing the Document or a portion of it, either copied
|
||||
verbatim, or with modifications and/or translated into another
|
||||
language.</para>
|
||||
|
||||
<para>A "Secondary Section" is a named appendix or a front-matter
|
||||
section of the Document that deals exclusively with the
|
||||
relationship of the publishers or authors of the Document to the
|
||||
Document's overall subject (or to related matters) and contains
|
||||
nothing that could fall directly within that overall subject.
|
||||
(For example, if the Document is in part a textbook of
|
||||
mathematics, a Secondary Section may not explain any mathematics.)
|
||||
The relationship could be a matter of historical connection with
|
||||
the subject or with related matters, or of legal, commercial,
|
||||
philosophical, ethical or political position regarding
|
||||
them.</para>
|
||||
|
||||
<para>The "Invariant Sections" are certain Secondary Sections
|
||||
whose titles are designated, as being those of Invariant Sections,
|
||||
in the notice that says that the Document is released under this
|
||||
License.</para>
|
||||
|
||||
<para>The "Cover Texts" are certain short passages of text that
|
||||
are listed, as Front-Cover Texts or Back-Cover Texts, in the
|
||||
notice that says that the Document is released under this
|
||||
License.</para>
|
||||
|
||||
<para>A "Transparent" copy of the Document means a
|
||||
machine-readable copy, represented in a format whose specification
|
||||
is available to the general public, whose contents can be viewed
|
||||
and edited directly and straightforwardly with generic text
|
||||
editors or (for images composed of pixels) generic paint programs
|
||||
or (for drawings) some widely available drawing editor, and that
|
||||
is suitable for input to text formatters or for automatic
|
||||
translation to a variety of formats suitable for input to text
|
||||
formatters. A copy made in an otherwise Transparent file format
|
||||
whose markup has been designed to thwart or discourage subsequent
|
||||
modification by readers is not Transparent. A copy that is not
|
||||
"Transparent" is called "Opaque".</para>
|
||||
|
||||
<para>Examples of suitable formats for Transparent copies include
|
||||
plain ASCII without markup, Texinfo input format, LaTeX input
|
||||
format, SGML or XML using a publicly available DTD, and
|
||||
standard-conforming simple HTML designed for human modification.
|
||||
Opaque formats include PostScript, PDF, proprietary formats that
|
||||
can be read and edited only by proprietary word processors, SGML
|
||||
or XML for which the DTD and/or processing tools are not generally
|
||||
available, and the machine-generated HTML produced by some word
|
||||
processors for output purposes only.</para>
|
||||
|
||||
<para>The "Title Page" means, for a printed book, the title page
|
||||
itself, plus such following pages as are needed to hold, legibly,
|
||||
the material this License requires to appear in the title page.
|
||||
For works in formats which do not have any title page as such,
|
||||
"Title Page" means the text near the most prominent appearance of
|
||||
the work's title, preceding the beginning of the body of the
|
||||
text.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 label="2">
|
||||
<title>VERBATIM COPYING</title>
|
||||
|
||||
<para>You may copy and distribute the Document in any medium,
|
||||
either commercially or noncommercially, provided that this
|
||||
License, the copyright notices, and the license notice saying this
|
||||
License applies to the Document are reproduced in all copies, and
|
||||
that you add no other conditions whatsoever to those of this
|
||||
License. You may not use technical measures to obstruct or
|
||||
control the reading or further copying of the copies you make or
|
||||
distribute. However, you may accept compensation in exchange for
|
||||
copies. If you distribute a large enough number of copies you
|
||||
must also follow the conditions in section 3.</para>
|
||||
|
||||
<para>You may also lend copies, under the same conditions stated
|
||||
above, and you may publicly display copies.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 label="3">
|
||||
<title>COPYING IN QUANTITY</title>
|
||||
|
||||
<para>If you publish printed copies of the Document numbering more
|
||||
than 100, and the Document's license notice requires Cover Texts,
|
||||
you must enclose the copies in covers that carry, clearly and
|
||||
legibly, all these Cover Texts: Front-Cover Texts on the front
|
||||
cover, and Back-Cover Texts on the back cover. Both covers must
|
||||
also clearly and legibly identify you as the publisher of these
|
||||
copies. The front cover must present the full title with all
|
||||
words of the title equally prominent and visible. You may add
|
||||
other material on the covers in addition. Copying with changes
|
||||
limited to the covers, as long as they preserve the title of the
|
||||
Document and satisfy these conditions, can be treated as verbatim
|
||||
copying in other respects.</para>
|
||||
|
||||
<para>If the required texts for either cover are too voluminous to
|
||||
fit legibly, you should put the first ones listed (as many as fit
|
||||
reasonably) on the actual cover, and continue the rest onto
|
||||
adjacent pages.</para>
|
||||
|
||||
<para>If you publish or distribute Opaque copies of the Document
|
||||
numbering more than 100, you must either include a
|
||||
machine-readable Transparent copy along with each Opaque copy, or
|
||||
state in or with each Opaque copy a publicly-accessible
|
||||
computer-network location containing a complete Transparent copy
|
||||
of the Document, free of added material, which the general
|
||||
network-using public has access to download anonymously at no
|
||||
charge using public-standard network protocols. If you use the
|
||||
latter option, you must take reasonably prudent steps, when you
|
||||
begin distribution of Opaque copies in quantity, to ensure that
|
||||
this Transparent copy will remain thus accessible at the stated
|
||||
location until at least one year after the last time you
|
||||
distribute an Opaque copy (directly or through your agents or
|
||||
retailers) of that edition to the public.</para>
|
||||
|
||||
<para>It is requested, but not required, that you contact the
|
||||
authors of the Document well before redistributing any large
|
||||
number of copies, to give them a chance to provide you with an
|
||||
updated version of the Document.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 label="4">
|
||||
<title>MODIFICATIONS</title>
|
||||
|
||||
<para>You may copy and distribute a Modified Version of the
|
||||
Document under the conditions of sections 2 and 3 above, provided
|
||||
that you release the Modified Version under precisely this
|
||||
License, with the Modified Version filling the role of the
|
||||
Document, thus licensing distribution and modification of the
|
||||
Modified Version to whoever possesses a copy of it. In addition,
|
||||
you must do these things in the Modified Version:</para>
|
||||
|
||||
<orderedlist numeration="upperalpha">
|
||||
<listitem><para>Use in the Title Page
|
||||
(and on the covers, if any) a title distinct from that of the
|
||||
Document, and from those of previous versions (which should, if
|
||||
there were any, be listed in the History section of the
|
||||
Document). You may use the same title as a previous version if
|
||||
the original publisher of that version gives permission.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para>List on the Title Page,
|
||||
as authors, one or more persons or entities responsible for
|
||||
authorship of the modifications in the Modified Version,
|
||||
together with at least five of the principal authors of the
|
||||
Document (all of its principal authors, if it has less than
|
||||
five).</para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para>State on the Title page
|
||||
the name of the publisher of the Modified Version, as the
|
||||
publisher.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para>Preserve all the
|
||||
copyright notices of the Document.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para>Add an appropriate
|
||||
copyright notice for your modifications adjacent to the other
|
||||
copyright notices.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para>Include, immediately
|
||||
after the copyright notices, a license notice giving the public
|
||||
permission to use the Modified Version under the terms of this
|
||||
License, in the form shown in the Addendum below.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para>Preserve in that license
|
||||
notice the full lists of Invariant Sections and required Cover
|
||||
Texts given in the Document's license notice.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para>Include an unaltered
|
||||
copy of this License.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para>Preserve the section
|
||||
entitled "History", and its title, and add to it an item stating
|
||||
at least the title, year, new authors, and publisher of the
|
||||
Modified Version as given on the Title Page. If there is no
|
||||
section entitled "History" in the Document, create one stating
|
||||
the title, year, authors, and publisher of the Document as given
|
||||
on its Title Page, then add an item describing the Modified
|
||||
Version as stated in the previous sentence.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para>Preserve the network
|
||||
location, if any, given in the Document for public access to a
|
||||
Transparent copy of the Document, and likewise the network
|
||||
locations given in the Document for previous versions it was
|
||||
based on. These may be placed in the "History" section. You
|
||||
may omit a network location for a work that was published at
|
||||
least four years before the Document itself, or if the original
|
||||
publisher of the version it refers to gives permission.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para>In any section entitled
|
||||
"Acknowledgements" or "Dedications", preserve the section's
|
||||
title, and preserve in the section all the substance and tone of
|
||||
each of the contributor acknowledgements and/or dedications
|
||||
given therein.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para>Preserve all the
|
||||
Invariant Sections of the Document, unaltered in their text and
|
||||
in their titles. Section numbers or the equivalent are not
|
||||
considered part of the section titles.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para>Delete any section
|
||||
entitled "Endorsements". Such a section may not be included in
|
||||
the Modified Version.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para>Do not retitle any
|
||||
existing section as "Endorsements" or to conflict in title with
|
||||
any Invariant Section.</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
|
||||
<para>If the Modified Version includes new front-matter sections
|
||||
or appendices that qualify as Secondary Sections and contain no
|
||||
material copied from the Document, you may at your option
|
||||
designate some or all of these sections as invariant. To do this,
|
||||
add their titles to the list of Invariant Sections in the Modified
|
||||
Version's license notice. These titles must be distinct from any
|
||||
other section titles.</para>
|
||||
|
||||
<para>You may add a section entitled "Endorsements", provided it
|
||||
contains nothing but endorsements of your Modified Version by
|
||||
various parties--for example, statements of peer review or that
|
||||
the text has been approved by an organization as the authoritative
|
||||
definition of a standard.</para>
|
||||
|
||||
<para>You may add a passage of up to five words as a Front-Cover
|
||||
Text, and a passage of up to 25 words as a Back-Cover Text, to the
|
||||
end of the list of Cover Texts in the Modified Version. Only one
|
||||
passage of Front-Cover Text and one of Back-Cover Text may be
|
||||
added by (or through arrangements made by) any one entity. If the
|
||||
Document already includes a cover text for the same cover,
|
||||
previously added by you or by arrangement made by the same entity
|
||||
you are acting on behalf of, you may not add another; but you may
|
||||
replace the old one, on explicit permission from the previous
|
||||
publisher that added the old one.</para>
|
||||
|
||||
<para>The author(s) and publisher(s) of the Document do not by
|
||||
this License give permission to use their names for publicity for
|
||||
or to assert or imply endorsement of any Modified Version.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 label="5">
|
||||
<title>COMBINING DOCUMENTS</title>
|
||||
|
||||
<para>You may combine the Document with other documents released
|
||||
under this License, under the terms defined in section 4 above for
|
||||
modified versions, provided that you include in the combination
|
||||
all of the Invariant Sections of all of the original documents,
|
||||
unmodified, and list them all as Invariant Sections of your
|
||||
combined work in its license notice.</para>
|
||||
|
||||
<para>The combined work need only contain one copy of this
|
||||
License, and multiple identical Invariant Sections may be replaced
|
||||
with a single copy. If there are multiple Invariant Sections with
|
||||
the same name but different contents, make the title of each such
|
||||
section unique by adding at the end of it, in parentheses, the
|
||||
name of the original author or publisher of that section if known,
|
||||
or else a unique number. Make the same adjustment to the section
|
||||
titles in the list of Invariant Sections in the license notice of
|
||||
the combined work.</para>
|
||||
|
||||
<para>In the combination, you must combine any sections entitled
|
||||
"History" in the various original documents, forming one section
|
||||
entitled "History"; likewise combine any sections entitled
|
||||
"Acknowledgements", and any sections entitled "Dedications". You
|
||||
must delete all sections entitled "Endorsements."</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 label="6">
|
||||
<title>COLLECTIONS OF DOCUMENTS</title>
|
||||
|
||||
<para>You may make a collection consisting of the Document and
|
||||
other documents released under this License, and replace the
|
||||
individual copies of this License in the various documents with a
|
||||
single copy that is included in the collection, provided that you
|
||||
follow the rules of this License for verbatim copying of each of
|
||||
the documents in all other respects.</para>
|
||||
|
||||
<para>You may extract a single document from such a collection,
|
||||
and distribute it individually under this License, provided you
|
||||
insert a copy of this License into the extracted document, and
|
||||
follow this License in all other respects regarding verbatim
|
||||
copying of that document.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 label="7">
|
||||
<title>AGGREGATION WITH INDEPENDENT WORKS</title>
|
||||
|
||||
<para>A compilation of the Document or its derivatives with other
|
||||
separate and independent documents or works, in or on a volume of
|
||||
a storage or distribution medium, does not as a whole count as a
|
||||
Modified Version of the Document, provided no compilation
|
||||
copyright is claimed for the compilation. Such a compilation is
|
||||
called an "aggregate", and this License does not apply to the
|
||||
other self-contained works thus compiled with the Document, on
|
||||
account of their being thus compiled, if they are not themselves
|
||||
derivative works of the Document.</para>
|
||||
|
||||
<para>If the Cover Text requirement of section 3 is applicable to
|
||||
these copies of the Document, then if the Document is less than
|
||||
one quarter of the entire aggregate, the Document's Cover Texts
|
||||
may be placed on covers that surround only the Document within the
|
||||
aggregate. Otherwise they must appear on covers around the whole
|
||||
aggregate.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 label="8">
|
||||
<title>TRANSLATION</title>
|
||||
|
||||
<para>Translation is considered a kind of modification, so you may
|
||||
distribute translations of the Document under the terms of section
|
||||
4. Replacing Invariant Sections with translations requires
|
||||
special permission from their copyright holders, but you may
|
||||
include translations of some or all Invariant Sections in addition
|
||||
to the original versions of these Invariant Sections. You may
|
||||
include a translation of this License provided that you also
|
||||
include the original English version of this License. In case of
|
||||
a disagreement between the translation and the original English
|
||||
version of this License, the original English version will
|
||||
prevail.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 label="9">
|
||||
<title>TERMINATION</title>
|
||||
|
||||
<para>You may not copy, modify, sublicense, or distribute the
|
||||
Document except as expressly provided for under this License. Any
|
||||
other attempt to copy, modify, sublicense or distribute the
|
||||
Document is void, and will automatically terminate your rights
|
||||
under this License. However, parties who have received copies, or
|
||||
rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full
|
||||
compliance.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 label="10">
|
||||
<title>FUTURE REVISIONS OF THIS LICENSE</title>
|
||||
|
||||
<para>The Free Software Foundation may publish new, revised
|
||||
versions of the GNU Free Documentation License from time to time.
|
||||
Such new versions will be similar in spirit to the present
|
||||
version, but may differ in detail to address new problems or
|
||||
concerns. See <ulink
|
||||
url="http://www.gnu.org/copyleft/">http://www.gnu.org/copyleft/</ulink>.</para>
|
||||
|
||||
<para>Each version of the License is given a distinguishing
|
||||
version number. If the Document specifies that a particular
|
||||
numbered version of this License "or any later version" applies to
|
||||
it, you have the option of following the terms and conditions
|
||||
either of that specified version or of any later version that has
|
||||
been published (not as a draft) by the Free Software Foundation.
|
||||
If the Document does not specify a version number of this License,
|
||||
you may choose any version ever published (not as a draft) by the
|
||||
Free Software Foundation.</para>
|
||||
</sect1>
|
||||
|
||||
</appendix>
|
||||
<!-- Keep this comment at the end of the file
|
||||
Local variables:
|
||||
mode: sgml
|
||||
sgml-omittag:nil
|
||||
sgml-shorttag:t
|
||||
sgml-minimize-attributes:nil
|
||||
sgml-always-quote-attributes:t
|
||||
sgml-indent-step:2
|
||||
sgml-parent-document: ("referenz.sgml" "appendix")
|
||||
sgml-exposed-tags:nil
|
||||
sgml-local-ecat-files:nil
|
||||
sgml-local-catalogs: CATALOG
|
||||
sgml-validate-command: "nsgmls -s referenz.sgml"
|
||||
ispell-skip-sgml: t
|
||||
End:
|
||||
-->
|
@ -1,205 +0,0 @@
|
||||
<glossary>
|
||||
|
||||
<warning> <para>
|
||||
Please note that this book is in no way a reference documentation
|
||||
on how DVDs work. Its only purpose is to describe the API
|
||||
available for programmers in VLC media player. It is assumed that
|
||||
you have basic knowledge of what MPEG is. The following paragraph
|
||||
is just here as a reminder :
|
||||
</para> </warning>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> AC3 </acronym> :
|
||||
Digital Audio Compression Standard </glossterm>
|
||||
<glossdef> <para> Specification for coding audio data, used in DVD.
|
||||
The documentation is
|
||||
<ulink url="http://www.linuxvideo.org/devel/library/ac3-standard_a_52.pdf">
|
||||
freely available </ulink>.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> B </acronym> (bi-directional) picture </glossterm>
|
||||
<glossdef> <para> Picture decoded from its own data, <emphasis>
|
||||
and </emphasis> from the data of the previous and next (that
|
||||
means <emphasis>in the future</emphasis>) reference
|
||||
pictures (I or P pictures). It is the most compressed picture
|
||||
format, but it is less fault-tolerant.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> DVD </acronym> :
|
||||
Digital Versatile Disc </glossterm>
|
||||
<glossdef> <para> Disc hardware format, using the UDF file system,
|
||||
an extension of the ISO 9660 file system format and a video format
|
||||
which is an extension of the MPEG-2 specification.
|
||||
It basically uses MPEG-2 PS files, with subtitles and sound
|
||||
tracks encoded as private data and fed into non-MPEG decoders,
|
||||
along with .ifo files describing the contents of the DVD. DVD
|
||||
specifications are very hard to get, and it takes some
|
||||
time to reverse-engineer it. Sometimes DVD are zoned and
|
||||
scrambled, so we use a brute-force algorithm to find the key.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> ES </acronym> : Elementary Stream </glossterm>
|
||||
<glossdef> <para> Continuous stream of data fed into a decoder,
|
||||
without any multiplexing layer. ES streams can be MPEG video
|
||||
MPEG audio, AC3 audio, LPCM audio, SPU subpictures...
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> Field picture </glossterm>
|
||||
<glossdef> <para> Picture split in two fields, even and odd, like
|
||||
television does. DVDs coming from TV shows typically use field
|
||||
pictures.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> Frame picture </glossterm>
|
||||
<glossdef> <para> Picture without even/odd discontinuities, unlike
|
||||
field pictures. DVDs coming from movies typically use frame
|
||||
pictures.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym>I</acronym> (intra) picture </glossterm>
|
||||
<glossdef> <para> Picture independantly coded. It can be
|
||||
decoded without any other reference frame. It is regularly
|
||||
sent (like twice a second) for resynchronization purposes.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> IDCT </acronym> : Inverse Discrete
|
||||
Cosinus Transform </glossterm>
|
||||
<glossdef> <para> IDCT is a classical mathematical algorithm
|
||||
to convert from a space domain to a frequency domain. In a
|
||||
nutshell, it codes differences instead of coding all absolute
|
||||
pixels. MPEG uses an 2-D IDCT in the video decoder, and a 1-D
|
||||
IDCT in the audio decoder.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> LPCM </acronym> :
|
||||
Linear Pulse Code Modulation </glossterm>
|
||||
<glossdef> <para> LPCM is a non-compressed audio encoding,
|
||||
available in DVDs.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> MPEG </acronym> :
|
||||
Motion Picture Expert Group </glossterm>
|
||||
<glossdef> <para> Specification describing a standard syntax of files
|
||||
and streams for carrying motion pictures and sound. MPEG-1 is
|
||||
ISO/IEC 11172 (three books), MPEG-2 is ISO/IEC 13818. MPEG-4
|
||||
version 1 is out, but this player doesn't support it. It is
|
||||
relatively easy to get an MPEG specification from ISO or
|
||||
equivalent, drafts are even freely available on the Internet.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> P </acronym> (predictive) picture </glossterm>
|
||||
<glossdef> <para> Picture decoded from its own data <emphasis>
|
||||
and </emphasis> data from a reference picture, which is the
|
||||
last I or P picture received.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> PES </acronym> :
|
||||
Packetized Elementary Stream </glossterm>
|
||||
<glossdef> <para> A chunk of elementary stream. It often corresponds
|
||||
to a logical boundary of the stream (for instance a picture
|
||||
change), but it is not mandatory. PES carry the synchronization
|
||||
information.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> PTS </acronym> :
|
||||
Presentation Time Stamp </glossterm>
|
||||
<glossdef> <para> Time at which the content of a PES packet is supposed
|
||||
to be played. It is used for A/V synchronization.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> PS </acronym> : Program Stream </glossterm>
|
||||
<glossdef> <para> File format obtained by concatenating PES packets
|
||||
and inserting Pack headers and System headers (for timing
|
||||
information). It is the only format described in MPEG-1, and
|
||||
the most used format in MPEG-2.
|
||||
</para></glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> RGB </acronym> : Red Green Blue </glossterm>
|
||||
<glossdef> <para> Picture format where every pixel is calculated in a
|
||||
vector space whose coordinates are red, green, and blue. This
|
||||
is natively used by monitors and TV sets.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> SPU </acronym> : Sub Picture Unit </glossterm>
|
||||
<glossdef> <para> Picture format allowing to do overlays, such
|
||||
as subtitles or DVD menus.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> SCR </acronym> :
|
||||
System Clock Reference </glossterm>
|
||||
<glossdef> <para> Time at which the first byte of a particular pack
|
||||
is supposed to be fed to the decoder. VLC uses it to read the
|
||||
stream at the right pace.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> SDL </acronym> :
|
||||
Simple DirectMedia Layer </glossterm>
|
||||
<glossdef> <para> <ulink url="http://www.libsdl.org/"> SDL </ulink>
|
||||
is a cross-platform multimedia library
|
||||
designed to provide fast access to the video framebuffer and
|
||||
the audio device. Since version 1.1, it features YUV overlay
|
||||
support, which reduces decoding times by a third.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> TS </acronym> : Transport Stream </glossterm>
|
||||
<glossdef> <para> Stream format constituted of fixed size packets
|
||||
(188 bytes), defined by ISO/IEC 13818-1. PES packets are
|
||||
split among several TS packets.
|
||||
A TS stream can contain several programs. It is used in
|
||||
streaming applications, in particular for satellite or cable
|
||||
broadcasting.
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry>
|
||||
<glossterm> <acronym> YUV </acronym> :
|
||||
Luminance/Chrominance </glossterm>
|
||||
<glossdef> <para> Picture format with 1 coordinate of luminance (black
|
||||
and white) and 2 coordinates of chrominance (red and blue).
|
||||
This is natively used by PAL video system, for backward
|
||||
compatibility with older black and white TV sets. Your eyes
|
||||
distinguish luminance variations much better than chrominance
|
||||
variations, so you can compress them more. It is therefore
|
||||
well suited for image compression, and is used by the MPEG
|
||||
specification. The RGB picture can be obtained from the YUV one
|
||||
via a costly matrix multiply operation, which can be done in
|
||||
hardware by most modern video cards ("YUV acceleration").
|
||||
</para> </glossdef>
|
||||
</glossentry>
|
||||
</glossary>
|
@ -1,132 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<appendix> <title> Project history </title>
|
||||
|
||||
<sect1> <title> VIA and the Network2000 project </title>
|
||||
|
||||
<para>
|
||||
The whole project started back in 1995. At that time, students of the
|
||||
<ulink url="http://www.ecp.fr/"> École Centrale de Paris </ulink>
|
||||
enjoyed a TokenRing network, managed by the <ulink
|
||||
url="http://www.via.ecp.fr/"> VIA Centrale Réseaux
|
||||
association</ulink>, and were looking
|
||||
for a solution to upgrade to a modern network. So the idea behind
|
||||
Network2000 was to find a project students would realize that would
|
||||
be interesting, would require a high-quality network, and could
|
||||
provide enough fame so that sponsors would be interested.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Someone came up with the idea of doing television broadcast on the
|
||||
network, so that students could watch TV in their room. This was
|
||||
interesting, mixed a lot of cool technologies, and provided fame
|
||||
because no one had written a free MPEG-2 decoder so far.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Foundation of the VideoLAN project </title>
|
||||
|
||||
<para>
|
||||
<ulink url="http://www.3com.com/"> 3Com</ulink>,
|
||||
<ulink url="http://www.bouygues.com/"> Bouygues </ulink> and
|
||||
la Société des Amis were
|
||||
interested and financed the project, which was then known after
|
||||
the name of VideoLAN.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The VideoLAN team, in particular <ulink url="mailto:walken@via.ecp.fr">
|
||||
Michel Lespinasse </ulink> (current maintainer of <ulink
|
||||
url="http://www.linuxvideo.org/">LiViD</ulink>'s mpeg2dec)
|
||||
and <ulink url="mailto:hpreg@via.ecp.fr"> Régis
|
||||
Duchesne</ulink>, started writing code in 1996. By the end of 1997 they had
|
||||
a working client-server solution, but it would crash a lot and was
|
||||
hard to extend.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
At that time it was still closed-source and only-for-demo code.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> VLC media player design </title>
|
||||
|
||||
<para>
|
||||
In 1998, <ulink url="mailto:seguin@via.ecp.fr"> Vincent Seguin</ulink>
|
||||
(structure, interface and video output),
|
||||
<ulink url="mailto:massiot@via.ecp.fr"> Christophe Massiot</ulink>
|
||||
(input and video decoder),
|
||||
<ulink url="mailto:maxx@via.ecp.fr"> Michel Kaempf</ulink>
|
||||
(audio decoder and audio output) and
|
||||
<ulink url="mailto:polux@via.ecp.fr"> Jean-Marc Dressler</ulink>
|
||||
(synchronization) decided to write a brand new player from scratch,
|
||||
called VideoLAN Client (VLC), so that it could be easily open sourced.
|
||||
Of course we based it on code written by our predecessors, but in
|
||||
an advanced structure, described in the first chapter (it hasn't been
|
||||
necessary to change it a lot).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
At the same time, <ulink url="mailto:benny@via.ecp.fr"> Benoît
|
||||
Steiner </ulink> started the writing of an advanced stream server, called
|
||||
VideoLAN Server (VLS).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Functional test seeds have been released internally in June 1999
|
||||
(vlc-DR1) and November 1999 (vlc-DR2), and we started large scale tests
|
||||
and presentations. The French audience discovered us at Linux Expo
|
||||
in June 1999, presenting our 20 minutes of Golden Eye (which is now
|
||||
a legend among developers :-). At that time only a network input was
|
||||
possible, file input was added later, but it remained kludgy for a while.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In early 2000, we (especially <ulink url="mailto:sam@via.ecp.fr"> Samuel
|
||||
Hocevar</ulink>, who is still a major contributor) started working
|
||||
on DVDs (PS files, AC3, SPU). In the summer 2000, pre-release builds
|
||||
have been seeded (0.2.0 versions), but they still lacked essential
|
||||
features.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In late 2000, <ulink url="mailto:massiot@via.ecp.fr"> Christophe Massiot
|
||||
</ulink> with the support of his company,
|
||||
<ulink url="http://www.idealx.com/"> IDEALX</ulink>, rewrote major
|
||||
parts of the input to allow modularization and advanced navigation, and <ulink
|
||||
url="mailto:stef@via.ecp.fr"> Stéphane Borel </ulink> worked on a
|
||||
fully-featured DVD plug-in for VLC.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> The Opening </title>
|
||||
|
||||
<para>
|
||||
For Linux Expo in February 2001, the <ulink url="http://www.gnu.org/">
|
||||
Free Software Foundation </ulink> and <ulink url="http://www.idealx.com/">
|
||||
IDEALX </ulink> wanted to make live streaming of the 2001 FSF awards
|
||||
from Paris to New York. VideoLAN was the chosen solution. Finally
|
||||
it couldn't be done live because of bandwidth considerations, but a
|
||||
<ulink url="http://www.via.ecp.fr/~massiot/encoding.html"> chain of
|
||||
fully open-source solutions </ulink> made it possible to record it.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
At the same time, the president of the <ulink url="http://www.ecp.fr/">
|
||||
École Centrale Paris</ulink> officially decided to place the software
|
||||
under GNU General Public Licence, thanks to <ulink
|
||||
url="mailto:henri@via.ecp.fr"> Henri Fallon</ulink>, <ulink
|
||||
url="mailto:jprey@ads.ecp.fr"> Jean-Philippe Rey</ulink>, and the IDEALX team.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
VideoLAN software is now one of the most popular open source DVD
|
||||
players available, and has contributors all around the world. The
|
||||
last chapter of this appendix is not written yet :-).
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
</appendix>
|
@ -1,454 +0,0 @@
|
||||
<chapter> <title> The complex multi-layer input </title>
|
||||
|
||||
<para>
|
||||
The idea behind the input module is to treat packets, without knowing
|
||||
at all what is in it. It only takes a packet,
|
||||
reads its ID, and delivers it to the decoder at the right time
|
||||
indicated in the packet header (SCR and PCR fields in MPEG).
|
||||
All the basic browsing operations are implemented without peeking at the
|
||||
content of the elementary stream.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Thus it remains very generic. This also means you can't do stuff like
|
||||
"play 3 frames now" or "move forward 10 frames" or "play as fast as you
|
||||
can but play all frames". It doesn't even know what a "frame" is. There
|
||||
is no privileged elementary stream, like the video one could be (for
|
||||
the simple reason that, according to MPEG, a stream may contain
|
||||
several video ES).
|
||||
</para>
|
||||
|
||||
<sect1> <title> What happens to a file </title>
|
||||
|
||||
<para>
|
||||
An input thread is spawned for every file read. Indeed, input structures
|
||||
and decoders need to be reinitialized because the specificities of
|
||||
the stream may be different. <function> input_CreateThread </function>
|
||||
is called by the interface thread (playlist module).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
At first, an input plug-in capable of reading the plugin item is looked
|
||||
for [this is inappropriate : we should first open the socket,
|
||||
and then probe the beginning of the stream to see which plug-in can read
|
||||
it]. The socket is opened by either <function> input_FileOpen</function>,
|
||||
<function> input_NetworkOpen</function>, or <function>
|
||||
input_DvdOpen</function>. This function sets two very important parameters :
|
||||
<parameter> b_pace_control </parameter> and <parameter> b_seekable
|
||||
</parameter> (see next section).
|
||||
</para>
|
||||
|
||||
<note> <para>
|
||||
We could use so-called "access" plugins for this whole mechanism
|
||||
of opening the input socket. This is not the case because we
|
||||
thought only those three methods were to be used at present,
|
||||
and if we need others we can still build them in.
|
||||
</para> </note>
|
||||
|
||||
<para>
|
||||
Now we can launch the input plugin's <function> pf_init </function>
|
||||
function, and an endless loop doing <function> pf_read </function>
|
||||
and <function> pf_demux</function>. The plugin is responsible
|
||||
for initializing the stream structures
|
||||
(<parameter>p_input->stream</parameter>), managing packet buffers,
|
||||
reading packets and demultiplex them. But in most tasks it will
|
||||
be assisted by functions from the advanced input API (c). That is
|
||||
what we will study in the coming sections !
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Stream Management </title>
|
||||
|
||||
<para>
|
||||
The function which has opened the input socket must specify two
|
||||
properties about it :
|
||||
</para>
|
||||
|
||||
<orderedlist>
|
||||
<listitem> <para> <emphasis> p_input->stream.b_pace_control
|
||||
</emphasis> : Whether or not the stream can be read at our own
|
||||
pace (determined by the stream's frequency and
|
||||
the host computer's system clock). For instance a file or a pipe
|
||||
(including TCP/IP connections) can be read at our pace, if we don't
|
||||
read fast enough, the other end of the pipe will just block on a
|
||||
<function> write() </function> operation. On the contrary, UDP
|
||||
streaming (such as the one used by VideoLAN Server) is done at
|
||||
the server's pace, and if we don't read fast enough, packets will
|
||||
simply be lost when the kernel's buffer is full. So the drift
|
||||
introduced by the server's clock must be regularly compensated.
|
||||
This property controls the clock management, and whether
|
||||
or not fast forward and slow motion can be done.</para>
|
||||
|
||||
<note> <title> Subtilities in the clock management </title> <para>
|
||||
With a UDP socket and a distant server, the drift is not
|
||||
negligible because on a whole movie it can account for
|
||||
seconds if one of the clocks is slightly fucked up. That means
|
||||
that presentation dates given by the input thread may be
|
||||
out of sync, to some extent, with the frequencies given in
|
||||
every Elementary Stream. Output threads (and, anecdotically,
|
||||
decoder threads) must deal with it. </para>
|
||||
|
||||
<para> The same kind of problems may happen when reading from
|
||||
a device (like video4linux's <filename> /dev/video </filename>)
|
||||
connected for instance to a video encoding board.
|
||||
There is no way we could differentiate
|
||||
it from a simple <command> cat foo.mpg | vlc - </command>, which
|
||||
doesn't imply any clock problem. So the Right Thing (c) would be
|
||||
to ask the user about the value of <parameter> b_pace_control
|
||||
</parameter>, but nobody would understand what it means (you are
|
||||
not the dumbest person on Earth, and obviously you have read this
|
||||
paragraph several times to understand it :-). Anyway,
|
||||
the drift should be negligible since the board would share the
|
||||
same clock as the CPU, so we chose to neglect it. </para> </note>
|
||||
</listitem>
|
||||
|
||||
<listitem> <para> <emphasis> p_input->stream.b_seekable
|
||||
</emphasis> : Whether we can do <function> lseek() </function>
|
||||
calls on the file descriptor or not. Basically whether we can
|
||||
jump anywhere in the stream (and thus display a scrollbar) or
|
||||
if we can only read one byte after the other. This has less impact
|
||||
on the stream management than the previous item, but it
|
||||
is not redundant, because for instance
|
||||
<command> cat foo.mpg | vlc - </command> is b_pace_control = 1
|
||||
but b_seekable = 0. On the contrary, you cannot have
|
||||
b_pace_control = 0 along with b_seekable = 1. If a stream is seekable,
|
||||
<parameter> p_input->stream.p_selected_area->i_size </parameter>
|
||||
must be set (in an arbitrary unit, for instance bytes, but it
|
||||
must be the same as p_input->i_tell which indicates the byte
|
||||
we are currently reading from the stream).</para>
|
||||
|
||||
<note> <title> Offset to time conversions </title> <para>
|
||||
Functions managing clocks are located in <filename>
|
||||
src/input/input_clock.c</filename>. All we know about a file
|
||||
is its start offset and its end offset
|
||||
(<parameter>p_input->stream.p_selected_area->i_size</parameter>),
|
||||
currently in bytes, but it could be plugin-dependant. So
|
||||
how the hell can we display in the interface a time in seconds ?
|
||||
Well, we cheat. PS streams have a <parameter> mux_rate </parameter>
|
||||
property which indicates how many bytes we should read in
|
||||
a second. This is subject to change at any time, but practically
|
||||
it is a constant for all streams we know. So we use it to
|
||||
determine time offsets. </para> </note> </listitem>
|
||||
</orderedlist>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Structures exported to the interface </title>
|
||||
|
||||
<para>
|
||||
Let's focus on the communication API between the input module and the
|
||||
interface. The most important file is <filename> include/input_ext-intf.h,
|
||||
</filename> which you should know almost by heart. This file defines
|
||||
the input_thread_t structure, the stream_descriptor_t and all programs
|
||||
and ES descriptors included (you can view it as a tree).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
First, note that the input_thread_t structure features two <type> void *
|
||||
</type> pointers, <parameter> p_method_data </parameter> and <parameter>
|
||||
p_plugin_data</parameter>, which you can respectivly use for buffer
|
||||
management data and plugin data.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Second, a stream description is stored in a tree featuring program
|
||||
descriptors, which themselves contain several elementary stream
|
||||
descriptors. For those of you who don't know all MPEG concepts, an
|
||||
elementary stream, aka ES, is a continuous stream of video or
|
||||
(exclusive) audio data, directly readable by a decoder, without
|
||||
decapsulation.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This tree structure is illustrated by the following
|
||||
figure, where one stream holds two programs.
|
||||
In most cases there will only be one program (to my
|
||||
knowledge only TS streams can carry several programs, for instance
|
||||
a movie and a football game at the same time - this is adequate
|
||||
for satellite and cable broadcasting).
|
||||
</para>
|
||||
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="stream.png" format="PNG" scalefit="1" scale="80"/>
|
||||
</imageobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="stream.gif" format="GIF" />
|
||||
</imageobject>
|
||||
<textobject>
|
||||
<phrase> The program tree </phrase>
|
||||
</textobject>
|
||||
<caption>
|
||||
<para> <emphasis> p_input->stream </emphasis> :
|
||||
The stream, programs and elementary streams can be viewed as a tree.
|
||||
</para>
|
||||
</caption>
|
||||
</mediaobject>
|
||||
|
||||
<warning> <para>
|
||||
For all modifications and accesses to the <parameter>p_input->stream
|
||||
</parameter> structure, you <emphasis>must</emphasis> hold
|
||||
the p_input->stream.stream_lock.
|
||||
</para> </warning>
|
||||
|
||||
<para>
|
||||
ES are described by an ID (the ID the appropriate demultiplexer will
|
||||
look for), a <parameter> stream_id </parameter> (the real MPEG stream
|
||||
ID), a type (defined
|
||||
in ISO/IEC 13818-1 table 2-29) and a litteral description. It also
|
||||
contains context information for the demultiplexer, and decoder
|
||||
information <parameter> p_decoder_fifo </parameter> we will talk
|
||||
about in the next chapter. If the stream you want to read is not an
|
||||
MPEG system layer (for instance AVI or RTP), a specific demultiplexer
|
||||
will have to be written. In that case, if you need to carry additional
|
||||
information, you can use <type> void * </type> <parameter> p_demux_data
|
||||
</parameter> at your convenience. It will be automatically freed on
|
||||
shutdown.
|
||||
</para>
|
||||
|
||||
<note> <title> Why ID and not use the plain MPEG <parameter>
|
||||
stream_id </parameter> ? </title> <para>
|
||||
When a packet (be it a TS packet, PS packet, or whatever) is read,
|
||||
the appropriate demultiplexer will look for an ID in the packet, find the
|
||||
relevant elementary stream, and demultiplex it if the user selected it.
|
||||
In case of TS packets, the only information we have is the
|
||||
ES PID, so the reference ID we keep is the PID. PID don't exist
|
||||
in PS streams, so we have to invent one. It is of course based on
|
||||
the <parameter> stream_id </parameter> found in all PS packets,
|
||||
but it is not enough, since private streams (ie. AC3, SPU and
|
||||
LPCM) all share the same <parameter> stream_id </parameter>
|
||||
(<constant>0xBD</constant>). In that case the first byte of the
|
||||
PES payload is a stream private ID, so we combine this with
|
||||
the stream_id to get our ID (if you did not understand everything,
|
||||
it isn't very important - just remember we used our brains
|
||||
before writing the code :-).
|
||||
</para> </note>
|
||||
|
||||
<para>
|
||||
The stream, program and ES structures are filled in by the plugin's
|
||||
<function> pf_init()
|
||||
</function> using functions in <filename> src/input/input_programs.c,
|
||||
</filename> but are subject to change at any time. The DVD plugin
|
||||
parses .ifo files to know which ES are in the stream; the TS plugin
|
||||
reads the PAT and PMT structures in the stream; the PS plugin can
|
||||
either parse the PSM structure (but it is rarely present), or build
|
||||
the tree "on the fly" by pre-parsing the first megabyte of data.
|
||||
</para>
|
||||
|
||||
<warning> <para>
|
||||
In most cases we need to pre-parse (that is, read the first MB of data,
|
||||
and go back to the beginning) a PS stream, because the PSM (Program
|
||||
Stream Map) structure is almost never present. This is not appropriate,
|
||||
though, but we don't have the choice. A few problems will arise. First,
|
||||
non-seekable streams cannot be pre-parsed, so the ES tree will be
|
||||
built on the fly. Second, if a new elementary stream starts after the
|
||||
first MB of data (for instance a subtitle track won't show up
|
||||
during the credits), it won't appear in the menu before we encounter
|
||||
the first packet. We cannot pre-parse the entire stream because it
|
||||
would take hours (even without decoding it).
|
||||
</para> </warning>
|
||||
|
||||
<para>
|
||||
It is currently the responsibility of the input plugin to spawn the necessary
|
||||
decoder threads. It must call <function> input_SelectES </function>
|
||||
<parameter>( input_thread_t * p_input, es_descriptor_t * p_es )
|
||||
</parameter> on the selected ES.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The stream descriptor also contains a list of areas. Areas are logical
|
||||
discontinuities in the stream, for instance chapters and titles in a
|
||||
DVD. There is only one area in TS and PS streams, though we could
|
||||
use them when the PSM (or PAT/PMT) version changes. The goal is that
|
||||
when you seek to another area, the input plugin loads the new stream
|
||||
descriptor tree (otherwise the selected ID may be wrong).
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Methods used by the interface </title>
|
||||
|
||||
<para>
|
||||
Besides, <filename> input_ext-intf.c </filename>provides a few functions
|
||||
to control the reading of the stream :
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> <function> input_SetStatus </function>
|
||||
<parameter> ( input_thread_t * p_input, int i_mode ) </parameter> :
|
||||
Changes the pace of reading. <parameter> i_mode </parameter> can
|
||||
be one of <constant> INPUT_STATUS_END, INPUT_STATUS_PLAY,
|
||||
INPUT_STATUS_PAUSE, INPUT_STATUS_FASTER, INPUT_STATUS_SLOWER.
|
||||
</constant> </para>
|
||||
|
||||
<note> <para> Internally, the pace of reading is determined
|
||||
by the variable <parameter>
|
||||
p_input->stream.control.i_rate</parameter>. The default
|
||||
value is <constant> DEFAULT_RATE</constant>. The lower the
|
||||
value, the faster the pace is. Rate changes are taken into account
|
||||
in <function> input_ClockManageRef</function>. Pause is
|
||||
accomplished by simply stopping the input thread (it is
|
||||
then awaken by a pthread signal). In that case, decoders
|
||||
will be stopped too. Please remember this if you do statistics
|
||||
on decoding times (like <filename> src/video_parser/vpar_synchro.c
|
||||
</filename> does). Don't call this function if <parameter>
|
||||
p_input->b_pace_control </parameter> == 0.</para> </note>
|
||||
</listitem>
|
||||
|
||||
<listitem> <para> <function> input_Seek </function> <parameter>
|
||||
( input_thread_t * p_input, off_t i_position ) </parameter> :
|
||||
Changes the offset of reading. Used to jump to another place in a
|
||||
file. You <emphasis>mustn't</emphasis> call this function if
|
||||
<parameter> p_input->stream.b_seekable </parameter> == 0.
|
||||
The position is a number (usually long long, depends on your
|
||||
libc) between <parameter>p_input->p_selected_area->i_start
|
||||
</parameter> and <parameter>p_input->p_selected_area->i_size
|
||||
</parameter> (current value is in <parameter>
|
||||
p_input->p_selected_area->i_tell</parameter>). </para>
|
||||
|
||||
<note> <para> Multimedia files can be very large, especially
|
||||
when we read a device like <filename> /dev/dvd</filename>, so
|
||||
offsets must be 64 bits large. Under a lot of systems, like
|
||||
FreeBSD, off_t are 64 bits by default, but it is not the
|
||||
case under GNU libc 2.x. That is why we need to compile VLC
|
||||
with -D_FILE_OFFSET_BITS=64 -D__USE_UNIX98. </para> </note>
|
||||
|
||||
<note> <title> Escaping stream discontinuities </title>
|
||||
<para>
|
||||
Changing the reading position at random can result in a
|
||||
messed up stream, and the decoder which reads it may
|
||||
segfault. To avoid this, we send several NULL packets
|
||||
(ie. packets containing nothing but zeros) before changing
|
||||
the reading position. Indeed, under most video and audio
|
||||
formats, a long enough stream of zeros is an escape sequence
|
||||
and the decoder can exit cleanly.
|
||||
</para> </note>
|
||||
</listitem>
|
||||
|
||||
<listitem> <para> <function> input_OffsetToTime </function>
|
||||
<parameter> ( input_thread_t * p_input, char * psz_buffer,
|
||||
off_t i_offset ) </parameter> : Converts an offset value to
|
||||
a time coordinate (used for interface display).
|
||||
[currently it is broken with MPEG-2 files]
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> input_ChangeES </function>
|
||||
<parameter> ( input_thread_t * p_input, es_descriptor_t * p_es,
|
||||
u8 i_cat ) </parameter> : Unselects all elementary streams of
|
||||
type <parameter> i_cat </parameter> and selects <parameter>
|
||||
p_es</parameter>. Used for instance to change language or
|
||||
subtitle track.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> input_ToggleES </function>
|
||||
<parameter> ( input_thread_t * p_input, es_descriptor_t * p_es,
|
||||
boolean_t b_select ) </parameter> : This is the clean way to
|
||||
select or unselect a particular elementary stream from the
|
||||
interface.
|
||||
</para> </listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="input_buff"> <title> Buffers management </title>
|
||||
|
||||
<para>
|
||||
Input plugins must implement a way to allocate and deallocate packets
|
||||
(whose structures will be described in the next chapter). We
|
||||
basically need four functions :
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> <function> pf_new_packet </function>
|
||||
<parameter> ( void * p_private_data, size_t i_buffer_size )
|
||||
</parameter> :
|
||||
Allocates a new <type> data_packet_t </type> and an associated
|
||||
buffer of i_buffer_size bytes.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> pf_new_pes </function>
|
||||
<parameter> ( void * p_private_data ) </parameter> :
|
||||
Allocates a new <type> pes_packet_t</type>.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> pf_delete_packet </function>
|
||||
<parameter> ( void * p_private_data, data_packet_t * p_data )
|
||||
</parameter> :
|
||||
Deallocates <parameter> p_data</parameter>.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> pf_delete_pes </function>
|
||||
<parameter> ( void * p_private_data, pes_packet_t * p_pes )
|
||||
</parameter> :
|
||||
Deallocates <parameter> p_pes</parameter>.
|
||||
</para> </listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
All functions are given <parameter> p_input->p_method_data </parameter>
|
||||
as first parameter, so that you can keep records of allocated and freed
|
||||
packets.
|
||||
</para>
|
||||
|
||||
<note> <title> Buffers management strategies </title>
|
||||
<para> Buffers management can be done in three ways : </para>
|
||||
|
||||
<orderedlist>
|
||||
<listitem> <para> <emphasis> Traditional libc allocation </emphasis> :
|
||||
For a long time we have used in the PS plugin
|
||||
<function> malloc()
|
||||
</function> and <function> free() </function> every time
|
||||
we needed to allocate or deallocate a packet. Contrary
|
||||
to a popular belief, it is not <emphasis>that</emphasis>
|
||||
slow.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> Netlist </emphasis> :
|
||||
In this method we allocate a very big buffer at the
|
||||
beginning of the problem, and then manage a list of pointers
|
||||
to free packets (the "netlist"). This only works well if
|
||||
all packets have the same size. It is used for long for
|
||||
the TS input. The DVD plugin also uses it, but adds a
|
||||
<emphasis> refcount </emphasis> flag because buffers (2048
|
||||
bytes) can be shared among several packets. It is now
|
||||
deprecated and won't be documented.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> Buffer cache </emphasis> :
|
||||
We are currently developing a new method. It is
|
||||
already in use in the PS plugin. The idea is to call
|
||||
<function> malloc() </function> and <function> free()
|
||||
</function> to absorb stream irregularities, but re-use
|
||||
all allocated buffers via a cache system. We are
|
||||
extending it so that it can be used in any plugin without
|
||||
performance hit, but it is currently left undocumented.
|
||||
</para> </listitem>
|
||||
</orderedlist>
|
||||
</note>
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Demultiplexing the stream </title>
|
||||
|
||||
<para>
|
||||
After being read by <function> pf_read </function>, your plugin must
|
||||
give a function pointer to the demultiplexer function. The demultiplexer
|
||||
is responsible for parsing the packet, gathering PES, and feeding decoders.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Demultiplexers for standard MPEG structures (PS and TS) have already
|
||||
been written. You just need to indicate <function> input_DemuxPS
|
||||
</function> and <function> input_DemuxTS </function> for <function>
|
||||
pf_demux</function>. You can also write your own demultiplexer.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is not the purpose of this document to describe the different levels
|
||||
of encapsulation in an MPEG stream. Please refer to your MPEG specification
|
||||
for that.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
@ -1,334 +0,0 @@
|
||||
<chapter> <title> VLC interface </title>
|
||||
|
||||
<sect1> <title> A typical VLC run course </title>
|
||||
|
||||
<para>
|
||||
This section describes what happens when you launch the <application>
|
||||
vlc</application>
|
||||
program. After the ELF dynamic loader blah blah blah, the main thread
|
||||
becomes the interface thread and starts up in <filename>
|
||||
src/interface/main.c </filename>. It passes through the following steps :
|
||||
</para>
|
||||
|
||||
<orderedlist>
|
||||
<listitem> <para> CPU detection : which CPU are we running on, what are
|
||||
its capabilities (MMX, MMXEXT, 3DNow, AltiVec...) ? </para> </listitem>
|
||||
<listitem> <para> Message interface initialization ; </para> </listitem>
|
||||
<listitem> <para> Command line options parsing ; </para> </listitem>
|
||||
<listitem> <para> Playlist creation ; </para> </listitem>
|
||||
<listitem> <para> Module bank initialization ; </para> </listitem>
|
||||
<listitem> <para> Interface opening ; </para> </listitem>
|
||||
<listitem> <para> Signal handler installation : SIGHUP, SIGINT
|
||||
and SIGQUIT are caught to manage a clean quit (please note that the SDL
|
||||
library also catches SIGSEGV) ; </para> </listitem>
|
||||
<listitem> <para> Audio output thread spawning ; </para> </listitem>
|
||||
<listitem> <para> Video output thread spawning ; </para> </listitem>
|
||||
<listitem> <para> Main loop : events management ; </para> </listitem>
|
||||
</orderedlist>
|
||||
|
||||
<para>
|
||||
Following sections describe each of these steps in particular, and many more.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> The message interface </title>
|
||||
|
||||
<para>
|
||||
It is a know fact that <function> printf() </function> functions are
|
||||
not necessarily thread-safe. As a result,
|
||||
one thread interrupted in a <function> printf() </function> 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.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This API is implemented in two ways. If <constant> INTF_MSG_QUEUE </constant>
|
||||
is defined in <filename> config.h </filename>, every <function>
|
||||
printf</function>-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 <constant> INTF_MSG_QUEUE </constant> 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).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Functions available to print messages are :
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> <function> intf_Msg </function> ( <parameter>
|
||||
char * psz_format, ... </parameter> ) :
|
||||
Print a message to <constant> stdout </constant>, plain and
|
||||
stupid (for instance "vlc 0.2.72 (Apr 16 2001)"). </para> </listitem>
|
||||
|
||||
<listitem> <para> <function> intf_ErrMsg </function> ( <parameter>
|
||||
char * psz_format, ... </parameter> ) :
|
||||
Print an error message to <constant> stderr </constant>. </para>
|
||||
</listitem>
|
||||
|
||||
<listitem> <para> <function> intf_WarnMsg </function> ( <parameter>
|
||||
int i_level, char * psz_format, ... </parameter> ) :
|
||||
Print a message to <constant> stderr </constant> if the warning
|
||||
level (determined by -v, -vv and -vvv) is low enough. </para>
|
||||
<note> <para> Please note
|
||||
that the lower the level, the less important the message is (dayou
|
||||
spik ingliche ?). </para> </note> </listitem>
|
||||
|
||||
<listitem> <para> <function> intf_DbgMsg </function> ( <parameter>
|
||||
char * psz_format, ... </parameter> ) :
|
||||
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 <filename> vlc-trace.log </filename>
|
||||
(if TRACE_LOG is defined in config.h), or printed to <constant> stderr
|
||||
</constant> (otherwise). </para> </listitem>
|
||||
|
||||
<listitem> <para> <function> intf_MsgImm, intf_ErrMsgImm, intf_WarnMsgImm,
|
||||
intf_DbgMsgImm </function> :
|
||||
Same as above, except that the message queue, in case <parameter>
|
||||
INTF_MSG_QUEUE </parameter> is defined,
|
||||
will be flushed before the function returns.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> intf_WarnHexDump </function> ( <parameter>
|
||||
int i_level, void * p_data, int i_size </parameter> ) :
|
||||
Dumps <parameter> i_size </parameter> bytes from <parameter>
|
||||
p_data </parameter> in hexadecimal. <parameter> i_level </parameter>
|
||||
works like <function> intf_WarnMsg </function>. This is useful for
|
||||
debugging purposes. </para> </listitem>
|
||||
|
||||
<listitem> <para> <function> intf_FlushMsg </function> () :
|
||||
Flush the message queue, if it is in use. </para> </listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Command line options </title>
|
||||
|
||||
<para>
|
||||
VLC uses GNU getopt to parse command line options. getopt structures are
|
||||
defined in <filename> src/interface/main.c </filename> in the "Command
|
||||
line options constants" section. To add a new option This section needs
|
||||
to be changed, along with
|
||||
<function> GetConfiguration </function> and <function> Usage</function>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Most configuration directives are exchanged via the environment array,
|
||||
using <function> main_Put*Variable </function> and <function>
|
||||
main_Get*Variable</function>. As a result, <command>
|
||||
./vlc --height 240 </command> is strictly equivalent to : <command>
|
||||
vlc_height=240 ./vlc</command>. That way configuration variables are
|
||||
available everywhere, including plugins.
|
||||
</para>
|
||||
|
||||
<warning> <para>
|
||||
Please note that for thread-safety issues, you should not use
|
||||
<function> main_Put*Variable </function> once the second thread has
|
||||
been spawned.
|
||||
</para> </warning>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Playlist management </title>
|
||||
|
||||
<para>
|
||||
The 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 <filename>
|
||||
src/interface/intf_playlist.c</filename>.
|
||||
<function> intf_PlaylistAdd </function> and <function>
|
||||
intf_PlaylistDelete</function> are typically the most common used.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The main interface loop <function> intf_Manage </function> is then
|
||||
supposed to <emphasis> start and kill input threads </emphasis> when necessary.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Module bank </title>
|
||||
|
||||
<para>
|
||||
On startup, VLC creates a bank of all available .so files (plugins) in
|
||||
<filename>., ./lib, /usr/local/lib/videolan/vlc</filename> <constant>
|
||||
(PLUGIN_PATH)</constant>, and built-in plugins. Every plugin is checked
|
||||
with its capabilities, which are :
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem> <para> MODULE_CAPABILITY_INTF : An interface plugin ;
|
||||
</para> </listitem>
|
||||
<listitem> <para> MODULE_CAPABILITY_ACCESS : A sam-ism, unused at
|
||||
present ;</para> </listitem>
|
||||
<listitem> <para> MODULE_CAPABILITY_INPUT : An input plugin, for
|
||||
instance PS or DVD ;</para> </listitem>
|
||||
<listitem> <para> MODULE_CAPABILITY_DECAPS : A sam-ism, unused at
|
||||
present ;</para> </listitem>
|
||||
<listitem> <para> MODULE_CAPABILITY_ADEC : An audio decoder ;
|
||||
</para> </listitem>
|
||||
<listitem> <para> MODULE_CAPABILITY_VDEC : A video decoder ;
|
||||
</para> </listitem>
|
||||
<listitem> <para> MODULE_CAPABILITY_MOTION : A motion compensation
|
||||
module (for the video decoder) ;</para> </listitem>
|
||||
<listitem> <para> MODULE_CAPABILITY_IDCT : An IDCT module (for
|
||||
the video decoder) ;</para> </listitem>
|
||||
<listitem> <para> MODULE_CAPABILITY_AOUT : An audio output module ;
|
||||
</para> </listitem>
|
||||
<listitem> <para> MODULE_CAPABILITY_VOUT : A video output module ;
|
||||
</para> </listitem>
|
||||
<listitem> <para> MODULE_CAPABILITY_YUV : A YUV module (for the
|
||||
video output) ;</para> </listitem>
|
||||
<listitem> <para> MODULE_CAPABILITY_AFX : An audio effects plugin
|
||||
(for the audio output ; unimplemented) ;</para> </listitem>
|
||||
<listitem> <para> MODULE_CAPABILITY_VFX : A video effects plugin
|
||||
(for the video output ; unimplemented) ;</para> </listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
How to write a plugin is described in the latter sections. Other threads
|
||||
can request a plugin descriptor with <function> module_Need </function>
|
||||
<parameter> ( module_bank_t * p_bank, int i_capabilities, void * p_data ).
|
||||
p_data </parameter> is an optional parameter (reserved for future use) for the
|
||||
<function> pf_probe() </function> function. The returned module_t
|
||||
structure contains pointers to the functions of the plug-in. See
|
||||
<filename>include/modules.h</filename> for more information.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> The interface main loop </title>
|
||||
|
||||
<para>
|
||||
The interface thread will first look for a suitable interface plugin.
|
||||
Then it enters the main interface loop, with the plugin's <function>
|
||||
pf_run </function> function. This function will do what's appropriate,
|
||||
and every 100 ms will call (typically via a GUI timer callback)
|
||||
<function>intf_Manage</function>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>intf_Manage</function> cleans up the module bank by unloading
|
||||
unnecessary modules, manages the playlist, and flushes waiting
|
||||
messages (if the message queue is in use).
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> How to write an interface plugin </title>
|
||||
|
||||
<sect2> <title> API for the Module </title>
|
||||
<para>
|
||||
Have a look the files in directories
|
||||
<filename>modules/misc/control</filename>,
|
||||
<filename> modules/misc/dummy</filename>,
|
||||
<filename> modules/misc/access</filename>,
|
||||
or <filename> modules/gui</filename>. 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
|
||||
<filename>modules/control/hotkeys.c</filename>.</para>
|
||||
|
||||
<para>An interface module is made of 3 entry functions and a module
|
||||
description:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem> <para> 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. </para></listitem>
|
||||
|
||||
<listitem> <para> <function> Open </function> ( <parameter>
|
||||
vlc_object_t* p_object </parameter> ): This is called by
|
||||
VLC to initialize the module. </para></listitem>
|
||||
|
||||
<listitem> <para> <function> Run </function> ( <parameter>
|
||||
vlc_object_t* p_object </parameter> ): really does the job
|
||||
of the interface module (waiting for user input and
|
||||
displaying info). It should check periodically that
|
||||
<constant>p_intf->b_die</constant> is
|
||||
not <constant>VLC_TRUE</constant>.
|
||||
</para></listitem>
|
||||
|
||||
<listitem> <para> <function> Close ( <parameter> vcl_object_t *
|
||||
p_object </parameter> ) </function> function is called by VLC to
|
||||
uninitialize the module (basically, this consists in destroying
|
||||
whatever have been allocated
|
||||
by <function>Open</function>) </para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
<para>The above functions take a <parameter>vlc_object_t*</parameter>
|
||||
as argument, but that may need to be cast into
|
||||
a <parameter>intf_thread_t*</parameter> depending on your needs. This
|
||||
structure is often needed as a parameter for exported VLC functions,
|
||||
such as <function>msg_Err()</function>, <function>msg_Warn()</function>,
|
||||
...</para>
|
||||
|
||||
<para>
|
||||
Define <parameter>intf_sys_t</parameter> to contain any variable you
|
||||
need (don't use static variables, they suck in a multi-threaded
|
||||
application :-).</para>
|
||||
|
||||
<para>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
|
||||
<filename>modules/gui/ncurses/ncurses.c</filename>. It is a quite
|
||||
simple complete interface module with playlist interaction, and
|
||||
progress bar, among other things.
|
||||
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2><title>Arranging for your Module to get Compiled</title>
|
||||
|
||||
<para>If you create a new directory for your module, add
|
||||
a <filename>Modules.am</filename> file in it. In this file, put
|
||||
something like : <constant>SOURCES_yourmodule = myfile1.c
|
||||
myfile2.c</constant></para>
|
||||
|
||||
<para>Then go to the main <filename>configure.ac</filename> file, and
|
||||
add in the <constant>AC_CONFIG_FILES</constant> section (towards the
|
||||
end of the file) a line similar to the others.</para>
|
||||
|
||||
<para>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 <filename>Modules.am</filename>
|
||||
file</para>
|
||||
|
||||
<para>This declares your module; it does not arrange for it to be
|
||||
automatically compiled; automatic compilatoin is described further
|
||||
below.</para>
|
||||
|
||||
<para>You do not write a <filename>Makefile</filename> for your
|
||||
module. Instead this is done via the bootstrap and configuration
|
||||
process. So now run:
|
||||
</para>
|
||||
|
||||
<!---don't know if <xmp> or <example> works. Until then... -->
|
||||
<para><filename>./bootstrap</filename></para>
|
||||
<para><filename>./configure</filename> <emphasis>configure-options</emphasis></para>
|
||||
<para><filename>make</filename></para>
|
||||
|
||||
<para>To build the module manually, go to the
|
||||
directory it resides and type
|
||||
<constant>make libyourmodule_plugin.so</constant> (or .dll, or
|
||||
whatever the file type for a shared library is on your Operating
|
||||
System.)</para>
|
||||
|
||||
<para>To <emphasis>automatically</emphasis> have your module get
|
||||
built, you also set this in the <filename>configure.ac</filename>
|
||||
file; add your module name to the <constant>default modules</constant>
|
||||
section in one of the
|
||||
<constant>AX_ADD_PLUGINS</constant> directives.</para>
|
||||
</sect2>
|
||||
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
@ -1,131 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "/usr/share/sgml/docbook/dtd/xml/4.1/docbookx.dtd"
|
||||
[
|
||||
<!ENTITY glossary SYSTEM "glossary.xml">
|
||||
<!ENTITY overview SYSTEM "overview.xml">
|
||||
<!ENTITY interface SYSTEM "interface.xml">
|
||||
<!ENTITY input SYSTEM "input.xml">
|
||||
<!ENTITY decoders SYSTEM "decoders.xml">
|
||||
<!ENTITY video_output SYSTEM "video_output.xml">
|
||||
<!ENTITY audio_output SYSTEM "audio_output.xml">
|
||||
<!ENTITY ports SYSTEM "ports.xml">
|
||||
<!ENTITY debugging SYSTEM "debugging.xml">
|
||||
<!ENTITY history SYSTEM "history.xml">
|
||||
<!ENTITY gfdl SYSTEM "gfdl.xml">
|
||||
]>
|
||||
|
||||
<book id="vlc-dev-doc">
|
||||
|
||||
<title> VLC media player API Documentation </title>
|
||||
|
||||
<bookinfo>
|
||||
|
||||
<author>
|
||||
<firstname> Christophe </firstname>
|
||||
<surname> Massiot </surname>
|
||||
<affiliation>
|
||||
<jobtitle> <ulink url="mailto:christophe.massiot@idealx.com">
|
||||
Developer </ulink> </jobtitle>
|
||||
<orgname> <ulink url="http://www.idealx.com/"> IDEALX
|
||||
S.A.S. </ulink> </orgname>
|
||||
<orgdiv> Industrial Computing </orgdiv>
|
||||
</affiliation>
|
||||
</author>
|
||||
<collab>
|
||||
<collabname> <ulink url="mailto:sam@zoy.org"> Samuel Hocevar
|
||||
</ulink> </collabname>
|
||||
<affiliation>
|
||||
<jobtitle> Developer </jobtitle>
|
||||
<orgname> VideoLAN project </orgname>
|
||||
</affiliation>
|
||||
</collab>
|
||||
<collab>
|
||||
<collabname> Jean-François Lecomte </collabname>
|
||||
<affiliation>
|
||||
<jobtitle> <ulink url="mailto:jean-francois.lecomte@idealx.com">
|
||||
Developer </ulink> </jobtitle>
|
||||
<orgname> <ulink url="http://www.idealx.com/"> IDEALX
|
||||
S.A.S. </ulink> </orgname>
|
||||
</affiliation>
|
||||
</collab>
|
||||
<collab>
|
||||
<collabname> <ulink url="mailto:henri@via.ecp.fr">Henri Fallon
|
||||
</ulink> </collabname>
|
||||
<affiliation>
|
||||
<jobtitle> Developer </jobtitle>
|
||||
<orgname> VideoLAN project </orgname>
|
||||
</affiliation>
|
||||
</collab>
|
||||
<pubdate> $Id$ </pubdate>
|
||||
<copyright> <year> 2001 </year>
|
||||
<holder> Christophe Massiot, for IDEALX S.A.S. </holder>
|
||||
</copyright>
|
||||
|
||||
<legalnotice> <para>
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.1
|
||||
or any later version published by the Free Software Foundation;
|
||||
A copy of the license is included in the section entitled "GNU
|
||||
Free Documentation License".
|
||||
</para> </legalnotice>
|
||||
</bookinfo>
|
||||
|
||||
<toc />
|
||||
|
||||
<!-- ============================ GLOSSARY ============================
|
||||
-->
|
||||
|
||||
&glossary;
|
||||
|
||||
<!-- ============================ OVERVIEW ============================
|
||||
-->
|
||||
|
||||
&overview;
|
||||
|
||||
<!-- =========================== INTERFACE ============================
|
||||
-->
|
||||
|
||||
&interface;
|
||||
|
||||
<!-- ============================= INPUT ==============================
|
||||
-->
|
||||
|
||||
&input;
|
||||
|
||||
<!-- ============================ DECODERS ============================
|
||||
-->
|
||||
|
||||
&decoders;
|
||||
|
||||
<!-- ========================== VIDEO OUTPUT ==========================
|
||||
-->
|
||||
|
||||
&video_output;
|
||||
|
||||
<!-- ========================== AUDIO OUTPUT ==========================
|
||||
-->
|
||||
|
||||
&audio_output;
|
||||
|
||||
<!-- ============================= PORTS ==============================
|
||||
-->
|
||||
|
||||
&ports;
|
||||
|
||||
<!-- ======================= ADVANCED DEBUGGING =======================
|
||||
-->
|
||||
|
||||
&debugging;
|
||||
|
||||
<!-- ======================== PROJECT HISTORY =========================
|
||||
-->
|
||||
|
||||
&history;
|
||||
|
||||
<!-- ============================= GFDL ===============================
|
||||
-->
|
||||
|
||||
&gfdl;
|
||||
|
||||
</book>
|
@ -1,131 +0,0 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "@DOCBOOKX_DTD@"
|
||||
[
|
||||
<!ENTITY glossary SYSTEM "glossary.xml">
|
||||
<!ENTITY overview SYSTEM "overview.xml">
|
||||
<!ENTITY interface SYSTEM "interface.xml">
|
||||
<!ENTITY input SYSTEM "input.xml">
|
||||
<!ENTITY decoders SYSTEM "decoders.xml">
|
||||
<!ENTITY video_output SYSTEM "video_output.xml">
|
||||
<!ENTITY audio_output SYSTEM "audio_output.xml">
|
||||
<!ENTITY ports SYSTEM "ports.xml">
|
||||
<!ENTITY debugging SYSTEM "debugging.xml">
|
||||
<!ENTITY history SYSTEM "history.xml">
|
||||
<!ENTITY gfdl SYSTEM "gfdl.xml">
|
||||
]>
|
||||
|
||||
<book>
|
||||
|
||||
<title> VLC media player API Documentation </title>
|
||||
|
||||
<bookinfo>
|
||||
|
||||
<author>
|
||||
<firstname> Christophe </firstname>
|
||||
<surname> Massiot </surname>
|
||||
<affiliation>
|
||||
<jobtitle> <ulink url="mailto:christophe.massiot@idealx.com">
|
||||
Developer </ulink> </jobtitle>
|
||||
<orgname> <ulink url="http://www.idealx.com/"> IDEALX
|
||||
S.A.S. </ulink> </orgname>
|
||||
<orgdiv> Industrial Computing </orgdiv>
|
||||
</affiliation>
|
||||
</author>
|
||||
<collab>
|
||||
<collabname> <ulink url="mailto:sam@zoy.org"> Samuel Hocevar
|
||||
</ulink> </collabname>
|
||||
<affiliation>
|
||||
<jobtitle> Developer </jobtitle>
|
||||
<orgname> VideoLAN project </orgname>
|
||||
</affiliation>
|
||||
</collab>
|
||||
<collab>
|
||||
<collabname> Jean-François Lecomte </collabname>
|
||||
<affiliation>
|
||||
<jobtitle> <ulink url="mailto:jean-francois.lecomte@idealx.com">
|
||||
Developer </ulink> </jobtitle>
|
||||
<orgname> <ulink url="http://www.idealx.com/"> IDEALX
|
||||
S.A.S. </ulink> </orgname>
|
||||
</affiliation>
|
||||
</collab>
|
||||
<collab>
|
||||
<collabname> <ulink url="mailto:henri@via.ecp.fr">Henri Fallon
|
||||
</ulink> </collabname>
|
||||
<affiliation>
|
||||
<jobtitle> Developer </jobtitle>
|
||||
<orgname> VideoLAN project </orgname>
|
||||
</affiliation>
|
||||
</collab>
|
||||
<pubdate> $Id$ </pubdate>
|
||||
<copyright> <year> 2001 </year>
|
||||
<holder> Christophe Massiot, for IDEALX S.A.S. </holder>
|
||||
</copyright>
|
||||
|
||||
<legalnotice> <para>
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.1
|
||||
or any later version published by the Free Software Foundation;
|
||||
A copy of the license is included in the section entitled "GNU
|
||||
Free Documentation License".
|
||||
</para> </legalnotice>
|
||||
</bookinfo>
|
||||
|
||||
<toc />
|
||||
|
||||
<!-- ============================ GLOSSARY ============================
|
||||
-->
|
||||
|
||||
&glossary;
|
||||
|
||||
<!-- ============================ OVERVIEW ============================
|
||||
-->
|
||||
|
||||
&overview;
|
||||
|
||||
<!-- =========================== INTERFACE ============================
|
||||
-->
|
||||
|
||||
&interface;
|
||||
|
||||
<!-- ============================= INPUT ==============================
|
||||
-->
|
||||
|
||||
&input;
|
||||
|
||||
<!-- ============================ DECODERS ============================
|
||||
-->
|
||||
|
||||
&decoders;
|
||||
|
||||
<!-- ========================== VIDEO OUTPUT ==========================
|
||||
-->
|
||||
|
||||
&video_output;
|
||||
|
||||
<!-- ========================== AUDIO OUTPUT ==========================
|
||||
-->
|
||||
|
||||
&audio_output;
|
||||
|
||||
<!-- ============================= PORTS ==============================
|
||||
-->
|
||||
|
||||
&ports;
|
||||
|
||||
<!-- ======================= ADVANCED DEBUGGING =======================
|
||||
-->
|
||||
|
||||
&debugging;
|
||||
|
||||
<!-- ======================== PROJECT HISTORY =========================
|
||||
-->
|
||||
|
||||
&history;
|
||||
|
||||
<!-- ============================= GFDL ===============================
|
||||
-->
|
||||
|
||||
&gfdl;
|
||||
|
||||
</book>
|
@ -1,244 +0,0 @@
|
||||
#FIG 3.2
|
||||
Landscape
|
||||
Center
|
||||
Metric
|
||||
A4
|
||||
100.00
|
||||
Single
|
||||
-2
|
||||
1200 2
|
||||
6 900 900 3150 3870
|
||||
6 1080 1620 2880 2070
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
1080 2070 2880 2070 2880 1620 1080 1620 1080 2070
|
||||
4 0 0 100 0 2 12 0.0000 4 135 735 1170 1800 interface\001
|
||||
4 0 0 100 0 0 12 0.0000 4 180 1635 1170 1980 management and loop\001
|
||||
-6
|
||||
6 1080 2520 2520 2970
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
1080 2970 2520 2970 2520 2520 1080 2520 1080 2970
|
||||
4 0 0 100 0 2 12 0.0000 4 180 660 1170 2700 intf_msg\001
|
||||
4 0 0 100 0 0 12 0.0000 4 150 1290 1170 2880 messages output\001
|
||||
-6
|
||||
2 1 0 1 4 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
1530 2070 1530 2520
|
||||
2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
1620 2070 1620 2520
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
1080 3645 2835 3645 2835 3195 1080 3195 1080 3645
|
||||
2 1 0 1 4 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
2655 2070 2655 3195
|
||||
2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
2745 2070 2745 3195
|
||||
2 4 0 1 0 7 100 0 -1 0.000 0 0 7 0 0 5
|
||||
3150 900 3150 3870 900 3870 900 900 3150 900
|
||||
4 0 0 100 0 0 12 0.0000 4 180 1920 1080 1350 Manage threads and user\001
|
||||
4 0 0 100 0 2 12 0.0000 4 180 570 1170 3375 playlist\001
|
||||
4 0 0 100 0 0 12 0.0000 4 180 1560 1170 3555 playlist management\001
|
||||
-6
|
||||
6 4500 225 5850 675
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
4500 675 5850 675 5850 225 4500 225 4500 675
|
||||
4 0 0 100 0 2 12 0.0000 4 135 375 4590 405 main\001
|
||||
4 0 0 100 0 0 12 0.0000 4 180 1185 4590 585 program control\001
|
||||
-6
|
||||
6 4095 900 5985 3240
|
||||
6 4275 1620 5805 2250
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
4275 2250 5805 2250 5805 1620 4275 1620 4275 2250
|
||||
4 0 0 100 0 2 12 0.0000 4 180 1020 4365 1800 video_output\001
|
||||
4 0 0 100 0 0 12 0.0000 4 180 1365 4365 1980 pictures rendering\001
|
||||
4 0 0 100 0 0 12 0.0000 4 180 1080 4365 2160 and displaying\001
|
||||
-6
|
||||
2 1 0 1 4 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
4725 2250 4725 2610
|
||||
2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
4815 2250 4815 2610
|
||||
2 1 0 1 2 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
4905 2250 4905 2610
|
||||
2 4 0 1 0 7 100 0 -1 0.000 0 0 7 0 0 5
|
||||
5985 900 5985 3240 4095 3240 4095 900 5985 900
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
4275 3060 5805 3060 5805 2610 4275 2610 4275 3060
|
||||
4 0 0 100 0 2 16 0.0000 4 225 1380 4275 1170 video_output\001
|
||||
4 0 0 100 0 0 12 0.0000 4 180 1425 4275 1350 pictures displaying\001
|
||||
4 0 0 100 0 2 12 0.0000 4 180 945 4365 2790 vout plug-in\001
|
||||
4 0 0 100 0 0 12 0.0000 4 180 1005 4365 2970 Output driver\001
|
||||
-6
|
||||
6 900 5490 6705 7470
|
||||
6 1080 6120 2700 6570
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
1080 6570 2700 6570 2700 6120 1080 6120 1080 6570
|
||||
4 0 0 100 0 2 12 0.0000 4 180 375 1170 6300 input\001
|
||||
4 0 0 100 0 0 12 0.0000 4 135 1455 1170 6480 file/network socket\001
|
||||
-6
|
||||
6 2970 6120 4590 6570
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
2970 6570 4590 6570 4590 6120 2970 6120 2970 6570
|
||||
4 0 0 100 0 2 12 0.0000 4 180 975 3060 6300 input plug-in\001
|
||||
4 0 0 100 0 0 12 0.0000 4 165 1515 3060 6480 init, read and demux\001
|
||||
-6
|
||||
6 4860 6120 6480 6570
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
4860 6570 6480 6570 6480 6120 4860 6120 4860 6570
|
||||
4 0 0 100 0 2 12 0.0000 4 135 765 4950 6300 programs\001
|
||||
4 0 0 100 0 0 12 0.0000 4 150 1530 4950 6480 stream management\001
|
||||
-6
|
||||
6 1080 6840 2700 7290
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
1080 7290 2700 7290 2700 6840 1080 6840 1080 7290
|
||||
4 0 0 100 0 2 12 0.0000 4 180 1080 1170 7020 input_ext-intf\001
|
||||
4 0 0 100 0 0 12 0.0000 4 180 1350 1170 7200 stream navigation\001
|
||||
-6
|
||||
6 2970 6840 4590 7290
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
2970 7290 4590 7290 4590 6840 2970 6840 2970 7290
|
||||
4 0 0 100 0 2 12 0.0000 4 165 1080 3060 7020 mpeg_system\001
|
||||
4 0 0 100 0 0 12 0.0000 4 180 1020 3060 7200 demultiplexer\001
|
||||
-6
|
||||
6 4860 6840 6480 7290
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
4860 7290 6480 7290 6480 6840 4860 6840 4860 7290
|
||||
4 0 0 100 0 2 12 0.0000 4 135 435 4950 7020 clock\001
|
||||
4 0 0 100 0 0 12 0.0000 4 180 1335 4950 7200 time management\001
|
||||
-6
|
||||
2 1 0 1 4 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
2700 6255 2970 6255
|
||||
2 1 0 1 4 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
4590 6255 4860 6255
|
||||
2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
2700 6345 2970 6345
|
||||
2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
4590 6345 4860 6345
|
||||
2 4 0 1 0 7 100 0 -1 0.000 0 0 7 0 0 5
|
||||
6705 5490 6705 7470 900 7470 900 5490 6705 5490
|
||||
2 1 0 1 1 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
3645 6570 3645 6840
|
||||
2 1 0 1 1 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
4590 7065 4860 7065
|
||||
4 0 0 100 0 2 16 0.0000 4 225 570 1080 5760 input\001
|
||||
-6
|
||||
6 4275 4185 5805 4635
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
4275 4635 5805 4635 5805 4185 4275 4185 4275 4635
|
||||
4 0 0 100 0 0 12 0.0000 4 135 870 4365 4545 ES decoder\001
|
||||
4 0 0 100 0 2 12 0.0000 4 180 1185 4365 4365 video_decoder\001
|
||||
-6
|
||||
6 6255 900 8685 4815
|
||||
6 6705 900 8685 3240
|
||||
6 6885 1620 8505 2250
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
6885 2250 8505 2250 8505 1620 6885 1620 6885 2250
|
||||
4 0 0 100 0 2 12 0.0000 4 180 1020 6975 1800 audio_output\001
|
||||
4 0 0 100 0 0 12 0.0000 4 135 1440 6975 1980 audio frames mixer\001
|
||||
4 0 0 100 0 0 12 0.0000 4 180 780 6975 2160 and player\001
|
||||
-6
|
||||
2 1 0 1 4 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
7335 2250 7335 2610
|
||||
2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
7425 2250 7425 2610
|
||||
2 4 0 1 0 7 100 0 -1 0.000 0 0 7 0 0 5
|
||||
8685 900 8685 3240 6705 3240 6705 900 8685 900
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
6885 3060 8325 3060 8325 2610 6885 2610 6885 3060
|
||||
4 0 0 100 0 2 16 0.0000 4 225 1410 6885 1170 audio_output\001
|
||||
4 0 0 100 0 2 12 0.0000 4 180 960 6975 2790 aout plug-in\001
|
||||
4 0 0 100 0 0 12 0.0000 4 180 960 6975 2970 output driver\001
|
||||
-6
|
||||
6 6885 4185 8505 4635
|
||||
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
|
||||
6885 4635 8505 4635 8505 4185 6885 4185 6885 4635
|
||||
4 0 0 100 0 2 12 0.0000 4 180 1185 6975 4365 audio_decoder\001
|
||||
4 0 0 100 0 0 12 0.0000 4 135 870 6975 4545 ES decoder\001
|
||||
-6
|
||||
2 1 0 1 1 7 100 0 -1 0.000 0 0 -1 1 0 4
|
||||
1 1 1.00 60.00 120.00
|
||||
6885 4275 6345 4275 6345 2070 6885 2070
|
||||
2 1 0 1 2 7 100 0 -1 0.000 0 0 -1 1 0 4
|
||||
1 1 1.00 60.00 120.00
|
||||
6885 4365 6255 4365 6255 1980 6885 1980
|
||||
2 4 0 1 0 7 100 0 -1 0.000 0 0 7 0 0 5
|
||||
8685 3465 8685 4815 6705 4815 6705 3465 8685 3465
|
||||
-6
|
||||
2 1 0 1 2 7 100 0 -1 0.000 0 0 -1 1 0 4
|
||||
1 1 1.00 60.00 120.00
|
||||
1080 1800 675 1800 675 6255 1080 6255
|
||||
2 1 0 1 2 7 100 0 -1 0.000 0 0 -1 1 0 3
|
||||
1 1 1.00 60.00 120.00
|
||||
4500 360 2250 360 2250 1620
|
||||
2 1 0 1 4 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
1530 3645 1530 6120
|
||||
2 1 0 1 2 7 100 0 -1 0.000 0 0 -1 1 0 4
|
||||
1 1 1.00 60.00 120.00
|
||||
4275 4410 3645 4410 3645 1890 4275 1890
|
||||
2 1 0 1 1 7 100 0 -1 0.000 0 0 -1 1 0 4
|
||||
1 1 1.00 60.00 120.00
|
||||
4275 4320 3735 4320 3735 1980 4275 1980
|
||||
2 1 0 1 4 7 100 0 -1 0.000 0 0 -1 1 0 4
|
||||
1 1 1.00 60.00 120.00
|
||||
4275 4500 3555 4500 3555 1800 4275 1800
|
||||
2 1 0 1 4 7 100 0 -1 0.000 0 0 -1 1 0 3
|
||||
1 1 1.00 60.00 120.00
|
||||
5850 450 7740 450 7740 1620
|
||||
2 1 0 1 2 7 100 0 -1 0.000 0 0 -1 1 0 3
|
||||
1 1 1.00 60.00 120.00
|
||||
5850 360 7830 360 7830 1620
|
||||
2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 4
|
||||
1 1 1.00 60.00 120.00
|
||||
1080 1710 585 1710 585 7020 1080 7020
|
||||
2 1 0 1 2 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
5130 6120 5130 4635
|
||||
2 1 0 1 4 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
5220 6120 5220 4635
|
||||
2 1 0 1 1 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
5310 6120 5310 4635
|
||||
2 4 0 1 0 7 100 0 -1 0.000 0 0 7 0 0 5
|
||||
5985 3465 5985 4815 4095 4815 4095 3465 5985 3465
|
||||
2 1 0 1 2 7 100 0 -1 0.000 0 0 -1 1 0 4
|
||||
1 1 1.00 60.00 120.00
|
||||
5670 6120 5670 5175 7425 5175 7425 4635
|
||||
2 1 0 1 4 7 100 0 -1 0.000 0 0 -1 1 0 4
|
||||
1 1 1.00 60.00 120.00
|
||||
5760 6120 5760 5265 7515 5265 7515 4635
|
||||
2 1 0 1 1 7 100 0 -1 0.000 0 0 -1 1 0 4
|
||||
1 1 1.00 60.00 120.00
|
||||
5850 6120 5850 5355 7605 5355 7605 4635
|
||||
2 1 0 1 2 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
6840 6165 7335 6165
|
||||
2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
6840 6435 7335 6435
|
||||
2 1 0 1 4 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
6840 6705 7335 6705
|
||||
2 1 0 1 1 7 100 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
6840 7155 7335 7155
|
||||
4 0 0 100 0 2 16 0.0000 4 165 930 1080 1170 interface\001
|
||||
4 0 0 100 0 2 16 0.0000 4 225 1485 4275 3735 video_decoder\001
|
||||
4 0 0 100 0 2 16 0.0000 4 225 1515 6930 3735 audio_decoder\001
|
||||
4 0 0 100 0 0 12 0.0000 4 135 585 7470 6480 manage\001
|
||||
4 0 0 100 0 0 12 0.0000 4 135 1155 7470 6210 store reference\001
|
||||
4 0 0 100 0 0 12 0.0000 4 135 1215 7470 6750 create/initialize/\001
|
||||
4 0 0 100 0 0 12 0.0000 4 135 330 7470 7200 feed\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 570 7470 6975 destroy\001
|
Before Width: | Height: | Size: 262 KiB |
Before Width: | Height: | Size: 13 KiB |
@ -1,247 +0,0 @@
|
||||
<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>
|
@ -1,159 +0,0 @@
|
||||
<appendix> <title> Ports </title>
|
||||
|
||||
<sect1> <title> Port steps </title>
|
||||
|
||||
<para>
|
||||
Basically, porting to a new architecture boils down to follow the
|
||||
following steps :
|
||||
</para>
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem> <para> <emphasis> Building the VLC : </emphasis>
|
||||
That may be the most difficult part, depending on how POSIX
|
||||
the architecture is. You have to produce valid C.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> Having video : </emphasis>
|
||||
If your architecture features an X server, it should be
|
||||
straightforward, though you might have problems with xvideo
|
||||
or xshm. Otherwise you can try to use SDL if it is supported,
|
||||
or end up writing your own video output plugin.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> Having audio : </emphasis>
|
||||
If your architecture features an OSS compatible DSP or ALSA, you
|
||||
can reuse an existing plugin. Otherwise you will have to write
|
||||
your own audio output plugin.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> Accessing DVDs : </emphasis>
|
||||
You are going to need a write access to the DVD device.
|
||||
Every system has specific ioctl() for key negociation with
|
||||
the DVD drive, so we have set up an abstration layer in
|
||||
<filename> plugins/dvd/dvd_ioctl.c</filename>. You might
|
||||
need to add stuff here. Some operating systems won't give
|
||||
you access to the key negociation (MacOS X), so you will
|
||||
have to write a kernel extension or you will only be able to read
|
||||
unencrypted DVDs. Other operating systems might only give
|
||||
you read access to the DVD device if you are root. Your mileage
|
||||
may vary.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> Writing a native interface : </emphasis>
|
||||
If your system doesn't support GTK or Qt, you will have to
|
||||
write a native interface plugin (for instance Aqua or Win32).
|
||||
You may also need to rewrite the video output plugin if
|
||||
you're currently using a slow compatibility layer.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <emphasis> Optimizing : </emphasis>
|
||||
If your architecture features a special set of multimedia
|
||||
instructions (such as MMX) that is not supported by VLC, you
|
||||
may want to write specific optimizations. Heavy calculation
|
||||
parts are : IDCT (see idct plugin), motion compensation
|
||||
(see motion plugin), and YUV (see video output) if you don't
|
||||
use the YUV overlay support of your video board (SDL or
|
||||
XVideo extension).
|
||||
</para> </listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Building </title>
|
||||
|
||||
<para>
|
||||
This is probably the most complicated part. If your platform is fully
|
||||
POSIX-compliant (such as GNU/Linux), it should be quick, otherwise
|
||||
expect troubles. Known issues are :
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem> <para> Finding a compiler : We use <application> gcc
|
||||
</application> on all platforms, and <application> mingw32
|
||||
</application> to cross-compile the win32 port. If you don't you're
|
||||
probably in <emphasis> very big </emphasis> trouble. Good luck.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> Finding <application> GNU make </application> : Our
|
||||
<filename>Makefile</filename> is heavily <application>GNU make
|
||||
</application> specific, so I suggest you install it.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> Running the <filename> configure </filename>
|
||||
script : This is basically a shell script, so if you have a UNIX
|
||||
shell on your platform it shouldn't be a problem. It will probe
|
||||
your system for headers and libraries needed. It needs
|
||||
adequate <filename> config.sub </filename> and <filename>
|
||||
config.guess</filename>, so if your platform is young your
|
||||
provider may have supplied customized versions. Check with it.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> Compiling the VLC binary : This is the most
|
||||
difficult. Type <command> make </command> or <command> gmake
|
||||
</command> and watch the results. It will probably break soon
|
||||
on a parse error. Add the headers missing, fix mistakes. If
|
||||
you cannot make it to also compiles on other platforms, use
|
||||
#ifdef directives. Add tests for functions or libraries in
|
||||
<filename> configure.in </filename> and run <command> autoheader
|
||||
</command> and <command> autoconf</command>. Always prefer
|
||||
tests on <property> #ifdef HAVE_MY_HEADER_T</property>,
|
||||
instead of <property> #ifdef SYS_MYOPERATINGSYSTEM</property>.
|
||||
You may especially experience problems with the network code
|
||||
in <filename> src/input/input.c</filename>.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> Threads : If your system has an exotic thread
|
||||
implementation, you will probably need to fill the wrappers in
|
||||
<filename> include/threads.h </filename> for your system.
|
||||
Currently supported implementations include the POSIX pthreads,
|
||||
the BeOS threads, and the Mach cthreads.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> Linking : You will need special flags to the
|
||||
compiler, to allow symbol exports (otherwise plug-ins won't
|
||||
work). For instance under GNU/Linux you need <parameter>
|
||||
-rdynamic</parameter>.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> Compiling plug-ins : You do not need external
|
||||
plug-ins at first, you can build all you need in (see <filename>
|
||||
Makefile.opts</filename>). In the long run though, it is a
|
||||
good idea to change <parameter> PCFLAGS</parameter> and <parameter>
|
||||
PLCFLAGS</parameter> to allow run-time loading of libraries.
|
||||
You are going to need <application> libdl</application>, or a
|
||||
similar dynamic loader. To add support for an exotic dynamic
|
||||
loader, have a look at <filename> include/modules_core.h
|
||||
</filename>. Currently supported implementations include the
|
||||
UNIX dynamic loader and the BeOS image loader.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> Assembling : If you use specific optimizations
|
||||
(such as MMX), you may have problem assembling files, because
|
||||
the assembler syntax may be different on your platform. Try
|
||||
without it at first. Pay attention to the optimization flags
|
||||
too, you may see a <emphasis>huge</emphasis> difference.
|
||||
</para> </listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
VLC should work both on little endian and big endian systems. All
|
||||
load operations should be aligned on the native size of the type, so
|
||||
that it works on exotic processors like Sparc or Alpha. It should
|
||||
work on 64-bit platforms, though it has not been optimized for it.
|
||||
A big boost for them would be to have a WORD_TYPE = u64 in <filename>
|
||||
include/input_ext-dec.h</filename>, but it is currently broken for
|
||||
unknown reasons.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you experience run-time problems, see the following appendix and
|
||||
pray for you to have <command> gdb</command>...
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
</appendix>
|
@ -1,42 +0,0 @@
|
||||
#FIG 3.2
|
||||
Landscape
|
||||
Center
|
||||
Metric
|
||||
A4
|
||||
100.00
|
||||
Single
|
||||
-2
|
||||
1200 2
|
||||
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
450 135 6750 135 6750 2295 450 2295 450 135
|
||||
2 2 0 1 0 7 50 0 19 0.000 0 0 -1 0 0 5
|
||||
900 405 1800 405 1800 900 900 900 900 405
|
||||
2 2 0 1 0 7 50 0 18 0.000 0 0 -1 0 0 5
|
||||
1800 405 2790 405 2790 900 1800 900 1800 405
|
||||
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
2790 405 6300 405 6300 900 2790 900 2790 405
|
||||
2 2 0 1 0 7 50 0 7 0.000 0 0 -1 0 0 5
|
||||
900 405 630 405 630 900 900 900 900 405
|
||||
2 2 0 1 0 7 50 0 7 0.000 0 0 -1 0 0 5
|
||||
6300 405 6570 405 6570 900 6300 900 6300 405
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
630 1350 630 945
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
2790 1395 2790 945
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
6300 1395 6300 945
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
6570 1710 6570 945
|
||||
4 0 0 50 0 0 12 0.0000 4 135 765 990 720 PS header\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 885 1845 720 PES header\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 1755 2970 720 PES payload (ES data)\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 630 585 1575 p_buffer\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 1215 2745 1620 p_payload_start\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 1125 5220 1575 p_payload_end\001
|
||||
4 2 0 50 0 0 12 0.0000 4 180 1275 6615 1890 p_buffer + i_size\001
|
||||
4 0 0 50 0 0 14 0.0000 4 195 2295 2205 2025 First (and last) data packet\001
|
||||
4 0 0 50 0 0 14 0.0000 4 195 1005 2835 2655 PES packet\001
|
Before Width: | Height: | Size: 73 KiB |
Before Width: | Height: | Size: 3.4 KiB |
@ -1,31 +0,0 @@
|
||||
/* screen.css
|
||||
*/
|
||||
|
||||
a:link {color: blue; text-decoration: underline}
|
||||
a:active {color: red; text-decoration: underline}
|
||||
a:visited {color: darkblue; text-decoration: underline}
|
||||
|
||||
body {font-family: "Verdana", Georgia, Times; font-size: 1em; color: #000000; background-color: #FFFFFF; margin: 1em 1em 1em 1em;}
|
||||
h1 {font-size: 1.4em; margin: 0em 0em 0em 0em;}
|
||||
h2 {font-size: 1.2em; margin: 0em 0em 0em 0em;}
|
||||
h3 {font-size: 1em; margin: 0em 0em 0em 0em;}
|
||||
h4 {font-size: 1em; margin: 0em 0em 0em 0em;}
|
||||
h5 {font-size: 1em; margin: 0em 0em 0em 0em;}
|
||||
p {font-size: 1em; margin: 0em 0em 0.5em 0em;}
|
||||
tt {font-family: "Courier New"; font-weight: bold;}
|
||||
hr {height: 1px;}
|
||||
|
||||
.navheader {}
|
||||
/* .navfooter {} */
|
||||
.revhistory table { border: none; padding: 0px 0px 0px 0px; margin: 1em 0em 1em 0em;}
|
||||
.revhistory th { border: none; padding: 0px 0px 0px 0px ;}
|
||||
.revhistory td { border: none; padding: 0px 0px 0px 0px ;}
|
||||
.note { border: 1px solid #CCCC99; background-color: #F5F5E7; padding: 0.5em 0.5em 0.5em 0.5em; margin: 1em 0em 1em 0em; }
|
||||
.caution { border: 1px solid #F6EA00; background-color: #FFFFC9; padding: 0.5em 0.5em 0.5em 0.5em; margin: 1em 0em 1em 0em;}
|
||||
.tipp { background-color: #F5F5DC }
|
||||
.important { font-family: "Courier New"; font-size: 0.8em; border: 1px solid #F95E00; background-color: #F9CDB3; padding: 0.5em 0.5em 0.5em 0.5em; margin: 2em 0em 2em 0em;}
|
||||
.screen { font-family: "Courier New"; font-size: 0.8em; border: 1px solid #999999; background-color: #EBEBEB; padding: 0.5em 0.5em 0.5em 0.5em; margin: 2em 0em 2em 0em;}
|
||||
.programlisting { font-family: "Courier New"; font-size: 0.8em; border: 1px solid #B2DBFF; background-color: #F0F8FF; padding: 0.5em 0.5em 0.5em 0.5em; margin: 2em 0em 2em 0em;}
|
||||
.important .programlisting { font-family: "Courier New"; font-size: 1em; border: 1px solid #B2DBFF; background-color: #F0F8FF; padding: 0.5em 0.5em 0.5em 0.5em; margin: 2em 0em 2em 0em;}
|
||||
.important .screen { font-family: "Courier New"; font-size: 1em; border: 1px solid #999999; background-color: #EBEBEB; padding: 0.5em 0.5em 0.5em 0.5em; margin: 2em 0em 2em 0em;}
|
||||
.informalexample { font-family: "Courier New"; font-size: 0.8em; border: 1px solid #B2DBFF; background-color: #F0F8FF; padding: 0.5em 0.5em 0.5em 0.5em; margin: 2em 0em 2em 0em;}
|
@ -1,63 +0,0 @@
|
||||
#FIG 3.2
|
||||
Landscape
|
||||
Center
|
||||
Metric
|
||||
A4
|
||||
100.00
|
||||
Single
|
||||
-2
|
||||
1200 2
|
||||
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
1305 90 3915 90 3915 1170 1305 1170 1305 90
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
0 0 1.00 60.00 120.00
|
||||
1980 1215 1035 3420
|
||||
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
225 3465 1800 3465 1800 4275 225 4275 225 3465
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
0 0 1.00 60.00 120.00
|
||||
630 4275 405 6210
|
||||
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
0 6300 1845 6300 1845 7605 0 7605 0 6300
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
0 0 1.00 60.00 120.00
|
||||
990 4275 990 5625
|
||||
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
720 5670 1260 5670 1260 5985 720 5985 720 5670
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
0 0 1.00 60.00 120.00
|
||||
1395 4275 1665 5580
|
||||
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
1440 5670 2025 5670 2025 5985 1440 5985 1440 5670
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
0 0 1.00 60.00 120.00
|
||||
3195 1215 4095 3375
|
||||
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
3645 3375 4590 3375 4590 3780 3645 3780 3645 3375
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
0 0 1.00 60.00 120.00
|
||||
3915 3780 3420 5670
|
||||
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
3060 5760 3690 5760 3690 6120 3060 6120 3060 5760
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
0 0 1.00 60.00 120.00
|
||||
4275 3780 4815 5670
|
||||
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
4545 5760 5085 5760 5085 6120 4545 6120 4545 5760
|
||||
4 0 0 50 0 0 12 0.0000 4 135 630 1485 360 Stream :\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 2250 1485 585 - b_pace_control, b_seekable\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 1065 1485 810 - i_size, i_tell\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 675 1485 1035 - control\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 855 360 3690 Program 1 :\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 1080 360 3915 - synchro info\001
|
||||
4 0 0 50 0 0 12 0.0000 4 150 1260 360 4140 - p_vout, p_aout\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 450 90 6525 ES 1 :\001
|
||||
4 0 0 50 0 0 12 0.0000 4 165 1635 90 6750 - audio, video or SPU\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 345 90 6975 - ID\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 615 90 7200 - i_type\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 1275 90 7425 - p_decoder_fifo\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 360 810 5895 ES 2\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 360 1575 5895 ES 3\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 765 3735 3645 Program 2\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 360 3195 6030 ES 4\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 360 4635 6030 ES 5\001
|
Before Width: | Height: | Size: 171 KiB |
Before Width: | Height: | Size: 5.6 KiB |
@ -1,44 +0,0 @@
|
||||
<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN" [
|
||||
<!ENTITY dbstyle SYSTEM
|
||||
"/usr/share/sgml/docbook/stylesheet/dsssl/modular/print/docbook.dsl" CDATA DSSSL>
|
||||
]>
|
||||
|
||||
<style-sheet>
|
||||
<style-specification use="docbook">
|
||||
<style-specification-body>
|
||||
|
||||
; Personnalization of James Clark's stylesheet for PS & PDF output
|
||||
; These parameters overide James Clark's one.
|
||||
; Written by Alexis de Lattre (alexis@videolan.org)
|
||||
|
||||
; Only produce a table of contents (not a table of figure, etc...)
|
||||
(define ($generate-book-lot-list$)
|
||||
(list ))
|
||||
|
||||
; Depth of the table of contents
|
||||
(define (toc-depth nd)
|
||||
2)
|
||||
|
||||
; Magins
|
||||
(define %left-margin%
|
||||
3pi)
|
||||
|
||||
(define %right-margin%
|
||||
3pi)
|
||||
|
||||
(define %top-margin%
|
||||
5pi)
|
||||
|
||||
(define %bottom-margin%
|
||||
3.5pi)
|
||||
|
||||
(define %header-margin%
|
||||
2pi)
|
||||
|
||||
(define %footer-margin%
|
||||
2pi)
|
||||
|
||||
</style-specification-body>
|
||||
</style-specification>
|
||||
<external-specification id="docbook" document="dbstyle">
|
||||
</style-sheet>
|
@ -1,33 +0,0 @@
|
||||
<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN" [
|
||||
<!ENTITY dbstyle SYSTEM "/usr/share/sgml/docbook/stylesheet/dsssl/modular/html/docbook.dsl" CDATA DSSSL>
|
||||
]>
|
||||
|
||||
<style-sheet>
|
||||
<style-specification use="docbook">
|
||||
<style-specification-body>
|
||||
|
||||
; Personnalization of James Clark's stylesheet for Text output
|
||||
; These parameters overide James Clark's one.
|
||||
; Written by Alexis de Lattre (alexis@videolan.org)
|
||||
|
||||
; Only produce a table of contents (not a table of figure, etc...)
|
||||
(define ($generate-book-lot-list$)
|
||||
(list ))
|
||||
|
||||
; Depth of the table of contents
|
||||
(define (toc-depth nd)
|
||||
1)
|
||||
|
||||
; No icons
|
||||
(define %admon-graphics%
|
||||
#f)
|
||||
|
||||
; Are sections enumerated?
|
||||
(define %section-autolabel%
|
||||
#t)
|
||||
|
||||
|
||||
</style-specification-body>
|
||||
</style-specification>
|
||||
<external-specification id="docbook" document="dbstyle">
|
||||
</style-sheet>
|
@ -1,66 +0,0 @@
|
||||
#FIG 3.2
|
||||
Landscape
|
||||
Center
|
||||
Metric
|
||||
A4
|
||||
100.00
|
||||
Single
|
||||
-2
|
||||
1200 2
|
||||
6 585 405 4725 1935
|
||||
6 585 405 4725 1935
|
||||
2 2 0 1 0 7 50 0 19 0.000 0 0 -1 0 0 5
|
||||
765 405 1665 405 1665 900 765 900 765 405
|
||||
2 2 0 1 0 7 50 0 18 0.000 0 0 -1 0 0 5
|
||||
1665 405 2655 405 2655 900 1665 900 1665 405
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
2655 1395 2655 945
|
||||
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
2655 405 4500 405 4500 900 2655 900 2655 405
|
||||
2 2 0 1 0 7 50 0 7 0.000 0 0 -1 0 0 5
|
||||
4500 405 4680 405 4680 900 4500 900 4500 405
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
630 1350 630 945
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
4500 1395 4500 945
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
4680 1710 4680 945
|
||||
4 0 0 50 0 0 12 0.0000 4 135 765 855 720 TS header\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 885 1710 720 PES header\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 1215 2070 1575 p_payload_start\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 1755 2700 720 PES payload (ES data)\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 630 585 1575 p_buffer\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 1125 3420 1575 p_payload_end\001
|
||||
4 2 0 50 0 0 12 0.0000 4 180 1275 4725 1890 p_buffer + i_size\001
|
||||
-6
|
||||
2 2 0 1 0 7 50 0 7 0.000 0 0 -1 0 0 5
|
||||
765 405 630 405 630 900 765 900 765 405
|
||||
-6
|
||||
6 5265 405 6975 900
|
||||
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
5265 405 6930 405 6930 900 5265 900 5265 405
|
||||
4 0 0 50 0 0 12 0.0000 4 180 1635 5310 720 PES payload (cont'd)\001
|
||||
-6
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
4680 630 5040 630
|
||||
2 2 0 1 0 7 50 0 19 0.000 0 0 -1 0 0 5
|
||||
5265 405 5085 405 5085 900 5265 900 5265 405
|
||||
2 2 0 1 0 7 50 0 19 0.000 0 0 -1 0 0 5
|
||||
5265 1575 5085 1575 5085 2070 5265 2070 5265 1575
|
||||
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
5265 1575 6930 1575 6930 2070 5265 2070 5265 1575
|
||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 1.00 60.00 120.00
|
||||
6840 900 6840 1530
|
||||
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
450 135 7110 135 7110 2565 450 2565 450 135
|
||||
4 0 0 50 0 0 14 0.0000 4 195 1440 1845 2340 First data packet\001
|
||||
4 0 0 50 0 0 14 0.0000 4 195 1695 5040 1170 Second data packet\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 1425 5400 1890 PES payload (end)\001
|
||||
4 0 0 50 0 0 14 0.0000 4 195 2370 4590 2340 Third (and last) data packet\001
|
||||
4 0 0 50 0 0 14 0.0000 4 195 1005 3330 2925 PES packet\001
|
Before Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 4.6 KiB |
@ -1,221 +0,0 @@
|
||||
<chapter> <title> The video output layer </title>
|
||||
|
||||
<sect1> <title> Data structures and main loop </title>
|
||||
|
||||
<para>
|
||||
Important data structures are defined in <filename> include/video.h
|
||||
</filename> and <filename> include/video_output.h</filename>. The main
|
||||
data structure is <type> picture_t</type>, which describes everything a
|
||||
video decoder thread needs. Please refer to this file for more
|
||||
information. Typically, <parameter> p_data </parameter> will be a
|
||||
pointer to YUV planar picture.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Note also the <type> subpicture_t </type> structure. In fact the VLC SPU
|
||||
decoder only parses the SPU header, and converts the SPU graphical data
|
||||
to an internal format which can be rendered much faster. So a part of
|
||||
the "real" SPU decoder lies in
|
||||
<filename> src/video_output/video_spu.c</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <type> vout_thread_t </type> structure is much more complex, but
|
||||
you needn't understand everything. Basically the video output thread
|
||||
manages a heap of pictures and subpictures (5 by default). Every
|
||||
picture has a status (displayed, destroyed, empty...) and eventually
|
||||
a presentation time. The main job of the video output is an infinite
|
||||
loop to : [this is subject to change in the near future]
|
||||
</para>
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem> <para> Find the next picture to display in the heap.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> Find the current subpicture to display.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> Render the picture (if the video output plug-in
|
||||
doesn't support YUV overlay). Rendering will call an optimized
|
||||
YUV plug-in, which will also do the scaling, add subtitles and
|
||||
an optional picture information field.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> Sleep until the specified date.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> Display the picture (plug-in function). For
|
||||
outputs which display RGB data, it is often accomplished with
|
||||
a buffer switching. <parameter> p_vout->p_buffer </parameter>
|
||||
is an array of two buffers where the YUV transform takes place,
|
||||
and p_vout->i_buffer_index indicates the currently displayed
|
||||
buffer.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> Manage events.
|
||||
</para> </listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> Methods used by video decoders </title>
|
||||
|
||||
<para>
|
||||
The video output exports a bunch of functions so that decoders can send
|
||||
their decoded data. The most important function is
|
||||
<function>vout_CreatePicture</function> which allocates the picture
|
||||
buffer to the size indicated by the video decoder. It then just needs
|
||||
to feed <type> (void *) </type><parameter> p_picture->p_data </parameter>
|
||||
with the decoded data, and call <function> vout_DisplayPicture </function>
|
||||
and <function> vout_DatePicture </function> upon necessary.
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem> <para> <type> picture_t * </type> <function>
|
||||
vout_CreatePicture </function>
|
||||
<parameter> ( vout_thread_t *p_vout, int i_type, int i_width,
|
||||
int i_height ) </parameter> :
|
||||
Returns an allocated picture buffer. <parameter> i_type </parameter>
|
||||
will be for instance <constant> YUV_420_PICTURE</constant>, and
|
||||
i_width and i_height are in pixels.
|
||||
</para>
|
||||
|
||||
<warning> <para> If no picture is available in the heap,
|
||||
<function> vout_CreatePicture </function> will return NULL.
|
||||
</para> </warning>
|
||||
</listitem>
|
||||
|
||||
<listitem> <para> <function> vout_LinkPicture </function>
|
||||
<parameter> ( vout_thread_t *p_vout, picture_t *p_pic ) </parameter> :
|
||||
Increases the refcount of the picture, so that it doesn't get
|
||||
accidently freed while the decoder still needs it. For instance,
|
||||
an I or P picture can still be needed after displaying to decode
|
||||
interleaved B pictures.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> vout_UnlinkPicture </function>
|
||||
<parameter> ( vout_thread_t *p_vout, picture_t *p_pic ) </parameter> :
|
||||
Decreases the refcount of the picture. An unlink must be done
|
||||
for every link previously made.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> vout_DatePicture </function>
|
||||
<parameter> ( vout_thread_t *p_vout, picture_t *p_pic ) </parameter> :
|
||||
Gives the picture a presentation date. You can start working on
|
||||
a picture before knowing precisely at what time it will be
|
||||
displayed. For instance to date an I or P picture, you must wait
|
||||
until you have decoded all previous B pictures (which are
|
||||
indeed placed after - decoding order != presentation order).
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> vout_DisplayPicture </function>
|
||||
<parameter> ( vout_thread_t *p_vout, picture_t *p_pic ) </parameter> :
|
||||
Tells the video output that a picture has been completely decoded
|
||||
and is ready to be rendered. It can be called before or after
|
||||
<function> vout_DatePicture</function>.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> vout_DestroyPicture </function>
|
||||
<parameter> ( vout_thread_t *p_vout, picture_t *p_pic ) </parameter> :
|
||||
Marks the picture as empty (useful in case of a stream parsing
|
||||
error).
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <type> subpicture_t * </type> <function>
|
||||
vout_CreateSubPicture </function> <parameter> ( vout_thread_t *p_vout,
|
||||
int i_channel, int i_type ) </parameter> :
|
||||
Returns an allocated subpicture buffer. <parameter> i_channel
|
||||
</parameter> is the ID of the subpicture channel, <parameter> i_type
|
||||
</parameter> is <constant> DVD_SUBPICTURE </constant> or
|
||||
<constant> TEXT_SUBPICTURE</constant>, <parameter> i_size
|
||||
</parameter> is the length in bytes of the packet.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> vout_DisplaySubPicture </function>
|
||||
<parameter> ( vout_thread_t *p_vout, subpicture_t *p_subpic )
|
||||
</parameter> :
|
||||
Tells the video output that a subpicture has been completely
|
||||
decoded. It obsoletes the previous subpicture.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> vout_DestroySubPicture </function>
|
||||
<parameter> ( vout_thread_t *p_vout, subpicture_t *p_subpic )
|
||||
</parameter> :
|
||||
Marks the subpicture as empty.
|
||||
</para> </listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> How to write a video output plug-in </title>
|
||||
|
||||
<para>
|
||||
A video output takes care of the system calls to display the pictures and
|
||||
manage the output window. Have a look at <filename>
|
||||
plugins/x11/vout_x11.c</filename>. You must write the following
|
||||
functions :
|
||||
</para>
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem> <para> <type> int </type> <function> vout_Probe </function>
|
||||
<parameter> ( probedata_t *p_data ) </parameter> :
|
||||
Returns a score between 0 and 999 to indicate whether it can
|
||||
run on the architecture. 999 is the best. <parameter> p_data
|
||||
</parameter> is currently unused.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <type> int </type> <function> vout_Create </function>
|
||||
<parameter> ( vout_thread_t *p_vout ) </parameter> :
|
||||
Basically, initializes and opens a new window. Returns TRUE if
|
||||
it failed.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <type> int </type> <function> vout_Init </function>
|
||||
<parameter> ( vout_thread_t *p_vout ) </parameter> :
|
||||
Creates optional picture buffers (for instance ximages or
|
||||
xvimages). Returns TRUE if it failed.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> vout_End </function> <parameter>
|
||||
( vout_thread_t *p_vout ) </parameter> :
|
||||
Frees optional picture buffers.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <type> int </type> <function> vout_Manage
|
||||
</function> <parameter> ( vout_thread_t *p_vout ) </parameter> :
|
||||
Manages events (including for instance resize events).
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> vout_Display </function> <parameter>
|
||||
( vout_thread_t *p_vout ) </parameter> :
|
||||
Displays a previously rendered buffer.
|
||||
</para> </listitem>
|
||||
|
||||
<listitem> <para> <function> vout_SetPalette </function>
|
||||
<parameter> ( vout_thread_t *p_vout, u16 *red, u16 *green,
|
||||
u16 *blue, u16 *transp ) </parameter> :
|
||||
Sets the 8 bpp palette. <parameter> red, green </parameter>
|
||||
and <parameter> blue </parameter> are arrays of 256 <type>
|
||||
unsigned shorts</type>.
|
||||
</para> </listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1> <title> How to write a YUV plug-in </title>
|
||||
|
||||
<para>
|
||||
Look at the C source <filename> plugins/yuv/transforms_yuv.c</filename>.
|
||||
You need to redefine just the same transformations. Basically, it is a
|
||||
matrix multiply operation. Good luck.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
@ -1,12 +0,0 @@
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0' xmlns="http://www.w3.org/TR/xhtml1/transitional" exclude-result-prefixes="#default">
|
||||
|
||||
<xsl:import href="/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/xhtml/chunk.xsl"/>
|
||||
|
||||
<xsl:variable name="toc.section.depth">1</xsl:variable>
|
||||
<xsl:param name="chunker.output.encoding" select="'UTF-8'"/>
|
||||
<xsl:param name="chunk.section.depth" select="0"/>
|
||||
<xsl:param name="html.stylesheet" select="'../screen.css'"/>
|
||||
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
@ -1,12 +0,0 @@
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0' xmlns="http://www.w3.org/TR/xhtml1/transitional" exclude-result-prefixes="#default">
|
||||
|
||||
<xsl:import href="/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/xhtml/docbook.xsl"/>
|
||||
|
||||
<xsl:param name="html.stylesheet" select="'../screen.css'"/>
|
||||
<xsl:param name="toc.section.depth" select="1"/>
|
||||
<xsl:param name="generate.toc" select="'book toc chapter nop'"/>
|
||||
|
||||
<xsl:output method="xml" encoding="UTF-8" indent="yes" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|