From 2a4dbb619807a5da276e21463eee3c1fc07840e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 19:32:52 +0200 Subject: Rename the sgml files to docbook (xml). --HG-- rename : doc/hackersguide/hackersguide.sgml => doc/hackersguide/hackersguide.docbook rename : doc/hackersguide/internals.sgml => doc/hackersguide/internals.docbook rename : doc/hackersguide/intro.sgml => doc/hackersguide/intro.docbook rename : doc/hackersguide/library.sgml => doc/hackersguide/library.docbook rename : doc/hackersguide/output.sgml => doc/hackersguide/output.docbook rename : doc/hackersguide/overview.sgml => doc/hackersguide/overview.docbook rename : doc/hackersguide/stream.sgml => doc/hackersguide/stream.docbook --- doc/hackersguide/hackersguide.docbook | 47 ++ doc/hackersguide/hackersguide.sgml | 47 -- doc/hackersguide/internals.docbook | 762 ++++++++++++++++++++++++++++++++ doc/hackersguide/internals.sgml | 762 -------------------------------- doc/hackersguide/intro.docbook | 54 +++ doc/hackersguide/intro.sgml | 54 --- doc/hackersguide/library.docbook | 410 +++++++++++++++++ doc/hackersguide/library.sgml | 410 ----------------- doc/hackersguide/output.docbook | 668 ++++++++++++++++++++++++++++ doc/hackersguide/output.sgml | 668 ---------------------------- doc/hackersguide/overview.docbook | 811 ++++++++++++++++++++++++++++++++++ doc/hackersguide/overview.sgml | 811 ---------------------------------- doc/hackersguide/stream.docbook | 656 +++++++++++++++++++++++++++ doc/hackersguide/stream.sgml | 656 --------------------------- 14 files changed, 3408 insertions(+), 3408 deletions(-) create mode 100644 doc/hackersguide/hackersguide.docbook delete mode 100644 doc/hackersguide/hackersguide.sgml create mode 100644 doc/hackersguide/internals.docbook delete mode 100644 doc/hackersguide/internals.sgml create mode 100644 doc/hackersguide/intro.docbook delete mode 100644 doc/hackersguide/intro.sgml create mode 100644 doc/hackersguide/library.docbook delete mode 100644 doc/hackersguide/library.sgml create mode 100644 doc/hackersguide/output.docbook delete mode 100644 doc/hackersguide/output.sgml create mode 100644 doc/hackersguide/overview.docbook delete mode 100644 doc/hackersguide/overview.sgml create mode 100644 doc/hackersguide/stream.docbook delete mode 100644 doc/hackersguide/stream.sgml (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/hackersguide.docbook b/doc/hackersguide/hackersguide.docbook new file mode 100644 index 000000000..ebc42d4c7 --- /dev/null +++ b/doc/hackersguide/hackersguide.docbook @@ -0,0 +1,47 @@ + + + + + + +]> + + + + + The xine hacker's guide + hackersguide + + GünterBartsch + HeikoSchäfer + RichardWareham + MiguelFreitas + JamesCourtier-Dutton + SiggiLangauf + MarcoZühlke + MikeMelanson + MichaelRoitzsch + + + 2001-2003 + the xine project team + + + + This document should help xine hackers to find their way through + xine's architecture and source code. It's a pretty free-form document + containing a loose collection of articles describing various aspects + of xine's internals. + + + + + &intro; + &library; + &overview; + &internals; + &stream; + &output; + + diff --git a/doc/hackersguide/hackersguide.sgml b/doc/hackersguide/hackersguide.sgml deleted file mode 100644 index ebc42d4c7..000000000 --- a/doc/hackersguide/hackersguide.sgml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - -]> - - - - - The xine hacker's guide - hackersguide - - GünterBartsch - HeikoSchäfer - RichardWareham - MiguelFreitas - JamesCourtier-Dutton - SiggiLangauf - MarcoZühlke - MikeMelanson - MichaelRoitzsch - - - 2001-2003 - the xine project team - - - - This document should help xine hackers to find their way through - xine's architecture and source code. It's a pretty free-form document - containing a loose collection of articles describing various aspects - of xine's internals. - - - - - &intro; - &library; - &overview; - &internals; - &stream; - &output; - - diff --git a/doc/hackersguide/internals.docbook b/doc/hackersguide/internals.docbook new file mode 100644 index 000000000..9bd1ec684 --- /dev/null +++ b/doc/hackersguide/internals.docbook @@ -0,0 +1,762 @@ + + xine internals + + + Engine architecture and data flow + + + + + + + + + xine engine architecture + + + + Media streams usually consist of audio and video data multiplexed + into one bitstream in the so-called system-layer (e.g. AVI, Quicktime or MPEG). + A demuxer plugin is used to parse the system layer and extract audio and video + packages. The demuxer uses an input plugin to read the data and stores it + in pre-allocated buffers from the global buffer pool. + The buffers are then added to the audio or video stream fifo. + + + From the other end of these fifos the audio and video decoder threads + consume the buffers and hand them over to the current audio or video + decoder plugin for decompression. These plugins then send the decoded + data to the output layer. The buffer holding the encoded + data is no longer needed and thus released to the global buffer pool. + + + In the output layer, the video frames and audio samples pass through a + post plugin tree, which can apply effects or other operations to the data. + When reaching the output loops, frames and samples are enqueued to be + displayed, when the presentation time has arrived. + + + A set of extra information travels with the data. Starting at the input and + demuxer level, where this information is generated, the data is attached to + the buffers as they wait in the fifo. The decoder loops copy the data to + a storage of their own. From there, every frame and audio buffer leaving + the stream layer is tagged with the data the decoder loop storage currently + holds. + + + + + Plugin system + + The plugin system enables some of xine's most valuable features: + + + + drop-in extensiability + + + + + support parallel installation of multiple (incompatible) libxine versions + + + + + support for multiple plugin directories + ($prefix/lib/xine/plugins, + $HOME/.xine/plugins, ...) + + + + + support for recursive plugin directories + (plugins are found even in subdirectories of the plugin directories) + + + + + version management + (On start, xine finds all plugins in its plugin (sub)directories and + chooses an appropriate version (usually the newest) for each plugin.) + + + + + simplification + (Plugins don't have to follow any special naming convention, + and any plugin may contain an arbitrary subset of input, demuxer, + decoder or output plugins.) + + + + + + Essentally, plugins are just shared objects, ie dynamic libraries. In + contrast to normal dynamic libraries, they are stored outside of the + system's library PATHs and libxine does its own bookkeeping, which + enables most advanced features mentioned above. + + + Plugin location and filesystem layout + + The primary goal for this new plugin mechanism was the need to support + simultaneous installation of several (most likely incompatible) + libxine versions without them overwriting each other's + plugins. Therefore, we have this simple layout: + + + Plugins are installed below XINE_PLUGINDIR + (/usr/local/lib/xine/plugins by default). + Note that plugins are never directly installed into XINE_PLUGINDIR. + Instead, a separate subdirectory is created for each "plugin + provider". A plugin provider is equivalent with the exact version of + one source package. Typical examples include "xine-lib-0.9.11" or + "xine-vcdnav-1.0". Every source package is free to install an + arbitrary number of plugins in its own, private directory. If a + package installs several plugins, they may optionally be organized + further into subdirectories. + + + So you will finally end up with something like this: + +   /usr/local/lib/xine/plugins +    xine-lib-0.9.11 +    demux_mpeg_block.so +    decode_mpeg.so +    video_out_xv.so +    ... +    xine-vcdnav-0.9.11 +    input_vcdnav.so +    xine-lib-1.2 +    input +    file.so +    stdin_fifo.so +    vcd.so +    demuxers +    fli.so +    avi.so +    ... +    decoders +    ffmpeg.so +    mpeg.so (may contain mpeg 1/2 audio and video decoders) +    pcm.so +    ... +    output +    video_xv.so +    audio_oss.so +    ... +    xine-lib-3.0 +    avi.so (avi demuxer) +    mpeg.so (contains mpeg demuxers and audio/video decoders) +    video_out_xv.so (Xv video out) +    ... + + + As you can see, every package is free to organize plugins at will + below its own plugin provider directory. + Additionally, administrators may choose to put plugins directly into + XINE_PLUGINDIR, or in a "local" subdirectory. + Users may wish to put additional plugins in ~/.xine/plugins/. + Again, there may be subdirectories to help organize the plugins. + + + The default value for XINE_PLUGINDIR can be obtained using the + xine-config --plugindir command. + + + + Plugin Content: What's inside the .so? + + Each plugin library (.so file) contains an arbitrary number of (virtual) + plugins. Typically, it will contain exactly one plugin. However, it + may be useful to put a set of related plugins in one library, so they + can share common code. + + + First of all, what is a virtual plugin? + A virtual plugin is essentially a structure that is defined by the + xine engine. This structure typically contains lots of function + pointers to the actual API functions. + For each plugin API, there are several API versions, and each API + version may specify a new, incompatible structure. Therefore, it is + essential that only those plugins are loaded that support current + libxine's API, so the .so file needs a plugin list that + provides libxine with the version information, even before it tries to + load any of the plugins. + + + This plugin list is held in an array named xine_plugin_info": + +   plugin_info_t xine_plugin_info[] = { +    /* type, API, "name", version, special_info, init_function */ +    { PLUGIN_DEMUX, 20, "flac", XINE_VERSION_CODE, NULL, demux_flac_init_class }, +    { PLUGIN_AUDIO_DECODER, 13, "flacdec", XINE_VERSION_CODE, &dec_info_audio, init_plugin }, +    { PLUGIN_NONE, 0, "", 0, NULL, NULL } +   }; + + + The structure of xine_plugin_info may never be changed. + If it ever needs to be changed, it must be renamed to avoid + erraneous loading of incompatible plugins. + + + xine_plugin_info can contain any number of plugins + and must be terminated with a PLUGIN_NONE entry. Available plugin + types are: + +   #define PLUGIN_NONE 0 +   #define PLUGIN_INPUT 1 +   #define PLUGIN_DEMUX 2 +   #define PLUGIN_AUDIO_DECODER 3 +   #define PLUGIN_VIDEO_DECODER 4 +   #define PLUGIN_SPU_DECODER 5 +   #define PLUGIN_AUDIO_OUT 6 +   #define PLUGIN_VIDEO_OUT 7 +   #define PLUGIN_POST 8 + + + The plugin version number is generated from xine-lib's version number + like this: MAJOR * 10000 + MINOR * 100 + SUBMINOR. + This is not required, but it's an easy way to ensure that the version + increases for every release. + + + Every entry in xine_plugin_info has an initialization + function for the plugin class context. + This function returns a pointer to freshly allocated (typically + via malloc()) structure containing mainly function + pointers; these are the "methods" of the plugin class. + + + The "plugin class" is not what we call to do the job yet (like decoding + a video or something), it must be instantiated. One reason for having the + class is to hold any global settings that must be accessed by every + instance. Remember that xine library is multistream capable: multible + videos can be decoded at the same time, thus several instances of the + same plugin are possible. + + + If you think this is pretty much an object-oriented aproach, + then you're right. + + + A fictitious file input plugin that supports input plugin API 12 and + 13, found in xine-lib 2.13.7 would then define this plugin list: + +   #include <xine/plugin.h> +   ... +   plugin_t *init_api12(void) { +    input_plugin_t *this; +    +    this = malloc(sizeof(input_plugin_t)); +    ... +    return (plugin_t *)this; +   } +   /* same thing, with different initialization for API 13 */ +    +   const plugin_info_t xine_plugin_info[] = { +    { PLUGIN_INPUT, 12, "file", 21307, init_api12 }, +    { PLUGIN_INPUT, 13, "file", 21307, init_api13 }, +    { PLUGIN_NONE, 0, "", 0, NULL } +   } + This input plugin supports two APIs, other plugins might provide a + mixture of demuxer and decoder plugins that belong together somehow + (ie. share common code). + + + You'll find exact definitions of public functions and plugin structs + in the appropriate header files for each plugin type: + input/input_plugin.h for input plugins, + demuxers/demux.h for demuxer plugins, + xine-engine/video_decoder.h for video decoder plugins, + xine-engine/audio_decoder.h for audio decoder plugins, + xine-engine/post.h for post plugins, + xine-engine/video_out.h for video out plugins, + xine-engine/audio_out.h for audio out plugins. + Additional information will also be given in the dedicated sections below. + + + Many plugins will need some additional "private" data fields. + These should be simply added at the end of the plugin structure. + For example a demuxer plugin called "foo" with two private + fields "xine" and "count" may have a plugin structure declared in + the following way: + +   typedef struct { +    /* public fields "inherited" from demux.h */ +    demux_plugin_t demux_plugin; +    +    xine_t *xine; +    int count; +   } demux_foo_t; + + + The plugin would then access public members via the + demux_plugin field and private fields directly. + + + Summary: Plugins consist of two C-style classes, each representing a different context. + + + + The first is the so called "plugin class" context. This is a singleton context, + which means it will exist either not at all or at most once per xine context. + This plugin class context is a C-style class which is subclassing the related + class from the xine plugin headers. This contains functions, which are + independent of the actual instance of the plugin. Most prominently, it contains + a factory method to instantiate the next context. + + + + + The second context is the instance context. This is another C-style class, which + is constructed and disposed withing the plugin class context. This one does + the actual work and subclasses the related plugin struct from the xine plugin + headers. It is instantiated for every separate running instance of the plugin + + + + + + + + + What is this metronom thingy? + + Metronom serves two purposes: + + + + Generate vpts (virtual presentation time stamps) from pts (presentation time stamps) + for a/v output and synchronization. + + + + + Provide a master clock (system clock reference, scr), possibly provided + by external scr plugins (this can be used if some hardware decoder or network + server dictates the time). + + + + + + pts/vpts values are given in 1/90000 sec units. pts values in mpeg streams + may wrap (that is, return to zero or any other value without further notice), + can be missing on some frames or (for broken streams) may "dance" around + the correct values. Metronom therefore has some heuristics built-in to generate + clean vpts values which can then be used in the output layers to schedule audio/video + output. + + + The heuristics used in metronom have always been a field of research. Current metronom's + implementation tries to stick to pts values as reported from demuxers, + that is, vpts may be obtained by a simple operation of vpts = pts + vpts_offset, + where vpts_offset takes into account any wraps. Whenever pts is zero, + metronom will estimate vpts based on previous values. If a difference is found between the + estimated and calculated vpts values by above formula, it will be smoothed by using a + "drift correction". + + + + + How does xine synchronize audio and video? + + Every image frame or audio buffer leaving decoder is tagged by metronom with + a vpts information. This will tell video_out and audio_out threads when that + data should be presented. Usually there isn't a significative delay associated + with video driver, so we expect it to get on screen at the time it's + delivered for drawing. Unfortunately the same isn't true for audio: all sound + systems implement some amount of buffering (or fifo), any data being send to it + now will only get played some time in future. audio_out thread + must take this into account for making perfect A-V sync by asking the sound latency + to audio driver. + + + Some audio drivers can't tell the current delay introduced in playback. This is + especially true for most sound servers like ESD or aRts and explain why in such + cases the sync is far from perfect. + + + Another problem xine must handle is the sound card clock drift. vpts are + compared to the system clock (or even to a different clock provided by a scr plugin) + for presentation but sound card is sampling audio by it's own clocking + mechanism, so a small drift may occur. As the playback goes on this + error will accumulate possibly resulting in audio gaps or audio drops. To avoid that + annoying effect, two countermeasures are available (switchable with xine config + option audio.synchronization.av_sync_method): + + + + The small sound card errors are feedbacked to metronom. The details + are given by audio_out.c comments: + +   /* By adding gap errors (difference between reported and expected +    * sound card clock) into metronom's vpts_offset we can use its +    * smoothing algorithms to correct sound card clock drifts. +    * obs: previously this error was added to xine scr. +    * +    * audio buf ---> metronom --> audio fifo --> (buf->vpts - hw_vpts) +    * (vpts_offset + error) gap +    * <---------- control --------------| +    * +    * Unfortunately audio fifo adds a large delay to our closed loop. +    * +    * These are designed to avoid updating the metronom too fast. +    * - it will only be updated 1 time per second (so it has a chance of +    * distributing the error for several frames). +    * - it will only be updated 2 times for the whole audio fifo size +    * length (so the control will wait to see the feedback effect) +    * - each update will be of gap/SYNC_GAP_RATE. +    * +    * Sound card clock correction can only provide smooth playback for +    * errors < 1% nominal rate. For bigger errors (bad streams) audio +    * buffers may be dropped or gaps filled with silence. +    */ + + + + + The audio is stretched or squeezed a slight bit by resampling, thus compensating + the drift: The next comment in audio_out.c explains: + +   /* Alternative for metronom feedback: fix sound card clock drift +    * by resampling all audio data, so that the sound card keeps in +    * sync with the system clock. This may help, if one uses a DXR3/H+ +    * decoder board. Those have their own clock (which serves as xine's +    * master clock) and can only operate at fixed frame rates (if you +    * want smooth playback). Resampling then avoids A/V sync problems, +    * gaps filled with 0-frames and jerky video playback due to different +    * clock speeds of the sound card and DXR3/H+. +    */ + + + + + + + + Overlays and OSD + + The roots of xine overlay capabilities are DVD subpictures and subtitles support + (also known as 'spu'). The DVD subtitles are encoded in a RLE (Run Length Encoding - the + most simple compressing technique) format, with a palette of colors and transparency + levels. You probably thought that subtitles were just simple text saved into DVDs, right? + Wrong, they are bitmaps. + + + In order to optimize to the most common case, xine's internal format for screen overlays + is a similar representation to the 'spu' data. This brings not only performance + benefit (since blending functions may skip large image areas due to RLE) but also + compatibility: it's possible to reencode any xine overlay to the original spu format + for displaying with mpeg hardware decoders like DXR3. + + + Displaying subtitles requires the ability to sync them to the video stream. This + is done using the same kind of pts/vpts stuff of a-v sync code. DVD subtitles, + for example, may request: show this spu at pts1 and hide it at pts2. This brings the + concept of the 'video overlay manager', that is a event-driven module for managing + overlay's showing and hiding. + + + The drawback of using internal RLE format is the difficulty in manipulating it + as graphic. To overcome that we created the 'OSD renderer', where OSD stands + for On Screen Display just like in TV sets. The osd renderer is a module + providing simple graphic primitives (lines, rectagles, draw text etc) over + a "virtual" bitmap area. Everytime we want to show that bitmap it will + be RLE encoded and sent to the overlay manager for displaying. + + + + + + + + + + overlays architecture + + + + Overlay Manager + + The overlay manager interface is available to any xine plugin. It's a bit unlikely + to be used directly, anyway here's a code snippet for enqueueing an overlay for + displaying: + +   video_overlay_event_t event; +    +   event.object.handle = this->video_overlay->get_handle(this->video_overlay,0); +    +   memset(this->event.object.overlay, 0, sizeof(*this->event.object.overlay)); +    +   /* set position and size for this overlay */ +   event.object.overlay->x = 0; +   event.object.overlay->y = 0; +   event.object.overlay->width = 100; +   event.object.overlay->height = 100; +    +   /* clipping region is mostly used by dvd menus for highlighting buttons */ +   event.object.overlay->clip_top = 0; +   event.object.overlay->clip_bottom = image_height; +   event.object.overlay->clip_left = 0; +   event.object.overlay->clip_right = image_width; +    +   /* the hard part: provide a RLE image */ +   event.object.overlay->rle = your_rle; +   event.object.overlay->data_size = your_size; +   event.object.overlay->num_rle = your_rle_count; +    +   /* palette must contain YUV values for each color index */ +   memcpy(event.object.overlay->clip_color, color, sizeof(color)); +    +   /* this table contains transparency levels for each color index. +    0 = completely transparent, 15 - completely opaque */ +   memcpy(event.object.overlay->clip_trans, trans, sizeof(trans)); +    +   /* set the event type and time for displaying */ +   event.event_type = EVENT_SHOW_SPU; +   event.vpts = 0; /* zero is a special vpts value, it means 'now' */ +   video_overlay->add_event(video_overlay, &event); + + + + OSD Renderer + + OSD is a general API for rendering stuff over playing video. It's available both + to xine plugins and to frontends. + + + The first thing you need is to allocate a OSD object for drawing from the + renderer. The code below allocates a 300x200 area. This size can't be changed + during the lifetime of a OSD object, but it's possible to place it anywhere + over the image. + + +   osd_object_t osd; +    +   osd = this->osd_renderer->new_object(osd_renderer, 300, 200); + + Now we may want to set font and color for text rendering. Although we will + refer to fonts over this document, in fact the OSD can be any kind of bitmap. Font + files are searched and loaded during initialization from + $prefix/share/xine/fonts/ and ~/.xine/fonts. + There's a sample utility to convert truetype fonts at + xine-lib/misc/xine-fontconv.c. Palette may be manipulated directly, + however most of the time it's convenient to use pre-defined text palettes. + + +   /* set sans serif 24 font */ +   osd_renderer->set_font(osd, "sans", 24); +    +   /* copy pre-defined colors for white, black border, transparent background to +    starting at the index used by the first text palette */ +   osd_renderer->set_text_palette(osd, TEXTPALETTE_WHITE_BLACK_TRANSPARENT, OSD_TEXT1); +    +   /* copy pre-defined colors for white, no border, translucid background to +    starting at the index used by the second text palette */ +   osd_renderer->set_text_palette(osd, TEXTPALETTE_WHITE_NONE_TRANSLUCID, OSD_TEXT2); + + Now render the text and show it: + +   osd_renderer->render_text(osd, 0, 0, "white text, black border", OSD_TEXT1); +   osd_renderer->render_text(osd, 0, 30, "white text, no border", OSD_TEXT2); +    +   osd_renderer->show(osd, 0); /* 0 stands for 'now' */ + + + There's a 1:1 mapping between OSD objects and overlays, therefore the + second time you send an OSD object for displaying it will actually substitute + the first image. By using set_position() function we can move overlay + over the video. + + +   for( i=0; i < 100; i+=10 ) { +    osd_renderer->set_position(osd, i, i ); +    osd_renderer->show(osd, 0); +    sleep(1); +   } +   osd_renderer->hide(osd, 0); + + For additional functions please check osd.h or the public header. + + + OSD palette notes + + The palette functions demand some additional explanation, skip this if you + just want to write text fast without worring with details! :) + + + We have a 256-entry palette, each one defining yuv and transparency levels. + Although xine fonts are bitmaps and may use any index they want, we have + defined a small convention: + + +   /* +    Palette entries as used by osd fonts: +    +    0: not used by font, always transparent +    1: font background, usually transparent, may be used to implement +    translucid boxes where the font will be printed. +    2-5: transition between background and border (usually only alpha +    value changes). +    6: font border. if the font is to be displayed without border this +    will probably be adjusted to font background or near. +    7-9: transition between border and foreground +    10: font color (foreground) +   */ + + The so called 'transitions' are used to implement font anti-aliasing. That + convention requires that any font file must use only the colors from 1 to 10. + When we use the set_text_palette() function we are just copying 11 palette + entries to the specified base index. + + + That base index is the same we pass to render_text() function to use the + text palette. With this scheme is possible to have several diferent text + colors at the same time and also draw fonts over custom background. + + +   /* obtains size the text will occupy */ +   renderer->get_text_size(osd, text, &width, &height); +    +   /* draws a box using font background color (translucid) */ +   renderer->filled_rect(osd, x1, y1, x1+width, y1+height, OSD_TEXT2 + 1); +    +   /* render text */ +   renderer->render_text(osd, x1, y1, text, OSD_TEXT2); + + + OSD text and palette FAQ + + Q: What is the format of the color palette entries? + + + A: It's the same as used by overlay blending code (YUV). + + + Q: What is the relation between a text palette and a palette + I set with xine_osd_set_palette? + + + A: xine_osd_set_palette will set the entire 256 color palette + to be used when we blend the osd image. + "text palette" is a sequence of 11 colors from palette to be + used to render text. that is, by calling osd_render_text() + with color_base=100 will render text using colors 100-110. + + + Q: Can I render text with colors in my own palette? + + + A: Sure. Just pass the color_base to osd_render_text() + + + Q: Has a text palette change effects on already drawed text? + + + A: osd_set_text_palette() will overwrite some colors on palette + with pre-defined ones. So yes, it will change the color + on already drawed text (if you do it before calling osd_show, + of course). + If you don't want to change the colors of drawed text just + use different color_base values. + + + Q: What about the shadows of osd-objects? Can I turn them off + or are they hardcoded? + + + A: osd objects have no shadows by itself, but fonts use 11 + colors to produce an anti-aliased effect. + if you set a "text palette" with entries 0-9 being transparent + and 10 being foreground you will get rid of any borders or + anti-aliasing. + + + + + + + MRLs + + This section defines a draft for a syntactic specification of MRLs as + used by xine-lib. The language of MRLs is designed to be a true subset + of the language of URIs as given in RFC2396. A type 2 grammar for the + language of MRLs is given in EBNF below. + + + Semantically, MRLs consist of two distinct parts that are evaluated by + different components of the xine architecture. The first part, + derivable from the symbol <input_source> in the given grammar, is + completely handed to the input plugins, with input plugins signaling + if they can handle the MRL. + + + The second part, derivable from <stream_setup> and delimited from the + first by a crosshatch ('#') contains parameters that modify the + initialization and playback behaviour of the stream to which the MRL + is passed. The possible parameters are mentioned in the manpage to + xine-ui. + + + The following definition should be regarded as a guideline only. + Of course any given input plugin only understands a subset of all + possible MRLs. On the other hand, invalid MRLs according to this + definition might be understood for convenience reasons. + Some user awareness is required at this point. + + + EBNF grammar for MRLs: + +   <mrl> ::= <input_source>[#<stream_setup>] +   <input_source> ::= (<absolute_mrl>|<relative_mrl>) +   <absolute_mrl> ::= <input>:(<hierarch_part>|<opaque_part>) +   <hierarch_part> ::= (<net_path>|<abs_path>)[?<query>] +   <opaque_part> ::= (<unreserved>|<escaped>|;|?|:|@|&|=|+|$|,){<mrl_char>} +   <relative_mrl> ::= (<abs_path>|<rel_path>) +   <net_path> ::= //<authority>[<abs_path>] +   <abs_path> ::= /<path_segments> +   <rel_path> ::= <rel_segment>[<abs_path>] +   <rel_segment> ::= <rel_char>{<rel_char>} +   <rel_char> ::= (<unreserved>|<escaped>|;|@|&|=|+|$|,) +   <input> ::= <alpha>{(<alpha>|<digit>|+|-|.)} +   <authority> ::= (<server>|<reg_name>) +   <server> ::= [[<userinfo>@]<host>[:<port>]] +   <userinfo> ::= {(<unreserved>|<escaped>|;|:|&|=|+|$|,)} +   <host> ::= (<hostname>|<ipv4_address>|<ipv6_reference>) +   <hostname> ::= {<domainlabel>.}<toplabel>[.] +   <domainlabel> ::= (<alphanum>|<alphanum>{(<alphanum>|-)}<alphanum>) +   <toplabel> ::= (<alpha>|<alpha>{(<alphanum>|-)}<alphanum>) +   <ipv4_address> ::= <digit>{<digit>}.<digit>{<digit>}.<digit>{<digit>}.<digit>{<digit>} +   <port> ::= {<digit>} +   <reg_name> ::= <reg_char>{<reg_char>} +   <reg_char> ::= (<unreserved>|<escaped>|;|:|@|&|=|+|$|,) +   <path_segments> ::= <segment>{/<segment>} +   <segment> ::= {<path_char>}{;<param>} +   <param> ::= {<path_char>} +   <path_char> ::= (<unreserved>|<escaped>|:|@|&|=|+|$|,) +   <query> ::= {<mrl_char>} +   <stream_setup> ::= <stream_option>;{<stream_option>} +   <stream_option> ::= (<configoption>|<engine_option>|novideo|noaudio|nospu) +   <configoption> ::= <configentry>:<configvalue> +   <configentry> ::= <unreserved>{<unreserved>} +   <configvalue> ::= <stream_char>{<stream_char>} +   <engine_option> ::= <unreserved>{<unreserved>}:<stream_char>{<stream_char>} +   <stream_char> ::= (<unreserved>|<escaped>|:|@|&|=|+|$|,) +   <mrl_char> ::= (<reserved>|<unreserved>|<escaped>) +   <reserved> ::= (;|/|?|:|@|&|=|+|$|,|[|]) +   <unreserved> ::= (<alphanum>|<mark>) +   <mark> ::= (-|_|.|!|~|*|'|(|)) +   <escaped> ::= %<hex><hex> +   <hex> ::= (<digit>|A|B|C|D|E|F|a|b|c|d|e|f) +   <alphanum> ::= (<alpha>|<digit>) +   <alpha> ::= (<lowalpha>|<upalpha>) +   <lowalpha> ::= (a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z) +   <upalpha> ::= (A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z) +   <digit> ::= (0|1|2|3|4|5|6|7|8|9) + With <ipv6_reference> being an IPv6 address enclosed in [ and ] as defined in RFC2732. + + + + diff --git a/doc/hackersguide/internals.sgml b/doc/hackersguide/internals.sgml deleted file mode 100644 index 9bd1ec684..000000000 --- a/doc/hackersguide/internals.sgml +++ /dev/null @@ -1,762 +0,0 @@ - - xine internals - - - Engine architecture and data flow - - - - - - - - - xine engine architecture - - - - Media streams usually consist of audio and video data multiplexed - into one bitstream in the so-called system-layer (e.g. AVI, Quicktime or MPEG). - A demuxer plugin is used to parse the system layer and extract audio and video - packages. The demuxer uses an input plugin to read the data and stores it - in pre-allocated buffers from the global buffer pool. - The buffers are then added to the audio or video stream fifo. - - - From the other end of these fifos the audio and video decoder threads - consume the buffers and hand them over to the current audio or video - decoder plugin for decompression. These plugins then send the decoded - data to the output layer. The buffer holding the encoded - data is no longer needed and thus released to the global buffer pool. - - - In the output layer, the video frames and audio samples pass through a - post plugin tree, which can apply effects or other operations to the data. - When reaching the output loops, frames and samples are enqueued to be - displayed, when the presentation time has arrived. - - - A set of extra information travels with the data. Starting at the input and - demuxer level, where this information is generated, the data is attached to - the buffers as they wait in the fifo. The decoder loops copy the data to - a storage of their own. From there, every frame and audio buffer leaving - the stream layer is tagged with the data the decoder loop storage currently - holds. - - - - - Plugin system - - The plugin system enables some of xine's most valuable features: - - - - drop-in extensiability - - - - - support parallel installation of multiple (incompatible) libxine versions - - - - - support for multiple plugin directories - ($prefix/lib/xine/plugins, - $HOME/.xine/plugins, ...) - - - - - support for recursive plugin directories - (plugins are found even in subdirectories of the plugin directories) - - - - - version management - (On start, xine finds all plugins in its plugin (sub)directories and - chooses an appropriate version (usually the newest) for each plugin.) - - - - - simplification - (Plugins don't have to follow any special naming convention, - and any plugin may contain an arbitrary subset of input, demuxer, - decoder or output plugins.) - - - - - - Essentally, plugins are just shared objects, ie dynamic libraries. In - contrast to normal dynamic libraries, they are stored outside of the - system's library PATHs and libxine does its own bookkeeping, which - enables most advanced features mentioned above. - - - Plugin location and filesystem layout - - The primary goal for this new plugin mechanism was the need to support - simultaneous installation of several (most likely incompatible) - libxine versions without them overwriting each other's - plugins. Therefore, we have this simple layout: - - - Plugins are installed below XINE_PLUGINDIR - (/usr/local/lib/xine/plugins by default). - Note that plugins are never directly installed into XINE_PLUGINDIR. - Instead, a separate subdirectory is created for each "plugin - provider". A plugin provider is equivalent with the exact version of - one source package. Typical examples include "xine-lib-0.9.11" or - "xine-vcdnav-1.0". Every source package is free to install an - arbitrary number of plugins in its own, private directory. If a - package installs several plugins, they may optionally be organized - further into subdirectories. - - - So you will finally end up with something like this: - -   /usr/local/lib/xine/plugins -    xine-lib-0.9.11 -    demux_mpeg_block.so -    decode_mpeg.so -    video_out_xv.so -    ... -    xine-vcdnav-0.9.11 -    input_vcdnav.so -    xine-lib-1.2 -    input -    file.so -    stdin_fifo.so -    vcd.so -    demuxers -    fli.so -    avi.so -    ... -    decoders -    ffmpeg.so -    mpeg.so (may contain mpeg 1/2 audio and video decoders) -    pcm.so -    ... -    output -    video_xv.so -    audio_oss.so -    ... -    xine-lib-3.0 -    avi.so (avi demuxer) -    mpeg.so (contains mpeg demuxers and audio/video decoders) -    video_out_xv.so (Xv video out) -    ... - - - As you can see, every package is free to organize plugins at will - below its own plugin provider directory. - Additionally, administrators may choose to put plugins directly into - XINE_PLUGINDIR, or in a "local" subdirectory. - Users may wish to put additional plugins in ~/.xine/plugins/. - Again, there may be subdirectories to help organize the plugins. - - - The default value for XINE_PLUGINDIR can be obtained using the - xine-config --plugindir command. - - - - Plugin Content: What's inside the .so? - - Each plugin library (.so file) contains an arbitrary number of (virtual) - plugins. Typically, it will contain exactly one plugin. However, it - may be useful to put a set of related plugins in one library, so they - can share common code. - - - First of all, what is a virtual plugin? - A virtual plugin is essentially a structure that is defined by the - xine engine. This structure typically contains lots of function - pointers to the actual API functions. - For each plugin API, there are several API versions, and each API - version may specify a new, incompatible structure. Therefore, it is - essential that only those plugins are loaded that support current - libxine's API, so the .so file needs a plugin list that - provides libxine with the version information, even before it tries to - load any of the plugins. - - - This plugin list is held in an array named xine_plugin_info": - -   plugin_info_t xine_plugin_info[] = { -    /* type, API, "name", version, special_info, init_function */ -    { PLUGIN_DEMUX, 20, "flac", XINE_VERSION_CODE, NULL, demux_flac_init_class }, -    { PLUGIN_AUDIO_DECODER, 13, "flacdec", XINE_VERSION_CODE, &dec_info_audio, init_plugin }, -    { PLUGIN_NONE, 0, "", 0, NULL, NULL } -   }; - - - The structure of xine_plugin_info may never be changed. - If it ever needs to be changed, it must be renamed to avoid - erraneous loading of incompatible plugins. - - - xine_plugin_info can contain any number of plugins - and must be terminated with a PLUGIN_NONE entry. Available plugin - types are: - -   #define PLUGIN_NONE 0 -   #define PLUGIN_INPUT 1 -   #define PLUGIN_DEMUX 2 -   #define PLUGIN_AUDIO_DECODER 3 -   #define PLUGIN_VIDEO_DECODER 4 -   #define PLUGIN_SPU_DECODER 5 -   #define PLUGIN_AUDIO_OUT 6 -   #define PLUGIN_VIDEO_OUT 7 -   #define PLUGIN_POST 8 - - - The plugin version number is generated from xine-lib's version number - like this: MAJOR * 10000 + MINOR * 100 + SUBMINOR. - This is not required, but it's an easy way to ensure that the version - increases for every release. - - - Every entry in xine_plugin_info has an initialization - function for the plugin class context. - This function returns a pointer to freshly allocated (typically - via malloc()) structure containing mainly function - pointers; these are the "methods" of the plugin class. - - - The "plugin class" is not what we call to do the job yet (like decoding - a video or something), it must be instantiated. One reason for having the - class is to hold any global settings that must be accessed by every - instance. Remember that xine library is multistream capable: multible - videos can be decoded at the same time, thus several instances of the - same plugin are possible. - - - If you think this is pretty much an object-oriented aproach, - then you're right. - - - A fictitious file input plugin that supports input plugin API 12 and - 13, found in xine-lib 2.13.7 would then define this plugin list: - -   #include <xine/plugin.h> -   ... -   plugin_t *init_api12(void) { -    input_plugin_t *this; -    -    this = malloc(sizeof(input_plugin_t)); -    ... -    return (plugin_t *)this; -   } -   /* same thing, with different initialization for API 13 */ -    -   const plugin_info_t xine_plugin_info[] = { -    { PLUGIN_INPUT, 12, "file", 21307, init_api12 }, -    { PLUGIN_INPUT, 13, "file", 21307, init_api13 }, -    { PLUGIN_NONE, 0, "", 0, NULL } -   } - This input plugin supports two APIs, other plugins might provide a - mixture of demuxer and decoder plugins that belong together somehow - (ie. share common code). - - - You'll find exact definitions of public functions and plugin structs - in the appropriate header files for each plugin type: - input/input_plugin.h for input plugins, - demuxers/demux.h for demuxer plugins, - xine-engine/video_decoder.h for video decoder plugins, - xine-engine/audio_decoder.h for audio decoder plugins, - xine-engine/post.h for post plugins, - xine-engine/video_out.h for video out plugins, - xine-engine/audio_out.h for audio out plugins. - Additional information will also be given in the dedicated sections below. - - - Many plugins will need some additional "private" data fields. - These should be simply added at the end of the plugin structure. - For example a demuxer plugin called "foo" with two private - fields "xine" and "count" may have a plugin structure declared in - the following way: - -   typedef struct { -    /* public fields "inherited" from demux.h */ -    demux_plugin_t demux_plugin; -    -    xine_t *xine; -    int count; -   } demux_foo_t; - - - The plugin would then access public members via the - demux_plugin field and private fields directly. - - - Summary: Plugins consist of two C-style classes, each representing a different context. - - - - The first is the so called "plugin class" context. This is a singleton context, - which means it will exist either not at all or at most once per xine context. - This plugin class context is a C-style class which is subclassing the related - class from the xine plugin headers. This contains functions, which are - independent of the actual instance of the plugin. Most prominently, it contains - a factory method to instantiate the next context. - - - - - The second context is the instance context. This is another C-style class, which - is constructed and disposed withing the plugin class context. This one does - the actual work and subclasses the related plugin struct from the xine plugin - headers. It is instantiated for every separate running instance of the plugin - - - - - - - - - What is this metronom thingy? - - Metronom serves two purposes: - - - - Generate vpts (virtual presentation time stamps) from pts (presentation time stamps) - for a/v output and synchronization. - - - - - Provide a master clock (system clock reference, scr), possibly provided - by external scr plugins (this can be used if some hardware decoder or network - server dictates the time). - - - - - - pts/vpts values are given in 1/90000 sec units. pts values in mpeg streams - may wrap (that is, return to zero or any other value without further notice), - can be missing on some frames or (for broken streams) may "dance" around - the correct values. Metronom therefore has some heuristics built-in to generate - clean vpts values which can then be used in the output layers to schedule audio/video - output. - - - The heuristics used in metronom have always been a field of research. Current metronom's - implementation tries to stick to pts values as reported from demuxers, - that is, vpts may be obtained by a simple operation of vpts = pts + vpts_offset, - where vpts_offset takes into account any wraps. Whenever pts is zero, - metronom will estimate vpts based on previous values. If a difference is found between the - estimated and calculated vpts values by above formula, it will be smoothed by using a - "drift correction". - - - - - How does xine synchronize audio and video? - - Every image frame or audio buffer leaving decoder is tagged by metronom with - a vpts information. This will tell video_out and audio_out threads when that - data should be presented. Usually there isn't a significative delay associated - with video driver, so we expect it to get on screen at the time it's - delivered for drawing. Unfortunately the same isn't true for audio: all sound - systems implement some amount of buffering (or fifo), any data being send to it - now will only get played some time in future. audio_out thread - must take this into account for making perfect A-V sync by asking the sound latency - to audio driver. - - - Some audio drivers can't tell the current delay introduced in playback. This is - especially true for most sound servers like ESD or aRts and explain why in such - cases the sync is far from perfect. - - - Another problem xine must handle is the sound card clock drift. vpts are - compared to the system clock (or even to a different clock provided by a scr plugin) - for presentation but sound card is sampling audio by it's own clocking - mechanism, so a small drift may occur. As the playback goes on this - error will accumulate possibly resulting in audio gaps or audio drops. To avoid that - annoying effect, two countermeasures are available (switchable with xine config - option audio.synchronization.av_sync_method): - - - - The small sound card errors are feedbacked to metronom. The details - are given by audio_out.c comments: - -   /* By adding gap errors (difference between reported and expected -    * sound card clock) into metronom's vpts_offset we can use its -    * smoothing algorithms to correct sound card clock drifts. -    * obs: previously this error was added to xine scr. -    * -    * audio buf ---> metronom --> audio fifo --> (buf->vpts - hw_vpts) -    * (vpts_offset + error) gap -    * <---------- control --------------| -    * -    * Unfortunately audio fifo adds a large delay to our closed loop. -    * -    * These are designed to avoid updating the metronom too fast. -    * - it will only be updated 1 time per second (so it has a chance of -    * distributing the error for several frames). -    * - it will only be updated 2 times for the whole audio fifo size -    * length (so the control will wait to see the feedback effect) -    * - each update will be of gap/SYNC_GAP_RATE. -    * -    * Sound card clock correction can only provide smooth playback for -    * errors < 1% nominal rate. For bigger errors (bad streams) audio -    * buffers may be dropped or gaps filled with silence. -    */ - - - - - The audio is stretched or squeezed a slight bit by resampling, thus compensating - the drift: The next comment in audio_out.c explains: - -   /* Alternative for metronom feedback: fix sound card clock drift -    * by resampling all audio data, so that the sound card keeps in -    * sync with the system clock. This may help, if one uses a DXR3/H+ -    * decoder board. Those have their own clock (which serves as xine's -    * master clock) and can only operate at fixed frame rates (if you -    * want smooth playback). Resampling then avoids A/V sync problems, -    * gaps filled with 0-frames and jerky video playback due to different -    * clock speeds of the sound card and DXR3/H+. -    */ - - - - - - - - Overlays and OSD - - The roots of xine overlay capabilities are DVD subpictures and subtitles support - (also known as 'spu'). The DVD subtitles are encoded in a RLE (Run Length Encoding - the - most simple compressing technique) format, with a palette of colors and transparency - levels. You probably thought that subtitles were just simple text saved into DVDs, right? - Wrong, they are bitmaps. - - - In order to optimize to the most common case, xine's internal format for screen overlays - is a similar representation to the 'spu' data. This brings not only performance - benefit (since blending functions may skip large image areas due to RLE) but also - compatibility: it's possible to reencode any xine overlay to the original spu format - for displaying with mpeg hardware decoders like DXR3. - - - Displaying subtitles requires the ability to sync them to the video stream. This - is done using the same kind of pts/vpts stuff of a-v sync code. DVD subtitles, - for example, may request: show this spu at pts1 and hide it at pts2. This brings the - concept of the 'video overlay manager', that is a event-driven module for managing - overlay's showing and hiding. - - - The drawback of using internal RLE format is the difficulty in manipulating it - as graphic. To overcome that we created the 'OSD renderer', where OSD stands - for On Screen Display just like in TV sets. The osd renderer is a module - providing simple graphic primitives (lines, rectagles, draw text etc) over - a "virtual" bitmap area. Everytime we want to show that bitmap it will - be RLE encoded and sent to the overlay manager for displaying. - - - - - - - - - - overlays architecture - - - - Overlay Manager - - The overlay manager interface is available to any xine plugin. It's a bit unlikely - to be used directly, anyway here's a code snippet for enqueueing an overlay for - displaying: - -   video_overlay_event_t event; -    -   event.object.handle = this->video_overlay->get_handle(this->video_overlay,0); -    -   memset(this->event.object.overlay, 0, sizeof(*this->event.object.overlay)); -    -   /* set position and size for this overlay */ -   event.object.overlay->x = 0; -   event.object.overlay->y = 0; -   event.object.overlay->width = 100; -   event.object.overlay->height = 100; -    -   /* clipping region is mostly used by dvd menus for highlighting buttons */ -   event.object.overlay->clip_top = 0; -   event.object.overlay->clip_bottom = image_height; -   event.object.overlay->clip_left = 0; -   event.object.overlay->clip_right = image_width; -    -   /* the hard part: provide a RLE image */ -   event.object.overlay->rle = your_rle; -   event.object.overlay->data_size = your_size; -   event.object.overlay->num_rle = your_rle_count; -    -   /* palette must contain YUV values for each color index */ -   memcpy(event.object.overlay->clip_color, color, sizeof(color)); -    -   /* this table contains transparency levels for each color index. -    0 = completely transparent, 15 - completely opaque */ -   memcpy(event.object.overlay->clip_trans, trans, sizeof(trans)); -    -   /* set the event type and time for displaying */ -   event.event_type = EVENT_SHOW_SPU; -   event.vpts = 0; /* zero is a special vpts value, it means 'now' */ -   video_overlay->add_event(video_overlay, &event); - - - - OSD Renderer - - OSD is a general API for rendering stuff over playing video. It's available both - to xine plugins and to frontends. - - - The first thing you need is to allocate a OSD object for drawing from the - renderer. The code below allocates a 300x200 area. This size can't be changed - during the lifetime of a OSD object, but it's possible to place it anywhere - over the image. - - -   osd_object_t osd; -    -   osd = this->osd_renderer->new_object(osd_renderer, 300, 200); - - Now we may want to set font and color for text rendering. Although we will - refer to fonts over this document, in fact the OSD can be any kind of bitmap. Font - files are searched and loaded during initialization from - $prefix/share/xine/fonts/ and ~/.xine/fonts. - There's a sample utility to convert truetype fonts at - xine-lib/misc/xine-fontconv.c. Palette may be manipulated directly, - however most of the time it's convenient to use pre-defined text palettes. - - -   /* set sans serif 24 font */ -   osd_renderer->set_font(osd, "sans", 24); -    -   /* copy pre-defined colors for white, black border, transparent background to -    starting at the index used by the first text palette */ -   osd_renderer->set_text_palette(osd, TEXTPALETTE_WHITE_BLACK_TRANSPARENT, OSD_TEXT1); -    -   /* copy pre-defined colors for white, no border, translucid background to -    starting at the index used by the second text palette */ -   osd_renderer->set_text_palette(osd, TEXTPALETTE_WHITE_NONE_TRANSLUCID, OSD_TEXT2); - - Now render the text and show it: - -   osd_renderer->render_text(osd, 0, 0, "white text, black border", OSD_TEXT1); -   osd_renderer->render_text(osd, 0, 30, "white text, no border", OSD_TEXT2); -    -   osd_renderer->show(osd, 0); /* 0 stands for 'now' */ - - - There's a 1:1 mapping between OSD objects and overlays, therefore the - second time you send an OSD object for displaying it will actually substitute - the first image. By using set_position() function we can move overlay - over the video. - - -   for( i=0; i < 100; i+=10 ) { -    osd_renderer->set_position(osd, i, i ); -    osd_renderer->show(osd, 0); -    sleep(1); -   } -   osd_renderer->hide(osd, 0); - - For additional functions please check osd.h or the public header. - - - OSD palette notes - - The palette functions demand some additional explanation, skip this if you - just want to write text fast without worring with details! :) - - - We have a 256-entry palette, each one defining yuv and transparency levels. - Although xine fonts are bitmaps and may use any index they want, we have - defined a small convention: - - -   /* -    Palette entries as used by osd fonts: -    -    0: not used by font, always transparent -    1: font background, usually transparent, may be used to implement -    translucid boxes where the font will be printed. -    2-5: transition between background and border (usually only alpha -    value changes). -    6: font border. if the font is to be displayed without border this -    will probably be adjusted to font background or near. -    7-9: transition between border and foreground -    10: font color (foreground) -   */ - - The so called 'transitions' are used to implement font anti-aliasing. That - convention requires that any font file must use only the colors from 1 to 10. - When we use the set_text_palette() function we are just copying 11 palette - entries to the specified base index. - - - That base index is the same we pass to render_text() function to use the - text palette. With this scheme is possible to have several diferent text - colors at the same time and also draw fonts over custom background. - - -   /* obtains size the text will occupy */ -   renderer->get_text_size(osd, text, &width, &height); -    -   /* draws a box using font background color (translucid) */ -   renderer->filled_rect(osd, x1, y1, x1+width, y1+height, OSD_TEXT2 + 1); -    -   /* render text */ -   renderer->render_text(osd, x1, y1, text, OSD_TEXT2); - - - OSD text and palette FAQ - - Q: What is the format of the color palette entries? - - - A: It's the same as used by overlay blending code (YUV). - - - Q: What is the relation between a text palette and a palette - I set with xine_osd_set_palette? - - - A: xine_osd_set_palette will set the entire 256 color palette - to be used when we blend the osd image. - "text palette" is a sequence of 11 colors from palette to be - used to render text. that is, by calling osd_render_text() - with color_base=100 will render text using colors 100-110. - - - Q: Can I render text with colors in my own palette? - - - A: Sure. Just pass the color_base to osd_render_text() - - - Q: Has a text palette change effects on already drawed text? - - - A: osd_set_text_palette() will overwrite some colors on palette - with pre-defined ones. So yes, it will change the color - on already drawed text (if you do it before calling osd_show, - of course). - If you don't want to change the colors of drawed text just - use different color_base values. - - - Q: What about the shadows of osd-objects? Can I turn them off - or are they hardcoded? - - - A: osd objects have no shadows by itself, but fonts use 11 - colors to produce an anti-aliased effect. - if you set a "text palette" with entries 0-9 being transparent - and 10 being foreground you will get rid of any borders or - anti-aliasing. - - - - - - - MRLs - - This section defines a draft for a syntactic specification of MRLs as - used by xine-lib. The language of MRLs is designed to be a true subset - of the language of URIs as given in RFC2396. A type 2 grammar for the - language of MRLs is given in EBNF below. - - - Semantically, MRLs consist of two distinct parts that are evaluated by - different components of the xine architecture. The first part, - derivable from the symbol <input_source> in the given grammar, is - completely handed to the input plugins, with input plugins signaling - if they can handle the MRL. - - - The second part, derivable from <stream_setup> and delimited from the - first by a crosshatch ('#') contains parameters that modify the - initialization and playback behaviour of the stream to which the MRL - is passed. The possible parameters are mentioned in the manpage to - xine-ui. - - - The following definition should be regarded as a guideline only. - Of course any given input plugin only understands a subset of all - possible MRLs. On the other hand, invalid MRLs according to this - definition might be understood for convenience reasons. - Some user awareness is required at this point. - - - EBNF grammar for MRLs: - -   <mrl> ::= <input_source>[#<stream_setup>] -   <input_source> ::= (<absolute_mrl>|<relative_mrl>) -   <absolute_mrl> ::= <input>:(<hierarch_part>|<opaque_part>) -   <hierarch_part> ::= (<net_path>|<abs_path>)[?<query>] -   <opaque_part> ::= (<unreserved>|<escaped>|;|?|:|@|&|=|+|$|,){<mrl_char>} -   <relative_mrl> ::= (<abs_path>|<rel_path>) -   <net_path> ::= //<authority>[<abs_path>] -   <abs_path> ::= /<path_segments> -   <rel_path> ::= <rel_segment>[<abs_path>] -   <rel_segment> ::= <rel_char>{<rel_char>} -   <rel_char> ::= (<unreserved>|<escaped>|;|@|&|=|+|$|,) -   <input> ::= <alpha>{(<alpha>|<digit>|+|-|.)} -   <authority> ::= (<server>|<reg_name>) -   <server> ::= [[<userinfo>@]<host>[:<port>]] -   <userinfo> ::= {(<unreserved>|<escaped>|;|:|&|=|+|$|,)} -   <host> ::= (<hostname>|<ipv4_address>|<ipv6_reference>) -   <hostname> ::= {<domainlabel>.}<toplabel>[.] -   <domainlabel> ::= (<alphanum>|<alphanum>{(<alphanum>|-)}<alphanum>) -   <toplabel> ::= (<alpha>|<alpha>{(<alphanum>|-)}<alphanum>) -   <ipv4_address> ::= <digit>{<digit>}.<digit>{<digit>}.<digit>{<digit>}.<digit>{<digit>} -   <port> ::= {<digit>} -   <reg_name> ::= <reg_char>{<reg_char>} -   <reg_char> ::= (<unreserved>|<escaped>|;|:|@|&|=|+|$|,) -   <path_segments> ::= <segment>{/<segment>} -   <segment> ::= {<path_char>}{;<param>} -   <param> ::= {<path_char>} -   <path_char> ::= (<unreserved>|<escaped>|:|@|&|=|+|$|,) -   <query> ::= {<mrl_char>} -   <stream_setup> ::= <stream_option>;{<stream_option>} -   <stream_option> ::= (<configoption>|<engine_option>|novideo|noaudio|nospu) -   <configoption> ::= <configentry>:<configvalue> -   <configentry> ::= <unreserved>{<unreserved>} -   <configvalue> ::= <stream_char>{<stream_char>} -   <engine_option> ::= <unreserved>{<unreserved>}:<stream_char>{<stream_char>} -   <stream_char> ::= (<unreserved>|<escaped>|:|@|&|=|+|$|,) -   <mrl_char> ::= (<reserved>|<unreserved>|<escaped>) -   <reserved> ::= (;|/|?|:|@|&|=|+|$|,|[|]) -   <unreserved> ::= (<alphanum>|<mark>) -   <mark> ::= (-|_|.|!|~|*|'|(|)) -   <escaped> ::= %<hex><hex> -   <hex> ::= (<digit>|A|B|C|D|E|F|a|b|c|d|e|f) -   <alphanum> ::= (<alpha>|<digit>) -   <alpha> ::= (<lowalpha>|<upalpha>) -   <lowalpha> ::= (a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z) -   <upalpha> ::= (A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z) -   <digit> ::= (0|1|2|3|4|5|6|7|8|9) - With <ipv6_reference> being an IPv6 address enclosed in [ and ] as defined in RFC2732. - - - - diff --git a/doc/hackersguide/intro.docbook b/doc/hackersguide/intro.docbook new file mode 100644 index 000000000..c7dce6254 --- /dev/null +++ b/doc/hackersguide/intro.docbook @@ -0,0 +1,54 @@ + + Introduction + + + Where am I? + + You are currently looking at a piece of documentation for xine. + xine is a free video player. It lives on + http://xinehq.de/. Specifically + this document goes under the moniker of the "xine Hackers' Guide". + + + + + What does this text do? + + This document should help xine hackers to find their way through + xine's architecture and source code. It's a pretty free-form document + containing a loose collection of articles describing various aspects + of xine's internals. It has been written by a number of people who work + on xine themselves and is intended to provide the important concepts and + methods used within xine. Readers should not consider this document to be + an exhausative description of the internals of xine. As with all projects + which provide access, the source-code should be considered the definitive + source of information. + + + + + New versions of this document + + This document is being developed in the xine-lib cvs repository within + the directory doc/hackersguide/. If you are + unsure what to do with the stuff in that directory, please read the + README file located there. + + + New versions of this document can also be obtained from the xine web site: + http://xinehq.de/. + + + + + Feedback + + All comments, error reports, additional information and criticism + concerning this document should be directed to the xine documentations + mailing list xine-docs@lists.sourceforge.net. + Questions about xine hacking in general should be sent to the + developer mailing list xine-devel@lists.sourceforge.net. + + + + diff --git a/doc/hackersguide/intro.sgml b/doc/hackersguide/intro.sgml deleted file mode 100644 index c7dce6254..000000000 --- a/doc/hackersguide/intro.sgml +++ /dev/null @@ -1,54 +0,0 @@ - - Introduction - - - Where am I? - - You are currently looking at a piece of documentation for xine. - xine is a free video player. It lives on - http://xinehq.de/. Specifically - this document goes under the moniker of the "xine Hackers' Guide". - - - - - What does this text do? - - This document should help xine hackers to find their way through - xine's architecture and source code. It's a pretty free-form document - containing a loose collection of articles describing various aspects - of xine's internals. It has been written by a number of people who work - on xine themselves and is intended to provide the important concepts and - methods used within xine. Readers should not consider this document to be - an exhausative description of the internals of xine. As with all projects - which provide access, the source-code should be considered the definitive - source of information. - - - - - New versions of this document - - This document is being developed in the xine-lib cvs repository within - the directory doc/hackersguide/. If you are - unsure what to do with the stuff in that directory, please read the - README file located there. - - - New versions of this document can also be obtained from the xine web site: - http://xinehq.de/. - - - - - Feedback - - All comments, error reports, additional information and criticism - concerning this document should be directed to the xine documentations - mailing list xine-docs@lists.sourceforge.net. - Questions about xine hacking in general should be sent to the - developer mailing list xine-devel@lists.sourceforge.net. - - - - diff --git a/doc/hackersguide/library.docbook b/doc/hackersguide/library.docbook new file mode 100644 index 000000000..1d987d259 --- /dev/null +++ b/doc/hackersguide/library.docbook @@ -0,0 +1,410 @@ + + Using the xine library + + + xine architecture as visible to libxine clients + + The following drawing shows the components of xine as outside applications + see them. For every component, the functions for creating and destroying it + are given. Every other function works in the context it is enclosed in. + Functions that facilitate the connection of the individual components are + also given. + + + + + + + + + + outside view on xine components + + + + The function are named just to give you an overview of what is actually + there. It is all thoroughly documented in the plublic header + xine.h, which is the main and preferably the only xine + header, clients should include. (xine/xineutils.h and the XML parser might + make an exception.) + + + Details on the OSD feature can be found in the OSD section. + + + + + Writing a new frontend to xine + + The best way to explain this seems to be actual code. Below you + will find a very easy and hopefully self-explaining xine frontend + to give you a start. + + + One important thing to note is that any X11 based xine-lib frontend + must call XInitThreads() before calling the + first Xlib function, because xine will access the display from + within a different thread than the frontend. + + + Source code of a simple X11 frontend + +/* +** Copyright (C) 2003 Daniel Caujolle-Bert <segfault@club-internet.fr> +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +*/ + +/* + * compile-command: "gcc -Wall -O2 `xine-config --cflags` `xine-config --libs` -L/usr/X11R6/lib -lX11 -lm -o xinimin xinimin.c" + */ + +#include <stdio.h> +#include <string.h> +#include <math.h> + +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> +#include <X11/Xutil.h> +#include <X11/extensions/XShm.h> + +#include <xine.h> +#include <xine/xineutils.h> + + +#define MWM_HINTS_DECORATIONS (1L << 1) +#define PROP_MWM_HINTS_ELEMENTS 5 +typedef struct { + uint32_t flags; + uint32_t functions; + uint32_t decorations; + int32_t input_mode; + uint32_t status; +} MWMHints; + +static xine_t *xine; +static xine_stream_t *stream; +static xine_video_port_t *vo_port; +static xine_audio_port_t *ao_port; +static xine_event_queue_t *event_queue; + +static Display *display; +static int screen; +static Window window[2]; +static int xpos, ypos, width, height, fullscreen; +static double pixel_aspect; + +static int running = 1; + +#define INPUT_MOTION (ExposureMask | ButtonPressMask | KeyPressMask | \ + ButtonMotionMask | StructureNotifyMask | \ + PropertyChangeMask | PointerMotionMask) + +/* this will be called by xine, if it wants to know the target size of a frame */ +static void dest_size_cb(void *data, int video_width, int video_height, double video_pixel_aspect, + int *dest_width, int *dest_height, double *dest_pixel_aspect) { + *dest_width = width; + *dest_height = height; + *dest_pixel_aspect = pixel_aspect; +} + +/* this will be called by xine when it's about to draw the frame */ +static void frame_output_cb(void *data, int video_width, int video_height, + double video_pixel_aspect, int *dest_x, int *dest_y, + int *dest_width, int *dest_height, + double *dest_pixel_aspect, int *win_x, int *win_y) { + *dest_x = 0; + *dest_y = 0; + *win_x = xpos; + *win_y = ypos; + *dest_width = width; + *dest_height = height; + *dest_pixel_aspect = pixel_aspect; +} + +static void event_listener(void *user_data, const xine_event_t *event) { + switch(event->type) { + case XINE_EVENT_UI_PLAYBACK_FINISHED: + running = 0; + break; + + case XINE_EVENT_PROGRESS: + { + xine_progress_data_t *pevent = (xine_progress_data_t *) event->data; + + printf("%s [%d%%]\n", pevent->description, pevent->percent); + } + break; + + /* you can handle a lot of other interesting events here */ + } +} + +int main(int argc, char **argv) { + char configfile[2048]; + x11_visual_t vis; + double res_h, res_v; + char *vo_driver = "auto"; + char *ao_driver = "auto"; + char *mrl = NULL; + int i; + Atom XA_NO_BORDER; + MWMHints mwmhints; + + /* parsing command line */ + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-vo") == 0) { + vo_driver = argv[++i]; + } + else if (strcmp(argv[i], "-ao") == 0) { + ao_driver = argv[++i]; + } + else + mrl = argv[i]; + } + + if (!mrl) { + printf("specify an mrl\n"); + return 1; + } + printf("mrl: '%s'\n", mrl); + + if (!XInitThreads()) { + printf("XInitThreads() failed\n"); + return 1; + } + + /* load xine config file and init xine */ + xine = xine_new(); + snprintf(configfile, sizeof(configfile), "%s%s", xine_get_homedir(), "/.xine/config"); + xine_config_load(xine, configfile); + xine_init(xine); + + display = XOpenDisplay(NULL); + screen = XDefaultScreen(display); + xpos = 0; + ypos = 0; + width = 320; + height = 200; + + /* some initalization for the X11 Window we will be showing video in */ + XLockDisplay(display); + fullscreen = 0; + window[0] = XCreateSimpleWindow(display, XDefaultRootWindow(display), + xpos, ypos, width, height, 1, 0, 0); + + window[1] = XCreateSimpleWindow(display, XDefaultRootWindow(display), + 0, 0, (DisplayWidth(display, screen)), + (DisplayHeight(display, screen)), 0, 0, 0); + + XSelectInput(display, window[0], INPUT_MOTION); + + XSelectInput(display, window[1], INPUT_MOTION); + + XA_NO_BORDER = XInternAtom(display, "_MOTIF_WM_HINTS", False); + mwmhints.flags = MWM_HINTS_DECORATIONS; + mwmhints.decorations = 0; + XChangeProperty(display, window[1], + XA_NO_BORDER, XA_NO_BORDER, 32, PropModeReplace, (unsigned char *) &mwmhints, + PROP_MWM_HINTS_ELEMENTS); + + XMapRaised(display, window[fullscreen]); + + res_h = (DisplayWidth(display, screen) * 1000 / DisplayWidthMM(display, screen)); + res_v = (DisplayHeight(display, screen) * 1000 / DisplayHeightMM(display, screen)); + XSync(display, False); + XUnlockDisplay(display); + + /* filling in the xine visual struct */ + vis.display = display; + vis.screen = screen; + vis.d = window[fullscreen]; + vis.dest_size_cb = dest_size_cb; + vis.frame_output_cb = frame_output_cb; + vis.user_data = NULL; + pixel_aspect = res_v / res_h; + + /* opening xine output ports */ + vo_port = xine_open_video_driver(xine, vo_driver, XINE_VISUAL_TYPE_X11, (void *)&vis); + ao_port = xine_open_audio_driver(xine , ao_driver, NULL); + + /* open a xine stream connected to these ports */ + stream = xine_stream_new(xine, ao_port, vo_port); + /* hook our event handler into the streams events */ + event_queue = xine_event_new_queue(stream); + xine_event_create_listener_thread(event_queue, event_listener, NULL); + + /* make the video window visible to xine */ + xine_port_send_gui_data(vo_port, XINE_GUI_SEND_DRAWABLE_CHANGED, (void *) window[fullscreen]); + xine_port_send_gui_data(vo_port, XINE_GUI_SEND_VIDEOWIN_VISIBLE, (void *) 1); + + /* start playback */ + if (!xine_open(stream, mrl) || !xine_play(stream, 0, 0)) { + printf("Unable to open mrl '%s'\n", mrl); + return 1; + } + + while (running) { + XEvent xevent; + int got_event; + + XLockDisplay(display); + got_event = XPending(display); + if( got_event ) + XNextEvent(display, &xevent); + XUnlockDisplay(display); + + if( !got_event ) { + xine_usec_sleep(20000); + continue; + } + + switch(xevent.type) { + + case KeyPress: + { + XKeyEvent kevent; + KeySym ksym; + char kbuf[256]; + int len; + + kevent = xevent.xkey; + + XLockDisplay(display); + len = XLookupString(&kevent, kbuf, sizeof(kbuf), &ksym, NULL); + XUnlockDisplay(display); + + switch (ksym) { + + case XK_q: + case XK_Q: + /* user pressed q => quit */ + running = 0; + break; + + case XK_f: + case XK_F: + { + /* user pressed f => toggle fullscreen */ + Window tmp_win; + + XLockDisplay(display); + XUnmapWindow(display, window[fullscreen]); + fullscreen = !fullscreen; + XMapRaised(display, window[fullscreen]); + XSync(display, False); + XTranslateCoordinates(display, window[fullscreen], + DefaultRootWindow(display), + 0, 0, &xpos, &ypos, &tmp_win); + XUnlockDisplay(display); + + xine_port_send_gui_data(vo_port, XINE_GUI_SEND_DRAWABLE_CHANGED, + (void*) window[fullscreen]); + } + break; + + case XK_Up: + /* cursor up => increase volume */ + xine_set_param(stream, XINE_PARAM_AUDIO_VOLUME, + (xine_get_param(stream, XINE_PARAM_AUDIO_VOLUME) + 1)); + break; + + case XK_Down: + /* cursor down => decrease volume */ + xine_set_param(stream, XINE_PARAM_AUDIO_VOLUME, + (xine_get_param(stream, XINE_PARAM_AUDIO_VOLUME) - 1)); + break; + + case XK_plus: + /* plus => next audio channel */ + xine_set_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, + (xine_get_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL) + 1)); + break; + + case XK_minus: + /* minus => previous audio channel */ + xine_set_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, + (xine_get_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL) - 1)); + break; + + case XK_space: + /* space => toggle pause mode */ + if (xine_get_param(stream, XINE_PARAM_SPEED) != XINE_SPEED_PAUSE) + xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE); + else + xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL); + break; + + } + } + break; + + case Expose: + /* this handles (partial) occlusion of our video window */ + if (xevent.xexpose.count != 0) + break; + xine_port_send_gui_data(vo_port, XINE_GUI_SEND_EXPOSE_EVENT, &xevent); + break; + + case ConfigureNotify: + { + XConfigureEvent *cev = (XConfigureEvent *) &xevent; + Window tmp_win; + + width = cev->width; + height = cev->height; + + if ((cev->x == 0) && (cev->y == 0)) { + XLockDisplay(display); + XTranslateCoordinates(display, cev->window, + DefaultRootWindow(cev->display), + 0, 0, &xpos, &ypos, &tmp_win); + XUnlockDisplay(display); + } else { + xpos = cev->x; + ypos = cev->y; + } + } + break; + + } + } + + /* cleanup */ + xine_close(stream); + xine_event_dispose_queue(event_queue); + xine_dispose(stream); + xine_close_audio_driver(xine, ao_port); + xine_close_video_driver(xine, vo_port); + xine_exit(xine); + + XLockDisplay(display); + XUnmapWindow(display, window[fullscreen]); + XDestroyWindow(display, window[0]); + XDestroyWindow(display, window[1]); + XUnlockDisplay(display); + + XCloseDisplay (display); + + return 0; +} + + + + diff --git a/doc/hackersguide/library.sgml b/doc/hackersguide/library.sgml deleted file mode 100644 index 1d987d259..000000000 --- a/doc/hackersguide/library.sgml +++ /dev/null @@ -1,410 +0,0 @@ - - Using the xine library - - - xine architecture as visible to libxine clients - - The following drawing shows the components of xine as outside applications - see them. For every component, the functions for creating and destroying it - are given. Every other function works in the context it is enclosed in. - Functions that facilitate the connection of the individual components are - also given. - - - - - - - - - - outside view on xine components - - - - The function are named just to give you an overview of what is actually - there. It is all thoroughly documented in the plublic header - xine.h, which is the main and preferably the only xine - header, clients should include. (xine/xineutils.h and the XML parser might - make an exception.) - - - Details on the OSD feature can be found in the OSD section. - - - - - Writing a new frontend to xine - - The best way to explain this seems to be actual code. Below you - will find a very easy and hopefully self-explaining xine frontend - to give you a start. - - - One important thing to note is that any X11 based xine-lib frontend - must call XInitThreads() before calling the - first Xlib function, because xine will access the display from - within a different thread than the frontend. - - - Source code of a simple X11 frontend - -/* -** Copyright (C) 2003 Daniel Caujolle-Bert <segfault@club-internet.fr> -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -** -*/ - -/* - * compile-command: "gcc -Wall -O2 `xine-config --cflags` `xine-config --libs` -L/usr/X11R6/lib -lX11 -lm -o xinimin xinimin.c" - */ - -#include <stdio.h> -#include <string.h> -#include <math.h> - -#include <X11/X.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/keysym.h> -#include <X11/Xatom.h> -#include <X11/Xutil.h> -#include <X11/extensions/XShm.h> - -#include <xine.h> -#include <xine/xineutils.h> - - -#define MWM_HINTS_DECORATIONS (1L << 1) -#define PROP_MWM_HINTS_ELEMENTS 5 -typedef struct { - uint32_t flags; - uint32_t functions; - uint32_t decorations; - int32_t input_mode; - uint32_t status; -} MWMHints; - -static xine_t *xine; -static xine_stream_t *stream; -static xine_video_port_t *vo_port; -static xine_audio_port_t *ao_port; -static xine_event_queue_t *event_queue; - -static Display *display; -static int screen; -static Window window[2]; -static int xpos, ypos, width, height, fullscreen; -static double pixel_aspect; - -static int running = 1; - -#define INPUT_MOTION (ExposureMask | ButtonPressMask | KeyPressMask | \ - ButtonMotionMask | StructureNotifyMask | \ - PropertyChangeMask | PointerMotionMask) - -/* this will be called by xine, if it wants to know the target size of a frame */ -static void dest_size_cb(void *data, int video_width, int video_height, double video_pixel_aspect, - int *dest_width, int *dest_height, double *dest_pixel_aspect) { - *dest_width = width; - *dest_height = height; - *dest_pixel_aspect = pixel_aspect; -} - -/* this will be called by xine when it's about to draw the frame */ -static void frame_output_cb(void *data, int video_width, int video_height, - double video_pixel_aspect, int *dest_x, int *dest_y, - int *dest_width, int *dest_height, - double *dest_pixel_aspect, int *win_x, int *win_y) { - *dest_x = 0; - *dest_y = 0; - *win_x = xpos; - *win_y = ypos; - *dest_width = width; - *dest_height = height; - *dest_pixel_aspect = pixel_aspect; -} - -static void event_listener(void *user_data, const xine_event_t *event) { - switch(event->type) { - case XINE_EVENT_UI_PLAYBACK_FINISHED: - running = 0; - break; - - case XINE_EVENT_PROGRESS: - { - xine_progress_data_t *pevent = (xine_progress_data_t *) event->data; - - printf("%s [%d%%]\n", pevent->description, pevent->percent); - } - break; - - /* you can handle a lot of other interesting events here */ - } -} - -int main(int argc, char **argv) { - char configfile[2048]; - x11_visual_t vis; - double res_h, res_v; - char *vo_driver = "auto"; - char *ao_driver = "auto"; - char *mrl = NULL; - int i; - Atom XA_NO_BORDER; - MWMHints mwmhints; - - /* parsing command line */ - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-vo") == 0) { - vo_driver = argv[++i]; - } - else if (strcmp(argv[i], "-ao") == 0) { - ao_driver = argv[++i]; - } - else - mrl = argv[i]; - } - - if (!mrl) { - printf("specify an mrl\n"); - return 1; - } - printf("mrl: '%s'\n", mrl); - - if (!XInitThreads()) { - printf("XInitThreads() failed\n"); - return 1; - } - - /* load xine config file and init xine */ - xine = xine_new(); - snprintf(configfile, sizeof(configfile), "%s%s", xine_get_homedir(), "/.xine/config"); - xine_config_load(xine, configfile); - xine_init(xine); - - display = XOpenDisplay(NULL); - screen = XDefaultScreen(display); - xpos = 0; - ypos = 0; - width = 320; - height = 200; - - /* some initalization for the X11 Window we will be showing video in */ - XLockDisplay(display); - fullscreen = 0; - window[0] = XCreateSimpleWindow(display, XDefaultRootWindow(display), - xpos, ypos, width, height, 1, 0, 0); - - window[1] = XCreateSimpleWindow(display, XDefaultRootWindow(display), - 0, 0, (DisplayWidth(display, screen)), - (DisplayHeight(display, screen)), 0, 0, 0); - - XSelectInput(display, window[0], INPUT_MOTION); - - XSelectInput(display, window[1], INPUT_MOTION); - - XA_NO_BORDER = XInternAtom(display, "_MOTIF_WM_HINTS", False); - mwmhints.flags = MWM_HINTS_DECORATIONS; - mwmhints.decorations = 0; - XChangeProperty(display, window[1], - XA_NO_BORDER, XA_NO_BORDER, 32, PropModeReplace, (unsigned char *) &mwmhints, - PROP_MWM_HINTS_ELEMENTS); - - XMapRaised(display, window[fullscreen]); - - res_h = (DisplayWidth(display, screen) * 1000 / DisplayWidthMM(display, screen)); - res_v = (DisplayHeight(display, screen) * 1000 / DisplayHeightMM(display, screen)); - XSync(display, False); - XUnlockDisplay(display); - - /* filling in the xine visual struct */ - vis.display = display; - vis.screen = screen; - vis.d = window[fullscreen]; - vis.dest_size_cb = dest_size_cb; - vis.frame_output_cb = frame_output_cb; - vis.user_data = NULL; - pixel_aspect = res_v / res_h; - - /* opening xine output ports */ - vo_port = xine_open_video_driver(xine, vo_driver, XINE_VISUAL_TYPE_X11, (void *)&vis); - ao_port = xine_open_audio_driver(xine , ao_driver, NULL); - - /* open a xine stream connected to these ports */ - stream = xine_stream_new(xine, ao_port, vo_port); - /* hook our event handler into the streams events */ - event_queue = xine_event_new_queue(stream); - xine_event_create_listener_thread(event_queue, event_listener, NULL); - - /* make the video window visible to xine */ - xine_port_send_gui_data(vo_port, XINE_GUI_SEND_DRAWABLE_CHANGED, (void *) window[fullscreen]); - xine_port_send_gui_data(vo_port, XINE_GUI_SEND_VIDEOWIN_VISIBLE, (void *) 1); - - /* start playback */ - if (!xine_open(stream, mrl) || !xine_play(stream, 0, 0)) { - printf("Unable to open mrl '%s'\n", mrl); - return 1; - } - - while (running) { - XEvent xevent; - int got_event; - - XLockDisplay(display); - got_event = XPending(display); - if( got_event ) - XNextEvent(display, &xevent); - XUnlockDisplay(display); - - if( !got_event ) { - xine_usec_sleep(20000); - continue; - } - - switch(xevent.type) { - - case KeyPress: - { - XKeyEvent kevent; - KeySym ksym; - char kbuf[256]; - int len; - - kevent = xevent.xkey; - - XLockDisplay(display); - len = XLookupString(&kevent, kbuf, sizeof(kbuf), &ksym, NULL); - XUnlockDisplay(display); - - switch (ksym) { - - case XK_q: - case XK_Q: - /* user pressed q => quit */ - running = 0; - break; - - case XK_f: - case XK_F: - { - /* user pressed f => toggle fullscreen */ - Window tmp_win; - - XLockDisplay(display); - XUnmapWindow(display, window[fullscreen]); - fullscreen = !fullscreen; - XMapRaised(display, window[fullscreen]); - XSync(display, False); - XTranslateCoordinates(display, window[fullscreen], - DefaultRootWindow(display), - 0, 0, &xpos, &ypos, &tmp_win); - XUnlockDisplay(display); - - xine_port_send_gui_data(vo_port, XINE_GUI_SEND_DRAWABLE_CHANGED, - (void*) window[fullscreen]); - } - break; - - case XK_Up: - /* cursor up => increase volume */ - xine_set_param(stream, XINE_PARAM_AUDIO_VOLUME, - (xine_get_param(stream, XINE_PARAM_AUDIO_VOLUME) + 1)); - break; - - case XK_Down: - /* cursor down => decrease volume */ - xine_set_param(stream, XINE_PARAM_AUDIO_VOLUME, - (xine_get_param(stream, XINE_PARAM_AUDIO_VOLUME) - 1)); - break; - - case XK_plus: - /* plus => next audio channel */ - xine_set_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, - (xine_get_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL) + 1)); - break; - - case XK_minus: - /* minus => previous audio channel */ - xine_set_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, - (xine_get_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL) - 1)); - break; - - case XK_space: - /* space => toggle pause mode */ - if (xine_get_param(stream, XINE_PARAM_SPEED) != XINE_SPEED_PAUSE) - xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE); - else - xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL); - break; - - } - } - break; - - case Expose: - /* this handles (partial) occlusion of our video window */ - if (xevent.xexpose.count != 0) - break; - xine_port_send_gui_data(vo_port, XINE_GUI_SEND_EXPOSE_EVENT, &xevent); - break; - - case ConfigureNotify: - { - XConfigureEvent *cev = (XConfigureEvent *) &xevent; - Window tmp_win; - - width = cev->width; - height = cev->height; - - if ((cev->x == 0) && (cev->y == 0)) { - XLockDisplay(display); - XTranslateCoordinates(display, cev->window, - DefaultRootWindow(cev->display), - 0, 0, &xpos, &ypos, &tmp_win); - XUnlockDisplay(display); - } else { - xpos = cev->x; - ypos = cev->y; - } - } - break; - - } - } - - /* cleanup */ - xine_close(stream); - xine_event_dispose_queue(event_queue); - xine_dispose(stream); - xine_close_audio_driver(xine, ao_port); - xine_close_video_driver(xine, vo_port); - xine_exit(xine); - - XLockDisplay(display); - XUnmapWindow(display, window[fullscreen]); - XDestroyWindow(display, window[0]); - XDestroyWindow(display, window[1]); - XUnlockDisplay(display); - - XCloseDisplay (display); - - return 0; -} - - - - diff --git a/doc/hackersguide/output.docbook b/doc/hackersguide/output.docbook new file mode 100644 index 000000000..806e89d0a --- /dev/null +++ b/doc/hackersguide/output.docbook @@ -0,0 +1,668 @@ + + xine's output layer + + + Post plugin layer + + In this section you will learn, how the powerful post plugin architecture + works and how to write post plugins. + + + General principle of post plugins + + The name "post plugin" comes from "postprocessing" which already describes + what these plugins are supposed to do: they take video frames, audio + buffers or subpicture planes as they leave the decoders and apply arbitrary + processing to them. Then they pass processed elements on to the output + loops. Post plugins can not only be chained to process the predecessor's + output and advance the data to their successor, they can form arbitrary trees, + since post plugins can have any number of inputs and outputs. Additionally, + the interconnection of the plugins currently inserted in such a tree can + be changed on the fly during playback. The public function + xine_post_wire() is used by frontends to form such + connections. + + + Due to the variety of possible applications, the interface post plugins have + to implement is just the basic foundation. The complexity comes from hooking + your post plugin into the engine data paths for video frames and audio buffers, + intercepting the data and performing your operation on them. This is done by + taking the interface of a video or audio port, replacing some of the functions + with your own ones and passing the interface to the decoder or predecessor + post plugin that is going to feed you with data by accessing this interface + and by doing that, calling the functions you provide. From there you can do + almost anything you want. Constructing video frames from audio buffers to + visualize sound is possible as well as just outputting an integer giving the + average brightness of an image. It is also possible to invent post plugins + with no output (not very useful, unless the plugin has some side-effect) or + no input at all; for the latter you have to create your own pthread, otherwise + your plugin will not do anything. An audio signal generator could be + implemented like this. The various data types, post plugins can + accept as input or offer as output are defined in xine.h + as XINE_POST_DATA_* defines. + + + Some terminology used in the following explanations: + + + + down direction: + The direction from the decoders to the output. This is the way video or audio + data (actual content and meta information) usually travels through the engine. + + + + + up direction: + The direction from the output to the decoders. This is the way some video or audio + metadata like metronom timestamps travel through the engine. + + + + + interception: + Post plugins are inserted into the engine data paths by the means of the decorator + design pattern. This works by taking engine structures with member funtions like + video or audio ports, video frames or overlay managers and inserting your own functions + into a copy of this structure. This is called interception. This modified structure + is then passed up to the plugin that uses it and thus calls your replaced functions. + + + + + + + Writing a xine post plugin + + The post plugin API is declared in src/xine-engine/post.h + The plugin info of post plugins contains the post plugin type, which is one of the + XINE_POST_TYPE_* defines and the init_class function of the plugin. + + +    post_plugin_t *open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target); + Returns an instance of the plugin. Some post plugins evaluate inputs + to open a variable number of inputs. Since almost all post plugins have audio or video + outputs, you can hand in a NULL-terminated array of ports to connect to these outputs. + In this function you can also intercept these ports so that your plugin is actually used. + There is a helper function to initialize a post_plugin_t, which you are + encouraged to use: _x_post_init(). + + +    char *get_identifier(post_class_t *class_gen); + This function returns a short identifier describing the plugin. + + +    char *get_description(post_class_t *class_gen); + This function returns a plaintext, one-line string describing the plugin. + + +    void dispose(post_class_t *class_gen); + This function frees the memory used by the video out plugin class object. + + + The post_plugin_t structure contains the publicly visible + part of the post plugin with the audio and video inputs and the type of + the post plugin. Not publicly visible are the lists of all inputs and outputs, + the dispose() function and some internal stuff which + plugins do not have to worry about. + + +    void dispose(post_plugin_t *this_gen); + This function frees the memory used by the plugin instance, but not necessarily + immediately. Since post plugins enter their own functions into engine structures, + they might still be needed when dispose() is being called. + They maintain a usage counter to detect that. To check for such a condition, you + should use the _x_post_dispose() helper function like that: + +   if (_x_post_dispose(this)) +     really_free(this); + _x_post_dispose() frees any ressources allocated by any of the + post plugin helper functions and returns boolean true, if the plugin is not needed + any more. + + + + Interception + + Currently, we have four engine structures which can be intercepted by post plugins: + video ports, video frames, overlay managers and audio ports. You could do this + interception manually, but since this is quite a complex process, there are helper + functions to assist you and their usage is encouraged. + + + Intercepting a video port + + +   post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, +     xine_video_port_t *port, post_in_t **input, post_out_t **output); + This function will intercept port and returns a structure + for you to pass up. All functions in the port will be replaced with dummy + pass through functions that do nothing but relaying the call down to the original + port. If you want (that is, input or output are + not NULL), this function will also create the input and output descriptors complete + with rewiring functions and add them to the relevant lists. + This is required, if you want this port to be advertised by the plugin to the outside world. + + + post_video_port_t makes a variety of interception schemes very easy. + If you want to replace any of the default functions with your own, just enter it + into new_port. You can use original_port + from within your function to propagate calls down to the original port. + The constraint is that your functions have to ensure that every original + port held open scores one usage counter point, so that opened ports are always + closed before the plugin is disposed. Therefore, you should use the macro + _x_post_inc_usage() before calling + original_port->open() and use the macro + _x_post_dec_usage() after calling + original_port->close(). Note that _x_post_dec_usage() + might dispose the plugin, when dispose() has been called + earlier and usage count drops to zero, so do never touch plugin structures after + _x_post_dec_usage(). In addition, you must never call a port + function of the original port when the port is not open. + + + Intercepting video frames or the overlay manager of the port is even easier. + You do not have to reimplement get_frame() or + get_overlay_manager(). Just enter a intercept_frame + or intercept_ovl function which returns boolean true, if + you want to intercept. The functions to insert in the intercepted frame or overlay + manager are taken from new_frame and new_manager + respectively. Note that the defaults are reversed: If you do not enter such a + decision function for either one, all frames and no overlay manager will be intercepted. + + + For convenience post_video_port_t also contains pointers to the + current stream and to the current post plugin and a user_data pointer, where you + can put in anything you need in addition. If your port is used by more than one + thread, you can also enforce locking on the port, frame or overlay manager level + by entering a lock into port_lock, frame_lock or + manager_lock respectively. + + + + Intercepting an audio port + + Audio port interception is just a stripped down version of video port interception. + Everything related to frames and overlay manager is not needed and audio buffers + do not need to be intercepted, since they have no member functions. Everything else + of the above still applies. + + + + Intercepting overlay manager + +    void _x_post_intercept_overlay_manager(video_overlay_manager_t *original, post_video_port_t *port); + Interception of the overlay manager is done automatically when your + intercept_ovl() decision function returns boolean true. + Should you ever decide not to use that, interception can be done with this helper + function, which simply creates an intercepted overlay manager with dummy + pass through functions in port->new_manager and stores the original + manager in port->original_manager. + + + No matter how you intercepted the overlay manager, your own replacement + functions will receive port->new_manager as the overlay manager + argument. But you most likely want to have access to the post_video_port_t + from within your functions. For that, there exists a pointer retrieval function: +    post_video_port_t *_x_post_ovl_manager_to_port(video_overlay_manager_t *manager); + + + + Intercepting a video frame + + +   vo_frame_t *_x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *port); +   vo_frame_t *_x_post_restore_video_frame(vo_frame_t *frame, post_video_port_t *port); + Interception of video frames is done automatically when your + intercept_frame() decision function returns boolean true or + when there is no such function in post_video_port_t. + Should you ever decide not to use that, interception can be done with the helper + function _x_post_intercept_video_frame(). + + + Since the same video frame can be in use in the decoder and in the output and in + any post plugin in between at the same time, simply modifying the frame + structure does not work, because every user of the frame needs to see his version + and the frame must always travel along the same path through the plugins for its + entire lifetime. To ensure that, _x_post_intercept_video_frame() + provides a shallow copy of the frame structure with the original frame attached to + copy->next. This copy will be filled with your own + frame functions from port->new_frame and with dummy pass + through functions for those you did not provide. This way, every part of xine + using this frame will see its own frame structure with a list of frame + contexts from down the data path attached to frame->next. + _x_post_restore_video_frame() reverses this and should be + used when the frame is freed or disposed. + + + Your own replacement functions will receive the copied frame as as argument. + But you most likely want to have access to the post_video_port_t + from within your functions. For that, there exists a pointer retrieval function: +    post_video_port_t *_x_post_video_frame_to_port(vo_frame_t *frame); + The constraint is that your functions have to ensure that every intercepted + frame scores one usage counter point, so that these frames are always + freed or disposed before the plugin is disposed. Therefore, you should use the macro + _x_post_inc_usage() before calling + _x_post_intercept_video_frame() and use the macro + _x_post_dec_usage() after calling + _x_post_restore_video_frame(). Note that _x_post_dec_usage() + might dispose the plugin, when dispose() has been called + earlier and usage count drops to zero, so do never touch plugin structures after + _x_post_dec_usage(). + + + From within your own frame functions, you can propagate calls to the original + frame by calling a function on frame->next. Since + modifications to the frame can travel both upwards and downwards (decoders and + output can modify the frame), changes need to be copied between the frame + structure contexts. You should use the _x_post_frame_copy_down() + and _x_post_frame_copy_up() helper functions like that: + +   _x_post_frame_copy_down(frame, frame->next); +   frame->next->draw(frame->next, stream); +   _x_post_frame_copy_up(frame, frame->next); + + + If your post plugin modifies the content of the frame, you have to modify + a deep copy of the frame, because the decoder might still use the frame as + a reference frame for future decoding. The usual procedure is: + +   modified_frame = port->original_port->get_frame(port->original_port, ...); +   _x_post_frame_copy_down(frame, modified_frame); +   copy_and_modify(frame, modified_frame); +   skip = modified_frame->draw(modified_frame, stream); +   _x_post_frame_copy_up(frame, modified_frame); +   modified_frame->free(modified_frame); + + + When the output receives a frame via draw(), + it usually receives the stream where the frame + originates as well and modifies the state of this stream by passing + the frame through the stream's metronom. Sometimes this is unwanted. + For example, when you pass the same frame to the output more than once, it + will confuse metronom. To solve this, you can call + frame->next->draw() with NULL as the stream. + You might also want to prevent frames from being passed down to the output + completely, because your post plugin creates something else from these frames, + but does not need them to be drawn. In both these situations, you have + to call the helper function _x_post_frame_u_turn() + when the frame is drawn, because this does some housekeeping which the + decoder might expect to take place. + + + The following diagram summarizes the situations of a video frame passing + through a post plugin: + + + + + + + + + + video frame passing through a post plugin + + + + + Summary of constraints + + + + Call _x_post_inc_usage() before port open() + before any other port function. + + + + + Call _x_post_inc_usage() before issueing an intercepted frame. + + + + + Call _x_post_dec_usage() after port close() + and do not call any port functions after that. + + + + + Call _x_post_dec_usage() after restoring a frame. + + + + + When a frame is drawn by your plugin, it must either be drawn on the original + port with the correct stream as argument or U-turned (or passed through a + private metronom manually). + + + + + If your post plugin keeps locked frames, release them when your input port is being + closed. + + + + + Do not assume your plugin is alive after _x_post_dec_usage(). + + + + + + + Rewiring and the ticket system + + Rewiring is the reconnection of one post plugin's outputs and another post plugin's + inputs. This can happen on the fly during playback, which makes this a very delicate + process. In one such input to output connection, only the output is active by either + writing data directly to the connected input or by calling functions there. Therefore + we have to notify only the output, when it is rewired. This is done by calling the + rewire() member function of the corresponding + xine_post_out_t when the frontend issues a rewiring on this output. + This is done from the frontend thread for the rewire operation to return synchroneously. + But since this can happen on the fly, we have to assure that no other thread is relying + on the connection while we modify it. For this, threads working within post plugins + have to be accounted and on demand suspended in safe positions. For this, xine offers + a synchronization facility called "tickets". + + + Ticket system principles and operations + + The idea of the ticket system is based on an extended read-write lock, where there can + be many readers in parallel, but only one exclusive writer. A certain interface might + require you to have a ticket before calling its functions. The ticket system now + allows multiple threads to operate within the component behind the interface by + granting as many tickets as needed. But should an outside operation require exclusive + access to the component, all granted tickets can be revoked and have to be given back + by the threads who hold them, which suspends the threads. After the exclusive + operation, tickets will be reissued so all suspended threads can continue where they + stopped. We will now look at the ticket primitives in detail: + + + + acquire() + + + You receive a new ticket. If the ticket is currently revoked, you can be blocked + until it is reissued. There is one exception to this: You can acquire a revoked + ticket, if you revoked it atomic yourself. You can also acquire a ticket irrevocably. + Between acquire and release of an irrevocable ticket, it is guaranteed that + you will not be blocked by ticket revocation. + + + + + release() + + + You give a ticket back when you do not need it any longer. If the ticket is + currently revoked, you can be blocked until it is reissued. If you acquired the + ticket irrevocably, you have to release it irrevocably as well. + + + + + renew() + + + You must only call this function, when the ticket has been revoked, so be + sure to check ticket_revoked before. You give the ticket + back and receive a new one. In between, you can be blocked until the ticket is + reissued. You have to renew irrevocably, if you cannot assure that the thread holds + no irrevocable tickets. If you can assure this, renew revocably. + + + + + revoke() + + + This function can only be called by the xine engine, plugins do not have access to it. + It revokes all tickets and after finite time, all threads will run into a + acquire(), release() or renew() + and will be suspended there. Then the revocation returns and you can modify structures + or call functions with the knowledge that all ticket holders will remain in safe + positions. When you additionally need exclusive access where no other revoker + can interfere, you have to revoke atomic. + + + + + issue() + + + This function can only be called by the xine engine, plugins do not have access to it. + It ends ticket revocation and hands out new tickets to all threads that applied with a + acquire() or renew(). If you revoked the + tickets atomic, you have to issue them atomic. + + + + + + When you use the ticket system in any way, you have to obey to the following rules: + + + + Assure to release irrevocable tickets ater a finite time. + + + + + Assure to release or renew revocable tickets ater a finite time. + + + + + Assure to reissue tickets you revoked atomic after a finite time. + + + + + Pair calls properly. + + + + + Never revoke a ticket you hold. + + + + + Never acquire a ticket you revoked atomic before. + + + + + Never acquire a ticket revocable more than once. + + + + + + + Ticket handling in decoder and post plugins + + The contract of the video and audio port interfaces is that you need to have + the port ticket, when you want to call functions of these interfaces. The decoder + plugins do not have to worry about this at all, since the decoder loops inside the + engine handle the ticketing. Post plugins get the ticket assigned by the engine, + but usually, a post plugin does not create a new thread, it is called by the + decoder thread and therefore already owns the necessary ticket. All port functions + are also ticket-safe as they follow all the rules given above. + + + You only have to remember that tickets need to be renewed as soon as possible, + when the are revoked. For this, the helper function + _x_post_rewire() should be used in prominent locations + where it is safe to be suspended. Candidates for such locations are at the + beginning of the port's open() and + get_frame()/get_buffer() functions. + The default pass through implementations for intercepted ports already do this. + + + The port tickets are revoked, whenever a rewiring takes place or the engine + switches into pause mode. The tickets are reissued, when the rewiring is finished + or the engine switches from pause mode into playback. Some post plugins might + contain critical parts, where they must not be interrupted by a rewire or pause. + These sections can be enclosed in _x_post_lock() and + _x_post_unlock(), which will simply acquire and release an + irrevocable ticket for you. As long as you hold such a ticket, it is guaranteed + that you will never be interrupted by a pause or rewire. + + + + + + + Video output + + In order to allow for device-dependant acceleration features, xine + calls upon the video output plugin for more than just displaying + images. The tasks performed by the video plugins are: + + + + Allocation of vo_frame_t structures and their + subsequent destruction. + + + + + Allocation of memory for use by one frame (this is to allow + for the ability of some video output plugins to map frames directly + into video-card memory hence removing the need for the frame to + be copied across the PCI/AGP bus at display time). + + + + + Most important, the ability to render/copy a given + frame to the output device. + + + + + Optionally the copying of the frame from a file dependant + colour-space and depth into the frame structure. This is to allow for + on-the fly colour-space conversion and scaling if required (e.g. the XShm + ouput plugin uses this mechanism). + + + + + + Although these extra responsibilities add great complexity to your + plugin it should be noted that they allow plugins to take full advantage + of any special hardware-acceleration without sacrificing flexibility. + + + Writing a xine video out plugin + + The video out plugin API is declared in src/xine-engine/video_out.h + The plugin info of video out plugins contains the visual type, priority, + and the init_class function of the plugin. + + + The visual_type field is used by xine to + determine if the GUI used by the client is supported by the plugin + (e.g. X11 output plugins require the GUI to be running under the + X Windowing system) and also to determine the type of information passed to the + open_plugin() function as its visual parameter. + + +    char *get_description(video_driver_class_t *this_gen); + This function returns a plaintext, one-line string describing the plugin. + + +    char *get_identifier(video_driver_class_t *this_gen); + This function returns a shorter identifier describing the plugin. + + +    void dispose(video_driver_class_t *this_gen); + This function frees the memory used by the video out plugin class object. + + +    vo_driver_t *get_instance(video_driver_class_t *class_gen, const void *visual); + Returns an instance of the plugin. + The visual is a pointer to a visual-dependant + structure/variable. For example, if you had previously claimed your + plugin was of the VISUAL_TYPE_X11 type, this would be a pointer + to a x11_visual_t, which amongst other things hold the + Display variable associated with the + X-server xine should display to. See plugin source-code for other + VISUAL_TYPE_* constants and associated structures. Note that this + field is provided by the client application and so if you wish to add another visual + type you will either need to extend an existing client or write a new + one. + + +    uint32_t get_capabilities(vo_driver_t *this_gen); + Returns a bit mask describing the output plugin's capabilities. + You may logically OR the VO_CAP_* constants together to get + a suitable bit-mask (via the '|' operator). + + + +   int get_property(vo_driver_t *self, int property); +   int set_property(vo_driver_t *self, int property, int value); +   void get_property_min_max(vo_driver_t *self, int property, int *min, int *max); + Handle the getting, setting of properties and define their bounds. + Valid property IDs can be found in the video_out.h + header file. + + +    int gui_data_exchange(vo_driver_t *self, int data_type, void *data); + Accepts various forms of data from the UI (e.g. the mouse has moved or the + window has been hidden). Look at existing plugins for examples of data + exchanges from various UIs. + + +    vo_frame_t *alloc_frame(vo_driver_t *self); + Returns a pointer to a xine video frame. + Typically the video plugin will add private fields to the end of the + vo_frame_t structure which are used for internal purposes by the plugin. + + + The function pointers within the frame structure provide a mechanism for the + driver to retain full control of how the frames are managed and rendered to. If + the VO_CAP_COPIES_IMAGE flag was set in the plugins capabilities then the + copy field is required and will be called sequentially for each 16-pixel high + strip in the image. The plugin may then decide, based on the frame's format, how + this is copied into the frame. + + +    void update_frame_format(vo_driver_t *self, vo_frame_t *img, uint32_t width, uint32_t height, double ratio, int format, int flags); + This function will be called each time the colour-depth/space or size of a frame changes. + Typically this function would allocate sufficient memory for the frame, assign the pointers + to the individual planes of the frame to the base field of the + frame and perform any driver-specific changes. + + +    void display_frame(vo_driver_t *self, vo_frame_t *vo_img); + Renders a given frame to the output device. + + + +   void overlay_begin(vo_driver_t *self, vo_frame_t *vo_img, int changed); +   void overlay_blend(vo_driver_t *self, vo_frame_t *vo_img, vo_overlay_t *overlay); +   void overlay_end(vo_driver_t *self, vo_frame_t *vo_img); + These are used to blend overlays on frames. overlay_begin() is called, + when the overlay appears for the first time, overlay_blend() is then + called for every subsequent frame and overlay_end() is called, when + the overlay should disappear again. + + +    int redraw_needed(vo_driver_t *self); + Queries the driver, if the current frame needs to be drawn again. + + +    void dispose(vo_driver_t *self); + Releases all resources and frees the plugin. + + + + + diff --git a/doc/hackersguide/output.sgml b/doc/hackersguide/output.sgml deleted file mode 100644 index 806e89d0a..000000000 --- a/doc/hackersguide/output.sgml +++ /dev/null @@ -1,668 +0,0 @@ - - xine's output layer - - - Post plugin layer - - In this section you will learn, how the powerful post plugin architecture - works and how to write post plugins. - - - General principle of post plugins - - The name "post plugin" comes from "postprocessing" which already describes - what these plugins are supposed to do: they take video frames, audio - buffers or subpicture planes as they leave the decoders and apply arbitrary - processing to them. Then they pass processed elements on to the output - loops. Post plugins can not only be chained to process the predecessor's - output and advance the data to their successor, they can form arbitrary trees, - since post plugins can have any number of inputs and outputs. Additionally, - the interconnection of the plugins currently inserted in such a tree can - be changed on the fly during playback. The public function - xine_post_wire() is used by frontends to form such - connections. - - - Due to the variety of possible applications, the interface post plugins have - to implement is just the basic foundation. The complexity comes from hooking - your post plugin into the engine data paths for video frames and audio buffers, - intercepting the data and performing your operation on them. This is done by - taking the interface of a video or audio port, replacing some of the functions - with your own ones and passing the interface to the decoder or predecessor - post plugin that is going to feed you with data by accessing this interface - and by doing that, calling the functions you provide. From there you can do - almost anything you want. Constructing video frames from audio buffers to - visualize sound is possible as well as just outputting an integer giving the - average brightness of an image. It is also possible to invent post plugins - with no output (not very useful, unless the plugin has some side-effect) or - no input at all; for the latter you have to create your own pthread, otherwise - your plugin will not do anything. An audio signal generator could be - implemented like this. The various data types, post plugins can - accept as input or offer as output are defined in xine.h - as XINE_POST_DATA_* defines. - - - Some terminology used in the following explanations: - - - - down direction: - The direction from the decoders to the output. This is the way video or audio - data (actual content and meta information) usually travels through the engine. - - - - - up direction: - The direction from the output to the decoders. This is the way some video or audio - metadata like metronom timestamps travel through the engine. - - - - - interception: - Post plugins are inserted into the engine data paths by the means of the decorator - design pattern. This works by taking engine structures with member funtions like - video or audio ports, video frames or overlay managers and inserting your own functions - into a copy of this structure. This is called interception. This modified structure - is then passed up to the plugin that uses it and thus calls your replaced functions. - - - - - - - Writing a xine post plugin - - The post plugin API is declared in src/xine-engine/post.h - The plugin info of post plugins contains the post plugin type, which is one of the - XINE_POST_TYPE_* defines and the init_class function of the plugin. - - -    post_plugin_t *open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target); - Returns an instance of the plugin. Some post plugins evaluate inputs - to open a variable number of inputs. Since almost all post plugins have audio or video - outputs, you can hand in a NULL-terminated array of ports to connect to these outputs. - In this function you can also intercept these ports so that your plugin is actually used. - There is a helper function to initialize a post_plugin_t, which you are - encouraged to use: _x_post_init(). - - -    char *get_identifier(post_class_t *class_gen); - This function returns a short identifier describing the plugin. - - -    char *get_description(post_class_t *class_gen); - This function returns a plaintext, one-line string describing the plugin. - - -    void dispose(post_class_t *class_gen); - This function frees the memory used by the video out plugin class object. - - - The post_plugin_t structure contains the publicly visible - part of the post plugin with the audio and video inputs and the type of - the post plugin. Not publicly visible are the lists of all inputs and outputs, - the dispose() function and some internal stuff which - plugins do not have to worry about. - - -    void dispose(post_plugin_t *this_gen); - This function frees the memory used by the plugin instance, but not necessarily - immediately. Since post plugins enter their own functions into engine structures, - they might still be needed when dispose() is being called. - They maintain a usage counter to detect that. To check for such a condition, you - should use the _x_post_dispose() helper function like that: - -   if (_x_post_dispose(this)) -     really_free(this); - _x_post_dispose() frees any ressources allocated by any of the - post plugin helper functions and returns boolean true, if the plugin is not needed - any more. - - - - Interception - - Currently, we have four engine structures which can be intercepted by post plugins: - video ports, video frames, overlay managers and audio ports. You could do this - interception manually, but since this is quite a complex process, there are helper - functions to assist you and their usage is encouraged. - - - Intercepting a video port - - -   post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, -     xine_video_port_t *port, post_in_t **input, post_out_t **output); - This function will intercept port and returns a structure - for you to pass up. All functions in the port will be replaced with dummy - pass through functions that do nothing but relaying the call down to the original - port. If you want (that is, input or output are - not NULL), this function will also create the input and output descriptors complete - with rewiring functions and add them to the relevant lists. - This is required, if you want this port to be advertised by the plugin to the outside world. - - - post_video_port_t makes a variety of interception schemes very easy. - If you want to replace any of the default functions with your own, just enter it - into new_port. You can use original_port - from within your function to propagate calls down to the original port. - The constraint is that your functions have to ensure that every original - port held open scores one usage counter point, so that opened ports are always - closed before the plugin is disposed. Therefore, you should use the macro - _x_post_inc_usage() before calling - original_port->open() and use the macro - _x_post_dec_usage() after calling - original_port->close(). Note that _x_post_dec_usage() - might dispose the plugin, when dispose() has been called - earlier and usage count drops to zero, so do never touch plugin structures after - _x_post_dec_usage(). In addition, you must never call a port - function of the original port when the port is not open. - - - Intercepting video frames or the overlay manager of the port is even easier. - You do not have to reimplement get_frame() or - get_overlay_manager(). Just enter a intercept_frame - or intercept_ovl function which returns boolean true, if - you want to intercept. The functions to insert in the intercepted frame or overlay - manager are taken from new_frame and new_manager - respectively. Note that the defaults are reversed: If you do not enter such a - decision function for either one, all frames and no overlay manager will be intercepted. - - - For convenience post_video_port_t also contains pointers to the - current stream and to the current post plugin and a user_data pointer, where you - can put in anything you need in addition. If your port is used by more than one - thread, you can also enforce locking on the port, frame or overlay manager level - by entering a lock into port_lock, frame_lock or - manager_lock respectively. - - - - Intercepting an audio port - - Audio port interception is just a stripped down version of video port interception. - Everything related to frames and overlay manager is not needed and audio buffers - do not need to be intercepted, since they have no member functions. Everything else - of the above still applies. - - - - Intercepting overlay manager - -    void _x_post_intercept_overlay_manager(video_overlay_manager_t *original, post_video_port_t *port); - Interception of the overlay manager is done automatically when your - intercept_ovl() decision function returns boolean true. - Should you ever decide not to use that, interception can be done with this helper - function, which simply creates an intercepted overlay manager with dummy - pass through functions in port->new_manager and stores the original - manager in port->original_manager. - - - No matter how you intercepted the overlay manager, your own replacement - functions will receive port->new_manager as the overlay manager - argument. But you most likely want to have access to the post_video_port_t - from within your functions. For that, there exists a pointer retrieval function: -    post_video_port_t *_x_post_ovl_manager_to_port(video_overlay_manager_t *manager); - - - - Intercepting a video frame - - -   vo_frame_t *_x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *port); -   vo_frame_t *_x_post_restore_video_frame(vo_frame_t *frame, post_video_port_t *port); - Interception of video frames is done automatically when your - intercept_frame() decision function returns boolean true or - when there is no such function in post_video_port_t. - Should you ever decide not to use that, interception can be done with the helper - function _x_post_intercept_video_frame(). - - - Since the same video frame can be in use in the decoder and in the output and in - any post plugin in between at the same time, simply modifying the frame - structure does not work, because every user of the frame needs to see his version - and the frame must always travel along the same path through the plugins for its - entire lifetime. To ensure that, _x_post_intercept_video_frame() - provides a shallow copy of the frame structure with the original frame attached to - copy->next. This copy will be filled with your own - frame functions from port->new_frame and with dummy pass - through functions for those you did not provide. This way, every part of xine - using this frame will see its own frame structure with a list of frame - contexts from down the data path attached to frame->next. - _x_post_restore_video_frame() reverses this and should be - used when the frame is freed or disposed. - - - Your own replacement functions will receive the copied frame as as argument. - But you most likely want to have access to the post_video_port_t - from within your functions. For that, there exists a pointer retrieval function: -    post_video_port_t *_x_post_video_frame_to_port(vo_frame_t *frame); - The constraint is that your functions have to ensure that every intercepted - frame scores one usage counter point, so that these frames are always - freed or disposed before the plugin is disposed. Therefore, you should use the macro - _x_post_inc_usage() before calling - _x_post_intercept_video_frame() and use the macro - _x_post_dec_usage() after calling - _x_post_restore_video_frame(). Note that _x_post_dec_usage() - might dispose the plugin, when dispose() has been called - earlier and usage count drops to zero, so do never touch plugin structures after - _x_post_dec_usage(). - - - From within your own frame functions, you can propagate calls to the original - frame by calling a function on frame->next. Since - modifications to the frame can travel both upwards and downwards (decoders and - output can modify the frame), changes need to be copied between the frame - structure contexts. You should use the _x_post_frame_copy_down() - and _x_post_frame_copy_up() helper functions like that: - -   _x_post_frame_copy_down(frame, frame->next); -   frame->next->draw(frame->next, stream); -   _x_post_frame_copy_up(frame, frame->next); - - - If your post plugin modifies the content of the frame, you have to modify - a deep copy of the frame, because the decoder might still use the frame as - a reference frame for future decoding. The usual procedure is: - -   modified_frame = port->original_port->get_frame(port->original_port, ...); -   _x_post_frame_copy_down(frame, modified_frame); -   copy_and_modify(frame, modified_frame); -   skip = modified_frame->draw(modified_frame, stream); -   _x_post_frame_copy_up(frame, modified_frame); -   modified_frame->free(modified_frame); - - - When the output receives a frame via draw(), - it usually receives the stream where the frame - originates as well and modifies the state of this stream by passing - the frame through the stream's metronom. Sometimes this is unwanted. - For example, when you pass the same frame to the output more than once, it - will confuse metronom. To solve this, you can call - frame->next->draw() with NULL as the stream. - You might also want to prevent frames from being passed down to the output - completely, because your post plugin creates something else from these frames, - but does not need them to be drawn. In both these situations, you have - to call the helper function _x_post_frame_u_turn() - when the frame is drawn, because this does some housekeeping which the - decoder might expect to take place. - - - The following diagram summarizes the situations of a video frame passing - through a post plugin: - - - - - - - - - - video frame passing through a post plugin - - - - - Summary of constraints - - - - Call _x_post_inc_usage() before port open() - before any other port function. - - - - - Call _x_post_inc_usage() before issueing an intercepted frame. - - - - - Call _x_post_dec_usage() after port close() - and do not call any port functions after that. - - - - - Call _x_post_dec_usage() after restoring a frame. - - - - - When a frame is drawn by your plugin, it must either be drawn on the original - port with the correct stream as argument or U-turned (or passed through a - private metronom manually). - - - - - If your post plugin keeps locked frames, release them when your input port is being - closed. - - - - - Do not assume your plugin is alive after _x_post_dec_usage(). - - - - - - - Rewiring and the ticket system - - Rewiring is the reconnection of one post plugin's outputs and another post plugin's - inputs. This can happen on the fly during playback, which makes this a very delicate - process. In one such input to output connection, only the output is active by either - writing data directly to the connected input or by calling functions there. Therefore - we have to notify only the output, when it is rewired. This is done by calling the - rewire() member function of the corresponding - xine_post_out_t when the frontend issues a rewiring on this output. - This is done from the frontend thread for the rewire operation to return synchroneously. - But since this can happen on the fly, we have to assure that no other thread is relying - on the connection while we modify it. For this, threads working within post plugins - have to be accounted and on demand suspended in safe positions. For this, xine offers - a synchronization facility called "tickets". - - - Ticket system principles and operations - - The idea of the ticket system is based on an extended read-write lock, where there can - be many readers in parallel, but only one exclusive writer. A certain interface might - require you to have a ticket before calling its functions. The ticket system now - allows multiple threads to operate within the component behind the interface by - granting as many tickets as needed. But should an outside operation require exclusive - access to the component, all granted tickets can be revoked and have to be given back - by the threads who hold them, which suspends the threads. After the exclusive - operation, tickets will be reissued so all suspended threads can continue where they - stopped. We will now look at the ticket primitives in detail: - - - - acquire() - - - You receive a new ticket. If the ticket is currently revoked, you can be blocked - until it is reissued. There is one exception to this: You can acquire a revoked - ticket, if you revoked it atomic yourself. You can also acquire a ticket irrevocably. - Between acquire and release of an irrevocable ticket, it is guaranteed that - you will not be blocked by ticket revocation. - - - - - release() - - - You give a ticket back when you do not need it any longer. If the ticket is - currently revoked, you can be blocked until it is reissued. If you acquired the - ticket irrevocably, you have to release it irrevocably as well. - - - - - renew() - - - You must only call this function, when the ticket has been revoked, so be - sure to check ticket_revoked before. You give the ticket - back and receive a new one. In between, you can be blocked until the ticket is - reissued. You have to renew irrevocably, if you cannot assure that the thread holds - no irrevocable tickets. If you can assure this, renew revocably. - - - - - revoke() - - - This function can only be called by the xine engine, plugins do not have access to it. - It revokes all tickets and after finite time, all threads will run into a - acquire(), release() or renew() - and will be suspended there. Then the revocation returns and you can modify structures - or call functions with the knowledge that all ticket holders will remain in safe - positions. When you additionally need exclusive access where no other revoker - can interfere, you have to revoke atomic. - - - - - issue() - - - This function can only be called by the xine engine, plugins do not have access to it. - It ends ticket revocation and hands out new tickets to all threads that applied with a - acquire() or renew(). If you revoked the - tickets atomic, you have to issue them atomic. - - - - - - When you use the ticket system in any way, you have to obey to the following rules: - - - - Assure to release irrevocable tickets ater a finite time. - - - - - Assure to release or renew revocable tickets ater a finite time. - - - - - Assure to reissue tickets you revoked atomic after a finite time. - - - - - Pair calls properly. - - - - - Never revoke a ticket you hold. - - - - - Never acquire a ticket you revoked atomic before. - - - - - Never acquire a ticket revocable more than once. - - - - - - - Ticket handling in decoder and post plugins - - The contract of the video and audio port interfaces is that you need to have - the port ticket, when you want to call functions of these interfaces. The decoder - plugins do not have to worry about this at all, since the decoder loops inside the - engine handle the ticketing. Post plugins get the ticket assigned by the engine, - but usually, a post plugin does not create a new thread, it is called by the - decoder thread and therefore already owns the necessary ticket. All port functions - are also ticket-safe as they follow all the rules given above. - - - You only have to remember that tickets need to be renewed as soon as possible, - when the are revoked. For this, the helper function - _x_post_rewire() should be used in prominent locations - where it is safe to be suspended. Candidates for such locations are at the - beginning of the port's open() and - get_frame()/get_buffer() functions. - The default pass through implementations for intercepted ports already do this. - - - The port tickets are revoked, whenever a rewiring takes place or the engine - switches into pause mode. The tickets are reissued, when the rewiring is finished - or the engine switches from pause mode into playback. Some post plugins might - contain critical parts, where they must not be interrupted by a rewire or pause. - These sections can be enclosed in _x_post_lock() and - _x_post_unlock(), which will simply acquire and release an - irrevocable ticket for you. As long as you hold such a ticket, it is guaranteed - that you will never be interrupted by a pause or rewire. - - - - - - - Video output - - In order to allow for device-dependant acceleration features, xine - calls upon the video output plugin for more than just displaying - images. The tasks performed by the video plugins are: - - - - Allocation of vo_frame_t structures and their - subsequent destruction. - - - - - Allocation of memory for use by one frame (this is to allow - for the ability of some video output plugins to map frames directly - into video-card memory hence removing the need for the frame to - be copied across the PCI/AGP bus at display time). - - - - - Most important, the ability to render/copy a given - frame to the output device. - - - - - Optionally the copying of the frame from a file dependant - colour-space and depth into the frame structure. This is to allow for - on-the fly colour-space conversion and scaling if required (e.g. the XShm - ouput plugin uses this mechanism). - - - - - - Although these extra responsibilities add great complexity to your - plugin it should be noted that they allow plugins to take full advantage - of any special hardware-acceleration without sacrificing flexibility. - - - Writing a xine video out plugin - - The video out plugin API is declared in src/xine-engine/video_out.h - The plugin info of video out plugins contains the visual type, priority, - and the init_class function of the plugin. - - - The visual_type field is used by xine to - determine if the GUI used by the client is supported by the plugin - (e.g. X11 output plugins require the GUI to be running under the - X Windowing system) and also to determine the type of information passed to the - open_plugin() function as its visual parameter. - - -    char *get_description(video_driver_class_t *this_gen); - This function returns a plaintext, one-line string describing the plugin. - - -    char *get_identifier(video_driver_class_t *this_gen); - This function returns a shorter identifier describing the plugin. - - -    void dispose(video_driver_class_t *this_gen); - This function frees the memory used by the video out plugin class object. - - -    vo_driver_t *get_instance(video_driver_class_t *class_gen, const void *visual); - Returns an instance of the plugin. - The visual is a pointer to a visual-dependant - structure/variable. For example, if you had previously claimed your - plugin was of the VISUAL_TYPE_X11 type, this would be a pointer - to a x11_visual_t, which amongst other things hold the - Display variable associated with the - X-server xine should display to. See plugin source-code for other - VISUAL_TYPE_* constants and associated structures. Note that this - field is provided by the client application and so if you wish to add another visual - type you will either need to extend an existing client or write a new - one. - - -    uint32_t get_capabilities(vo_driver_t *this_gen); - Returns a bit mask describing the output plugin's capabilities. - You may logically OR the VO_CAP_* constants together to get - a suitable bit-mask (via the '|' operator). - - - -   int get_property(vo_driver_t *self, int property); -   int set_property(vo_driver_t *self, int property, int value); -   void get_property_min_max(vo_driver_t *self, int property, int *min, int *max); - Handle the getting, setting of properties and define their bounds. - Valid property IDs can be found in the video_out.h - header file. - - -    int gui_data_exchange(vo_driver_t *self, int data_type, void *data); - Accepts various forms of data from the UI (e.g. the mouse has moved or the - window has been hidden). Look at existing plugins for examples of data - exchanges from various UIs. - - -    vo_frame_t *alloc_frame(vo_driver_t *self); - Returns a pointer to a xine video frame. - Typically the video plugin will add private fields to the end of the - vo_frame_t structure which are used for internal purposes by the plugin. - - - The function pointers within the frame structure provide a mechanism for the - driver to retain full control of how the frames are managed and rendered to. If - the VO_CAP_COPIES_IMAGE flag was set in the plugins capabilities then the - copy field is required and will be called sequentially for each 16-pixel high - strip in the image. The plugin may then decide, based on the frame's format, how - this is copied into the frame. - - -    void update_frame_format(vo_driver_t *self, vo_frame_t *img, uint32_t width, uint32_t height, double ratio, int format, int flags); - This function will be called each time the colour-depth/space or size of a frame changes. - Typically this function would allocate sufficient memory for the frame, assign the pointers - to the individual planes of the frame to the base field of the - frame and perform any driver-specific changes. - - -    void display_frame(vo_driver_t *self, vo_frame_t *vo_img); - Renders a given frame to the output device. - - - -   void overlay_begin(vo_driver_t *self, vo_frame_t *vo_img, int changed); -   void overlay_blend(vo_driver_t *self, vo_frame_t *vo_img, vo_overlay_t *overlay); -   void overlay_end(vo_driver_t *self, vo_frame_t *vo_img); - These are used to blend overlays on frames. overlay_begin() is called, - when the overlay appears for the first time, overlay_blend() is then - called for every subsequent frame and overlay_end() is called, when - the overlay should disappear again. - - -    int redraw_needed(vo_driver_t *self); - Queries the driver, if the current frame needs to be drawn again. - - -    void dispose(vo_driver_t *self); - Releases all resources and frees the plugin. - - - - - diff --git a/doc/hackersguide/overview.docbook b/doc/hackersguide/overview.docbook new file mode 100644 index 000000000..d405ac18c --- /dev/null +++ b/doc/hackersguide/overview.docbook @@ -0,0 +1,811 @@ + + xine code overview + + + Walking the source tree + + The src/ directory in xine-lib contains several + modules, this should give you a quick overview on where + to find what sources. + + + Directories marked with "(imported)" contain + code that is copied from an external project into xine-lib. + Everything below such a directory is up to this project. When modifying + code there, be sure to send the patches on. If some xine specific + adaptation of the code is absolutely necessary, a patch containing + the changes should be stored in Mercurial to not lose the changes the + next time we sync with the external project. + + + + + audio_out + + + Audio output plugins. These provide a thin abstraction layer + around different types of audio output architectures or platforms. + Basically an audio output plugin provides functions to query and setup + the audio hardware and output audio data (e.g. PCM samples). + + + + + + demuxers + + + Demuxer plugins that handle various system layer file formats + like avi, asf or mpeg. The ideal demuxer know nothing about where the + data comes from and who decodes it. It should basically just unpack + it into chunks the rest of the engine can eat. + + + + + + dxr3 + + + Code to support the DXR3 / hollywood+ hardware mpeg decoder. + + + + + + input + + + Input plugins encapsulate the origin of the data. Data sources like + ordinary files, DVDs, CDA or streaming media are handled here. + + + + + dvb + + + Some headers for Digital Video Broadcast. + + + + + + libdvdnav (imported) + + + The libdvdnav library for DVD navigation is used + by xine's DVD input plugin. + + + + + + libreal, librtsp + + + Support for RealMedia streaming as used by the RTSP input plugin. + + + + + + vcd + + + The enhanced VCD input plugin which also handles VCD navigation. + + + + + libcdio, libvcd (imported) + + + Libraries used by the enhanced VCD plugin. + + + + + + + + + + + + + + + + liba52 (imported) + + + A52 (aka AC3, aka Dolby Digital) audio decoder library and xine plugin. + + + We maintain some small integration improving differences between the + original liba52 and our copy in the file + diff_against_release.patch. + + + + + + libdts (imported) + + + AC5 (aka DTS) audio decoder library and xine plugin, which is capable + of software decoding as well as digital passthrough. + + + + + + libfaad (imported) + + + The Free AAC Decoder library and xine plugin. + + + + + + libffmpeg + + + A xine decoder plugin using various audio and video decoders from the + ffmpeg decoder pack libavcodec. Their MPEG encoder is also for the DXR3. + + + To optimize the integration of libavcodec and the xine engine, we maintain + some differences between the original ffmpeg and our copy in the file + diff_to_ffmpeg_cvs.txt. + + + + + libavcodec (imported) + + + The libavcodec decoder pack as used by xine's ffmpeg plugin. + + + + + + + + + + + libflac + + + A xine demuxer and decoder plugin for the Free Lossless Audio Codec library, + which has to be installed separately. + + + + + + liblpcm + + + Audio decoder plugin that "decodes" raw PCM data; most notably + endianess-conversions are done here. + + + + + + libmad (imported) + + + Mpeg audio decoder plugin (i.e. mp2 and mp3 decoding). + ISO/IEC compliant decoder using fixed point math. + + + + + + libmpeg2 (imported) + + + Most important MPEG video decoder plugin, provides fast and + high-precision MPEG-1/2 video decoding. + + + Although this is an imported library, we have heavily modified + our internal copy to blend it as seamlessly as possible into + the xine engine in order to get the maximum MPEG decoding + performance. + + + + + + libmpeg2new + + + James started an effort to bring a recent and unmodified version + of libmpeg2 into xine to one day replace our current internal + modified libmpeg2 with one closer to the original. But since + the full feature catalog has not yet been achieved with the new + one, it is still disabled. + + + + + include, libmpeg2 (imported) + + + The code of the imported new libmpeg2. + + + + + + + + + + + libreal + + + A thin wrapper around Real's binary codecs from the Linux RealPlayer to + use them as a xine plugin. + + + + + + libspeex + + + A xine decoder plugin for the speex library, + which has to be installed separately. + + + + + + libspucc + + + Closed caption subtitle decoder plugin. + + + + + + libspudec + + + DVD SPU subtitle decoder plugin. + + + + + + libsputext + + + Plain text subtitle decoder plugins. + + + + + + libtheora + + + A xine decoder plugin for the theora library, + which has to be installed separately. + + + + + + libvorbis + + + A xine decoder plugin for the ogg/vorbis library, + which has to be installed separately. + + + + + + libw32dll + + + Video and audio decoder plugins that exploit some wine code + to use win32 (media player and Quicktime) codecs in xine. + Works on x86 platforms only. + + + + + + DirectShow, dmo, + qtx, wine (imported) + + + + Stripped down version of wine to support Video for Windows DLLs + and additional code to use DirectShow, DMO and QuickTime DLLs. + + + + + + + + + + + libxineadec + + + xine's decoder pack of additional audio decoders. + + + + + gsm610 (imported) + + + The gsm610 audio decoder library as used by the related xine plugin. + + + + + + nosefart (imported) + + + The nosefart audio decoder library as used by the related xine plugin. + + + + + + + + + + + libxinevdec + + + xine's decoder pack of additional video decoders. + + + + + + post + + + Video and audio post effect plugins live here. Post plugins + modify streams of video frames or audio buffers as they leave + the decoder to provide conversion or effects. + + + + + audio + + + Some audio effects as xine audio filter posts. + + + + + + deinterlace (imported) + + + The tvtime deinterlacer as a xine video filter post. + + + + + + goom (imported) + + + The goom audio visualizer as a xine visualizer post. + + + + + + mosaico + + + Some post plugins merging multiple frames into one. For example + picture in picture can be done with this. + + + + + + planar + + + Some simple 2D video effects as xine video filter posts. + + + + + + visualizations + + + Audio visualization post plugins. + + + + + + + + + + + video_out + + + Contains various video output driver plugins. Video output drivers + are thin abstraction layers over various video output platforms + (e.g. X11, directfb, directX,...). Video output driver plugins + provide functions like frame allocation and drawing and handle + stuff like hardware acceleration, scaling and colorspace conversion + if necessary. They do not handle a/v sync since this is done + in the xine-engine already. + + + + + libdha (imported) + + + A library for direct hardware access to the graphics card + as used by the vidix video out plugin. + + + + + + vidix (imported) + + + The vidix system for high performance video output + as used by the vidix video out plugin. + + + + + + + + + + + xine-engine + + + The heart of xine - it's engine. Contains code to + load and handle all the plugins, the configuration repository + as well as the generic decoding loops and code for synchronized output. + A lot of helper functions for plugins to use live here as well. + What's in the individual files should be guessable by the files' + names. This document is not going to explain the source, because + it simply changes too often. A look at the architectural drawing + in the internals section should + give you a pretty good idea, what to expect in this directory. + Basically, everything in this picture that is not called "plugin" + lives here. + + + + + + xine-utils + + + Collection of utility functions and platform abstractions. + Also contains a simple XML parser for frontend playlist handling. + + + + + + + + + + Object oriented programming in C + + xine uses a lot of design principles normally found in + object oriented designs. As xine is written in C, a few + basic principles shall be explained here on how xine + is object oriented anyway. + + + Classes are structs containing function pointers and public member data. + Example: + +   typedef struct my_stack_s my_class_t; +    +   struct my_stack_s { +    /* method "push" with one parameter and no return value */ +    void (*push)(my_stack_t *this, int i); +    +    /* method "add" with no parameters and no return value */ +    void (*add)(my_stack_t *this); +    +    /* method "pop" with no parameters (except "this") and a return value */ +    int (*pop) (my_stack_t *this); +   }; +    +   /* constructor */ +   my_class_t *new_my_stack(void); + + + To derive from such a class, private member variables can be added: + +   typedef struct { +    my_stack_t stack; /* public part */ +    +    /* private part follows here */ +    int values[MAX_STACK_SIZE]; +    int stack_size; +   } intstack_t; + Each method is implemented as a static method (static to prevent + namespace pollution). The "this" pointer needs to be cast to the + private pointer type to gain access to the private member variables. + + + Implementation of the "push" method follows: + +   static void push (my_stack_t *this_gen, int i) { +    intstack_t *this = (intstack_t *)this_gen; +    this->values[MAX_STACK_SIZE - ++this->stack_size] = i; +   } + + + The part added to the derived class is private, because when + defining the new structure directly in the .c file, where it will + be used, outside modules have no way of seeing the definition + of the derived class. A public derivation is possible by defining + the above structure in a .h file for others to include. + + + Something similar to a protected, package or friend visibility is also + possible: + +   struct my_stack_s { +    void (*push)(my_stack_t *this, int i); +    void (*add)(my_stack_t *this); +    int (*pop)(my_stack_t *this); +    +   #ifdef STACK_INTERNAL +    void (*flush)(my_stack_t *this); +   #endif +   }; + All modules, who need to access the internal part have to add +    #define STACK_INTERNAL + before including the header with the definition. It is clear that only + those friend modules can derive from this class. + + + Finally the contructor malloc()s the data struct (private variant) + and fills in function pointers and default values. Usually the + constructor is the only public (i.e. non-static) function in the module: + +   my_stack_t *new_my_stack(void) { +    intstack_t *this; +    +    /* alloc memory */ +    this = malloc(sizeof(intstack_t)); +    +    /* fill in methods */ +    this->push = push; +    this->add = add; +    this->pop = pop; +    +    /* init data fields */ +    this->stack_size = 0; +    +    /* return public part */ +    return &this->stack; +   } + + + Why not using C++? + + After all these considerations about object oriented C, you might + ask, why we do not use C++ after all? The easy answer would be: xine wants + to be as fast as possible and C++ is simply too slow. But this is only the + easy answer and it is not entirely true any more. Thoughtfully applied, you + can write very fast C++ code with today's compilers, but these compilers might + not be available on all platforms in the necessary quality. Even with + a sophisticated compiler, C++ is much harder to optimize than plain C and thus + C compiles much faster. Another big problem is that the C++ ABI is not as + well-defined as the C ABI. With C, you can easily mix libraries and + applications built by different compilers. With C++, this is unlikely to work. + But the final argument is that xine does not really need C++. xine's + inheritance hierarchy is very flat, mostly one level only and does not need + things like multiple or virtual inheritance. Most of the external projects + that are used by xine are plain C as well and using more than one language + complicates the build system. As we saw above, we can emulate + object orientation reduced to our real needs in plain C. + + + + + + Coding style and guidelines + + This section contains some guidelines for writing xine-code. + These are really just guidelines, no strict rules. + Contributions will not be rejected if they do not meet these + rules but they will be even more appreciated if they do. + + + + Comment your interfaces directly in the header files. + No doxygen comments, ordinary C comments will do. + + + + + Use C-style comments (/* */), not C++-style (//). + + + + + When in doubt, use lower case. BTW: This thing is called xine, never Xine. + + + + + Use expressive variable and function identifiers on all public interfaces. + Use underscores to seperate words in identifiers, not uppercase + letters (my_function_name is ok, myFunctionName is not ok). + + + + + Avoid macros unless they are really useful. Avoid gotos. + + + + + use something like +    printf("module: ..."[,...]); + for console output. All console output goes to stdout and + must be prefixed by the module name which generates the + output (see example above). + + + + + Refer to emac's C-mode for all questions of proper indentiation. + That first of all means: indent with two spaces. + + + + + + + + The xine logging system + + xine offers a wide range of possibilities to display + strings. This section should describe when to use + which way and how to do it right. + + + xine_log + + Output which is done thru this function will be + displayed for the end user by the frontend. + If xine->verbosity is not 0 the messages will also + be displayed on the console. Ideally these strings + are translated. + This function is for information which the user should + read always. +    xine_log(xine_t *xine, int buf, const char *format, ...); + buf is either XINE_LOG_MSG for general messages or + XINE_LOG_PLUGIN for messages about plugins. + + + + xprintf + + This macro uses the xine->verbosity value to decide + if the string should be printed to the console. Possible + values are XINE_VERBOSITY_NONE, XINE_VERBOSITY_LOG or + XINE_VERBOSITY_DEBUG. By default nothing is printed. + When you use xine-ui you can enable this output with + the --verbose=[1,2] options. + This function should be used for information which the + user should only read up on request. +    xprintf(xine_t *xine, int verbosity, const char *format, ...); + + + + lprintf/llprintf + + These macros are for debugging purpose only. Under normal + circumstances it is disabled. And can only be enabled by changing + a define statement and a recompilation. It has to be enabled for these + files that are of interest. + It should only be used for information which is intended for developers. + +   lprintf(const char *format, ...); +   llprintf(bool, const char *format, ...); + bool is a flag which enables or disables this logging. + + + lprintf can be enabled by defining LOG at the top of the source file. + llprintf can be used for more than one categorie + per file by using diffent lables: + +   #define LOG_LOAD 1 +   #define LOG_SAVE 0 +    +   llprintf(LOG_LOAD, "loading was successful\n"); +   llprintf(LOG_SAVE, "could not save to file %s\n", filename); + + + In this case only the first messages is printed. To enable/disable change the defines. + + + LOG_MODULE should be used to set the modulename for xprintf/lprintf/llprintf. + Each output line will start with "modulename: ". +    #define LOG_MODULE "modulename" + + + LOG_VERBOSE can be defined to enable the logging of functionname and linenumbers. + Then the output will be: "modulename: (function_name:42) message". + + + + _x_assert/_x_abort + + These are not purely logging functions, but despite their original C library versions, + they always output debugging text, which is why usage of these functions is preferred. + + + _x_assert() checks a condition and prints a note, + when the condition is false. In addition, a debug build and only a debug build will + terminate the application, when the condition is false. Release versions will only + print the note, but try to continue. + + + _x_abort() always terminates the application after printing a note. + + + + + + How to contribute + + Make sure you send your patches in unified diff format to + the xine-devel mailing list. You'll have to subscribe first, + otherwise you're not allowed to post. Please do not send + patches to individual developers unless instructed otherwise + because your patch is more likely to get lost in an overfull + INBOX in that case. Please be patient, it may take 1-2 weeks + before you hear any comments on your work (developers may be + working on other parts of the code or are simply busy at + the moment). + + + + diff --git a/doc/hackersguide/overview.sgml b/doc/hackersguide/overview.sgml deleted file mode 100644 index d405ac18c..000000000 --- a/doc/hackersguide/overview.sgml +++ /dev/null @@ -1,811 +0,0 @@ - - xine code overview - - - Walking the source tree - - The src/ directory in xine-lib contains several - modules, this should give you a quick overview on where - to find what sources. - - - Directories marked with "(imported)" contain - code that is copied from an external project into xine-lib. - Everything below such a directory is up to this project. When modifying - code there, be sure to send the patches on. If some xine specific - adaptation of the code is absolutely necessary, a patch containing - the changes should be stored in Mercurial to not lose the changes the - next time we sync with the external project. - - - - - audio_out - - - Audio output plugins. These provide a thin abstraction layer - around different types of audio output architectures or platforms. - Basically an audio output plugin provides functions to query and setup - the audio hardware and output audio data (e.g. PCM samples). - - - - - - demuxers - - - Demuxer plugins that handle various system layer file formats - like avi, asf or mpeg. The ideal demuxer know nothing about where the - data comes from and who decodes it. It should basically just unpack - it into chunks the rest of the engine can eat. - - - - - - dxr3 - - - Code to support the DXR3 / hollywood+ hardware mpeg decoder. - - - - - - input - - - Input plugins encapsulate the origin of the data. Data sources like - ordinary files, DVDs, CDA or streaming media are handled here. - - - - - dvb - - - Some headers for Digital Video Broadcast. - - - - - - libdvdnav (imported) - - - The libdvdnav library for DVD navigation is used - by xine's DVD input plugin. - - - - - - libreal, librtsp - - - Support for RealMedia streaming as used by the RTSP input plugin. - - - - - - vcd - - - The enhanced VCD input plugin which also handles VCD navigation. - - - - - libcdio, libvcd (imported) - - - Libraries used by the enhanced VCD plugin. - - - - - - - - - - - - - - - - liba52 (imported) - - - A52 (aka AC3, aka Dolby Digital) audio decoder library and xine plugin. - - - We maintain some small integration improving differences between the - original liba52 and our copy in the file - diff_against_release.patch. - - - - - - libdts (imported) - - - AC5 (aka DTS) audio decoder library and xine plugin, which is capable - of software decoding as well as digital passthrough. - - - - - - libfaad (imported) - - - The Free AAC Decoder library and xine plugin. - - - - - - libffmpeg - - - A xine decoder plugin using various audio and video decoders from the - ffmpeg decoder pack libavcodec. Their MPEG encoder is also for the DXR3. - - - To optimize the integration of libavcodec and the xine engine, we maintain - some differences between the original ffmpeg and our copy in the file - diff_to_ffmpeg_cvs.txt. - - - - - libavcodec (imported) - - - The libavcodec decoder pack as used by xine's ffmpeg plugin. - - - - - - - - - - - libflac - - - A xine demuxer and decoder plugin for the Free Lossless Audio Codec library, - which has to be installed separately. - - - - - - liblpcm - - - Audio decoder plugin that "decodes" raw PCM data; most notably - endianess-conversions are done here. - - - - - - libmad (imported) - - - Mpeg audio decoder plugin (i.e. mp2 and mp3 decoding). - ISO/IEC compliant decoder using fixed point math. - - - - - - libmpeg2 (imported) - - - Most important MPEG video decoder plugin, provides fast and - high-precision MPEG-1/2 video decoding. - - - Although this is an imported library, we have heavily modified - our internal copy to blend it as seamlessly as possible into - the xine engine in order to get the maximum MPEG decoding - performance. - - - - - - libmpeg2new - - - James started an effort to bring a recent and unmodified version - of libmpeg2 into xine to one day replace our current internal - modified libmpeg2 with one closer to the original. But since - the full feature catalog has not yet been achieved with the new - one, it is still disabled. - - - - - include, libmpeg2 (imported) - - - The code of the imported new libmpeg2. - - - - - - - - - - - libreal - - - A thin wrapper around Real's binary codecs from the Linux RealPlayer to - use them as a xine plugin. - - - - - - libspeex - - - A xine decoder plugin for the speex library, - which has to be installed separately. - - - - - - libspucc - - - Closed caption subtitle decoder plugin. - - - - - - libspudec - - - DVD SPU subtitle decoder plugin. - - - - - - libsputext - - - Plain text subtitle decoder plugins. - - - - - - libtheora - - - A xine decoder plugin for the theora library, - which has to be installed separately. - - - - - - libvorbis - - - A xine decoder plugin for the ogg/vorbis library, - which has to be installed separately. - - - - - - libw32dll - - - Video and audio decoder plugins that exploit some wine code - to use win32 (media player and Quicktime) codecs in xine. - Works on x86 platforms only. - - - - - - DirectShow, dmo, - qtx, wine (imported) - - - - Stripped down version of wine to support Video for Windows DLLs - and additional code to use DirectShow, DMO and QuickTime DLLs. - - - - - - - - - - - libxineadec - - - xine's decoder pack of additional audio decoders. - - - - - gsm610 (imported) - - - The gsm610 audio decoder library as used by the related xine plugin. - - - - - - nosefart (imported) - - - The nosefart audio decoder library as used by the related xine plugin. - - - - - - - - - - - libxinevdec - - - xine's decoder pack of additional video decoders. - - - - - - post - - - Video and audio post effect plugins live here. Post plugins - modify streams of video frames or audio buffers as they leave - the decoder to provide conversion or effects. - - - - - audio - - - Some audio effects as xine audio filter posts. - - - - - - deinterlace (imported) - - - The tvtime deinterlacer as a xine video filter post. - - - - - - goom (imported) - - - The goom audio visualizer as a xine visualizer post. - - - - - - mosaico - - - Some post plugins merging multiple frames into one. For example - picture in picture can be done with this. - - - - - - planar - - - Some simple 2D video effects as xine video filter posts. - - - - - - visualizations - - - Audio visualization post plugins. - - - - - - - - - - - video_out - - - Contains various video output driver plugins. Video output drivers - are thin abstraction layers over various video output platforms - (e.g. X11, directfb, directX,...). Video output driver plugins - provide functions like frame allocation and drawing and handle - stuff like hardware acceleration, scaling and colorspace conversion - if necessary. They do not handle a/v sync since this is done - in the xine-engine already. - - - - - libdha (imported) - - - A library for direct hardware access to the graphics card - as used by the vidix video out plugin. - - - - - - vidix (imported) - - - The vidix system for high performance video output - as used by the vidix video out plugin. - - - - - - - - - - - xine-engine - - - The heart of xine - it's engine. Contains code to - load and handle all the plugins, the configuration repository - as well as the generic decoding loops and code for synchronized output. - A lot of helper functions for plugins to use live here as well. - What's in the individual files should be guessable by the files' - names. This document is not going to explain the source, because - it simply changes too often. A look at the architectural drawing - in the internals section should - give you a pretty good idea, what to expect in this directory. - Basically, everything in this picture that is not called "plugin" - lives here. - - - - - - xine-utils - - - Collection of utility functions and platform abstractions. - Also contains a simple XML parser for frontend playlist handling. - - - - - - - - - - Object oriented programming in C - - xine uses a lot of design principles normally found in - object oriented designs. As xine is written in C, a few - basic principles shall be explained here on how xine - is object oriented anyway. - - - Classes are structs containing function pointers and public member data. - Example: - -   typedef struct my_stack_s my_class_t; -    -   struct my_stack_s { -    /* method "push" with one parameter and no return value */ -    void (*push)(my_stack_t *this, int i); -    -    /* method "add" with no parameters and no return value */ -    void (*add)(my_stack_t *this); -    -    /* method "pop" with no parameters (except "this") and a return value */ -    int (*pop) (my_stack_t *this); -   }; -    -   /* constructor */ -   my_class_t *new_my_stack(void); - - - To derive from such a class, private member variables can be added: - -   typedef struct { -    my_stack_t stack; /* public part */ -    -    /* private part follows here */ -    int values[MAX_STACK_SIZE]; -    int stack_size; -   } intstack_t; - Each method is implemented as a static method (static to prevent - namespace pollution). The "this" pointer needs to be cast to the - private pointer type to gain access to the private member variables. - - - Implementation of the "push" method follows: - -   static void push (my_stack_t *this_gen, int i) { -    intstack_t *this = (intstack_t *)this_gen; -    this->values[MAX_STACK_SIZE - ++this->stack_size] = i; -   } - - - The part added to the derived class is private, because when - defining the new structure directly in the .c file, where it will - be used, outside modules have no way of seeing the definition - of the derived class. A public derivation is possible by defining - the above structure in a .h file for others to include. - - - Something similar to a protected, package or friend visibility is also - possible: - -   struct my_stack_s { -    void (*push)(my_stack_t *this, int i); -    void (*add)(my_stack_t *this); -    int (*pop)(my_stack_t *this); -    -   #ifdef STACK_INTERNAL -    void (*flush)(my_stack_t *this); -   #endif -   }; - All modules, who need to access the internal part have to add -    #define STACK_INTERNAL - before including the header with the definition. It is clear that only - those friend modules can derive from this class. - - - Finally the contructor malloc()s the data struct (private variant) - and fills in function pointers and default values. Usually the - constructor is the only public (i.e. non-static) function in the module: - -   my_stack_t *new_my_stack(void) { -    intstack_t *this; -    -    /* alloc memory */ -    this = malloc(sizeof(intstack_t)); -    -    /* fill in methods */ -    this->push = push; -    this->add = add; -    this->pop = pop; -    -    /* init data fields */ -    this->stack_size = 0; -    -    /* return public part */ -    return &this->stack; -   } - - - Why not using C++? - - After all these considerations about object oriented C, you might - ask, why we do not use C++ after all? The easy answer would be: xine wants - to be as fast as possible and C++ is simply too slow. But this is only the - easy answer and it is not entirely true any more. Thoughtfully applied, you - can write very fast C++ code with today's compilers, but these compilers might - not be available on all platforms in the necessary quality. Even with - a sophisticated compiler, C++ is much harder to optimize than plain C and thus - C compiles much faster. Another big problem is that the C++ ABI is not as - well-defined as the C ABI. With C, you can easily mix libraries and - applications built by different compilers. With C++, this is unlikely to work. - But the final argument is that xine does not really need C++. xine's - inheritance hierarchy is very flat, mostly one level only and does not need - things like multiple or virtual inheritance. Most of the external projects - that are used by xine are plain C as well and using more than one language - complicates the build system. As we saw above, we can emulate - object orientation reduced to our real needs in plain C. - - - - - - Coding style and guidelines - - This section contains some guidelines for writing xine-code. - These are really just guidelines, no strict rules. - Contributions will not be rejected if they do not meet these - rules but they will be even more appreciated if they do. - - - - Comment your interfaces directly in the header files. - No doxygen comments, ordinary C comments will do. - - - - - Use C-style comments (/* */), not C++-style (//). - - - - - When in doubt, use lower case. BTW: This thing is called xine, never Xine. - - - - - Use expressive variable and function identifiers on all public interfaces. - Use underscores to seperate words in identifiers, not uppercase - letters (my_function_name is ok, myFunctionName is not ok). - - - - - Avoid macros unless they are really useful. Avoid gotos. - - - - - use something like -    printf("module: ..."[,...]); - for console output. All console output goes to stdout and - must be prefixed by the module name which generates the - output (see example above). - - - - - Refer to emac's C-mode for all questions of proper indentiation. - That first of all means: indent with two spaces. - - - - - - - - The xine logging system - - xine offers a wide range of possibilities to display - strings. This section should describe when to use - which way and how to do it right. - - - xine_log - - Output which is done thru this function will be - displayed for the end user by the frontend. - If xine->verbosity is not 0 the messages will also - be displayed on the console. Ideally these strings - are translated. - This function is for information which the user should - read always. -    xine_log(xine_t *xine, int buf, const char *format, ...); - buf is either XINE_LOG_MSG for general messages or - XINE_LOG_PLUGIN for messages about plugins. - - - - xprintf - - This macro uses the xine->verbosity value to decide - if the string should be printed to the console. Possible - values are XINE_VERBOSITY_NONE, XINE_VERBOSITY_LOG or - XINE_VERBOSITY_DEBUG. By default nothing is printed. - When you use xine-ui you can enable this output with - the --verbose=[1,2] options. - This function should be used for information which the - user should only read up on request. -    xprintf(xine_t *xine, int verbosity, const char *format, ...); - - - - lprintf/llprintf - - These macros are for debugging purpose only. Under normal - circumstances it is disabled. And can only be enabled by changing - a define statement and a recompilation. It has to be enabled for these - files that are of interest. - It should only be used for information which is intended for developers. - -   lprintf(const char *format, ...); -   llprintf(bool, const char *format, ...); - bool is a flag which enables or disables this logging. - - - lprintf can be enabled by defining LOG at the top of the source file. - llprintf can be used for more than one categorie - per file by using diffent lables: - -   #define LOG_LOAD 1 -   #define LOG_SAVE 0 -    -   llprintf(LOG_LOAD, "loading was successful\n"); -   llprintf(LOG_SAVE, "could not save to file %s\n", filename); - - - In this case only the first messages is printed. To enable/disable change the defines. - - - LOG_MODULE should be used to set the modulename for xprintf/lprintf/llprintf. - Each output line will start with "modulename: ". -    #define LOG_MODULE "modulename" - - - LOG_VERBOSE can be defined to enable the logging of functionname and linenumbers. - Then the output will be: "modulename: (function_name:42) message". - - - - _x_assert/_x_abort - - These are not purely logging functions, but despite their original C library versions, - they always output debugging text, which is why usage of these functions is preferred. - - - _x_assert() checks a condition and prints a note, - when the condition is false. In addition, a debug build and only a debug build will - terminate the application, when the condition is false. Release versions will only - print the note, but try to continue. - - - _x_abort() always terminates the application after printing a note. - - - - - - How to contribute - - Make sure you send your patches in unified diff format to - the xine-devel mailing list. You'll have to subscribe first, - otherwise you're not allowed to post. Please do not send - patches to individual developers unless instructed otherwise - because your patch is more likely to get lost in an overfull - INBOX in that case. Please be patient, it may take 1-2 weeks - before you hear any comments on your work (developers may be - working on other parts of the code or are simply busy at - the moment). - - - - diff --git a/doc/hackersguide/stream.docbook b/doc/hackersguide/stream.docbook new file mode 100644 index 000000000..d05bbba65 --- /dev/null +++ b/doc/hackersguide/stream.docbook @@ -0,0 +1,656 @@ + + xine's stream layer + + + Input layer + + Many media players expect streams to be stored within files on + some local medium. In actual fact, media may be streamed over a + network (e.g. via HTTP or RTP), encoded onto a specialized medium + (e.g. DVD), etc. To allow you to access all this media, xine supports + the concept of an "input plugin". The tasks performed by an + input plugin are: + + + + Validation of Media Resource Locators (MRLs). + + + + + MRL specific session management (e.g. opening and closing local files). + + + + + Reading blocks/specific numbers of bytes from the input device. + + + + + + In addition to these tasks, the input plugin may keep track of some + input device-specific state information (e.g. a DVD plugin may keep + track of navigational state data such as current title/chapter). + + + There are two classes of input device which xine recognizes. + Byte-oriented devices can, upon request, return an arbitary + non-zero number of bytes from a stream. Examples of such devices + are files or network streams. Block-oriented devices, however, have + a prefered block or "frame"-size. An example of such a device is + a DVD where data is stored in logical blocks of 2048 bytes. One may + pass the hint to xine that the plugin is block-oriented by setting the + INPUT_CAP_BLOCK capability. Note that this is only a hint and + xine does not guarantee that all requests to the plugin will + be purely block based. + + + Writing a xine input plugin + + An input plugin provides API functions which allow the engine to + access the data source the plugin encapsulates. The input plugin API + is declared in input/input_plugin.h. + + + An input plugin exports a public function of the form: +    void *input_init_plugin(xine_t *xine, void *data); + This function initializes an input plugin class object with the + following functions: + + +    char *get_description(input_class_t *this_gen); + This function returns a plaintext, one-line string describing the plugin. + + +    char *get_identifier(input_class_t *this_gen); + This function returns a shorter identifier describing the plugin. + + +    xine_mrl_t **get_dir(input_class_t *this_gen, const char *filename, int *nFiles); + Retrieves a directory listing from the plugin. This function is optional. + + +    char **get_autoplay_list(input_class_t *this_gen, int *num_files); + Retrieves the autoplay playlist from the plugin. This function is optional. + + +    int eject_media(input_class_t *this_gen); + Ejects the medium. This function is optional. + + +    void dispose(input_class_t *this_gen); + This function frees the memory used by the input plugin class object. + + +    input_plugin_t *get_instance(input_class_t *class_gen, xine_stream_t *stream, const char *mrl); + The plugin should try, if it can handle the specified MRL and return an + instance of itself if so. If not, NULL should be returned. When a new MRL + is to be played, xine engine asks all the available input plugins one by + one if they can handle the MRL. + Note that input plugins are not guaranteed to be queried + in any particular order and the first input plugin to claim an MRL + gets control so try not to duplicate MRLs already found within xine. + + +    int open(input_plugin_t *this_gen); + You should do any device-specific initialisation within this function. + + +    uint32_t get_capabilities(input_plugin_t *this_gen); + Returns a bit mask describing the input device's capabilities. + You may logically OR the INPUT_CAP_* constants together to get + a suitable bit-mask (via the '|' operator). + + +    off_t read(input_plugin_t *this_gen, char *buf, off_t nlen); + Reads a specified number of bytes into a buffer and returns the number of bytes actually copied. + + +    buf_element_t *read_block(input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t len); + Should the input plugin set the block-oriented hint and if the + demuxer supports it, this function will be called to read a block directly + into a xine buffer from the buffer pool. + + +    off_t seek(input_plugin_t *this_gen, off_t offset, int origin); + This function is called by xine when it is required that subsequent + reads come from another part of the stream. + + +    off_t get_current_pos(input_plugin_t *this_gen); + Returns the current position within a finite length stream. + + +    off_t get_length(input_plugin_t *this_gen); + Similarly this function returns the length of the stream. + + +    uint32_t get_blocksize(input_plugin_t *this_gen); + Returns the device's prefered block-size if applicable. + + +    char *get_mrl(input_plugin_t *this_gen); + Returns the current MRL. + + +    int get_optional_data(input_plugin_t *this_gen, void *data, int data_type); + This function allows the input to advertise extra information that is + not available through other API functions. See INPUT_OPTIONAL_* defines. + + +    void dispose(input_plugin_t *this_gen); + This function closes all resources and frees the input_plugin_t object. + + + + + + Demuxer layer + + This section is designed to familiarize a programmer with general demuxer + concepts and how they apply to the xine multimedia library. + + + Introduction to demuxer theory + + xine's demuxer layer is responsible for taking apart multimedia files or + streams so that the engine can decode them and present them to the user. + "Demuxer" is short for demultiplexor, which is the opposite of + multiplexing. This refers to the process of combining 2 or more things + into one. Multimedia streams usually, at a minimum, multiplex an audio + stream and a video stream together into one stream. Sometimes, there are + multiple audio streams (e.g., for multiple language tracks). Sometimes, + there is a subtitle data stream multiplexed into the multimedia stream. + + + There are many different multimedia formats in existence and there are + varying strategies for demuxing different types of multimedia files. + Formats in the MPEG family, for example, are designed to allow easy + playback from almost any place within the file. Many formats cannot deal + with this circumstance and at least need to be demuxed from the beginning + of the stream and played through to the end. Some formats, such as MPEG and + AVI, have marker information before every chunk in the stream. Other + formats, such as Apple Quicktime, are required to have a master index that + contains all information for taking apart a file. Many game-oriented + multimedia formats are designed strictly for playing from start to finish + without any regard to random seeking within the file. + + + + Input considerations + + A xine demuxer interacts with xine's input layer in order to receive + data. The underlying input plugin might be a file, a network stream, or + a block-oriented disc storage device like a DVD. A file input offers the + most flexibility in being able to read either blocks of data or individual + bytes, and being able to seek freely. Other input plugins may not allow the + demuxer to seek (such as stdin or certain network streams). Some input + plugins only allow the demuxer to read blocks of data and not individual + bytes (such as the CD-DA input plugin). The demuxer needs to check the + capabilities of the underlying input plugin before attempting to seek + around. + + + + Seeking Policy + + If possible, it is desirable that a demuxer can seek randomly through + the stream. This is easier for some file formats and essentially impossible + for other formats. xine's seeking API function allows a seek target to be + specified in terms of a ratio from 0 to 65535, or time in milliseconds from 0. + Time-based seeking is useful for specifying, e.g., a 1-minute jump forward + or backward in a stream. With the ratio-based seeking, the demuxer can + interpret the ratio value in the domain he sees most fit. This can also be + some sort of time or a simple file offset. + + + If a multimedia stream has video, there generally needs to be a way to + identify keyframes in the stream in order to facilitate seeking. Many + game-oriented formats fall over in this area as they carry no keyframe + information aside from the implicit assumption that the first frame is a + keyframe. + + + In a stream with video, a seek operation should always jump to a keyframe. + xine Policy: When the seek target is between 2 keyframes, jump to the + earlier keyframe. E.g., if there are keyframes at stream offsets 10000 and + 20000, and the user requests a seek to offset 18000, choose the keyframe + at offset 10000. + + + Note that there can be difficulties when the audio and video streams are + not tightly interleaved. In many formats, the audio frames are several + time units ahead of the video frames for the purpose of pre-buffering. + This is a typical scenario in the middle of a stream: + +   audio frame @ time 10 +   video frame @ time 8 +   audio frame @ time 11 +   video frame @ time 9 +   audio frame @ time 12 +    keyframe @ time 10 +   audio frame @ time 13 + If the demuxer seeks to the keyframe @ time 10, the next audio chunk will + have a timestamp of 13, which is well ahead of where the video is. While + the xine engine will eventually recover, it will make playback choppy for + a few seconds after the seek. One strategy for dealing with this situation + is to seek back to the nearest keyframe before the requested seek and then + seek back to find the audio frame with the nearest timestamp before the + keyframe. In this example, that would mean seeking back to [af@time 10]. + Then, demux the chunks in order, but skip the video frames until the next + keyframe is encountered. + + + + Writing a xine demuxer + + A demuxer plugin provides API functions which allow the engine to + initialize demuxing, dispatch data chunks to the engine, seek within the + stream, get the stream length, among other functions. The demuxer API + is declared in demuxers/demux.h. + + + Writing a new xine demuxer is largely a process of using other demuxers as + references and understanding how they interact with the engine. This + section will give a brief overview of each API function. + + + A demuxer plugin exports a public function of the form: +    void *demux_wc3movie_init_plugin(xine_t *xine, void *data); + This function initializes a demuxer plugin class object with 6 + demuxer-specific functions. These functions mainly provide information + that a frontend can use to build user-friendly features. These functions + include: + + +    char *get_description(demux_class_t *this_gen); + This function returns a plaintext, one-line string describing the plugin. + + +    char *get_identifier(demux_class_t *this_gen); + This function returns a shorter identifier describing the plugin. + + +    char *get_extensions(demux_class_t *this_gen); + This function returns a string with the file extensions that this demuxer + is known to use. For example, Microsoft .WAV files use "wav". If there are + multiple known extensions, separate each extension with a space. For + example, Apple Quicktime has the extensions "mov qt mp4". + + +    char *get_mimetypes(demux_class_t *this_gen) + This function returns a string with the MIME types that this demuxer is + known to use. Multiple MIME type specifications should be separated with a + semicolon (;). For example, Apple Quicktime uses several MIME types: + +   return "video/quicktime: mov,qt: Quicktime animation;" +    "video/x-quicktime: mov,qt: Quicktime animation;" +    "application/x-quicktimeplayer: qtl: Quicktime list;"; + + +    void class_dispose(demux_class_t *this_gen); + This function frees the memory used by the demuxer plugin class object. + + +    demux_plugin_t *open_plugin(demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen); + This function is invoked by the xine engine to determine if the demuxer is + able to handle a particular multimedia stream. The engine can specify if + the demuxer is supposed to check the stream by content (validate the actual + stream data and see if it is of the expected type), by extension (check the + name of the MRL and see if the file extension is correct), or explicitly + (the engine is passing on a user request to force this demuxer to be used). + + + The order in which the engine queries the available demuxers is determined + by the priority stated in the demuxer_info_t, which is attached to every + demuxer's plugin info structure. Demuxers with higher priority values are + called before those with lower priority. The order amongst demuxers of + equal priority is undefined. The idea behind this is to have the demuxers + for high-level container formats have high priorities, while the raw format + demuxers have low priorities. This way, a stream of a high-level container + format with a beginning that happens to look like a low-level raw format is + still handled by the correct demuxer, because it is queried first. + + + NOTE: In the course of checking the stream by content, care must be taken + not to consume bytes out of a non-seekable stream. If the stream is + non-seekable, use the input plugin's preview buffer facility to get a cache + of the first few bytes. If the stream is seekable, reset the stream before + operating on the data (you do not know where some other demuxer left the + stream positioned). + + + If the demuxer can handle the stream, it creates a new demux_plugin_t + structure and initializes the main demuxer functions which are called by + the engine to do the tough demuxing duty. These functions include: + + +    void demux_send_headers(demux_plugin_t *this_gen); + This function generally reads the headers of the stream, does whatever it + has to do to figure out what audio and video codecs are used in the file, + and asks the xine engine to initialize the correct decoders with the + proper parameters (like width and height for video, sample rate and + channels for audio). + + +    int demux_send_chunk(demux_plugin_t *this_gen); + This function reads data from the stream and sends it to the appropriate + decoder. This is where the bulk of the demuxing work is performed. Despite + the name, the function is actually free to send as much data as it wants + to, or as much as it can. A good policy is to send an entire chunk of + compressed audio or video data and then return. The chunk is likely large + enough that it will have to be broken up into multiple xine buffers. If + a chunk of audio is 20000 bytes large, and the engine is returning + 4096-byte buffers, send 4 full buffers and 1 partial buffer to the audio + decoder and then return. + + +    int demux_seek(demux_plugin_t *this_gen, off_t start_pos, int start_time, int playing); + This function is called by the engine to request stream repositioning. + This function should be implemented if possible. See the section on + "Seeking Policy" for more information. A seek operation should reposition + the demuxer's internal accounting variables to be ready to start + dispatching chunks from the new position when the xine engine calls + demux_send_chunk() again. If seeking is not feasible, the function quietly + returns and the demuxer's position is unaffected. + + +    void demux_dispose(demux_plugin_t *this_gen); + This function frees the demux_plugin_t object. + + +    int demux_get_status(demux_plugin_t *this_gen); + This function returns the current internal status of the demuxer. There + are 2 states: DEMUX_OK, for when the demuxer is demuxing or ready to demux, + and DEMUX_FINISHED, for when the demuxer has reached the end of the stream + or has encountered some sort of error. + + +    int demux_get_stream_length(demux_plugin_t *this_gen); + This function returns the length (time duration) of the stream in + milliseconds. If the length of the stream cannot be determined, return 0. + + +    uint32_t demux_get_capabilities(demux_plugin_t *this_gen); + This function returns an array of bit flags indicating special features of + the demuxer. See DEMUX_CAP_* defines. + + +    int demux_get_optional_data(demux_plugin_t *this_gen, void *data, int data_type); + This function allows the demuxer to advertise extra information that is + not available through other API functions. See DEMUX_OPTIONAL_* defines. + + + + Buffer types + + Demuxer must send data to decoders using two fifos names video_fifo + and audio_fifo. Both are available at stream + level. The following code fragment shows how it's done. + + +   buf_element_t *buf; +    +   buf = stream->video_fifo->buffer_pool_alloc(stream->video_fifo); +   buf->type = BUF_CONTROL_START; +   stream->video_fifo->put(stream->video_fifo, buf); + + Buffers must have set the type field as shown. All buffer types are + defined in xine-engine/buffer.h. + + + The control buffer types are very important and must be sent by all kinds of demuxers. + They tell decoders to start/stop their operations and inform metronom about + discontinuities, either relative or absolute. There is also a reset buffer + type that must be sent when demuxers are seeking as a "warm restart" indication to + the decoders. + + + To help finding out buffer types for known codecs, functions from buffer_types.c + may be used to convert "FOURCC" codes or audio format tags (as used in AVI files) to the xine + byffer type: +    buf->type = fourcc_to_buf_video((void*)this->avi->bih.biCompression); + + + + + + Decoder layer + + This section is designed to familiarize a programmer with basic audio + and video decoding concepts and how they apply to the xine decoder API. + + + Audio and video decoders + + Audio and video data requires an enormous amount of storage. Thus, the + raw data is encoded using a variety of compression techniques which + drastically reduces the amount of space required to transmit and store the + data. Before playback, the compressed data needs to be decoded. + + + The process of decoding data is rather straightforward in a computer + science sense: An array of encoded data is fed into a decoder and the + decoder outputs an array of decoded data which is ready to be presented + to the user (either displayed on the screen or played through the + speakers). + + + + Video output formats + + Raw video data comes in a variety of formats, most commonly in RGB and + YUV. xine's output layer currently only accepts data in YV12 format (a.k.a. + YUV 4:2:0 planar) or YUY2 format (a.k.a. YUV 4:2:2 packed). If the output + format is a RGB space, the data must be converted to an acceptable YUV + format before being dispatched to the video output unit. xine has a number + of support functions to facilitate converting RGB to YUV. + + + + Audio output formats + + Raw audio data equates to uncompressed PCM audio. xine's audio output + modules expect 8-bit PCM data to be unsigned and 16-bit PCM data to be + signed and in little endian format. When there is more than one channel, + the channel data is interleaved. For example, stereo data is interleaved + as left sample, right sample: LRLRLRLR. If there are 4 or 6 channels, the + same interleaving applies: 123456123456. + + + + Writing a xine decoder + + Writing a new xine decoder for an audio or video format entails + accumulating a buffer of encoded data, performing the necessary operations + for decoding and then passing it on the appropriate output module. The + best reference for understanding the decoder API is the various decoding + modules available. In particular, xine has example video and audio + decoders named src/libxinevdec/foovideo.c and + src/libxineadec/fooaudio.c, respectively. + + + This section will give a brief overview of each API function. + The decoder API is declared in src/xine-engine/video_decoder.h + and src/xine-engine/audio_decoder.h. + + + A decoder plugin must, like every plugin, export a public array of + plugin_info_t types. The array usually has 2 entries: The first contains + the plugin information regarding the decoder and the second entry is + a terminating NULL entry. However, there may be more entries. + Each entry contains 6 fields: + + + + plugin type: Either PLUGIN_VIDEO_DECODER or PLUGIN_AUDIO_DECODER. + + + + + API: The plugin API revision that this plugin adheres to. + + + + + name: A character string that identifies the plugin. + + + + + version: #define'd as XINE_VERSION_CODE. + + + + + supported types: A structure that defines the buffer types that this plugin can handle. + + + + + init function: The function that the xine engine calls in order to initialize this decoder plugin. + + + + The supported types field is a decoder_info_t structure. This struct + combines a list of buffer types that the plugin can handle, along with + a relative default priority. The priority allows xine to have multiple + plugins that can handle one data type and the plugin with the highest + priority takes precedence. The code defines the default priority, which + can be overriden by the user. + The list of buffer types is an array of uint32_t types from the list of + buffer types defined in src/xine-engine/buffer.h. + + +    void *init_plugin(xine_t *xine, void *data); + This function allocates a plugin class and initializes a set of functions + for the xine engine to invoke. These functions include: + + +    char *get_identifier(video_decoder_class_t *this); +    char *get_identifier(audio_decoder_class_t *this); + This function returns a brief character string identifying the plugin. + + +    char *get_description(video_decoder_class_t *this); +    char *get_description(audio_decoder_class_t *this); + This function returns a slightly longer description of the plugin. + + +    void dispose_class(video_decoder_class_t *this); +    void dispose_class(audio_decoder_class_t *this); + This function frees the resources allocated by the plugin class. + + +    video_decoder_t *open_plugin(video_decoder_class_t *class_gen, xine_stream_t *stream); +    audio_decoder_t *open_plugin(audio_decoder_class_t *class_gen, xine_stream_t *stream); + This function initializes the decoder plugin's private state. It also + initializes and returns either an audio_decoder_t or a video_decoder_t for + the engine. The decoder_t contains a number of functions that the plugin + invokes to handle data decoding. These functions include: + + +    void decode_data(video_decoder_t *this_gen, buf_element_t *buf); +    void decode_data(audio_decoder_t *this_gen, buf_element_t *buf); + This function performs the bulk of the decoding work. The xine engine + delivers buffers (xine_buffer_t data types) to this function and it is up + to this function to assemble the parts of the buffer, decode the data, and + send the decoded data to the proper output unit. The constraint is that + you must never call a port function of the output port when the port has + not been opened by you. (See the open() and + close() functions of xine_video_port_t + and xine_audio_port_t.) + + + A buffer has a decoder_flags field which can have + a number of flags set. The first buffer that a decoder receives ought + to have the BUF_FLAG_HEADER flag set. This indicates that the buffer + content contains the essential setup information for decoding + (width, height, etc. for video; sample rate, channels, etc. for audio). + + + If the BUF_FLAG_HEADER flag is not set, the content of the buffer should + be accumulated in a private buffer until a buffer with a + BUF_FLAG_FRAME_END flag is set. This indicates that the entire chunk has + been transmitted to the decoder and is ready to be decoded. Fetch either + an empty video frame or audio buffer from the appropriate output unit. Perform + the appropriate decoding operations and set the pts for the output buffer + (and the duration, a.k.a. video_step, for video). Dispatch the decoded + data to the output and reset the internal buffer accumulation accounting. + + +    void flush(video_decoder_t *this_gen); +    void flush(audio_decoder_t *this_gen); + This function is called when either the xine engine flushes the stream, e.g., + after a seek operation or when decoding runs too slow and frames arrive in + the output loops fast enough. Decoders should release everything they have + already decoded, drop the rest and wait for new input. + + +    void reset(video_decoder_t *this_gen); +    void reset(audio_decoder_t *this_gen); + This function is called when the xine engine resets the stream. + Decoders should get ready to receive data that has nothing to do + with the one it worked on up to now. + + +    void discontinuity(video_decoder_t *this_gen); +    void discontinuity(audio_decoder_t *this_gen); + This function is called when the xine engine encounters a pts + discontinuity. Decoders should forget all timestamping information + they might have accumulated from the stream to not confuse metronom. + + +    void dispose(video_decoder_t *this_gen); +    void dispose(audio_decoder_t *this_gen); + This function frees the resources used by the decoder plugin. + + + + SPU decoder + + A lot written above also applies for subpicture unit (SPU) decoders. The + SPU decoder API is declared in src/xine-engine/spu_decoder.h. + Details on the data, SPU decoders are expected to output, see the section on + overlays and OSD. + + + However, there are some differences to consider. At first, unlike audio and + video, subtitles do not form a continuous stream. The decoder will therefore + only be called once in a while. The metronom call for timestamping, + which for audio and video is done by the engine, has to be done manually for SPU: +    vpts = metronom->got_spu_packet(metronom, buf->pts); + + + Another difference is that while both audio and video decoders are automatically + blocked in their get_buffer()/get_frame() + methods when the output cannot take any more data, this does not work for SPU, + because it could take minutes before the next free slot becomes available and we must not + block the decoder thread for that long since it might be shared with a video decoder. + But when a SPU decoder does not share the thread and we let it run without any + blocking, it will overflow the available overlay slots very soon. Since SPU + decoders should not have to know, whether they share the thread or not, a helper + function _x_spu_decoder_sleep() is provided, which, when told + the timestamp of the next overlay, will wait long enough to not overflow the + overlay slots, but short enough to not hinder a video decoder in the same thread. + + + There are also two functions in the SPU decoder API, which have not been discussed above: + + +    int get_interact_info(spu_decoder_t *this_gen, void *data); + Since SPUs are sometimes (on DVDs for example) used for user interaction like menu + highlights, this function can be called to get data filled with + the current interaction information. The caller and the decoder have to agree on + what this is exactly. With DVDs, you can get a copy of the current NAV packet here. + + +    void set_button(spu_decoder_t *this_gen, int32_t button, int32_t mode); + Also for interaction, you can ask the decoder here to change the + current highlighting. + + + + + diff --git a/doc/hackersguide/stream.sgml b/doc/hackersguide/stream.sgml deleted file mode 100644 index d05bbba65..000000000 --- a/doc/hackersguide/stream.sgml +++ /dev/null @@ -1,656 +0,0 @@ - - xine's stream layer - - - Input layer - - Many media players expect streams to be stored within files on - some local medium. In actual fact, media may be streamed over a - network (e.g. via HTTP or RTP), encoded onto a specialized medium - (e.g. DVD), etc. To allow you to access all this media, xine supports - the concept of an "input plugin". The tasks performed by an - input plugin are: - - - - Validation of Media Resource Locators (MRLs). - - - - - MRL specific session management (e.g. opening and closing local files). - - - - - Reading blocks/specific numbers of bytes from the input device. - - - - - - In addition to these tasks, the input plugin may keep track of some - input device-specific state information (e.g. a DVD plugin may keep - track of navigational state data such as current title/chapter). - - - There are two classes of input device which xine recognizes. - Byte-oriented devices can, upon request, return an arbitary - non-zero number of bytes from a stream. Examples of such devices - are files or network streams. Block-oriented devices, however, have - a prefered block or "frame"-size. An example of such a device is - a DVD where data is stored in logical blocks of 2048 bytes. One may - pass the hint to xine that the plugin is block-oriented by setting the - INPUT_CAP_BLOCK capability. Note that this is only a hint and - xine does not guarantee that all requests to the plugin will - be purely block based. - - - Writing a xine input plugin - - An input plugin provides API functions which allow the engine to - access the data source the plugin encapsulates. The input plugin API - is declared in input/input_plugin.h. - - - An input plugin exports a public function of the form: -    void *input_init_plugin(xine_t *xine, void *data); - This function initializes an input plugin class object with the - following functions: - - -    char *get_description(input_class_t *this_gen); - This function returns a plaintext, one-line string describing the plugin. - - -    char *get_identifier(input_class_t *this_gen); - This function returns a shorter identifier describing the plugin. - - -    xine_mrl_t **get_dir(input_class_t *this_gen, const char *filename, int *nFiles); - Retrieves a directory listing from the plugin. This function is optional. - - -    char **get_autoplay_list(input_class_t *this_gen, int *num_files); - Retrieves the autoplay playlist from the plugin. This function is optional. - - -    int eject_media(input_class_t *this_gen); - Ejects the medium. This function is optional. - - -    void dispose(input_class_t *this_gen); - This function frees the memory used by the input plugin class object. - - -    input_plugin_t *get_instance(input_class_t *class_gen, xine_stream_t *stream, const char *mrl); - The plugin should try, if it can handle the specified MRL and return an - instance of itself if so. If not, NULL should be returned. When a new MRL - is to be played, xine engine asks all the available input plugins one by - one if they can handle the MRL. - Note that input plugins are not guaranteed to be queried - in any particular order and the first input plugin to claim an MRL - gets control so try not to duplicate MRLs already found within xine. - - -    int open(input_plugin_t *this_gen); - You should do any device-specific initialisation within this function. - - -    uint32_t get_capabilities(input_plugin_t *this_gen); - Returns a bit mask describing the input device's capabilities. - You may logically OR the INPUT_CAP_* constants together to get - a suitable bit-mask (via the '|' operator). - - -    off_t read(input_plugin_t *this_gen, char *buf, off_t nlen); - Reads a specified number of bytes into a buffer and returns the number of bytes actually copied. - - -    buf_element_t *read_block(input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t len); - Should the input plugin set the block-oriented hint and if the - demuxer supports it, this function will be called to read a block directly - into a xine buffer from the buffer pool. - - -    off_t seek(input_plugin_t *this_gen, off_t offset, int origin); - This function is called by xine when it is required that subsequent - reads come from another part of the stream. - - -    off_t get_current_pos(input_plugin_t *this_gen); - Returns the current position within a finite length stream. - - -    off_t get_length(input_plugin_t *this_gen); - Similarly this function returns the length of the stream. - - -    uint32_t get_blocksize(input_plugin_t *this_gen); - Returns the device's prefered block-size if applicable. - - -    char *get_mrl(input_plugin_t *this_gen); - Returns the current MRL. - - -    int get_optional_data(input_plugin_t *this_gen, void *data, int data_type); - This function allows the input to advertise extra information that is - not available through other API functions. See INPUT_OPTIONAL_* defines. - - -    void dispose(input_plugin_t *this_gen); - This function closes all resources and frees the input_plugin_t object. - - - - - - Demuxer layer - - This section is designed to familiarize a programmer with general demuxer - concepts and how they apply to the xine multimedia library. - - - Introduction to demuxer theory - - xine's demuxer layer is responsible for taking apart multimedia files or - streams so that the engine can decode them and present them to the user. - "Demuxer" is short for demultiplexor, which is the opposite of - multiplexing. This refers to the process of combining 2 or more things - into one. Multimedia streams usually, at a minimum, multiplex an audio - stream and a video stream together into one stream. Sometimes, there are - multiple audio streams (e.g., for multiple language tracks). Sometimes, - there is a subtitle data stream multiplexed into the multimedia stream. - - - There are many different multimedia formats in existence and there are - varying strategies for demuxing different types of multimedia files. - Formats in the MPEG family, for example, are designed to allow easy - playback from almost any place within the file. Many formats cannot deal - with this circumstance and at least need to be demuxed from the beginning - of the stream and played through to the end. Some formats, such as MPEG and - AVI, have marker information before every chunk in the stream. Other - formats, such as Apple Quicktime, are required to have a master index that - contains all information for taking apart a file. Many game-oriented - multimedia formats are designed strictly for playing from start to finish - without any regard to random seeking within the file. - - - - Input considerations - - A xine demuxer interacts with xine's input layer in order to receive - data. The underlying input plugin might be a file, a network stream, or - a block-oriented disc storage device like a DVD. A file input offers the - most flexibility in being able to read either blocks of data or individual - bytes, and being able to seek freely. Other input plugins may not allow the - demuxer to seek (such as stdin or certain network streams). Some input - plugins only allow the demuxer to read blocks of data and not individual - bytes (such as the CD-DA input plugin). The demuxer needs to check the - capabilities of the underlying input plugin before attempting to seek - around. - - - - Seeking Policy - - If possible, it is desirable that a demuxer can seek randomly through - the stream. This is easier for some file formats and essentially impossible - for other formats. xine's seeking API function allows a seek target to be - specified in terms of a ratio from 0 to 65535, or time in milliseconds from 0. - Time-based seeking is useful for specifying, e.g., a 1-minute jump forward - or backward in a stream. With the ratio-based seeking, the demuxer can - interpret the ratio value in the domain he sees most fit. This can also be - some sort of time or a simple file offset. - - - If a multimedia stream has video, there generally needs to be a way to - identify keyframes in the stream in order to facilitate seeking. Many - game-oriented formats fall over in this area as they carry no keyframe - information aside from the implicit assumption that the first frame is a - keyframe. - - - In a stream with video, a seek operation should always jump to a keyframe. - xine Policy: When the seek target is between 2 keyframes, jump to the - earlier keyframe. E.g., if there are keyframes at stream offsets 10000 and - 20000, and the user requests a seek to offset 18000, choose the keyframe - at offset 10000. - - - Note that there can be difficulties when the audio and video streams are - not tightly interleaved. In many formats, the audio frames are several - time units ahead of the video frames for the purpose of pre-buffering. - This is a typical scenario in the middle of a stream: - -   audio frame @ time 10 -   video frame @ time 8 -   audio frame @ time 11 -   video frame @ time 9 -   audio frame @ time 12 -    keyframe @ time 10 -   audio frame @ time 13 - If the demuxer seeks to the keyframe @ time 10, the next audio chunk will - have a timestamp of 13, which is well ahead of where the video is. While - the xine engine will eventually recover, it will make playback choppy for - a few seconds after the seek. One strategy for dealing with this situation - is to seek back to the nearest keyframe before the requested seek and then - seek back to find the audio frame with the nearest timestamp before the - keyframe. In this example, that would mean seeking back to [af@time 10]. - Then, demux the chunks in order, but skip the video frames until the next - keyframe is encountered. - - - - Writing a xine demuxer - - A demuxer plugin provides API functions which allow the engine to - initialize demuxing, dispatch data chunks to the engine, seek within the - stream, get the stream length, among other functions. The demuxer API - is declared in demuxers/demux.h. - - - Writing a new xine demuxer is largely a process of using other demuxers as - references and understanding how they interact with the engine. This - section will give a brief overview of each API function. - - - A demuxer plugin exports a public function of the form: -    void *demux_wc3movie_init_plugin(xine_t *xine, void *data); - This function initializes a demuxer plugin class object with 6 - demuxer-specific functions. These functions mainly provide information - that a frontend can use to build user-friendly features. These functions - include: - - -    char *get_description(demux_class_t *this_gen); - This function returns a plaintext, one-line string describing the plugin. - - -    char *get_identifier(demux_class_t *this_gen); - This function returns a shorter identifier describing the plugin. - - -    char *get_extensions(demux_class_t *this_gen); - This function returns a string with the file extensions that this demuxer - is known to use. For example, Microsoft .WAV files use "wav". If there are - multiple known extensions, separate each extension with a space. For - example, Apple Quicktime has the extensions "mov qt mp4". - - -    char *get_mimetypes(demux_class_t *this_gen) - This function returns a string with the MIME types that this demuxer is - known to use. Multiple MIME type specifications should be separated with a - semicolon (;). For example, Apple Quicktime uses several MIME types: - -   return "video/quicktime: mov,qt: Quicktime animation;" -    "video/x-quicktime: mov,qt: Quicktime animation;" -    "application/x-quicktimeplayer: qtl: Quicktime list;"; - - -    void class_dispose(demux_class_t *this_gen); - This function frees the memory used by the demuxer plugin class object. - - -    demux_plugin_t *open_plugin(demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen); - This function is invoked by the xine engine to determine if the demuxer is - able to handle a particular multimedia stream. The engine can specify if - the demuxer is supposed to check the stream by content (validate the actual - stream data and see if it is of the expected type), by extension (check the - name of the MRL and see if the file extension is correct), or explicitly - (the engine is passing on a user request to force this demuxer to be used). - - - The order in which the engine queries the available demuxers is determined - by the priority stated in the demuxer_info_t, which is attached to every - demuxer's plugin info structure. Demuxers with higher priority values are - called before those with lower priority. The order amongst demuxers of - equal priority is undefined. The idea behind this is to have the demuxers - for high-level container formats have high priorities, while the raw format - demuxers have low priorities. This way, a stream of a high-level container - format with a beginning that happens to look like a low-level raw format is - still handled by the correct demuxer, because it is queried first. - - - NOTE: In the course of checking the stream by content, care must be taken - not to consume bytes out of a non-seekable stream. If the stream is - non-seekable, use the input plugin's preview buffer facility to get a cache - of the first few bytes. If the stream is seekable, reset the stream before - operating on the data (you do not know where some other demuxer left the - stream positioned). - - - If the demuxer can handle the stream, it creates a new demux_plugin_t - structure and initializes the main demuxer functions which are called by - the engine to do the tough demuxing duty. These functions include: - - -    void demux_send_headers(demux_plugin_t *this_gen); - This function generally reads the headers of the stream, does whatever it - has to do to figure out what audio and video codecs are used in the file, - and asks the xine engine to initialize the correct decoders with the - proper parameters (like width and height for video, sample rate and - channels for audio). - - -    int demux_send_chunk(demux_plugin_t *this_gen); - This function reads data from the stream and sends it to the appropriate - decoder. This is where the bulk of the demuxing work is performed. Despite - the name, the function is actually free to send as much data as it wants - to, or as much as it can. A good policy is to send an entire chunk of - compressed audio or video data and then return. The chunk is likely large - enough that it will have to be broken up into multiple xine buffers. If - a chunk of audio is 20000 bytes large, and the engine is returning - 4096-byte buffers, send 4 full buffers and 1 partial buffer to the audio - decoder and then return. - - -    int demux_seek(demux_plugin_t *this_gen, off_t start_pos, int start_time, int playing); - This function is called by the engine to request stream repositioning. - This function should be implemented if possible. See the section on - "Seeking Policy" for more information. A seek operation should reposition - the demuxer's internal accounting variables to be ready to start - dispatching chunks from the new position when the xine engine calls - demux_send_chunk() again. If seeking is not feasible, the function quietly - returns and the demuxer's position is unaffected. - - -    void demux_dispose(demux_plugin_t *this_gen); - This function frees the demux_plugin_t object. - - -    int demux_get_status(demux_plugin_t *this_gen); - This function returns the current internal status of the demuxer. There - are 2 states: DEMUX_OK, for when the demuxer is demuxing or ready to demux, - and DEMUX_FINISHED, for when the demuxer has reached the end of the stream - or has encountered some sort of error. - - -    int demux_get_stream_length(demux_plugin_t *this_gen); - This function returns the length (time duration) of the stream in - milliseconds. If the length of the stream cannot be determined, return 0. - - -    uint32_t demux_get_capabilities(demux_plugin_t *this_gen); - This function returns an array of bit flags indicating special features of - the demuxer. See DEMUX_CAP_* defines. - - -    int demux_get_optional_data(demux_plugin_t *this_gen, void *data, int data_type); - This function allows the demuxer to advertise extra information that is - not available through other API functions. See DEMUX_OPTIONAL_* defines. - - - - Buffer types - - Demuxer must send data to decoders using two fifos names video_fifo - and audio_fifo. Both are available at stream - level. The following code fragment shows how it's done. - - -   buf_element_t *buf; -    -   buf = stream->video_fifo->buffer_pool_alloc(stream->video_fifo); -   buf->type = BUF_CONTROL_START; -   stream->video_fifo->put(stream->video_fifo, buf); - - Buffers must have set the type field as shown. All buffer types are - defined in xine-engine/buffer.h. - - - The control buffer types are very important and must be sent by all kinds of demuxers. - They tell decoders to start/stop their operations and inform metronom about - discontinuities, either relative or absolute. There is also a reset buffer - type that must be sent when demuxers are seeking as a "warm restart" indication to - the decoders. - - - To help finding out buffer types for known codecs, functions from buffer_types.c - may be used to convert "FOURCC" codes or audio format tags (as used in AVI files) to the xine - byffer type: -    buf->type = fourcc_to_buf_video((void*)this->avi->bih.biCompression); - - - - - - Decoder layer - - This section is designed to familiarize a programmer with basic audio - and video decoding concepts and how they apply to the xine decoder API. - - - Audio and video decoders - - Audio and video data requires an enormous amount of storage. Thus, the - raw data is encoded using a variety of compression techniques which - drastically reduces the amount of space required to transmit and store the - data. Before playback, the compressed data needs to be decoded. - - - The process of decoding data is rather straightforward in a computer - science sense: An array of encoded data is fed into a decoder and the - decoder outputs an array of decoded data which is ready to be presented - to the user (either displayed on the screen or played through the - speakers). - - - - Video output formats - - Raw video data comes in a variety of formats, most commonly in RGB and - YUV. xine's output layer currently only accepts data in YV12 format (a.k.a. - YUV 4:2:0 planar) or YUY2 format (a.k.a. YUV 4:2:2 packed). If the output - format is a RGB space, the data must be converted to an acceptable YUV - format before being dispatched to the video output unit. xine has a number - of support functions to facilitate converting RGB to YUV. - - - - Audio output formats - - Raw audio data equates to uncompressed PCM audio. xine's audio output - modules expect 8-bit PCM data to be unsigned and 16-bit PCM data to be - signed and in little endian format. When there is more than one channel, - the channel data is interleaved. For example, stereo data is interleaved - as left sample, right sample: LRLRLRLR. If there are 4 or 6 channels, the - same interleaving applies: 123456123456. - - - - Writing a xine decoder - - Writing a new xine decoder for an audio or video format entails - accumulating a buffer of encoded data, performing the necessary operations - for decoding and then passing it on the appropriate output module. The - best reference for understanding the decoder API is the various decoding - modules available. In particular, xine has example video and audio - decoders named src/libxinevdec/foovideo.c and - src/libxineadec/fooaudio.c, respectively. - - - This section will give a brief overview of each API function. - The decoder API is declared in src/xine-engine/video_decoder.h - and src/xine-engine/audio_decoder.h. - - - A decoder plugin must, like every plugin, export a public array of - plugin_info_t types. The array usually has 2 entries: The first contains - the plugin information regarding the decoder and the second entry is - a terminating NULL entry. However, there may be more entries. - Each entry contains 6 fields: - - - - plugin type: Either PLUGIN_VIDEO_DECODER or PLUGIN_AUDIO_DECODER. - - - - - API: The plugin API revision that this plugin adheres to. - - - - - name: A character string that identifies the plugin. - - - - - version: #define'd as XINE_VERSION_CODE. - - - - - supported types: A structure that defines the buffer types that this plugin can handle. - - - - - init function: The function that the xine engine calls in order to initialize this decoder plugin. - - - - The supported types field is a decoder_info_t structure. This struct - combines a list of buffer types that the plugin can handle, along with - a relative default priority. The priority allows xine to have multiple - plugins that can handle one data type and the plugin with the highest - priority takes precedence. The code defines the default priority, which - can be overriden by the user. - The list of buffer types is an array of uint32_t types from the list of - buffer types defined in src/xine-engine/buffer.h. - - -    void *init_plugin(xine_t *xine, void *data); - This function allocates a plugin class and initializes a set of functions - for the xine engine to invoke. These functions include: - - -    char *get_identifier(video_decoder_class_t *this); -    char *get_identifier(audio_decoder_class_t *this); - This function returns a brief character string identifying the plugin. - - -    char *get_description(video_decoder_class_t *this); -    char *get_description(audio_decoder_class_t *this); - This function returns a slightly longer description of the plugin. - - -    void dispose_class(video_decoder_class_t *this); -    void dispose_class(audio_decoder_class_t *this); - This function frees the resources allocated by the plugin class. - - -    video_decoder_t *open_plugin(video_decoder_class_t *class_gen, xine_stream_t *stream); -    audio_decoder_t *open_plugin(audio_decoder_class_t *class_gen, xine_stream_t *stream); - This function initializes the decoder plugin's private state. It also - initializes and returns either an audio_decoder_t or a video_decoder_t for - the engine. The decoder_t contains a number of functions that the plugin - invokes to handle data decoding. These functions include: - - -    void decode_data(video_decoder_t *this_gen, buf_element_t *buf); -    void decode_data(audio_decoder_t *this_gen, buf_element_t *buf); - This function performs the bulk of the decoding work. The xine engine - delivers buffers (xine_buffer_t data types) to this function and it is up - to this function to assemble the parts of the buffer, decode the data, and - send the decoded data to the proper output unit. The constraint is that - you must never call a port function of the output port when the port has - not been opened by you. (See the open() and - close() functions of xine_video_port_t - and xine_audio_port_t.) - - - A buffer has a decoder_flags field which can have - a number of flags set. The first buffer that a decoder receives ought - to have the BUF_FLAG_HEADER flag set. This indicates that the buffer - content contains the essential setup information for decoding - (width, height, etc. for video; sample rate, channels, etc. for audio). - - - If the BUF_FLAG_HEADER flag is not set, the content of the buffer should - be accumulated in a private buffer until a buffer with a - BUF_FLAG_FRAME_END flag is set. This indicates that the entire chunk has - been transmitted to the decoder and is ready to be decoded. Fetch either - an empty video frame or audio buffer from the appropriate output unit. Perform - the appropriate decoding operations and set the pts for the output buffer - (and the duration, a.k.a. video_step, for video). Dispatch the decoded - data to the output and reset the internal buffer accumulation accounting. - - -    void flush(video_decoder_t *this_gen); -    void flush(audio_decoder_t *this_gen); - This function is called when either the xine engine flushes the stream, e.g., - after a seek operation or when decoding runs too slow and frames arrive in - the output loops fast enough. Decoders should release everything they have - already decoded, drop the rest and wait for new input. - - -    void reset(video_decoder_t *this_gen); -    void reset(audio_decoder_t *this_gen); - This function is called when the xine engine resets the stream. - Decoders should get ready to receive data that has nothing to do - with the one it worked on up to now. - - -    void discontinuity(video_decoder_t *this_gen); -    void discontinuity(audio_decoder_t *this_gen); - This function is called when the xine engine encounters a pts - discontinuity. Decoders should forget all timestamping information - they might have accumulated from the stream to not confuse metronom. - - -    void dispose(video_decoder_t *this_gen); -    void dispose(audio_decoder_t *this_gen); - This function frees the resources used by the decoder plugin. - - - - SPU decoder - - A lot written above also applies for subpicture unit (SPU) decoders. The - SPU decoder API is declared in src/xine-engine/spu_decoder.h. - Details on the data, SPU decoders are expected to output, see the section on - overlays and OSD. - - - However, there are some differences to consider. At first, unlike audio and - video, subtitles do not form a continuous stream. The decoder will therefore - only be called once in a while. The metronom call for timestamping, - which for audio and video is done by the engine, has to be done manually for SPU: -    vpts = metronom->got_spu_packet(metronom, buf->pts); - - - Another difference is that while both audio and video decoders are automatically - blocked in their get_buffer()/get_frame() - methods when the output cannot take any more data, this does not work for SPU, - because it could take minutes before the next free slot becomes available and we must not - block the decoder thread for that long since it might be shared with a video decoder. - But when a SPU decoder does not share the thread and we let it run without any - blocking, it will overflow the available overlay slots very soon. Since SPU - decoders should not have to know, whether they share the thread or not, a helper - function _x_spu_decoder_sleep() is provided, which, when told - the timestamp of the next overlay, will wait long enough to not overflow the - overlay slots, but short enough to not hinder a video decoder in the same thread. - - - There are also two functions in the SPU decoder API, which have not been discussed above: - - -    int get_interact_info(spu_decoder_t *this_gen, void *data); - Since SPUs are sometimes (on DVDs for example) used for user interaction like menu - highlights, this function can be called to get data filled with - the current interaction information. The caller and the decoder have to agree on - what this is exactly. With DVDs, you can get a copy of the current NAV packet here. - - -    void set_button(spu_decoder_t *this_gen, int32_t button, int32_t mode); - Also for interaction, you can ask the decoder here to change the - current highlighting. - - - - - -- cgit v1.2.3 From e7e047b720d82991637f229ee14cbbc8a8c0496a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 19:33:51 +0200 Subject: Update the doctype and rename entities. --- doc/hackersguide/hackersguide.docbook | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/hackersguide.docbook b/doc/hackersguide/hackersguide.docbook index ebc42d4c7..353430991 100644 --- a/doc/hackersguide/hackersguide.docbook +++ b/doc/hackersguide/hackersguide.docbook @@ -1,10 +1,11 @@ - - - - - - + + + + + + + ]> -- cgit v1.2.3 From 80751a1ece262617bd07a70b23c63dfb79867ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 19:34:45 +0200 Subject: Use UTF-8 encoding. --- doc/hackersguide/hackersguide.docbook | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/hackersguide.docbook b/doc/hackersguide/hackersguide.docbook index 353430991..f743260d0 100644 --- a/doc/hackersguide/hackersguide.docbook +++ b/doc/hackersguide/hackersguide.docbook @@ -14,13 +14,13 @@ The xine hacker's guide hackersguide - GünterBartsch - HeikoSchäfer + GünterBartsch + HeikoSchäfer RichardWareham MiguelFreitas JamesCourtier-Dutton SiggiLangauf - MarcoZühlke + MarcoZühlke MikeMelanson MichaelRoitzsch -- cgit v1.2.3 From 6c444a564e57da5da66018835222e365f24a0114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 19:35:23 +0200 Subject: Update copyright year and add my name to authors. --- doc/hackersguide/hackersguide.docbook | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/hackersguide.docbook b/doc/hackersguide/hackersguide.docbook index f743260d0..203e8e782 100644 --- a/doc/hackersguide/hackersguide.docbook +++ b/doc/hackersguide/hackersguide.docbook @@ -23,9 +23,10 @@ MarcoZühlke MikeMelanson MichaelRoitzsch + DiegoPettenò - 2001-2003 + 2001-2007 the xine project team -- cgit v1.2.3 From a1cebdf816465524b3bd9933f13c809a6f212700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 19:37:33 +0200 Subject: Rename the .sgml to .docbook. --- doc/hackersguide/Makefile.am | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/Makefile.am b/doc/hackersguide/Makefile.am index 35d96ca9a..b147501e9 100644 --- a/doc/hackersguide/Makefile.am +++ b/doc/hackersguide/Makefile.am @@ -1,12 +1,12 @@ include $(top_srcdir)/misc/Makefile.common -hackersguide_sgml = hackersguide.sgml \ - intro.sgml \ - library.sgml \ - overview.sgml \ - internals.sgml \ - stream.sgml \ - output.sgml +hackersguide_docbook = hackersguide.docbook \ + intro.docbook \ + library.docbook \ + overview.docbook \ + internals.docbook \ + stream.docbook \ + output.docbook hackersguide_fig = architecture.fig \ library.fig \ overlays.fig \ @@ -15,7 +15,7 @@ hackersguide_fig = architecture.fig \ hackersguide_DATA = hackersguide.html \ architecture.png library.png overlays.png post_frame.png -EXTRA_DIST = README $(hackersguide_sgml) $(hackersguide_fig) \ +EXTRA_DIST = README $(hackersguide_docbook) $(hackersguide_fig) \ $(hackersguide_DATA) hackersguidedir = $(htmldir)/hackersguide -- cgit v1.2.3 From 3384501fddd058d34ea28d26b637566aaede63b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 19:39:52 +0200 Subject: Remove the copy of original sgml files. --- doc/hackersguide/Makefile.am | 8 -------- 1 file changed, 8 deletions(-) (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/Makefile.am b/doc/hackersguide/Makefile.am index b147501e9..03a634038 100644 --- a/doc/hackersguide/Makefile.am +++ b/doc/hackersguide/Makefile.am @@ -24,16 +24,8 @@ docs: $(hackersguide_DATA) distclean-local: clean-docs -docs-prepare: $(addprefix $(srcdir)/, $(hackersguide_sgml)) - if test "$(srcdir)" != "." -a "$(srcdir)" != "`pwd`"; then \ - for file in $(hackersguide_sgml) ; do \ - test -f ./$$file -a ./$$file -nt $(srcdir)/$$file || cp $(srcdir)/$$file .; \ - done ; \ - fi - clean-docs: rm -f $(hackersguide_DATA) - test "x$(srcdir)" = x. || rm -f $(hackersguide_sgml) *.fig dist-hook: @if test x"$(distcheck_lax)" = x ; then \ -- cgit v1.2.3 From 89de608ef6e547a747e55da6a5a832e0da0afe9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 19:43:33 +0200 Subject: Don't create a distclean-local hook when you can just use DISTCLEANFILES variable. --- doc/hackersguide/Makefile.am | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/Makefile.am b/doc/hackersguide/Makefile.am index 03a634038..5dd6f5c25 100644 --- a/doc/hackersguide/Makefile.am +++ b/doc/hackersguide/Makefile.am @@ -20,12 +20,7 @@ EXTRA_DIST = README $(hackersguide_docbook) $(hackersguide_fig) \ hackersguidedir = $(htmldir)/hackersguide -docs: $(hackersguide_DATA) - -distclean-local: clean-docs - -clean-docs: - rm -f $(hackersguide_DATA) +DISTCLEANFILES = $(hackersguide_DATA) dist-hook: @if test x"$(distcheck_lax)" = x ; then \ -- cgit v1.2.3 From 79244eca1dde680dd469e732937f2a75895b5b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 19:51:49 +0200 Subject: Add missing line. --- doc/hackersguide/hackersguide.docbook | 1 + 1 file changed, 1 insertion(+) (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/hackersguide.docbook b/doc/hackersguide/hackersguide.docbook index 203e8e782..c311f3fe2 100644 --- a/doc/hackersguide/hackersguide.docbook +++ b/doc/hackersguide/hackersguide.docbook @@ -1,5 +1,6 @@ -- cgit v1.2.3 From 77948a92b71a1eb0ecd806ead31cb25112ec7c90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 19:54:25 +0200 Subject: Make the docbook valid XML. --- doc/hackersguide/internals.docbook | 12 ++++++------ doc/hackersguide/library.docbook | 4 ++-- doc/hackersguide/output.docbook | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/internals.docbook b/doc/hackersguide/internals.docbook index 9bd1ec684..7018f3202 100644 --- a/doc/hackersguide/internals.docbook +++ b/doc/hackersguide/internals.docbook @@ -5,10 +5,10 @@ Engine architecture and data flow - + - + xine engine architecture @@ -398,7 +398,7 @@     *     * audio buf ---> metronom --> audio fifo --> (buf->vpts - hw_vpts)     * (vpts_offset + error) gap -    * <---------- control --------------| +    * <---------- control --------------|     *     * Unfortunately audio fifo adds a large delay to our closed loop.     * @@ -410,7 +410,7 @@     * - each update will be of gap/SYNC_GAP_RATE.     *     * Sound card clock correction can only provide smooth playback for -    * errors < 1% nominal rate. For bigger errors (bad streams) audio +    * errors < 1% nominal rate. For bigger errors (bad streams) audio     * buffers may be dropped or gaps filled with silence.     */ @@ -468,10 +468,10 @@ - + - + overlays architecture diff --git a/doc/hackersguide/library.docbook b/doc/hackersguide/library.docbook index 1d987d259..de27f9e46 100644 --- a/doc/hackersguide/library.docbook +++ b/doc/hackersguide/library.docbook @@ -12,10 +12,10 @@ - + - + outside view on xine components diff --git a/doc/hackersguide/output.docbook b/doc/hackersguide/output.docbook index 806e89d0a..bd5ff200e 100644 --- a/doc/hackersguide/output.docbook +++ b/doc/hackersguide/output.docbook @@ -295,10 +295,10 @@ - + - + video frame passing through a post plugin -- cgit v1.2.3 From 95160592434ddc3b5e6537295bb8df1d36ee8979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 20:01:29 +0200 Subject: Add a new rule to build hackersguide.html from the docbook version. --- doc/hackersguide/Makefile.am | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/Makefile.am b/doc/hackersguide/Makefile.am index 5dd6f5c25..cb95b8ad3 100644 --- a/doc/hackersguide/Makefile.am +++ b/doc/hackersguide/Makefile.am @@ -29,23 +29,8 @@ dist-hook: $(MAKE) docs ; \ fi -if HAVE_SGMLTOOLS -hackersguide.html: $(hackersguide_sgml) - @$(MAKE) docs-prepare - $(SGMLTOOLS) -b onehtml hackersguide.sgml; -else -hackersguide.html: $(hackersguide_sgml) - @$(MAKE) docs-prepare - if test x"$(fail_if_missing)" = x"yes"; then \ - echo "Please install sgmltools-lite."; \ - exit 1; \ - fi - if test x"$(fail_if_missing)" != x"yes"; then \ - touch $@; \ - sleep 1; \ - touch $(notdir $^); \ - fi -endif +hackersguide.html: $(hackersguide_docbook) + xmlto html-nochunks $(srcdir)/hackersguide.docbook if HAVE_FIG2DEV fig.png: -- cgit v1.2.3 From 88d3a205d0a9fcebfc82ced0c0e49e5d7384262f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 20:03:02 +0200 Subject: Assume presence of fig2dev command while doing make dist or make install from Hg. --- doc/hackersguide/Makefile.am | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/Makefile.am b/doc/hackersguide/Makefile.am index cb95b8ad3..d98a69250 100644 --- a/doc/hackersguide/Makefile.am +++ b/doc/hackersguide/Makefile.am @@ -32,20 +32,7 @@ dist-hook: hackersguide.html: $(hackersguide_docbook) xmlto html-nochunks $(srcdir)/hackersguide.docbook -if HAVE_FIG2DEV -fig.png: - $(FIG2DEV) -L png -S 4 $< $@; -else .fig.png: - if test x"$(fail_if_missing)" = x"yes"; then \ - echo "Please install fig2dev."; \ - exit 1; \ - fi - if test x"$(fail_if_missing)" != x"yes"; then \ - touch $@; \ - sleep 1; \ - touch $(notdir $^); \ - fi -endif + fig2dev -L png -S 4 $< $@; SUFFIXES = .png .fig -- cgit v1.2.3 From e1f7855d284ddd922b930438863feebe29ded210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 20:06:21 +0200 Subject: Remove the dist-hook. --- doc/hackersguide/Makefile.am | 7 ------- 1 file changed, 7 deletions(-) (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/Makefile.am b/doc/hackersguide/Makefile.am index d98a69250..7cd4cf2cc 100644 --- a/doc/hackersguide/Makefile.am +++ b/doc/hackersguide/Makefile.am @@ -22,13 +22,6 @@ hackersguidedir = $(htmldir)/hackersguide DISTCLEANFILES = $(hackersguide_DATA) -dist-hook: - @if test x"$(distcheck_lax)" = x ; then \ - $(MAKE) fail_if_missing=yes docs ; \ - else \ - $(MAKE) docs ; \ - fi - hackersguide.html: $(hackersguide_docbook) xmlto html-nochunks $(srcdir)/hackersguide.docbook -- cgit v1.2.3 From 8720685a91816b4895a102adf70cd3bab80da95f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 20:10:58 +0200 Subject: Reorder hackersguidedir. --- doc/hackersguide/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/Makefile.am b/doc/hackersguide/Makefile.am index 7cd4cf2cc..b2fce9040 100644 --- a/doc/hackersguide/Makefile.am +++ b/doc/hackersguide/Makefile.am @@ -12,14 +12,13 @@ hackersguide_fig = architecture.fig \ overlays.fig \ post_frame.fig +hackersguidedir = $(htmldir)/hackersguide hackersguide_DATA = hackersguide.html \ architecture.png library.png overlays.png post_frame.png EXTRA_DIST = README $(hackersguide_docbook) $(hackersguide_fig) \ $(hackersguide_DATA) -hackersguidedir = $(htmldir)/hackersguide - DISTCLEANFILES = $(hackersguide_DATA) hackersguide.html: $(hackersguide_docbook) -- cgit v1.2.3 From df5fa8969966cb05704b7bbbd46d79b423adc23d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 20:49:01 +0200 Subject: Convert the figure files to SVG (with white background). --- doc/hackersguide/architecture.fig | 560 ---------- doc/hackersguide/architecture.svg | 2134 +++++++++++++++++++++++++++++++++++++ doc/hackersguide/library.fig | 313 ------ doc/hackersguide/library.svg | 1732 ++++++++++++++++++++++++++++++ doc/hackersguide/overlays.fig | 64 -- doc/hackersguide/overlays.svg | 256 +++++ doc/hackersguide/post_frame.fig | 347 ------ doc/hackersguide/post_frame.svg | 1564 +++++++++++++++++++++++++++ 8 files changed, 5686 insertions(+), 1284 deletions(-) delete mode 100644 doc/hackersguide/architecture.fig create mode 100644 doc/hackersguide/architecture.svg delete mode 100644 doc/hackersguide/library.fig create mode 100644 doc/hackersguide/library.svg delete mode 100644 doc/hackersguide/overlays.fig create mode 100644 doc/hackersguide/overlays.svg delete mode 100644 doc/hackersguide/post_frame.fig create mode 100644 doc/hackersguide/post_frame.svg (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/architecture.fig b/doc/hackersguide/architecture.fig deleted file mode 100644 index cc035149d..000000000 --- a/doc/hackersguide/architecture.fig +++ /dev/null @@ -1,560 +0,0 @@ -#FIG 3.2 -Landscape -Center -Metric -A4 -100.00 -Single --2 -1200 2 -6 2520 3915 3555 4950 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 2520 3915 3555 3915 3555 4950 2520 4950 2520 3915 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 - 2520 4140 3555 4140 -4 0 0 50 0 20 11 0.0000 4 150 945 2565 4680 demuxer plugin\001 -4 0 0 50 0 20 11 0.0000 4 150 840 2655 4095 demuxer loop\001 --6 -6 4500 3735 6300 5355 -6 5715 4500 6075 4770 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 5715 4500 6075 4500 6075 4770 5715 4770 5715 4500 -4 0 0 50 0 20 11 0.0000 4 120 195 5805 4680 buf\001 --6 -6 4680 4005 5040 4275 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 4680 4005 5040 4005 5040 4275 4680 4275 4680 4005 -4 0 0 50 0 20 11 0.0000 4 120 195 4770 4185 buf\001 --6 -6 4860 4320 5220 4590 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 4860 4320 5220 4320 5220 4590 4860 4590 4860 4320 -4 0 0 50 0 20 11 0.0000 4 120 195 4950 4500 buf\001 --6 -6 5220 4680 5580 4950 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 5220 4680 5580 4680 5580 4950 5220 4950 5220 4680 -4 0 0 50 0 20 11 0.0000 4 120 195 5310 4860 buf\001 --6 -6 5355 4095 5715 4365 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 5355 4095 5715 4095 5715 4365 5355 4365 5355 4095 -4 0 0 50 0 20 11 0.0000 4 120 195 5445 4275 buf\001 --6 -6 4635 4635 4995 4905 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 4635 4635 4995 4635 4995 4905 4635 4905 4635 4635 -4 0 0 50 0 20 11 0.0000 4 120 195 4725 4815 buf\001 --6 -6 5805 3960 6165 4230 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 5805 3960 6165 3960 6165 4230 5805 4230 5805 3960 -4 0 0 50 0 20 11 0.0000 4 120 195 5895 4140 buf\001 --6 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 4500 3735 6300 3735 6300 5355 4500 5355 4500 3735 -4 0 0 50 0 20 11 0.0000 4 150 660 5085 5265 buffer pool\001 --6 -6 1260 4230 2160 4770 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 1260 4230 2160 4230 2160 4770 1260 4770 1260 4230 -4 0 0 50 0 20 11 0.0000 4 150 705 1350 4545 input plugin\001 --6 -6 1710 3735 2070 4005 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 1710 3735 2070 3735 2070 4005 1710 4005 1710 3735 -4 0 0 20 0 20 11 0.0000 4 120 195 1800 3915 buf\001 --6 -6 3915 4320 4275 4590 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 3915 4320 4275 4320 4275 4590 3915 4590 3915 4320 -4 0 0 20 0 20 11 0.0000 4 120 195 4005 4500 buf\001 --6 -6 6525 5130 6885 5400 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 6525 5130 6885 5130 6885 5400 6525 5400 6525 5130 -4 0 0 20 0 20 11 0.0000 4 120 195 6615 5310 buf\001 --6 -6 6525 3555 6885 3825 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 6525 3555 6885 3555 6885 3825 6525 3825 6525 3555 -4 0 0 20 0 20 11 0.0000 4 120 195 6615 3735 buf\001 --6 -6 7335 5265 7695 5535 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 7335 5265 7695 5265 7695 5535 7335 5535 7335 5265 -4 0 0 20 0 20 11 0.0000 4 120 255 7425 5445 disc\001 --6 -6 7290 3375 7650 3645 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 7290 3375 7650 3375 7650 3645 7290 3645 7290 3375 -4 0 0 20 0 20 11 0.0000 4 120 255 7380 3555 disc\001 --6 -6 8865 5085 9225 5355 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 8865 5085 9225 5085 9225 5355 8865 5355 8865 5085 -4 0 0 20 0 20 11 0.0000 4 150 195 8955 5265 pts\001 --6 -6 9180 5985 9540 6255 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 9180 5985 9540 5985 9540 6255 9180 6255 9180 5985 -4 0 0 20 0 20 11 0.0000 4 150 270 9270 6165 vpts\001 --6 -6 8910 3645 9270 3915 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 8910 3645 9270 3645 9270 3915 8910 3915 8910 3645 -4 0 0 20 0 20 11 0.0000 4 150 195 9000 3825 pts\001 --6 -6 7380 4050 8865 4950 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 7380 4050 8865 4050 8865 4950 7380 4950 7380 4050 -4 0 0 50 0 20 11 0.0000 4 120 630 7830 4545 metronom\001 --6 -6 8505 3555 8865 3825 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 8505 3555 8865 3555 8865 3825 8505 3825 8505 3555 -4 0 0 20 0 20 11 0.0000 4 150 195 8595 3735 pts\001 --6 -6 8010 3330 8370 3600 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 8010 3330 8370 3330 8370 3600 8010 3600 8010 3330 -4 0 0 20 0 20 11 0.0000 4 150 270 8100 3510 vpts\001 --6 -6 1170 1575 9900 7425 -2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 9855 1620 1215 1620 1215 7380 9855 7380 9855 1620 -4 0 0 50 0 20 11 0.0000 4 135 735 1350 1800 xine stream\001 --6 -6 1215 270 9900 540 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 1215 270 9900 270 9900 540 1215 540 1215 270 -4 0 0 50 0 20 11 0.0000 4 150 780 4590 450 stream layer\001 --6 -6 6795 630 9900 900 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 6795 630 9900 630 9900 900 6795 900 6795 630 -4 0 0 50 0 20 11 0.0000 4 150 840 7965 810 decoder layer\001 --6 -6 3915 630 6705 900 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 3915 630 6705 630 6705 900 3915 900 3915 630 -4 0 0 50 0 20 11 0.0000 4 135 750 5040 810 stream fifos\001 --6 -6 2340 630 3825 900 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 2340 630 3825 630 3825 900 2340 900 2340 630 -4 0 0 50 0 20 11 0.0000 4 150 885 2655 810 demuxer layer\001 --6 -6 1215 630 2250 900 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 1215 630 2250 630 2250 900 1215 900 1215 630 -4 0 0 50 0 20 11 0.0000 4 150 645 1395 810 input layer\001 --6 -6 11295 4050 12780 4950 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 11295 4050 12780 4050 12780 4950 11295 4950 11295 4050 -2 1 0 1 0 7 50 0 -1 3.000 0 0 -1 0 0 2 - 12780 4500 11700 4500 -2 1 0 1 0 7 50 0 -1 3.000 0 0 -1 0 0 3 - 11700 4950 11700 4320 12780 4320 -4 0 0 50 0 20 11 0.0000 4 135 1005 11430 4275 metronom clock\001 -4 0 0 50 0 20 11 0.0000 4 150 975 11745 4455 clock sync loop\001 -4 0 0 50 0 20 11 0.0000 4 150 600 11745 4770 scr plugin\001 --6 -6 11295 5220 11655 5490 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 11295 5220 11655 5220 11655 5490 11295 5490 11295 5220 -4 0 0 20 0 20 11 0.0000 4 120 270 11385 5400 time\001 --6 -6 11295 3555 11655 3825 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 11295 3555 11655 3555 11655 3825 11295 3825 11295 3555 -4 0 0 20 0 20 11 0.0000 4 120 270 11385 3735 time\001 --6 -6 9990 270 12870 540 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 9990 270 12870 270 12870 540 9990 540 9990 270 -4 0 0 50 0 20 11 0.0000 4 150 735 11075 450 output layer\001 --6 -6 10035 1620 10845 7290 -6 10260 4275 10710 4680 -4 0 0 40 0 20 11 0.0000 4 150 270 10260 4410 post\001 -4 0 0 40 0 20 11 0.0000 4 150 435 10260 4635 plugins\001 --6 -2 2 0 1 0 7 50 0 20 0.000 0 0 -1 0 0 5 - 10125 1620 10845 1620 10845 7200 10125 7200 10125 1620 -2 2 0 1 0 7 60 0 20 0.000 0 0 -1 0 0 5 - 10080 1665 10800 1665 10800 7245 10080 7245 10080 1665 -2 2 0 1 0 7 70 0 20 0.000 0 0 -1 0 0 5 - 10035 1710 10755 1710 10755 7290 10035 7290 10035 1710 --6 -6 11070 900 12870 1620 -2 2 0 1 0 7 50 0 -1 3.000 0 0 -1 0 0 5 - 11070 1620 12870 1620 12870 900 11070 900 11070 1620 -2 1 0 1 0 7 50 0 -1 3.000 0 0 -1 0 0 2 - 11655 900 11655 1620 -4 0 0 50 0 20 11 0.0000 4 150 1035 11790 1305 overlay manager\001 -4 0 0 50 0 20 11 0.0000 4 120 300 11205 1305 OSD\001 --6 -6 11115 1845 11475 2115 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 11115 1845 11475 1845 11475 2115 11115 2115 11115 1845 -4 0 0 20 0 20 11 0.0000 4 120 225 11205 2025 spu\001 --6 -6 9360 4545 9720 4815 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 9360 4545 9720 4545 9720 4815 9360 4815 9360 4545 -4 0 0 20 0 20 11 0.0000 4 150 195 9450 4725 pts\001 --6 -6 8100 5130 8460 5400 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 8100 5130 8460 5130 8460 5400 8100 5400 8100 5130 -4 0 0 20 0 20 11 0.0000 4 150 270 8190 5310 vpts\001 --6 -6 9450 3150 9810 3420 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 9450 3150 9810 3150 9810 3420 9450 3420 9450 3150 -4 0 0 20 0 20 11 0.0000 4 150 270 9540 3330 vpts\001 --6 -6 7920 3645 8280 3915 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 7920 3645 8280 3645 8280 3915 7920 3915 7920 3645 -4 0 0 20 0 20 11 0.0000 4 150 270 8010 3825 vpts\001 --6 -6 9360 4140 9720 4410 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 9360 4140 9720 4140 9720 4410 9360 4410 9360 4140 -4 0 0 20 0 20 11 0.0000 4 150 195 9450 4320 pts\001 --6 -6 1485 8550 3375 8730 -2 1 2 1 0 7 50 0 -1 1.000 0 0 -1 1 0 2 - 0 0 1.00 60.00 120.00 - 1485 8640 2025 8640 -4 0 0 50 0 20 11 0.0000 4 150 1170 2205 8685 extra info datapath\001 --6 -6 1485 8235 3285 8415 -2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 - 0 0 1.00 60.00 120.00 - 1485 8325 2025 8325 -4 0 0 50 0 20 11 0.0000 4 150 1065 2205 8370 detailed datapath\001 --6 -6 1485 7920 2745 8100 -2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 - 0 0 1.00 60.00 120.00 - 1485 8010 2025 8010 -4 0 0 50 0 20 11 0.0000 4 150 540 2205 8055 datapath\001 --6 -6 4095 7875 5445 8145 -6 4095 7875 4455 8145 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 4095 7875 4455 7875 4455 8145 4095 8145 4095 7875 -4 0 0 20 0 20 11 0.0000 4 120 195 4185 8055 buf\001 --6 -4 0 0 50 0 20 11 0.0000 4 135 660 4770 8055 xine buffer\001 --6 -6 4095 8190 5580 8460 -6 4095 8190 4455 8460 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 4095 8190 4455 8190 4455 8460 4095 8460 4095 8190 -4 0 0 20 0 20 11 0.0000 4 120 255 4185 8370 disc\001 --6 -4 0 0 50 0 20 11 0.0000 4 150 780 4770 8370 discontinuity\001 --6 -6 4095 8505 6255 8775 -6 4095 8505 4455 8775 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 4095 8505 4455 8505 4455 8775 4095 8775 4095 8505 -4 0 0 20 0 20 11 0.0000 4 150 195 4185 8685 pts\001 --6 -4 0 0 50 0 20 11 0.0000 4 150 1470 4770 8685 presentation timestamp\001 --6 -6 6930 7875 9495 8145 -6 6930 7875 7290 8145 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 6930 7875 7290 7875 7290 8145 6930 8145 6930 7875 -4 0 0 20 0 20 11 0.0000 4 150 270 7020 8055 vpts\001 --6 -4 0 0 50 0 20 11 0.0000 4 150 1890 7605 8055 virtual presentation timestamp\001 --6 -6 6930 8190 8550 8460 -6 6930 8190 7290 8460 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 6930 8190 7290 8190 7290 8460 6930 8460 6930 8190 -4 0 0 20 0 20 11 0.0000 4 120 225 7020 8370 spu\001 --6 -4 0 0 50 0 20 11 0.0000 4 150 915 7605 8370 subpicture unit\001 --6 -6 4230 2385 6390 3015 -6 4320 2430 4680 2700 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 4320 2430 4680 2430 4680 2700 4320 2700 4320 2430 -4 0 0 50 0 20 11 0.0000 4 120 195 4410 2610 buf\001 --6 -6 5940 2430 6300 2700 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 5940 2430 6300 2430 6300 2700 5940 2700 5940 2430 -4 0 0 50 0 20 11 0.0000 4 120 195 6030 2610 buf\001 --6 -6 5220 2430 5580 2700 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 5220 2430 5580 2430 5580 2700 5220 2700 5220 2430 -4 0 0 50 0 20 11 0.0000 4 120 195 5310 2610 buf\001 --6 -6 4770 2430 5130 2700 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 4770 2430 5130 2430 5130 2700 4770 2700 4770 2430 -4 0 0 50 0 20 11 0.0000 4 120 195 4860 2610 buf\001 --6 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 4365 2475 10 10 4355 2475 4375 2475 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 4815 2475 10 10 4805 2475 4825 2475 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 5265 2475 10 10 5255 2475 5275 2475 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 5985 2475 10 10 5975 2475 5995 2475 -2 2 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 5 - 4230 2385 6390 2385 6390 3015 4230 3015 4230 2385 -4 0 0 50 0 20 11 0.0000 4 135 570 5040 2925 video fifo\001 -4 0 0 50 0 20 11 0.0000 4 30 135 5715 2610 ...\001 --6 -6 4230 5985 6390 6615 -6 4320 6030 4680 6300 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 4320 6030 4680 6030 4680 6300 4320 6300 4320 6030 -4 0 0 50 0 20 11 0.0000 4 120 195 4410 6210 buf\001 --6 -6 5940 6030 6300 6300 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 5940 6030 6300 6030 6300 6300 5940 6300 5940 6030 -4 0 0 50 0 20 11 0.0000 4 120 195 6030 6210 buf\001 --6 -6 5220 6030 5580 6300 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 5220 6030 5580 6030 5580 6300 5220 6300 5220 6030 -4 0 0 50 0 20 11 0.0000 4 120 195 5310 6210 buf\001 --6 -6 4770 6030 5130 6300 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 4770 6030 5130 6030 5130 6300 4770 6300 4770 6030 -4 0 0 50 0 20 11 0.0000 4 120 195 4860 6210 buf\001 --6 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 4355 6075 10 10 4345 6075 4365 6075 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 4815 6075 10 10 4805 6075 4825 6075 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 5265 6075 10 10 5255 6075 5275 6075 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 5985 6075 10 10 5975 6075 5995 6075 -2 2 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 5 - 4230 5985 6390 5985 6390 6615 4230 6615 4230 5985 -4 0 0 50 0 20 11 0.0000 4 135 570 5040 6525 audio fifo\001 -4 0 0 50 0 20 11 0.0000 4 30 135 5715 6210 ...\001 --6 -6 3735 5310 4095 5580 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 3770 5355 10 10 3760 5355 3780 5355 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 3735 5310 4095 5310 4095 5580 3735 5580 3735 5310 -4 0 0 20 0 20 11 0.0000 4 120 195 3825 5490 buf\001 --6 -6 3735 3330 4095 3600 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 3780 3375 10 10 3770 3375 3790 3375 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 3735 3330 4095 3330 4095 3600 3735 3600 3735 3330 -4 0 0 20 0 20 11 0.0000 4 120 195 3825 3510 buf\001 --6 -6 6525 2565 6885 2835 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 6570 2600 10 10 6560 2600 6580 2600 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 6525 2565 6885 2565 6885 2835 6525 2835 6525 2565 -4 0 0 20 0 20 11 0.0000 4 120 195 6615 2745 buf\001 --6 -6 6525 6165 6885 6435 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 6570 6210 10 10 6560 6210 6580 6210 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 6525 6165 6885 6165 6885 6435 6525 6435 6525 6165 -4 0 0 20 0 20 11 0.0000 4 120 195 6615 6345 buf\001 --6 -6 7065 5850 8865 6750 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 7145 5895 10 10 7135 5895 7155 5895 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 7065 5850 8865 5850 8865 6750 7065 6750 7065 5850 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 - 7425 6750 7425 6120 8865 6120 -4 0 0 50 0 20 11 0.0000 4 150 1170 7200 6030 audio decoder loop\001 -4 0 0 50 0 20 11 0.0000 4 150 1275 7515 6480 audio decoder plugin\001 --6 -6 7065 2250 8865 3150 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 7110 2295 10 10 7100 2295 7120 2295 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 7065 2250 8865 2250 8865 3150 7065 3150 7065 2250 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 - 7425 3150 7425 2880 8865 2880 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4 - 8865 2790 7425 2790 7425 2520 8865 2520 -4 0 0 50 0 20 11 0.0000 4 150 1170 7200 2430 video decoder loop\001 -4 0 0 50 0 20 11 0.0000 4 150 1170 7515 3060 spu decoder plugin\001 -4 0 0 50 0 20 11 0.0000 4 150 1275 7515 2700 video decoder plugin\001 --6 -6 9045 2340 9720 2610 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 9090 2385 10 10 9080 2385 9100 2385 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 9045 2340 9720 2340 9720 2610 9045 2610 9045 2340 -4 0 0 20 0 20 11 0.0000 4 120 435 9135 2520 frames\001 --6 -6 9045 6480 9720 6750 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 9080 6525 10 10 9070 6525 9090 6525 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 9045 6480 9720 6480 9720 6750 9045 6750 9045 6480 -4 0 0 20 0 20 11 0.0000 4 150 525 9135 6660 samples\001 --6 -6 11070 5850 12870 6750 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 11070 5850 12870 5850 12870 6750 11070 6750 11070 5850 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 - 11430 6750 11430 6120 12870 6120 -2 1 0 1 0 7 50 0 -1 1.000 0 0 -1 0 0 2 - 12240 5850 12240 6120 -4 0 0 50 0 20 11 0.0000 4 150 870 11205 6030 audio out loop\001 -4 0 0 50 0 20 11 0.0000 4 150 975 11520 6480 audio out plugin\001 -4 0 0 50 0 20 11 0.0000 4 135 435 12330 6030 out fifo\001 --6 -6 11070 2250 12870 3150 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 11070 2250 12870 2250 12870 3150 11070 3150 11070 2250 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 - 11430 3150 11430 2520 12870 2520 -2 1 0 1 0 7 50 0 -1 1.000 0 0 -1 0 0 2 - 12240 2250 12240 2520 -4 0 0 50 0 20 11 0.0000 4 150 870 11205 2430 video out loop\001 -4 0 0 50 0 20 11 0.0000 4 150 975 11520 2880 video out plugin\001 -4 0 0 50 0 20 11 0.0000 4 135 435 12330 2430 out fifo\001 --6 -6 11565 1620 12510 2250 -6 11700 1800 12375 2070 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 11700 1800 12375 1800 12375 2070 11700 2070 11700 1800 -4 0 0 20 0 20 11 0.0000 4 120 435 11790 1980 frames\001 --6 -3 2 0 1 0 7 50 0 -1 3.000 0 1 0 3 - 0 0 1.00 60.00 120.00 - 12060 2250 11565 1935 12060 1620 - 0.000 -1.000 0.000 -3 2 0 1 0 7 50 0 -1 3.000 0 1 0 3 - 0 0 1.00 60.00 120.00 - 12060 1620 12510 1935 12060 2250 - 0.000 -1.000 0.000 --6 -1 4 0 1 0 0 10 0 20 0.000 1 0.0000 7110 8640 10 10 7100 8640 7120 8640 -2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 - 0 0 1.00 60.00 120.00 - 7155 5850 6300 4500 -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 - 4500 4500 3555 4500 -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 - 2160 4500 2520 4500 -2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 - 0 0 1.00 57.26 114.51 - 3555 4500 4230 6300 -2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 - 0 0 1.00 60.00 120.00 - 6390 2700 7065 2700 -2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 - 0 0 1.00 57.26 114.51 - 3555 4500 4230 2700 -2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 - 0 0 1.00 60.00 120.00 - 6390 6300 7065 6300 -2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 - 0 0 1.00 60.00 120.00 - 7155 3150 6300 4500 -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 - 7290 3150 7965 4050 -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 - 7290 5850 7965 4950 -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 - 8550 3150 8550 4050 -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 - 8325 4050 8325 3150 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 - 1215 1845 2205 1845 2205 1620 -2 1 2 1 0 7 50 0 -1 3.000 0 0 -1 0 0 2 - 2295 7560 2295 585 -2 1 2 1 0 7 50 0 -1 3.000 0 0 -1 0 0 2 - 3870 7560 3870 585 -2 1 2 1 0 7 50 0 -1 3.000 0 0 -1 0 0 2 - 6750 7560 6750 585 -2 1 1 1 0 7 50 0 -1 3.000 0 0 -1 0 0 2 - 9945 7560 9945 270 -2 1 0 1 0 7 50 0 -1 3.000 0 0 -1 1 0 2 - 0 0 1.00 60.00 120.00 - 11520 4950 11250 5850 -2 1 0 1 0 7 50 0 -1 3.000 0 0 -1 1 0 2 - 0 0 1.00 60.00 120.00 - 11520 4050 11250 3150 -2 1 0 1 0 7 50 0 -1 3.000 0 0 -1 1 1 2 - 0 0 1.00 60.00 120.00 - 0 0 1.00 60.00 120.00 - 8865 6570 11070 6570 -2 1 0 1 0 7 50 0 -1 3.000 0 0 -1 1 1 2 - 0 0 1.00 60.00 120.00 - 0 0 1.00 60.00 120.00 - 8865 2565 11070 2565 -2 1 0 1 0 7 50 0 -1 3.000 0 0 -1 1 1 3 - 0 0 1.00 60.00 120.00 - 0 0 1.00 60.00 120.00 - 8865 3060 9720 3060 11655 1620 -3 2 1 1 0 7 50 0 -1 4.000 0 1 0 5 - 0 0 1.00 60.00 120.00 - 4500 4365 3060 4365 2025 3915 1530 4275 2520 4365 - 0.000 -1.000 -1.000 -1.000 0.000 -3 2 0 1 0 7 50 0 -1 0.000 0 1 0 3 - 0 0 1.00 60.00 120.00 - 8865 6210 9290 5502 8865 4860 - 0.000 -1.000 0.000 -3 2 0 1 0 7 50 0 -1 0.000 0 0 1 3 - 0 0 1.00 60.00 120.00 - 8865 6390 9450 5490 8865 4725 - 0.000 -1.000 0.000 -3 2 0 1 0 7 50 0 -1 0.000 0 0 1 3 - 0 0 1.00 60.00 120.00 - 8865 4140 9405 3510 8865 2700 - 0.000 -1.000 0.000 -3 2 0 1 0 7 50 0 -1 0.000 0 0 1 3 - 0 0 1.00 60.00 120.00 - 8865 2610 9540 3510 8865 4275 - 0.000 -1.000 0.000 -3 2 1 1 0 7 50 0 -1 4.000 0 1 0 8 - 0 0 1.00 60.00 120.00 - 8865 6480 10485 6300 11160 5850 10890 5130 9720 4635 8730 4725 - 8190 5490 8595 6120 - 0.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 0.000 -3 2 1 1 0 7 50 0 -1 4.000 0 1 0 7 - 0 0 1.00 60.00 120.00 - 8865 2700 10665 2745 11160 3375 10215 4230 8730 4275 7920 3780 - 7740 3150 - 0.000 -1.000 -1.000 -1.000 -1.000 -1.000 0.000 -3 2 2 1 0 7 50 0 -1 1.000 0 1 0 3 - 0 0 1.00 60.00 120.00 - 3285 4950 3285 5445 3735 5355 - 0.000 -1.000 0.000 -3 2 2 1 0 7 50 0 -1 1.000 0 1 0 4 - 0 0 1.00 60.00 120.00 - 3555 4185 3735 3825 3330 3510 3780 3375 - 0.000 -1.000 -1.000 0.000 -3 2 2 1 0 7 50 0 -1 1.000 0 1 0 3 - 0 0 1.00 60.00 120.00 - 6570 6210 6570 5940 7065 5895 - 0.000 -1.000 0.000 -3 2 2 1 0 7 50 0 -1 1.000 0 1 0 3 - 0 0 1.00 60.00 120.00 - 6570 2610 6570 2295 7065 2295 - 0.000 -1.000 0.000 -3 2 2 1 0 7 50 0 -1 1.000 0 1 0 3 - 0 0 1.00 60.00 120.00 - 7155 2250 8190 1845 9090 2385 - 0.000 -1.000 0.000 -3 2 2 1 0 7 50 0 -1 1.000 0 1 0 4 - 0 0 1.00 60.00 120.00 - 7110 5940 6975 6795 8010 7290 9090 6570 - 0.000 -1.000 -1.000 0.000 -4 0 0 50 0 20 11 0.0000 4 135 585 7605 8685 extra info\001 diff --git a/doc/hackersguide/architecture.svg b/doc/hackersguide/architecture.svg new file mode 100644 index 000000000..2bc41c638 --- /dev/null +++ b/doc/hackersguide/architecture.svg @@ -0,0 +1,2134 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + demuxer plugin + demuxer loop + + buf + + buf + + buf + + buf + + buf + + buf + + buf + + buffer pool + + input plugin + + metronom + + xine stream + + stream layer + + decoder layer + + stream fifos + + demuxer layer + + input layer + + + + metronom clock + clock sync loop + scr plugin + + output layer + + + + overlay manager + OSD + + + extra info datapath + + + detailed datapath + + + datapath + xine buffer + discontinuity + presentation timestamp + virtual presentation timestamp + subpicture unit + + buf + + buf + + buf + + buf + + video fifo + ... + + buf + + buf + + buf + + buf + + audio fifo + ... + + + audio decoder loop + audio decoder plugin + + + + video decoder loop + spu decoder plugin + video decoder plugin + + + + audio out loop + audio out plugin + out fifo + + + + video out loop + video out plugin + out fifo + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + extra info + post + plugins + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + buf + buf + buf + buf + disc + disc + pts + vpts + pts + pts + vpts + time + time + spu + pts + vpts + vpts + vpts + pts + buf + disc + pts + vpts + spu + buf + buf + buf + buf + frames + samples + frames + + + + + + + + + + + + + + + + + + + diff --git a/doc/hackersguide/library.fig b/doc/hackersguide/library.fig deleted file mode 100644 index 13dc79f0e..000000000 --- a/doc/hackersguide/library.fig +++ /dev/null @@ -1,313 +0,0 @@ -#FIG 3.2 -Landscape -Center -Metric -A4 -100.00 -Single --2 -1200 2 -6 900 405 1350 855 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 900 450 1080 450 1080 855 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 1170 855 1170 450 1350 450 --6 -6 1890 7470 3330 7965 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 1890 7470 3330 7470 3330 7965 1890 7965 1890 7470 -4 0 0 50 0 20 11 0.0000 4 150 885 2205 7740 xine_stream_t\001 --6 -6 3330 7335 4365 8055 -2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 7 - 3330 7695 3510 7335 4185 7335 4365 7695 4185 8055 3510 8055 - 3330 7695 -4 0 0 50 0 20 11 0.0000 4 165 930 3420 7740 xine_post_wire\001 --6 -6 3915 6210 7335 8235 -6 4770 6705 5220 7155 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 4770 6750 4950 6750 4950 7155 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 5040 7155 5040 6750 5220 6750 --6 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 - 4635 7425 5445 7425 5445 7155 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 4635 7155 7065 7155 7065 8235 4635 8235 4635 7155 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4 - 4635 8235 4365 8235 4365 7155 4635 7155 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4 - 7065 8235 7335 8235 7335 7155 7065 7155 -4 0 0 50 0 20 11 0.0000 4 165 1785 3915 6570 xine_list_post_plugins_typed\001 -4 0 0 50 0 20 11 0.0000 4 165 1365 3915 6345 xine_list_post_plugins\001 -4 0 0 50 0 20 11 0.0000 4 165 1155 5265 6795 xine_post_dispose\001 -4 0 0 50 0 20 11 0.0000 4 165 720 4680 7335 xine_post_t\001 -4 0 0 50 0 20 11 0.0000 4 165 855 3915 6795 xine_post_init\001 -4 0 0 50 0 20 11 1.5708 4 165 900 4545 8100 xine_post_in_t\001 -4 0 0 50 0 20 11 1.5708 4 165 990 7245 8145 xine_post_out_t\001 -4 0 0 50 0 20 11 0.0000 4 165 1065 6075 7875 xine_post_output\001 -4 0 0 50 0 20 11 0.0000 4 165 1395 4680 7875 xine_post_list_outputs\001 -4 0 0 50 0 20 11 0.0000 4 165 1305 4680 7650 xine_post_list_inputs\001 -4 0 0 50 0 20 11 0.0000 4 165 975 6075 7650 xine_post_input\001 --6 -6 7335 7335 8370 8055 -2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 7 - 7335 7695 7515 7335 8190 7335 8370 7695 8190 8055 7515 8055 - 7335 7695 -4 0 0 50 0 20 11 0.0000 4 165 930 7425 7740 xine_post_wire\001 --6 -6 8370 7425 9630 7920 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 8390 7438 9630 7438 9630 7920 8390 7920 8390 7438 -4 0 0 50 0 20 11 0.0000 4 165 720 8705 7708 xine_post_t\001 --6 -6 9630 7335 11520 8055 -2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 7 - 9630 7695 9810 7335 11340 7335 11520 7695 11340 8055 9810 8055 - 9630 7695 -4 0 0 50 0 20 11 0.0000 4 165 1650 9765 7740 xine_post_wire_video_port\001 --6 -6 11520 7425 12780 7920 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 11540 7438 12780 7438 12780 7920 11540 7920 11540 7438 -4 0 0 50 0 20 11 0.0000 4 165 1095 11655 7708 xine_video_port_t\001 --6 -6 2250 5580 2970 7470 -2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 7 - 2610 7470 2250 7290 2250 5760 2610 5580 2970 5760 2970 7290 - 2610 7470 -4 0 0 50 0 20 11 1.5708 4 150 1680 2655 7335 xine_stream_master_slave\001 --6 -6 10215 2565 13635 4005 -6 11655 2790 12105 3240 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 11655 2835 11835 2835 11835 3240 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 11925 3240 11925 2835 12105 2835 --6 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 - 11520 3510 12690 3510 12690 3240 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 11520 3240 13590 3240 13590 4005 11520 4005 11520 3240 -4 0 0 50 0 20 11 0.0000 4 165 1890 10215 2700 xine_list_video_output_plugins\001 -4 0 0 50 0 20 11 0.0000 4 150 1485 12150 2880 xine_close_video_driver\001 -4 0 0 50 0 20 11 0.0000 4 165 1455 10215 2880 xine_open_video_driver\001 -4 0 0 50 0 20 11 0.0000 4 165 1095 11565 3420 xine_video_port_t\001 -4 0 0 50 0 20 11 0.0000 4 165 1545 11655 3780 xine_port_send_gui_data\001 --6 -6 9630 4995 11520 5715 -2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 7 - 9630 5355 9810 4995 11340 4995 11520 5355 11340 5715 9810 5715 - 9630 5355 -4 0 0 50 0 20 11 0.0000 4 165 1650 9765 5400 xine_post_wire_audio_port\001 --6 -6 8370 5085 9630 5580 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 8390 5098 9630 5098 9630 5580 8390 5580 8390 5098 -4 0 0 50 0 20 11 0.0000 4 165 720 8705 5368 xine_post_t\001 --6 -6 10215 4185 13635 5625 -6 11655 4410 12105 4860 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 11655 4455 11835 4455 11835 4860 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 11925 4860 11925 4455 12105 4455 --6 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 - 11520 5130 12690 5130 12690 4860 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 11520 4860 13590 4860 13590 5625 11520 5625 11520 4860 -4 0 0 50 0 20 11 0.0000 4 165 1890 10215 4320 xine_list_audio_output_plugins\001 -4 0 0 50 0 20 11 0.0000 4 150 1485 12150 4500 xine_close_audio_driver\001 -4 0 0 50 0 20 11 0.0000 4 165 1455 10215 4500 xine_open_audio_driver\001 -4 0 0 50 0 20 11 0.0000 4 165 1095 11565 5040 xine_audio_port_t\001 --6 -6 945 3060 7290 5580 -6 2025 3105 2475 3555 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 2025 3150 2205 3150 2205 3555 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 2295 3555 2295 3150 2475 3150 --6 -6 7020 3555 7290 5580 -6 7065 3555 7245 4545 -4 0 0 50 0 20 11 1.5708 4 165 990 7200 4545 xine_post_out_t\001 --6 -6 7065 4545 7245 5535 -4 0 0 50 0 20 11 1.5708 4 165 990 7200 5535 xine_post_out_t\001 --6 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 - 7020 4590 7290 4590 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4 - 7020 5580 7290 5580 7290 3555 7020 3555 --6 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 - 1890 3825 2835 3825 2835 3555 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 1890 3555 7020 3555 7020 5580 1890 5580 1890 3555 -4 0 0 50 0 20 11 0.0000 4 165 885 3015 4545 xine_get_error\001 -4 0 0 50 0 20 11 0.0000 4 165 990 3015 4770 xine_get_status\001 -4 0 0 50 0 20 11 0.0000 4 165 1275 3015 4995 xine_get_pos_length\001 -4 0 0 50 0 20 11 0.0000 4 165 1260 3015 5220 xine_get_audio_lang\001 -4 0 0 50 0 20 11 0.0000 4 165 1155 3015 5445 xine_get_spu_lang\001 -4 0 0 50 0 20 11 0.0000 4 165 630 2115 4095 xine_open\001 -4 0 0 50 0 20 11 0.0000 4 165 585 2115 4320 xine_play\001 -4 0 0 50 0 20 11 0.0000 4 165 600 2115 4545 xine_stop\001 -4 0 0 50 0 20 11 0.0000 4 150 660 2115 4770 xine_close\001 -4 0 0 50 0 20 11 0.0000 4 165 630 2115 4995 xine_eject\001 -4 0 0 50 0 20 11 0.0000 4 165 990 3015 4095 xine_set_param\001 -4 0 0 50 0 20 11 0.0000 4 165 990 3015 4320 xine_get_param\001 -4 0 0 50 0 20 11 0.0000 4 165 1320 2520 3195 xine_stream_dispose\001 -4 0 0 50 0 20 11 0.0000 4 150 885 1935 3735 xine_stream_t\001 -4 0 0 50 0 20 11 0.0000 4 150 1095 945 3195 xine_stream_new\001 -4 0 0 50 0 20 11 0.0000 4 165 1470 5535 4095 xine_get_current_frame\001 -4 0 0 50 0 20 11 0.0000 4 165 1380 5535 4320 xine_get_current_vpts\001 -4 0 0 50 0 20 11 0.0000 4 150 1020 5535 4545 xine_trick_mode\001 -4 0 0 50 0 20 11 0.0000 4 165 1425 5535 4995 xine_get_audio_source\001 -4 0 0 50 0 20 11 0.0000 4 165 1425 5535 5220 xine_get_video_source\001 -4 0 0 50 0 20 11 0.0000 4 165 1335 4185 4095 xine_get_stream_info\001 -4 0 0 50 0 20 11 0.0000 4 165 1215 4185 4320 xine_get_meta_info\001 --6 -6 945 1260 2430 1890 -4 0 0 50 0 20 11 0.0000 4 150 510 945 1395 xine_init\001 -4 0 0 50 0 20 11 0.0000 4 165 1470 945 1620 xine_engine_set_param\001 -4 0 0 50 0 20 11 0.0000 4 165 1470 945 1845 xine_engine_get_param\001 --6 -6 5850 1260 8055 2790 -4 0 0 50 0 20 11 0.0000 4 165 1395 5850 1395 xine_get_browse_mrls\001 -4 0 0 50 0 20 11 0.0000 4 165 2190 5850 1620 xine_get_autoplay_input_plugin_ids\001 -4 0 0 50 0 20 11 0.0000 4 165 1470 5850 1845 xine_get_autoplay_mrls\001 -4 0 0 50 0 20 11 0.0000 4 165 1530 5850 2070 xine_get_file_extensions\001 -4 0 0 50 0 20 11 0.0000 4 165 1365 5850 2295 xine_get_mime_types\001 -4 0 0 50 0 20 11 0.0000 4 165 2025 5850 2520 xine_get_demux_for_mime_type\001 -4 0 0 50 0 20 11 0.0000 4 165 2085 5850 2745 xine_get_input_plugin_description\001 --6 -6 3960 1260 5670 2340 -4 0 0 50 0 20 11 0.0000 4 165 1380 3960 1395 xine_config_register_*\001 -4 0 0 50 0 20 11 0.0000 4 165 1680 3960 1620 xine_config_get_first_entry\001 -4 0 0 50 0 20 11 0.0000 4 165 1710 3960 1845 xine_config_get_next_entry\001 -4 0 0 50 0 20 11 0.0000 4 165 1575 3960 2070 xine_config_lookup_entry\001 -4 0 0 50 0 20 11 0.0000 4 165 1590 3960 2295 xine_config_update_entry\001 --6 -6 2655 1260 3780 1890 -4 0 0 50 0 20 11 0.0000 4 165 1035 2655 1395 xine_config_load\001 -4 0 0 50 0 20 11 0.0000 4 165 1080 2655 1620 xine_config_save\001 -4 0 0 50 0 20 11 0.0000 4 165 1095 2655 1845 xine_config_reset\001 --6 -6 2655 9630 6345 12150 -6 4005 9675 4455 10125 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 4005 9720 4185 9720 4185 10125 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 4275 10125 4275 9720 4455 9720 --6 -6 3825 10485 6255 11295 -6 4725 10575 5175 11025 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 4725 10620 4905 10620 4905 11025 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 4995 11025 4995 10620 5175 10620 --6 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 4455 11025 5445 11025 5445 11295 4455 11295 4455 11025 -4 0 0 50 0 20 11 0.0000 4 150 795 4590 11205 xine_event_t\001 -4 0 0 50 0 20 11 0.0000 4 150 990 5265 10665 xine_event_free\001 -4 0 0 50 0 20 11 0.0000 4 165 945 3825 10620 xine_event_get\001 -4 0 0 50 0 20 11 0.0000 4 150 1005 3825 10755 xine_event_wait\001 --6 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 - 3690 10395 5085 10395 5085 10125 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 3690 10125 6345 10125 6345 11700 3690 11700 3690 10125 -4 0 0 50 0 20 11 0.0000 4 165 1455 2655 9765 xine_event_new_queue\001 -4 0 0 50 0 20 11 0.0000 4 165 1680 4545 9765 xine_event_dispose_queue\001 -4 0 0 50 0 20 11 0.0000 4 165 1245 3780 10305 xine_event_queue_t\001 -4 0 0 50 0 20 11 0.0000 4 150 2130 3825 11565 xine_event_create_listener_thread\001 -4 0 0 50 0 20 11 0.0000 4 150 1050 2655 12105 xine_event_send\001 --6 -6 8415 1260 10710 2340 -4 0 0 50 0 22 11 0.0000 4 165 1605 8415 1395 xine_list_input_plugins\001 -4 0 0 50 0 22 11 0.0000 4 165 1830 8415 1620 xine_list_demuxer_plugins\001 -4 0 0 50 0 22 11 0.0000 4 165 2250 8415 1845 xine_list_video_decoder_plugins\001 -4 0 0 50 0 22 11 0.0000 4 165 2265 8415 2070 xine_list_audio_decoder_plugins\001 -4 0 0 50 0 22 11 0.0000 4 165 1500 8415 2295 xine_list_spu_plugins\001 --6 -6 11115 1260 12870 2340 -4 0 0 50 0 20 11 0.0000 4 165 1725 11115 1395 xine_get_log_section_count\001 -4 0 0 50 0 20 11 0.0000 4 165 1275 11115 1620 xine_get_log_names\001 -4 0 0 50 0 20 11 0.0000 4 165 510 11115 1845 xine_log\001 -4 0 0 50 0 20 11 0.0000 4 165 780 11115 2070 xine_get_log\001 -4 0 0 50 0 20 11 0.0000 4 165 1275 11115 2295 xine_register_log_cb\001 --6 -6 6930 9630 11205 11925 -6 7785 9675 8235 10125 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 7785 9720 7965 9720 7965 10125 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 0 0 1.00 60.00 120.00 - 8055 10125 8055 9720 8235 9720 --6 -6 7605 10485 9225 11790 -4 0 0 50 0 20 11 0.0000 4 150 1065 7605 10620 xine_osd_draw_*\001 -4 0 0 50 0 20 11 0.0000 4 165 1455 7605 11520 xine_osd_set_encoding\001 -4 0 0 50 0 20 11 0.0000 4 150 1140 7605 11295 xine_osd_set_font\001 -4 0 0 50 0 20 11 0.0000 4 165 1470 7605 11070 xine_osd_get_text_size\001 -4 0 0 50 0 20 11 0.0000 4 165 1380 7605 11745 xine_osd_set_position\001 -4 0 0 50 0 20 11 0.0000 4 165 1590 7605 10845 xine_osd_get_capabilities\001 --6 -6 9405 10260 11070 11790 -4 0 0 50 0 20 11 0.0000 4 150 960 9405 10395 xine_osd_show\001 -4 0 0 50 0 20 11 0.0000 4 165 1320 9405 11520 xine_osd_get_palette\001 -4 0 0 50 0 20 11 0.0000 4 165 1635 9405 11295 xine_osd_set_text_palette\001 -4 0 0 50 0 20 11 0.0000 4 150 930 9405 11070 xine_osd_clear\001 -4 0 0 50 0 20 11 0.0000 4 150 885 9405 10845 xine_osd_hide\001 -4 0 0 50 0 20 11 0.0000 4 150 1590 9405 10620 xine_osd_show_unscaled\001 -4 0 0 50 0 20 11 0.0000 4 165 1320 9405 11745 xine_osd_set_palette\001 --6 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 - 7470 10395 8325 10395 8325 10125 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 7470 10125 11205 10125 11205 11925 7470 11925 7470 10125 -4 0 0 50 0 20 11 0.0000 4 150 870 8325 9765 xine_osd_free\001 -4 0 0 50 0 20 11 0.0000 4 150 675 7560 10305 xine_osd_t\001 -4 0 0 50 0 20 11 0.0000 4 150 885 6930 9765 xine_osd_new\001 --6 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 - 765 1125 1350 1125 1350 855 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 765 855 14085 855 14085 8595 765 8595 765 855 -2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 7 - 7290 3780 7470 3420 11340 3420 11520 3780 11340 4140 7470 4140 - 7290 3780 -2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 7 - 7290 5355 7470 4995 8190 4995 8370 5355 8190 5715 7470 5715 - 7290 5355 -2 1 2 1 0 7 50 0 -1 3.000 0 0 -1 0 0 2 - 2520 9000 1890 7470 -2 1 2 1 0 7 50 0 -1 3.000 0 0 -1 0 0 2 - 1890 7965 2520 12510 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 - 2520 9270 3555 9270 3555 9000 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 2520 9000 11745 9000 11745 12510 2520 12510 2520 9000 -4 0 0 50 0 20 11 0.0000 4 150 375 855 1035 xine_t\001 -4 0 0 50 0 20 11 0.0000 4 150 555 1395 495 xine_exit\001 -4 0 0 50 0 20 11 0.0000 4 150 585 315 495 xine_new\001 -4 0 0 50 0 20 11 0.0000 4 150 1155 2790 495 xine_health_check\001 -4 0 0 50 0 20 11 0.0000 4 150 885 2610 9180 xine_stream_t\001 diff --git a/doc/hackersguide/library.svg b/doc/hackersguide/library.svg new file mode 100644 index 000000000..d8a5728b2 --- /dev/null +++ b/doc/hackersguide/library.svg @@ -0,0 +1,1732 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + xine_stream_t + + xine_post_wire + + + + + + + + + xine_list_post_plugins_typed + xine_list_post_plugins + xine_post_dispose + xine_post_t + xine_post_init + + xine_post_in_t + + + xine_post_out_t + + xine_post_output + xine_post_list_outputs + xine_post_list_inputs + xine_post_input + + xine_post_wire + + xine_post_t + + xine_post_wire_video_port + + xine_video_port_t + + + xine_stream_master_slave + + + + + + + + xine_list_video_output_plugins + xine_close_video_driver + xine_open_video_driver + xine_video_port_t + xine_port_send_gui_data + + xine_post_wire_audio_port + + xine_post_t + + + + + + + xine_list_audio_output_plugins + xine_close_audio_driver + xine_open_audio_driver + xine_audio_port_t + + + + + + xine_post_out_t + + + xine_post_out_t + + + + + + xine_get_error + xine_get_status + xine_get_pos_length + xine_get_audio_lang + xine_get_spu_lang + xine_open + xine_play + xine_stop + xine_close + xine_eject + xine_set_param + xine_get_param + xine_stream_dispose + xine_stream_t + xine_stream_new + xine_get_current_frame + xine_get_current_vpts + xine_trick_mode + xine_get_audio_source + xine_get_video_source + xine_get_stream_info + xine_get_meta_info + xine_init + xine_engine_set_param + xine_engine_get_param + xine_get_browse_mrls + xine_get_autoplay_input_plugin_ids + xine_get_autoplay_mrls + xine_get_file_extensions + xine_get_mime_types + xine_get_demux_for_mime_type + xine_get_input_plugin_description + xine_config_register_* + xine_config_get_first_entry + xine_config_get_next_entry + xine_config_lookup_entry + xine_config_update_entry + xine_config_load + xine_config_save + xine_config_reset + + + + + + + + + + xine_event_t + xine_event_free + xine_event_get + xine_event_wait + + + xine_event_new_queue + xine_event_dispose_queue + xine_event_queue_t + xine_event_create_listener_thread + xine_event_send + xine_list_input_plugins + xine_list_demuxer_plugins + xine_list_video_decoder_plugins + xine_list_audio_decoder_plugins + xine_list_spu_plugins + xine_get_log_section_count + xine_get_log_names + xine_log + xine_get_log + xine_register_log_cb + + + + + xine_osd_draw_* + xine_osd_set_encoding + xine_osd_set_font + xine_osd_get_text_size + xine_osd_set_position + xine_osd_get_capabilities + xine_osd_show + xine_osd_get_palette + xine_osd_set_text_palette + xine_osd_clear + xine_osd_hide + xine_osd_show_unscaled + xine_osd_set_palette + + + xine_osd_free + xine_osd_t + xine_osd_new + + + + + + + + + xine_t + xine_exit + xine_new + xine_health_check + xine_stream_t + + diff --git a/doc/hackersguide/overlays.fig b/doc/hackersguide/overlays.fig deleted file mode 100644 index 0301aead2..000000000 --- a/doc/hackersguide/overlays.fig +++ /dev/null @@ -1,64 +0,0 @@ -#FIG 3.2 -Portrait -Center -Metric -A4 -100.00 -Single --2 -1200 2 -0 32 #ffffff -6 3600 2340 5670 3555 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 3600 2340 5670 2340 5670 3555 3600 3555 3600 2340 -4 0 0 50 0 20 14 0.0000 4 165 1050 4140 3015 OSD renderer\001 --6 -6 495 3825 2700 4365 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 495 3825 2700 3825 2700 4365 495 4365 495 3825 -4 0 0 50 0 20 14 0.0000 4 195 1320 900 4185 public libxine API\001 --6 -6 495 2880 2700 3420 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 495 2880 2700 2880 2700 3420 495 3420 495 2880 -4 0 0 50 0 20 14 0.0000 4 195 1830 675 3240 libsputext (text subtitles)\001 --6 -6 495 2160 2700 2700 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 495 2160 2700 2160 2700 2700 495 2700 495 2160 -4 0 0 50 0 20 14 0.0000 4 195 1965 585 2520 libspucc (closed captions)\001 --6 -6 6435 1575 8865 2790 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 6435 1575 8865 1575 8865 2790 6435 2790 6435 1575 -4 0 0 50 0 20 14 0.0000 4 210 1260 6975 2250 overlay manager\001 --6 -6 6435 3780 8865 4995 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 6435 3780 8865 3780 8865 4995 6435 4995 6435 3780 -4 0 0 50 0 20 14 0.0000 4 165 675 7290 4455 video out\001 --6 -6 495 1440 2700 1980 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 495 1440 2700 1440 2700 1980 495 1980 495 1440 -4 0 0 50 0 20 14 0.0000 4 195 1920 585 1800 libspudec (DVD subtitles)\001 --6 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 4 - 0 0 1.00 60.00 120.00 - 2700 4095 3105 4095 3105 3375 3600 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 - 2700 1710 6435 1710 -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 - 2700 3150 3600 3150 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 1 2 - 0 0 1.00 60.00 120.00 - 0 0 1.00 60.00 120.00 - 7650 2790 7650 3780 -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 - 5670 2565 6435 2565 -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 - 2700 2430 3600 2430 diff --git a/doc/hackersguide/overlays.svg b/doc/hackersguide/overlays.svg new file mode 100644 index 000000000..af8cc3572 --- /dev/null +++ b/doc/hackersguide/overlays.svg @@ -0,0 +1,256 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + OSD renderer + + public libxine API + + libsputext (text subtitles) + + libspucc (closed captions) + + overlay manager + + video out + + libspudec (DVD subtitles) + + + + + + + + + + + + + + + diff --git a/doc/hackersguide/post_frame.fig b/doc/hackersguide/post_frame.fig deleted file mode 100644 index 4f576abdd..000000000 --- a/doc/hackersguide/post_frame.fig +++ /dev/null @@ -1,347 +0,0 @@ -#FIG 3.2 -Landscape -Center -Metric -A4 -100.00 -Single --2 -1200 2 -6 2970 585 9360 9945 -2 1 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 3 - 3015 900 3915 900 3915 630 -2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 3015 630 9315 630 9315 9900 3015 9900 3015 630 -4 0 0 50 0 20 11 0.0000 4 165 675 3105 810 post plugin\001 --6 -6 5040 1125 7200 1530 -2 2 0 1 0 4 40 0 20 0.000 0 0 -1 0 0 5 - 5040 1125 7200 1125 7200 1530 5040 1530 5040 1125 -4 0 0 30 0 20 11 0.0000 4 165 1545 5220 1395 _x_post_intercept_frame\001 --6 -6 3645 990 4635 1620 -2 2 0 1 0 3 40 0 20 0.000 0 0 -1 0 0 5 - 3735 1080 4635 1080 4635 1620 3735 1620 3735 1080 -2 2 0 1 0 4 30 0 20 0.000 0 0 -1 0 0 5 - 3645 990 4545 990 4545 1530 3645 1530 3645 990 --6 -6 5040 2160 7200 2565 -2 2 0 1 0 7 40 0 20 0.000 0 0 -1 0 0 5 - 5040 2160 7200 2160 7200 2565 5040 2565 5040 2160 -4 0 0 30 0 20 11 0.0000 4 165 1710 5220 2430 _x_post_frame_copy_down\001 --6 -6 5040 3060 7200 3465 -2 2 0 1 0 7 40 0 20 0.000 0 0 -1 0 0 5 - 5040 3060 7200 3060 7200 3465 5040 3465 5040 3060 -4 0 0 30 0 20 11 0.0000 4 165 1530 5220 3330 _x_post_frame_copy_up\001 --6 -6 3645 2025 4635 2655 -2 2 0 1 0 4 30 0 20 0.000 0 0 -1 0 0 5 - 3645 2025 4545 2025 4545 2565 3645 2565 3645 2025 -2 2 0 1 0 3 40 0 20 0.000 0 0 -1 0 0 5 - 3735 2115 4635 2115 4635 2655 3735 2655 3735 2115 -4 0 0 20 0 18 25 0.0000 4 270 225 3825 2430 d\001 --6 -6 7830 2025 8820 2655 -2 2 0 1 0 3 40 0 20 0.000 0 0 -1 0 0 5 - 7920 2115 8820 2115 8820 2655 7920 2655 7920 2115 -2 2 0 1 0 4 30 0 -1 0.000 0 0 -1 0 0 5 - 7830 2025 8730 2025 8730 2565 7830 2565 7830 2025 -4 0 0 20 0 18 25 0.0000 4 270 225 8100 2520 d\001 --6 -6 7830 2925 8820 3555 -2 2 0 1 0 3 40 0 20 0.000 0 0 -1 0 0 5 - 7920 3015 8820 3015 8820 3555 7920 3555 7920 3015 -2 2 0 1 0 4 30 0 -1 0.000 0 0 -1 0 0 5 - 7830 2925 8730 2925 8730 3465 7830 3465 7830 2925 -4 0 0 20 0 18 25 0.0000 4 285 555 8100 3420 d u\001 --6 -6 3645 2925 4635 3555 -2 2 0 1 0 4 30 0 20 0.000 0 0 -1 0 0 5 - 3645 2925 4545 2925 4545 3465 3645 3465 3645 2925 -2 2 0 1 0 3 40 0 20 0.000 0 0 -1 0 0 5 - 3735 3015 4635 3015 4635 3555 3735 3555 3735 3015 -4 0 0 20 0 18 25 0.0000 4 285 555 3825 3330 d u\001 --6 -6 7875 4725 8775 5265 -2 2 0 1 0 3 40 0 15 0.000 0 0 -1 0 0 5 - 7875 4725 8775 4725 8775 5265 7875 5265 7875 4725 -4 0 0 20 0 18 25 0.0000 4 270 225 8055 5130 d\001 --6 -6 3645 4005 4635 4635 -2 2 0 1 0 4 30 0 20 0.000 0 0 -1 0 0 5 - 3645 4005 4545 4005 4545 4545 3645 4545 3645 4005 -2 2 0 1 0 3 40 0 20 0.000 0 0 -1 0 0 5 - 3735 4095 4635 4095 4635 4635 3735 4635 3735 4095 -4 0 0 20 0 18 25 0.0000 4 270 225 3825 4410 d\001 --6 -6 7875 6300 8775 6840 -2 2 0 1 0 3 40 0 15 0.000 0 0 -1 0 0 5 - 7875 6300 8775 6300 8775 6840 7875 6840 7875 6300 -4 0 0 20 0 18 25 0.0000 4 285 555 8055 6705 d u\001 --6 -6 7875 5625 8775 6165 -2 2 0 1 0 3 40 0 15 0.000 0 0 -1 0 0 5 - 7875 5625 8775 5625 8775 6165 7875 6165 7875 5625 -4 0 0 20 0 18 25 0.0000 4 285 555 8055 6030 d u\001 --6 -6 3645 7245 4635 7875 -2 2 0 1 0 4 30 0 20 0.000 0 0 -1 0 0 5 - 3645 7245 4545 7245 4545 7785 3645 7785 3645 7245 -2 2 0 1 0 3 40 0 20 0.000 0 0 -1 0 0 5 - 3735 7335 4635 7335 4635 7875 3735 7875 3735 7335 -4 0 0 20 0 18 25 0.0000 4 270 225 3825 7650 d\001 --6 -6 3645 8145 4635 8775 -2 2 0 1 0 4 30 0 20 0.000 0 0 -1 0 0 5 - 3645 8145 4545 8145 4545 8685 3645 8685 3645 8145 -2 2 0 1 0 3 40 0 20 0.000 0 0 -1 0 0 5 - 3735 8235 4635 8235 4635 8775 3735 8775 3735 8235 -4 0 0 20 0 18 25 0.0000 4 285 555 3825 8550 d u\001 --6 -6 5040 7830 7200 8235 -2 2 0 1 0 7 40 0 20 0.000 0 0 -1 0 0 5 - 5040 7830 7200 7830 7200 8235 5040 8235 5040 7830 -4 0 0 30 0 20 11 0.0000 4 165 1395 5220 8100 _x_post_frame_u_turn\001 --6 -6 990 1125 2340 1530 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 990 1125 2340 1125 2340 1530 990 1530 990 1125 -4 0 0 50 0 20 11 0.0000 4 165 630 1170 1395 get_frame\001 --6 -6 990 2025 2340 3510 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 990 2025 2340 2025 2340 3510 990 3510 990 2025 -4 0 0 50 0 20 11 0.0000 4 120 255 1170 2475 field\001 -4 0 0 50 0 20 11 0.0000 4 120 255 1170 2700 lock\001 -4 0 0 50 0 20 11 0.0000 4 165 705 1170 2925 proc_frame\001 -4 0 0 50 0 20 11 0.0000 4 165 630 1170 3150 proc_slice\001 -4 0 0 50 0 20 11 0.0000 4 165 1065 1170 3375 proc_macroblock\001 -4 0 0 50 0 20 11 0.0000 4 120 300 1170 2250 draw\001 --6 -6 990 4095 2340 6795 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 990 4095 2340 4095 2340 6795 990 6795 990 4095 -4 0 0 50 0 20 11 0.0000 4 120 255 1170 4555 field\001 -4 0 0 50 0 20 11 0.0000 4 120 255 1170 4761 lock\001 -4 0 0 50 0 20 11 0.0000 4 165 705 1170 4969 proc_frame\001 -4 0 0 50 0 20 11 0.0000 4 165 630 1170 5175 proc_slice\001 -4 0 0 50 0 20 11 0.0000 4 165 1065 1170 5383 proc_macroblock\001 -4 0 0 50 0 20 11 0.0000 4 120 300 1170 4347 draw\001 --6 -6 990 7335 2340 8640 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 990 7335 2340 7335 2340 8640 990 8640 990 7335 -4 0 0 50 0 20 11 0.0000 4 120 300 1170 7605 draw\001 --6 -6 9990 1125 11340 1530 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 9990 1125 11340 1125 11340 1530 9990 1530 9990 1125 -4 0 0 50 0 20 11 0.0000 4 165 630 10170 1395 get_frame\001 --6 -6 9990 2025 11340 3510 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 9990 2025 11340 2025 11340 3510 9990 3510 9990 2025 -4 0 0 50 0 20 11 0.0000 4 120 255 10170 2475 field\001 -4 0 0 50 0 20 11 0.0000 4 120 255 10170 2700 lock\001 -4 0 0 50 0 20 11 0.0000 4 165 705 10170 2925 proc_frame\001 -4 0 0 50 0 20 11 0.0000 4 165 630 10170 3150 proc_slice\001 -4 0 0 50 0 20 11 0.0000 4 165 1065 10170 3375 proc_macroblock\001 -4 0 0 50 0 20 11 0.0000 4 120 300 10170 2250 draw\001 --6 -6 9990 4140 11340 4545 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 9990 4140 11340 4140 11340 4545 9990 4545 9990 4140 -4 0 0 50 0 20 11 0.0000 4 165 630 10170 4410 get_frame\001 --6 -6 9990 4725 11340 6210 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 9990 4725 11340 4725 11340 6210 9990 6210 9990 4725 -4 0 0 50 0 20 11 0.0000 4 120 255 10170 5175 field\001 -4 0 0 50 0 20 11 0.0000 4 120 255 10170 5400 lock\001 -4 0 0 50 0 20 11 0.0000 4 165 705 10170 5625 proc_frame\001 -4 0 0 50 0 20 11 0.0000 4 165 630 10170 5850 proc_slice\001 -4 0 0 50 0 20 11 0.0000 4 165 1065 10170 6075 proc_macroblock\001 -4 0 0 50 0 20 11 0.0000 4 120 300 10170 4950 draw\001 --6 -6 9990 6390 11340 6795 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 9990 6390 11340 6390 11340 6795 9990 6795 9990 6390 -4 0 0 50 0 20 11 0.0000 4 120 240 10170 6660 free\001 --6 -6 180 585 765 1755 -2 2 0 2 0 7 20 0 -1 6.000 0 0 -1 0 0 5 - 225 630 720 630 720 1710 225 1710 225 630 -4 0 0 20 0 20 15 1.5708 4 210 960 540 1665 interception\001 --6 -6 180 1890 765 3735 -2 2 0 2 0 7 20 0 -1 6.000 0 0 -1 0 0 5 - 225 1935 720 1935 720 3690 225 3690 225 1935 -4 0 0 20 0 20 15 1.5708 4 225 1065 540 3375 pass through\001 --6 -6 180 3870 765 7020 -2 2 0 2 0 7 20 0 -1 6.000 0 0 -1 0 0 5 - 225 3915 720 3915 720 6975 225 6975 225 3915 -4 0 0 20 0 20 15 1.5708 4 225 1380 540 6165 modifying a copy\001 --6 -6 180 7155 765 8910 -2 2 0 2 0 7 20 0 -1 6.000 0 0 -1 0 0 5 - 225 7200 720 7200 720 8865 225 8865 225 7200 -4 0 0 20 0 20 15 1.5708 4 180 1245 540 8685 dead-end draw\001 --6 -6 180 9045 765 9945 -2 2 0 2 0 7 20 0 -1 6.000 0 0 -1 0 0 5 - 225 9090 720 9090 720 9900 225 9900 225 9090 -4 0 0 20 0 20 15 1.5708 4 225 570 540 9810 freeing\001 --6 -6 5040 4455 7200 4860 -2 2 0 1 0 7 40 0 20 0.000 0 0 -1 0 0 5 - 5040 4455 7200 4455 7200 4860 5040 4860 5040 4455 -4 0 0 30 0 20 11 0.0000 4 165 1710 5220 4725 _x_post_frame_copy_down\001 --6 -6 5040 6030 7200 6435 -2 2 0 1 0 7 40 0 20 0.000 0 0 -1 0 0 5 - 5040 6030 7200 6030 7200 6435 5040 6435 5040 6030 -4 0 0 30 0 20 11 0.0000 4 165 1530 5220 6300 _x_post_frame_copy_up\001 --6 -6 3645 6255 4635 6885 -2 2 0 1 0 4 30 0 20 0.000 0 0 -1 0 0 5 - 3645 6255 4545 6255 4545 6795 3645 6795 3645 6255 -2 2 0 1 0 3 40 0 20 0.000 0 0 -1 0 0 5 - 3735 6345 4635 6345 4635 6885 3735 6885 3735 6345 -4 0 0 20 0 18 25 0.0000 4 285 555 3825 6660 d u\001 --6 -6 5040 9270 7200 9675 -2 2 0 1 0 3 40 0 20 0.000 0 0 -1 0 0 5 - 5040 9270 7200 9270 7200 9675 5040 9675 5040 9270 -4 0 0 30 0 20 11 0.0000 4 165 1845 5220 9540 _x_post_restore_video_frame\001 --6 -6 990 9270 2340 9675 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 990 9270 2340 9270 2340 9675 990 9675 990 9270 -4 0 0 50 0 20 11 0.0000 4 165 855 1170 9540 free / dispose\001 --6 -6 9990 9270 11340 9675 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 9990 9270 11340 9270 11340 9675 9990 9675 9990 9270 -4 0 0 50 0 20 11 0.0000 4 165 855 10170 9540 free / dispose\001 --6 -6 6660 4995 7515 5580 -2 3 0 1 0 7 50 0 15 0.000 0 0 -1 0 0 4 - 7065 4995 6840 5220 7290 5220 7065 4995 -4 0 0 50 0 20 11 0.0000 4 150 825 6660 5400 modify frame\001 -4 0 0 50 0 20 11 0.0000 4 120 465 6840 5580 content\001 --6 -6 405 10170 2970 11250 -6 990 10170 1980 10800 -2 2 0 1 0 7 40 0 20 0.000 0 0 -1 0 0 5 - 1080 10260 1980 10260 1980 10800 1080 10800 1080 10260 -2 2 0 1 0 7 30 0 20 0.000 0 0 -1 0 0 5 - 990 10170 1890 10170 1890 10710 990 10710 990 10170 --6 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 1 1 1.00 120.00 180.00 - 630 11025 630 10440 990 10440 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 1 1 1.00 120.00 180.00 - 2340 11025 2340 10530 1980 10530 -4 0 0 20 0 20 15 0.0000 4 165 465 405 11250 frame\001 -4 0 0 20 0 20 15 0.0000 4 165 975 1980 11250 frame->next\001 --6 -6 3375 10080 6300 11250 -2 2 0 1 0 4 40 0 20 0.000 0 0 -1 0 0 5 - 3375 10710 4275 10710 4275 11250 3375 11250 3375 10710 -2 2 0 1 0 3 40 0 20 0.000 0 0 -1 0 0 5 - 3375 10080 4275 10080 4275 10620 3375 10620 3375 10080 -4 0 0 50 0 20 15 0.0000 4 225 1890 4410 10440 frame from original port\001 -4 0 0 50 0 20 15 0.0000 4 210 1425 4410 11070 intercepted frame\001 --6 -6 6660 10035 11250 11295 -6 8505 10035 9405 10575 -2 2 0 1 0 3 40 0 -1 0.000 0 0 -1 0 0 5 - 8505 10035 9405 10035 9405 10575 8505 10575 8505 10035 -4 0 0 20 0 18 25 0.0000 4 285 555 8685 10440 d u\001 --6 -6 6660 10170 8055 11295 -4 2 0 50 0 20 15 0.0000 4 165 1005 8055 10350 downstream\001 -4 2 0 50 0 20 15 0.0000 4 165 1380 8055 10650 meta-information\001 -4 2 0 50 0 20 15 0.0000 4 180 1080 8055 10950 from decoder\001 -4 2 0 50 0 20 15 0.0000 4 210 705 8055 11250 to output\001 --6 -6 9855 10170 11250 11295 -4 0 0 50 0 20 15 0.0000 4 210 765 9855 10350 upstream\001 -4 0 0 50 0 20 15 0.0000 4 165 1380 9855 10650 meta-information\001 -4 0 0 50 0 20 15 0.0000 4 210 915 9855 10950 from output\001 -4 0 0 50 0 20 15 0.0000 4 180 870 9855 11250 to decoder\001 --6 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 1 1 1.00 120.00 180.00 - 8100 10800 8775 10800 8775 10485 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 - 1 1 1.00 120.00 180.00 - 9810 10800 9135 10800 9135 10485 --6 -6 3645 9135 4635 9765 -2 2 0 1 0 4 30 0 20 0.000 0 0 -1 0 0 5 - 3645 9135 4545 9135 4545 9675 3645 9675 3645 9135 -2 2 0 1 0 3 40 0 20 0.000 0 0 -1 0 0 5 - 3735 9225 4635 9225 4635 9765 3735 9765 3735 9225 -4 0 0 20 0 18 25 0.0000 4 270 225 3825 9540 d\001 --6 -6 7875 9180 8775 9720 -2 2 0 1 0 3 40 0 20 0.000 0 0 -1 0 0 5 - 7875 9180 8775 9180 8775 9720 7875 9720 7875 9180 -4 0 0 20 0 18 25 0.0000 4 270 225 8055 9585 d\001 --6 -2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 - 0 0 1.00 120.00 180.00 - 9990 1305 7200 1305 -2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 - 0 0 1.00 120.00 180.00 - 5040 1305 2340 1305 -2 2 0 1 0 3 40 0 20 0.000 0 0 -1 0 0 5 - 7875 1035 8775 1035 8775 1575 7875 1575 7875 1035 -2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 - 0 0 1.00 120.00 180.00 - 2340 2340 9990 2340 -2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 - 0 0 1.00 120.00 180.00 - 9990 3240 2340 3240 -2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 1 0 4 - 0 0 1.00 120.00 180.00 - 2340 4320 5625 4320 5625 6570 2340 6570 -2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 1 0 4 - 0 0 1.00 120.00 180.00 - 9990 5895 6570 5895 6570 6570 9990 6570 -2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 1 0 4 - 0 0 1.00 120.00 180.00 - 9990 4320 6570 4320 6570 4995 9990 4995 -2 2 0 1 0 3 40 0 20 0.000 0 0 -1 0 0 5 - 7875 4050 8775 4050 8775 4590 7875 4590 7875 4050 -2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 1 0 4 - 0 0 1.00 120.00 180.00 - 2340 7560 5625 7560 5625 8460 2340 8460 -2 1 1 1 0 7 50 0 -1 10.000 0 0 -1 0 0 2 - 0 1800 11610 1800 -2 1 1 1 0 7 50 0 -1 10.000 0 0 -1 0 0 2 - 0 3780 11610 3780 -2 1 1 1 0 7 50 0 -1 10.000 0 0 -1 0 0 2 - 0 7065 11610 7065 -2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 - 0 0 1.00 120.00 180.00 - 2340 9450 5040 9450 -2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 - 0 0 1.00 120.00 180.00 - 7200 9450 9990 9450 -2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 6 - 6075 90 6075 540 3195 540 3015 315 3195 90 6075 90 -2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 6 - 6165 90 6165 540 9135 540 9315 315 9135 90 6165 90 -2 1 1 1 0 7 50 0 -1 10.000 0 0 -1 0 0 2 - 0 8955 11610 8955 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 - 3195 9990 3195 11385 -2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 - 6480 9990 6480 11385 -4 0 0 20 0 20 20 0.0000 4 210 270 5715 405 up\001 -4 0 0 20 0 20 20 0.0000 4 210 585 6300 405 down\001 diff --git a/doc/hackersguide/post_frame.svg b/doc/hackersguide/post_frame.svg new file mode 100644 index 000000000..3558fe605 --- /dev/null +++ b/doc/hackersguide/post_frame.svg @@ -0,0 +1,1564 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + post plugin + + get_frame + + field + lock + proc_frame + proc_slice + proc_macroblock + draw + + field + lock + proc_frame + proc_slice + proc_macroblock + draw + + draw + + get_frame + + field + lock + proc_frame + proc_slice + proc_macroblock + draw + + get_frame + + field + lock + proc_frame + proc_slice + proc_macroblock + draw + + free + + free / dispose + + free / dispose + + modify frame + content + + + + + frame from original port + intercepted frame + downstream + meta-information + from decoder + to output + upstream + meta-information + from output + to decoder + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _x_post_intercept_frame + + _x_post_frame_copy_down + _x_post_frame_copy_up + + + + + + + + _x_post_frame_u_turn + _x_post_frame_copy_down + _x_post_frame_copy_up + + _x_post_restore_video_frame + + + d + d + d u + d u + d + d + d u + d u + d + d u + + + interception + + + + pass through + + + + modifying a copy + + + + dead-end draw + + + + freeing + + d u + frame + frame->next + d u + d + d + up + down + + -- cgit v1.2.3 From 1c25f30813a2c2638c7a942ab96b8b90f6a993c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 20:49:56 +0200 Subject: Convert the rule too. --- doc/hackersguide/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/Makefile.am b/doc/hackersguide/Makefile.am index b2fce9040..abd208fc9 100644 --- a/doc/hackersguide/Makefile.am +++ b/doc/hackersguide/Makefile.am @@ -24,7 +24,7 @@ DISTCLEANFILES = $(hackersguide_DATA) hackersguide.html: $(hackersguide_docbook) xmlto html-nochunks $(srcdir)/hackersguide.docbook -.fig.png: - fig2dev -L png -S 4 $< $@; +.svg.png: + rsvg -f png $< $@ SUFFIXES = .png .fig -- cgit v1.2.3 From 5a0f828681473f5aec1add957e152437f4e5d8dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 2 Jun 2007 20:50:31 +0200 Subject: Rename the files. --- doc/hackersguide/Makefile.am | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/Makefile.am b/doc/hackersguide/Makefile.am index abd208fc9..4b5985599 100644 --- a/doc/hackersguide/Makefile.am +++ b/doc/hackersguide/Makefile.am @@ -7,16 +7,16 @@ hackersguide_docbook = hackersguide.docbook \ internals.docbook \ stream.docbook \ output.docbook -hackersguide_fig = architecture.fig \ - library.fig \ - overlays.fig \ - post_frame.fig +hackersguide_svg = architecture.svg \ + library.svg \ + overlays.svg \ + post_frame.svg hackersguidedir = $(htmldir)/hackersguide hackersguide_DATA = hackersguide.html \ architecture.png library.png overlays.png post_frame.png -EXTRA_DIST = README $(hackersguide_docbook) $(hackersguide_fig) \ +EXTRA_DIST = README $(hackersguide_docbook) $(hackersguide_svg) \ $(hackersguide_DATA) DISTCLEANFILES = $(hackersguide_DATA) -- cgit v1.2.3 From b6055c5fe61d918259d1c253aa32fa97dd3e5163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Sat, 9 Jun 2007 18:20:13 +0200 Subject: Resurrect the check for xmlto/rsvg (rather than sgmltools/fig2dev) so that the build can be done even without those installed. --- doc/hackersguide/Makefile.am | 48 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) (limited to 'doc/hackersguide') diff --git a/doc/hackersguide/Makefile.am b/doc/hackersguide/Makefile.am index 4b5985599..025f4a1ec 100644 --- a/doc/hackersguide/Makefile.am +++ b/doc/hackersguide/Makefile.am @@ -21,10 +21,50 @@ EXTRA_DIST = README $(hackersguide_docbook) $(hackersguide_svg) \ DISTCLEANFILES = $(hackersguide_DATA) +SUFFIXES = .png .fig + +docs: $(hackersguide_DATA) + +clean-docs: + rm -f $(hackersguide_DATA) + +dist-hook: + @if test x"$(distcheck_lax)" = x ; then \ + $(MAKE) fail_if_missing=yes docs ; \ + else \ + $(MAKE) docs ; \ + fi + +distclean-local: clean-docs + +if HAVE_XMLTO +hackersguide.html: $(hackersguide_docbook) + xmlto html-nochunks $^ +else hackersguide.html: $(hackersguide_docbook) - xmlto html-nochunks $(srcdir)/hackersguide.docbook + if test x"$(fail_if_missing)" = x"yes"; then \ + echo "Please install xmlto."; \ + exit 1; \ + fi + if test x"$(fail_if_missing)" != x"yes"; then \ + touch $@; \ + sleep 1; \ + touch $^; \ + fi +endif +if HAVE_RSVG .svg.png: - rsvg -f png $< $@ - -SUFFIXES = .png .fig + rsvg -f png $^ $@ +else +.svg.png: + if test x"$(fail_if_missing)" = x"yes"; then \ + echo "Please install rsvg."; \ + exit 1; \ + fi + if test x"$(fail_if_missing)" != x"yes"; then \ + touch $@; \ + sleep 1; \ + touch $^; \ + fi +endif -- cgit v1.2.3