From 60239a297dd0e7a6454dbd15de9d0186dea93c14 Mon Sep 17 00:00:00 2001 From: Michael Roitzsch Date: Sun, 12 Oct 2003 19:06:43 +0000 Subject: updated hackersguide: * added some small pieces * incorporated some former READMEs and Mike's fabulous demuxer and decoder doc * splitted into multiple files * made new drawings (hopefully I am not the only one to understand them) * Makefile support for building a HTML version which is now installed in the user's doc directory CVS patchset: 5494 CVS date: 2003/10/12 19:06:43 --- doc/hackersguide/hackersguide.sgml | 2025 +----------------------------------- 1 file changed, 28 insertions(+), 1997 deletions(-) (limited to 'doc/hackersguide/hackersguide.sgml') diff --git a/doc/hackersguide/hackersguide.sgml b/doc/hackersguide/hackersguide.sgml index f27ae3da6..ebc42d4c7 100644 --- a/doc/hackersguide/hackersguide.sgml +++ b/doc/hackersguide/hackersguide.sgml @@ -1,2016 +1,47 @@ + + + + + + ]> - + + The xine hacker's guide hackersguide - GünterBartsch - HeikoSchäfer - RichardWareham - MiguelFreitas - JamesCourtier-Dutton - + GünterBartsch + HeikoSchäfer + RichardWareham + MiguelFreitas + JamesCourtier-Dutton + SiggiLangauf + MarcoZühlke + MikeMelanson + MichaelRoitzsch - 2001-2002 - the xine project team + 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. - + - - - - -Introduction - &intro; - - -Overview - - Source modules - The source directory in xine-lib contains several - modules, this should give you a quick overview on where - to find what sources: - - - xine-engine - The heart of xine - it's engine. Contains code to - load and handle all the plugins, as well as the generic decoding - and synchroniation/output code. - - - - audio_out - - Audio output plugins, these provide a thin abstraction layer - over different types of audio output architectures/platforms. - Basically an audio output plugin provides functions to query/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. - - - - dxr3 - - Code specific to the dxr3 / hollywood+ hardware mpeg decoder. - - - - liba52 - - Dolby digital audio decoder plugin. - - - - libdivx4 - - Video decoder plugin using libdivx4linux if it is installed. - - - - libdts - - Audio decoder plugin that does nothing but passing through - DTS (AC5) data to the audio output plugin. This is only usefull - when using an external hardware DTS decoder. - - - - libffmpeg - - Various Audio/Video decoder plugins based on ffmpeg; most - importantly this contains a free mpeg-4 video decoder. - - - - liblpcm - - Audio decoder plugin that "decodes" raw PCM data; most notably - endianess-conversions are done here. - - - - libmad - - Mpeg audio decoder plugin (i.e. mp3 decoding). - ISO/IEC compliant decoder using fixed point math. - - - - libmpeg2 - - Most important mpeg video decoder plugin, provides fast and - high-precision mpeg-1/2 video decoding. - - - - libspucc, libspudec, libsputext - - Various subtitle (spu: subpicture, dvd slang) decoder plugins. - - - - libvorbis - - Vorbis audio decoder plugin. - - - - libw32dll - - Video/Audio decoder plugins that exploit some wine code - to use win32 (media player) codecs in xine. Works on x86 platforms - only. - - - - 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. - - - - xine-utils - - collection of utility functions and platform abstractions. - - - - libac3, libmpg123, libvfill - - deprecated. - - - - - Architecture and data flow - - - - - - - - - xine architecture - - - - Media streams usually consist of audio- and video-packages 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- fifo. - - - From the other end of these fifos audio-/video-decoder threads - remove 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 audio-/video- output layers. The buffer holding the encoded - data is no longer needed and thus released to the global buffer pool. - - - - 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 (ideally only) function pointers in xine. - 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 (...); - - - to implement such a "class", frequently "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; - } - - - Finally the contructor mallocs() the data structs (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 (...) { - 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; - - /* cast & return */ - - return (my_stack_t *) this; - } - - - - - - Library interfaces - - - - -xine internals - - 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 do 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. Unfortunatelly the same isn't true for audio: all sound - cards 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 - specially true for most sound servers like ESD or aRts and explain why in such - cases rarelly the sync is perfect. - - - Another problem xine must handle is the sound card clock drift. vpts are - compared to the system clock for presentation but sound card is sampling audio at - it's own clocking mechanism, so a small drift may occur. As the playback goes on this - error will be integrated possibly resulting audio gaps or frame drops. To avoid that - annoying effect 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 xine engine from the inside - - - - Overlays and OSD - - The roots of xine overlays 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 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 snipped 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 = something; - - /* palette must contain YUV values for each color index */ - memcpy(event.object.overlay->clip_color, color, sizeof(color)); - - /* this table contains transparency level 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,(void *)&event); - - - - - OSD Renderer - - OSD is a general API for rendereing 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 it can be any kind of bitmap. Font - files are searched and loaded during initialization from /usr/[local]/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. - - - 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. - - - - - - Plugin architecture - - xine plugins are built as shared libraries that export a plugin info - record named xine_plugin_info. This is used by plugin - loader to identify the "virtual" plugin types inside the shared library. - - -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 } -}; - - - xine_plugin_info can contain any number of plugins - and must be terminated with a PLUGIN_NONE. 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 - - - Every entry in xine_plugin_info has a class initialization - function. 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. - - - All plugins are installed in a special xine plugins directory - which can be found using the xine-config --plugindir - command. - - - You'll find exact definitions of public functions and plugin structs - in the appropriate header files for each plugin type - (e.g. demux/demux.h, input/input_plugin.h, - xine-engine/video_out.h, etc) within the xine source-code. - - - 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 fields via the - demux_plugin field and private fields directly. - - - - -Extending xine's input - - Adding support for a new file format (writing a demuxer) - - Use an existing demuxer plugin, e.g. demux_mpeg_block - as an example. - - - Demuxer API - - You need to implement all the functions given in demux.h: - -struct demux_plugin_s { - - /* - * send headers, followed by BUF_CONTROL_HEADERS_DONE down the - * fifos, then return. do not start demux thread (yet) - */ - - void (*send_headers) (demux_plugin_t *this); - - /* - * ask demux to seek - * - * for seekable streams, a start position can be specified - * - * start_pos : position in input source - * start_time : position measured in seconds from stream start - * - * if both parameters are !=0 start_pos will be used - * for non-seekable streams both values will be ignored - * - * returns the demux status (like get_status, but immediately after - * starting the demuxer) - */ - - int (*seek) (demux_plugin_t *this, - off_t start_pos, int start_time); - - /* - * send a chunk of data down to decoder fifos - * - * the meaning of "chunk" is specific to every demux, usually - * it involves parsing one unit of data from stream. - * - * this function will be called from demux loop and should return - * the demux current status - */ - - int (*send_chunk) (demux_plugin_t *this); - - /* - * free resources - */ - - void (*dispose) (demux_plugin_t *this) ; - - /* - * returns DEMUX_OK or DEMUX_FINISHED - */ - - int (*get_status) (demux_plugin_t *this) ; - - /* - * gets stream length in miliseconds (might be estimated) - * may return 0 for non-seekable streams - */ - - int (*get_stream_length) (demux_plugin_t *this); - - /* - * get audio/video frames - * - * experimental, function pointers can be NULL for now. - */ - - int (*get_video_frame) (demux_plugin_t *this, - int timestamp, /* msec */ - int *width, int *height, - int *ratio_code, - int *duration, /* msec */ - int *format, - uint8_t *img) ; - - /* called by video_out for every frame it receives */ - void (*got_video_frame_cb) (demux_plugin_t *this, - vo_frame_t *frame); - - /* - * return capabilities of demuxed stream - */ - - uint32_t (*get_capabilities) (demux_plugin_t *this); - - /* - * request optional data from input plugin. - */ - int (*get_optional_data) (demux_plugin_t *this, void *data, int data_type); - - /* - * "backwards" link to plugin class - */ - - demux_class_t *demux_class; -} ; - - - - - Buffer types - - Demuxer must send data to decoders using two fifo of buffers fifo_video - and audio_fifo. Both are available at stream - struct. The following code fragment shows how it's done. - - - buf_element_t *buf; - - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_NEWPTS; - buf->disc_off = start_pts; - this->video_fifo->put (this->video_fifo, buf); - - - Buffers must have set the type field as shown. Several buffer types are - defined in buffer.h, and most of them are information needed to - select a particular decoder. - - -/* - * buffer types - * - * a buffer type ID describes the contents of a buffer - * it consists of three fields: - * - * buf_type = 0xMMDDCCCC - * - * MM : major buffer type (CONTROL, VIDEO, AUDIO, SPU) - * DD : decoder selection (e.g. MPEG, OPENDIVX ... for VIDEO) - * CCCC : channel number or other subtype information for the decoder - */ - -#define BUF_MAJOR_MASK 0xFF000000 -#define BUF_DECODER_MASK 0x00FF0000 - -/* control buffer types */ - -#define BUF_CONTROL_BASE 0x01000000 -#define BUF_CONTROL_START 0x01000000 -#define BUF_CONTROL_END 0x01010000 -#define BUF_CONTROL_QUIT 0x01020000 -#define BUF_CONTROL_DISCONTINUITY 0x01030000 /* former AVSYNC_RESET */ -#define BUF_CONTROL_NOP 0x01040000 -#define BUF_CONTROL_AUDIO_CHANNEL 0x01050000 -#define BUF_CONTROL_SPU_CHANNEL 0x01060000 -#define BUF_CONTROL_NEWPTS 0x01070000 -#define BUF_CONTROL_RESET_DECODER 0x01080000 - -/* video buffer types: (please keep in sync with buffer_types.c) */ - -#define BUF_VIDEO_BASE 0x02000000 -#define BUF_VIDEO_MPEG 0x02000000 -#define BUF_VIDEO_MPEG4 0x02010000 -#define BUF_VIDEO_CINEPAK 0x02020000 -#define BUF_VIDEO_SORENSON 0x02030000 -#define BUF_VIDEO_MSMPEG4_V12 0x02040000 -#define BUF_VIDEO_MSMPEG4_V3 0x02050000 -#define BUF_VIDEO_MJPEG 0x02060000 -#define BUF_VIDEO_IV50 0x02070000 -#define BUF_VIDEO_IV41 0x02080000 -#define BUF_VIDEO_IV32 0x02090000 -#define BUF_VIDEO_IV31 0x020a0000 -#define BUF_VIDEO_ATIVCR1 0x020b0000 -#define BUF_VIDEO_ATIVCR2 0x020c0000 -#define BUF_VIDEO_I263 0x020d0000 -#define BUF_VIDEO_RV10 0x020e0000 -#define BUF_VIDEO_RGB 0x02100000 -#define BUF_VIDEO_YUY2 0x02110000 -#define BUF_VIDEO_JPEG 0x02120000 -#define BUF_VIDEO_WMV7 0x02130000 -#define BUF_VIDEO_WMV8 0x02140000 -#define BUF_VIDEO_MSVC 0x02150000 -#define BUF_VIDEO_DV 0x02160000 -#define BUF_VIDEO_REAL 0x02170000 -#define BUF_VIDEO_VP31 0x02180000 -#define BUF_VIDEO_H263 0x02190000 -#define BUF_VIDEO_3IVX 0x021A0000 - -/* audio buffer types: (please keep in sync with buffer_types.c) */ - -#define BUF_AUDIO_BASE 0x03000000 -#define BUF_AUDIO_A52 0x03000000 -#define BUF_AUDIO_MPEG 0x03010000 -#define BUF_AUDIO_LPCM_BE 0x03020000 -#define BUF_AUDIO_LPCM_LE 0x03030000 -#define BUF_AUDIO_DIVXA 0x03040000 -#define BUF_AUDIO_DTS 0x03050000 -#define BUF_AUDIO_MSADPCM 0x03060000 -#define BUF_AUDIO_IMAADPCM 0x03070000 -#define BUF_AUDIO_MSGSM 0x03080000 -#define BUF_AUDIO_VORBIS 0x03090000 -#define BUF_AUDIO_IMC 0x030a0000 -#define BUF_AUDIO_LH 0x030b0000 -#define BUF_AUDIO_VOXWARE 0x030c0000 -#define BUF_AUDIO_ACELPNET 0x030d0000 -#define BUF_AUDIO_AAC 0x030e0000 -#define BUF_AUDIO_REAL 0x030f0000 -#define BUF_AUDIO_VIVOG723 0x03100000 - - -/* spu buffer types: */ - -#define BUF_SPU_BASE 0x04000000 -#define BUF_SPU_CLUT 0x04000000 -#define BUF_SPU_PACKAGE 0x04010000 -#define BUF_SPU_SUBP_CONTROL 0x04020000 -#define BUF_SPU_NAV 0x04030000 -#define BUF_SPU_TEXT 0x04040000 - -/* demuxer block types: */ - -#define BUF_DEMUX_BLOCK 0x05000000 - - - The control buffer types are very important and must be sent by all kind 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 - type. - - - buf->type = fourcc_to_buf_video((void*)this->avi->bih.biCompression); - this->video_fifo->put (this->video_fifo, buf); - - - - - Adding support for a new audio/video format - (writing a decoder) - - - - Adding support for a new media type, - e.g. disc format, network transport method - (writing an input plugin) - - 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 specialist medium - (e.g. DVD), etc. To allow you to access 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 recognises. - 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. - - - The plugin struct input_plugin_t (defined in - xine/input_plugin.h) has the following - definition: - - -struct input_plugin_s { - - /* - * return capabilities of the current playable entity. See - * get_current_pos below for a description of a "playable entity" - * Capabilities a created by "OR"ing a mask of constants listed - * below which start "INPUT_CAP". - * - * depending on the values set, some of the functions below - * will or will not get called or should (not) be able to - * do certain tasks. - * - * for example if INPUT_CAP_SEEKABLE is set, - * the seek() function is expected to work fully at any time. - * however, if the flag is not set, the seek() function should - * make a best-effort attempt to seek, e.g. at least - * relative forward seeking should work. - */ - uint32_t (*get_capabilities) (input_plugin_t *this); - - /* - * read nlen bytes, return number of bytes read - */ - off_t (*read) (input_plugin_t *this, char *buf, off_t nlen); - - - /* - * read one block, return newly allocated block (or NULL on failure) - * for blocked input sources len must be == blocksize - * the fifo parameter is only used to get access to the buffer_pool_alloc function - */ - buf_element_t *(*read_block)(input_plugin_t *this, fifo_buffer_t *fifo, off_t len); - - - /* - * seek position, return new position - * - * if seeking failed, -1 is returned - */ - off_t (*seek) (input_plugin_t *this, off_t offset, int origin); - - - /* - * get current position in stream. - * - */ - off_t (*get_current_pos) (input_plugin_t *this); - - - /* - * return number of bytes in the next playable entity or -1 if the - * input is unlimited, as would be the case in a network stream. - * - * A "playable entity" tends to be the entities listed in a playback - * list or the units on which playback control generally works on. - * It might be the number of bytes in a VCD "segment" or "track" (if - * the track has no "entry" subdivisions), or the number of bytes in - * a PS (Program Segment or "Chapter") of a DVD. If there are no - * subdivisions of the input medium and it is considered one - * indivisible entity, it would be the byte count of that entity; - * for example, the length in bytes of an MPEG file. - - * This length information is used, for example when in setting the - * absolute or relative play position or possibly calculating the - * bit rate. - */ - off_t (*get_length) (input_plugin_t *this); - - - /* - * return block size in bytes of next complete playable entity (if - * supported, 0 otherwise). See the description above under - * get_length for a description of a "complete playable entity". - * - * this block size is only used for mpeg streams stored on - * a block oriented storage media, e.g. DVDs and VCDs, to speed - * up the demuxing process. only set this (and the INPUT_CAP_BLOCK - * flag) if this is the case for your input plugin. - * - * make this function simply return 0 if unsure. - */ - - uint32_t (*get_blocksize) (input_plugin_t *this); - - - /* - * return current MRL - */ - char * (*get_mrl) (input_plugin_t *this); - - - /* - * request optional data from input plugin. - */ - int (*get_optional_data) (input_plugin_t *this, void *data, int data_type); - - - /* - * close stream, free instance resources - */ - void (*dispose) (input_plugin_t *this); - - /* - * "backward" link to input plugin class struct - */ - - input_class_t *input_class; - -}; - - - The get_capabilities parameter points to a function - which returns a bit mask describing the input device's capabilities. - You may logically OR the following constants together to get - a suitable bit-mask (via the '|' operator). - - - - - INPUT_CAP_NOCAP -- Input device has no capabilities (alias for '0'). - - - - - INPUT_CAP_SEEKABLE -- Input device may be 'seeked' (i.e. - random access is possible, usually not available on, e.g., network - streams). - - - - - INPUT_CAP_BLOCK -- Input device has a prefered block size (i.e. is - block-oriented). - - - - - INPUT_CAP_AUTOPLAY -- Device can return an 'autoplay' list. - - - - - INPUT_CAP_GET_DIR -- Device supports the concept of 'directorys' or - 'folders' containing other MRLs. - - - - - INPUT_CAP_BROWSABLE -- Device supports possible MRL enumeration and - browsing via the MRL browser. - - - - - INPUT_CAP_CLUT -- Somewhat of an obsolete kludge. Device supports - the querying of sub-picture-unit colour palettes. - - - - - INPUT_CAP_AUDIOLANG -- Device supports multiple audio streams with - different names. - - - - - INPUT_CAP_SPULANG -- Device supports multiple sub-picture-unit (SPU) - streams with different names. - - - - - INPUT_CAP_VARIABLE_BITRATE -- xine may not experimentally read from the - plugin in order to guestimate bit-rate. - - - - - INPUT_CAP_PREVIEW -- xine may attempt preview mode. - Requires INPUT_CAP_SEEKABLE. Most input plugins that are SEEKABLE are - also PREVIEWable. xine-dvdnav is an exception to this because it blocks - the input during a still video image. E.g DVD Menus. - - - - - - The open parameter points to a function which accepts - an MRL and returns a flag indicating whether this plugin accepts the - MRL or not. Note that input plugins are not guaranteed to be queried - in anay particular order and the first input plugin to claim an MRL - gets control so try not to duplicate MRLs already found within xine. - You should also do any device-specific initialisation within this - function. - - - The close parameter points to a function which - cleans up after open. - - - The read reads a specified number of bytes into - a buffer and returns the number of bytes actually copied. - - - Should the input plugin set the block-oriented hint and if the - demuxer supports it, the function pointed to by - read_block will be called to read a block directly - into xine's demuxer FIFO buffer. - - - The seek parameter points to a function called by - xine when it is required that subsequent reads come from another part - of the stream. - - - The get_current_pos parameter points to a function - which returns the current position within a finite length stream. - Similarly the get_length function returns the - length of the stream. - - - The get_blocksize parameter points to a function - which returns the device's prefered block-size if applicable. - - - The get_dir parameter point to a function - which returns a NULL terminated - array of pointers to MRLs which are within the 'directory' passed. - - - The eject_media parameter points to a function - called when the user requests that the media be 'ejected' if possible. - - - The get_mrl parameter points to a function which - returns the current MRL. - - - The stop parameter points to a function which - stops (but does not close) the input device. - - - get_identifier points to a function returning a - (short) human-readable description for the plugin (e.g. CDA, NAV, DVD). - - - get_autoplay_list points to a function returning - a NULL-temrinated array of MRLs which arise due to the 'autoplay' - feature of the plugin. - - - - -Extending xine's output - - Adding support for a new type of video output - (e.g. framebuffer device) - - 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 a vo_frame_s structure and its - 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 importantly, the ability to render/copy a given - frame to the output device. - - - - (Optional) 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 scalaing 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. - - - All video plugins take the form of a shared library which exports at least - the functions init_video_out_plugin() and - get_video_out_plugin_info() which - returns a pointer to a vo_info_s. This structure has the - following declaration: - - - struct vo_info_s { - int interface_version; /* plugin interface version */ - char *id; /* id of this plugin */ - char *description; /* human-readable description of this plugin */ - int visual_type; /* visual type supported by this plugin */ - int priority; /* priority of this plugin for auto-probing */ - }; - - At the time of writing, the current interface version was `3' but - you may wish to look at an existing plugin's source-code to check. - - - The visual_type field is used by the xine UI to - determine if it is supported by the UI (e.g. X11 output plugins require - the GUI to be running under the X Windowing system) and also to - determine the information passed to the - init_video_out_plugin() function. - The library must also export this function and it has the following - declaration: - - - vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) - - The arguments to the function are as follows - - - - config -- A pointer to an object which - allows you to register, change and access configuration information. - See elsewhere in this document for more information. - - - visual_gen -- 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 the Display variable associated with the - X-server xine is running under. See plugin source-code for other - VISUAL_TYPE_... constants and associated structures. Note that this - field is provided by the UI and so if you wish to add another visual - type you will either need to extend an existing UI or write a new - one. - - - - The function creates and returns a pointer to a vo_driver_s - structure which contains the following function pointers: - - -struct vo_driver_s { - - uint32_t (*get_capabilities) (vo_driver_t *this); /* for constants see above */ - - /* - * allocate an vo_frame_t struct, - * the driver must supply the copy, field and dispose functions - */ - vo_frame_t* (*alloc_frame) (vo_driver_t *this); - - - /* - * check if the given image fullfills the format specified - * (re-)allocate memory if necessary - */ - void (*update_frame_format) (vo_driver_t *this, vo_frame_t *img, - uint32_t width, uint32_t height, - int ratio_code, int format, int flags); - - /* display a given frame */ - void (*display_frame) (vo_driver_t *this, vo_frame_t *vo_img); - - /* overlay_begin and overlay_end are used by drivers suporting - * persistent overlays. they can be optimized to update only when - * overlay image has changed. - * - * sequence of operation (pseudo-code): - * overlay_begin(this,img,true_if_something_changed_since_last_blend ); - * while(visible_overlays) - * overlay_blend(this,img,overlay[i]); - * overlay_end(this,img); - * - * any function pointer from this group may be set to NULL. - */ - void (*overlay_begin) (vo_driver_t *this, vo_frame_t *vo_img, int changed); - void (*overlay_blend) (vo_driver_t *this, vo_frame_t *vo_img, vo_overlay_t *overlay); - void (*overlay_end) (vo_driver_t *this, vo_frame_t *vo_img); - - /* - * these can be used by the gui directly: - */ - - int (*get_property) (vo_driver_t *this, int property); - int (*set_property) (vo_driver_t *this, - int property, int value); - void (*get_property_min_max) (vo_driver_t *this, - int property, int *min, int *max); - - /* - * general purpose communication channel between gui and driver - * - * this should be used to propagate events, display data, window sizes - * etc. to the driver - */ - - int (*gui_data_exchange) (vo_driver_t *this, int data_type, - void *data); - - /* check if a redraw is needed (due to resize) - * this is only used for still frames, normal video playback - * must call that inside display_frame() function. - */ - int (*redraw_needed) (vo_driver_t *this); - - /* - * free all resources, close driver - */ - - void (*dispose) (vo_driver_t *this); - - void *node; /* needed by plugin_loader */ -}; - - - The get_info field is simply a pointer to the - get_video_out_plugin_info() function described - above. - - - The get_capbilities field points to a function - which returns a bit-wise ORed combination of the following constants - which reflects the video output plugin's capabilities. - - - -#define VO_CAP_COPIES_IMAGE 0x00000001 /* driver copies image (i.e. converts it to - rgb buffers in the private fields of - image buffer) */ - -#define VO_CAP_YV12 0x00000002 /* driver can handle YUV 4:2:0 pictures */ -#define VO_CAP_YUY2 0x00000004 /* driver can handle YUY2 pictures */ - -#define VO_CAP_HUE 0x00000010 /* driver can set HUE value */ -#define VO_CAP_SATURATION 0x00000020 /* driver can set SATURATION value */ -#define VO_CAP_BRIGHTNESS 0x00000040 /* driver can set BRIGHTNESS value */ -#define VO_CAP_CONTRAST 0x00000080 /* driver can set CONTRAST value */ -#define VO_CAP_COLORKEY 0x00000100 /* driver can set COLORKEY value */ -#define VO_CAP_AUTOPAINT_COLORKEY 0x00000200 /* driver can set AUTOPAINT_COLORKEY value */ - - - - A plugin should use the VO_CAP_COPIES_IMAGE flag if it wishes to provide a - copy function to perform on-the-fly colour-space conversion and - scaling. - - - The get_property, set_proprty and - get_property_min_max fields point to functions which - handle the getting, setting of properties and define their bounds. - Valid property IDs can be found in the video_out.h - header file. - - - The gui_data_exchange field points to a function which can - accept 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. - - - The alloc_frame field points to a function which returns - a pointer to a vo_frame_s structure which is defined as: - - -struct vo_frame_s { - struct vo_frame_s *next; - - int64_t pts; /* presentation time stamp (1/90000 sec) */ - int64_t vpts; /* virtual pts, generated by metronom */ - int bad_frame; /* e.g. frame skipped or based on skipped frame */ - int duration; /* frame length in time, in 1/90000 sec */ - - /* yv12 (planar) base[0]: y, base[1]: u, base[2]: v */ - /* yuy2 (interleaved) base[0]: yuyv..., base[1]: --, base[2]: -- */ - uint8_t *base[3]; - - /* info that can be used for interlaced output (e.g. tv-out) */ - int top_field_first; - int repeat_first_field; - - /* pan/scan offset */ - int pan_scan_x; - int pan_scan_y; - - /* additional information to be able to duplicate frames: */ - int width, height; - int ratio; /* aspect ratio, codes see below */ - int format; /* IMGFMT_YV12 or IMGFMT_YUY2 */ - - int drawn; /* used by decoder, frame has already been drawn */ - - int lock_counter; - pthread_mutex_t mutex; /* protect access to lock_count */ - - /* "backward" references to where this frame originates from */ - vo_instance_t *instance; - vo_driver_t *driver; - - int id; /* debugging - track this frame */ - - /* - * member functions - */ - - /* this frame is no longer used by the decoder */ - void (*free) (vo_frame_t *vo_img); - - /* tell video driver to copy/convert a slice of this frame, may be NULL */ - void (*copy) (vo_frame_t *vo_img, uint8_t **src); - - /* tell video driver that the decoder starts a new field */ - void (*field) (vo_frame_t *vo_img, int which_field); - - /* append this frame to the display queue, - returns number of frames to skip if decoder is late */ - int (*draw) (vo_frame_t *vo_img); - - /* this frame is no longer used by the video driver */ - void (*displayed) (vo_frame_t *vo_img); - - /* free memory/resources for this frame */ - void (*dispose) (vo_frame_t *vo_img); -}; - - - Typically the video plugin will add private fields to the end of this structure - which are used for internal purposes by the plugin. - - - The function pointers within the frame structure provides 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. - - - Returning to the vo_driver_s structure, the - update_frame_format field points to a function which 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 and driver-specific changes. - - - The display_frame field points to a function to render a - given frame to the output device. - - - The overlay_blend field points to a function which accepts - an association between a frame and overlay which will result in the latter - being overlayed on the former. - - - - Adding support for a new type of audio output - - - - -Using xine as a library - - Writing a new frontend to xine - - - 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. -** -*/ -#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> - -#ifndef XShmGetEventBase -extern int XShmGetEventBase(Display *); -#endif - -#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 completion_event; -static int xpos, ypos, width, height, fullscreen; -static double pixel_aspect; - -static int running = 0; - - -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) { - - if(!running) - return; - - *dest_width = width; - *dest_height = height; - *dest_pixel_aspect = pixel_aspect; -} - -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) { - if(!running) - return; - - *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; - - } -} - -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; - int i; - Atom XA_NO_BORDER; - MWMHints mwmhints; - - if(argc <= 1) { - printf("specify an mrl\n"); - return 1; - } - - for(i = 1; i < argc; i++) { - if(!strcmp(argv[i], "-vo")) { - vo_driver = argv[++i]; - } - else if(!strcmp(argv[i], "-ao")) { - ao_driver = argv[++i]; - } - else - mrl = argv[i]; - } - - mrl = argv[1]; - printf("mrl: '%s'\n", mrl); - - if(!XInitThreads()) { - printf("XInitThreads() failed\n"); - return 1; - } - - xine = xine_new(); - sprintf(configfile, "%s%s", xine_get_homedir(), "/.xine/config2"); - xine_config_load(xine, configfile); - xine_init(xine); - - display = XOpenDisplay(NULL); - screen = XDefaultScreen(display); - xpos = 0; - ypos = 0; - width = 320; - height = 200; - - 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], (ExposureMask | ButtonPressMask | KeyPressMask | - ButtonMotionMask | StructureNotifyMask | - PropertyChangeMask | PointerMotionMask)); - - XSelectInput(display, window[1], (ExposureMask | ButtonPressMask | KeyPressMask | - ButtonMotionMask | StructureNotifyMask | - PropertyChangeMask | PointerMotionMask)); - - 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); - - if(XShmQueryExtension(display) == True) - completion_event = XShmGetEventBase(display) + ShmCompletion; - else - completion_event = -1; - - 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); - - 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; - - if(fabs(pixel_aspect - 1.0) < 0.01) - pixel_aspect = 1.0; - - 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); - - stream = xine_stream_new(xine, ao_port, vo_port); - event_queue = xine_event_new_queue(stream); - xine_event_create_listener_thread(event_queue, event_listener, NULL); - - xine_gui_send_vo_data(stream, XINE_GUI_SEND_DRAWABLE_CHANGED, (void *) window[fullscreen]); - xine_gui_send_vo_data(stream, XINE_GUI_SEND_VIDEOWIN_VISIBLE, (void *) 1); - - if((!xine_open(stream, mrl)) || (!xine_play(stream, 0, 0))) { - printf("Unable to open mrl '%s'\n", mrl); - return 1; - } - - running = 1; - - while(running) { - XEvent xevent; - - XNextEvent(display, &xevent); - - 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: - running = 0; - break; - - case XK_f: - case XK_F: - { - 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_gui_send_vo_data(stream, XINE_GUI_SEND_DRAWABLE_CHANGED, - (void*) window[fullscreen]); - } - break; - - case XK_Up: - xine_set_param(stream, XINE_PARAM_AUDIO_VOLUME, - (xine_get_param(stream, XINE_PARAM_AUDIO_VOLUME) + 1)); - break; - - case XK_Down: - xine_set_param(stream, XINE_PARAM_AUDIO_VOLUME, - (xine_get_param(stream, XINE_PARAM_AUDIO_VOLUME) - 1)); - break; - - case XK_plus: - xine_set_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, - (xine_get_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL) + 1)); - break; - - case XK_minus: - xine_set_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, - (xine_get_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL) - 1)); - break; - - case XK_space: - 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: - if(xevent.xexpose.count != 0) - break; - xine_gui_send_vo_data(stream, 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; - - } - - if(xevent.type == completion_event) - xine_gui_send_vo_data(stream, XINE_GUI_SEND_COMPLETION_EVENT, &xevent); - } - - 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 1; -} - -/* - * Local variables: - * compile-command: "gcc -Wall -O2 `xine-config --cflags` `xine-config --libs` -lX11 -lm -o xinimin xinimin.c" - * End: - */ - - - - - -misc - - 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 appreciated if they do. - - - - when in doubt, use lower case. BTW: This thing is called xine, never Xine. - - - - - comment your interfaces in the header files. - - - - - 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 if possible. avoid gotos. - - - - - use - - #ifdef LOG - printf ("module: ..."[,...]); - #endif - - for debug output. All debug output 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. - - - - - use c-style comments (/* */), not c++-style (//) - - - - - - - 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 otherwise instructed - 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). - - - + + &intro; + &library; + &overview; + &internals; + &stream; + &output; - -- cgit v1.2.3