diff options
Diffstat (limited to 'src/xine-engine')
-rw-r--r-- | src/xine-engine/Makefile.am | 82 | ||||
-rw-r--r-- | src/xine-engine/attributes.h | 27 | ||||
-rw-r--r-- | src/xine-engine/audio_decoder.c | 194 | ||||
-rw-r--r-- | src/xine-engine/audio_decoder.h | 66 | ||||
-rw-r--r-- | src/xine-engine/buffer.c | 225 | ||||
-rw-r--r-- | src/xine-engine/buffer.h | 147 | ||||
-rw-r--r-- | src/xine-engine/configfile.c | 293 | ||||
-rw-r--r-- | src/xine-engine/configfile.h | 101 | ||||
-rw-r--r-- | src/xine-engine/cpu_accel.c | 110 | ||||
-rw-r--r-- | src/xine-engine/cpu_accel.h | 514 | ||||
-rw-r--r-- | src/xine-engine/load_plugins.c | 200 | ||||
-rw-r--r-- | src/xine-engine/metronom.c | 298 | ||||
-rw-r--r-- | src/xine-engine/metronom.h | 179 | ||||
-rw-r--r-- | src/xine-engine/monitor.c | 84 | ||||
-rw-r--r-- | src/xine-engine/monitor.h | 89 | ||||
-rw-r--r-- | src/xine-engine/utils.c | 125 | ||||
-rw-r--r-- | src/xine-engine/utils.h | 39 | ||||
-rw-r--r-- | src/xine-engine/video_decoder.c | 180 | ||||
-rw-r--r-- | src/xine-engine/video_decoder.h | 73 | ||||
-rw-r--r-- | src/xine-engine/xine.c | 607 | ||||
-rw-r--r-- | src/xine-engine/xine_internal.h | 76 |
21 files changed, 3709 insertions, 0 deletions
diff --git a/src/xine-engine/Makefile.am b/src/xine-engine/Makefile.am new file mode 100644 index 000000000..993659dc1 --- /dev/null +++ b/src/xine-engine/Makefile.am @@ -0,0 +1,82 @@ +## +## Process this file with automake to produce Makefile.in +## + +CFLAGS = @GLOBAL_CFLAGS@ + +lib_LTLIBRARIES = libxine.la + +if HAVE_W32DLL +W32_LIBS = $(top_srcdir)/src/libw32dll/libw32dll.la +endif + +##libxine_la_SOURCES = xine.c buffer.c metronom.c configfile.c \ +## monitor.c utils.c audio_decoder.c video_decoder.c load_plugins.c +libxine_la_SOURCES = metronom.c configfile.c monitor.c utils.c cpu_accel.c +libxine_la_DEPENDENCIES = libsdeps +libxine_la_LIBADD = \ + $(top_srcdir)/src/demuxers/libdemux.la \ + $(top_srcdir)/src/libmpeg2/libmpeg2.la \ + $(top_srcdir)/src/libac3/libac3.la \ + $(top_srcdir)/src/libmpg123/libmpg123.la \ + $(W32_LIBS) \ +## $(top_srcdir)/src/libspudec/libspudec.la \ + $(THREAD_LIBS) \ + $(DYNAMIC_LD_LIBS) + -lXext -lm +libxine_la_LDFLAGS = -version-info 5:0:5 + +include_HEADERS = buffer.h metronom.h configfile.h \ + monitor.h cpu_accel.h attributes.h utils.h audio_decoder.h \ + video_decoder.h +noinst_HEADERS = xine_internal.h + +cpu_accel.lo: + $(CC) -DHAVE_CONFIG_H $(INCLUDES) -pipe `echo "@DEBUG_CFLAGS@" | sed -e 's/\-DDEBUG//' -e 's/\-g//'` -fomit-frame-pointer -Wall -Wp,-MD,.deps/cpu_accel.P -c $(basename $@).c -o $@ +# echo timestamp > $(basename $@).o + + +debug: + $(MAKE) CFLAGS="$(DEBUG_CFLAGS)" + + +libsdeps: +## @cd $(top_builddir)/src/demuxers && $(MAKE) libdemux.la +## @cd $(top_builddir)/src/libmpeg2 && $(MAKE) libmpeg2.la +## @cd $(top_builddir)/src/libac3 && $(MAKE) libac3.la +## @cd $(top_builddir)/src/libmpg123 && $(MAKE) libmpg123.la +##@W32DLL_DEP@ @cd $(top_builddir)/src/libw32dll && $(MAKE) libw32dll.la +## @cd $(top_builddir)/src/libspudec && $(MAKE) libspudec.la + + +## +## Install header files (default=$includedir/xine) +## +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(includedir)/xine + @list='$(include_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \ + echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/xine/$$p"; \ + $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/xine/$$p; \ + done + + +## +## Remove them +## +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + list='$(include_HEADERS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(includedir)/xine/$$p; \ + done + + +mostlyclean-generic: + -rm -f *~ \#* .*~ .\#* + + +maintainer-clean-generic: + -@echo "This command is intended for maintainers to use;" + -@echo "it deletes files that may require special tools to rebuild." + -rm -f Makefile.in diff --git a/src/xine-engine/attributes.h b/src/xine-engine/attributes.h new file mode 100644 index 000000000..8ed7aef9e --- /dev/null +++ b/src/xine-engine/attributes.h @@ -0,0 +1,27 @@ +/* + * attributes.h + * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * + * mpeg2dec 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. + * + * mpeg2dec 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 + */ + +//use gcc attribs to align critical data structures +#ifdef ATTRIBUTE_ALIGNED_MAX +#define ATTR_ALIGN(align) __attribute__ ((__aligned__ ((ATTRIBUTE_ALIGNED_MAX < align) ? ATTRIBUTE_ALIGNED_MAX : align))) +#else +#define ATTR_ALIGN(align) +#endif diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c new file mode 100644 index 000000000..f879093e0 --- /dev/null +++ b/src/xine-engine/audio_decoder.c @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: audio_decoder.c,v 1.1 2001/04/18 22:36:01 f1rmb Exp $ + * + * + * functions that implement audio decoding + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "audio_decoder.h" + +#define MAX_NUM_DECODERS 10 + +typedef struct ad_globals_s { + + pthread_t mAudioThread; + + fifo_buffer_t *mBufAudio; + + audio_decoder_t *mDecoders[MAX_NUM_DECODERS]; + audio_decoder_t *mCurDecoder; + + uint32_t mnCurPos; + + ao_instance_t *mAudioOut + + gui_status_callback_func_t gui_status_callback; + + int mbStreamFinished; + + pthread_mutex_t mXineLock; + +} ad_globals_t; + +static ad_globals_t gAD; + + +void *audio_decoder_loop (void *dummy) { + + buf_element_t *pBuf; + int bRunning = 1; + + while (bRunning) { + + pBuf = gAD.mBufAudio->fifo_buffer_get (gAD.mBufAudio); + + if (gAD.mAudioOut) { + + gAD.mnCurPos = pBuf->nInputPos; + + /* + if (gXine.mnStatus == XINE_PLAY) + gXine.mStatusCallback (gXine.mnStatus); + */ + + switch (pBuf->nType) { + + case BUF_STREAMSTART: + if (gAD.mCurDecoder) { + gAD.mCurDecoder->close (); + gAD.mCurDecoder = NULL; + } + + pthread_mutex_lock (&gAD.mXineLock); + gAD.mbStreamFinished = 0; + pthread_mutex_unlock (&gAD.mXineLock); + + break; + + case BUF_AC3AUDIO: + case BUF_MPEGAUDIO: + case BUF_MSAUDIO: + case BUF_LINEARPCM: + + decoder = gAD.mDecoders [pBuf->nType]; + + if (decoder) { + if (gAD.mCurDecoder != decoder) { + + if (gAD.mCurDecoder) + gAD.mCurDecoder->close (); + + gAD.mCurDecoder = decoder; + gAD.mCurDecoder->init (gAD.mVideoOut); + + } + + decoder->decode_data (pBuf); + } + + break; + + case BUF_STREAMEND: + if (gAD.mCurDecoder) { + gAD.mCurDecoder->close (); + gAD.mCurDecoder = NULL; + } + + gAD.mbStreamFinished = 1; + + pthread_mutex_lock (&gAD.mXineLock); + + gVD.mbStreamFinished = 1; + + if (video_decoder_is_stream_finished ()) { + pthread_mutex_unlock (&gAD.mXineLock); + xine_notify_stream_finished (); + } else + pthread_mutex_unlock (&gAD.mXineLock); + + break; + + case BUF_QUIT: + if (gAD.mCurDecoder) { + gAD.mCurDecoder->close (); + gAD.mCurDecoder = NULL; + } + bRunning = 0; + break; + + } + } + pBuf->free_buffer (pBuf); + } + + return NULL; +} + +int audio_decoder_is_stream_finished () { + return gAD.mbStreamFinished ; +} + +uint32_t audio_decoder_get_pos () { + return gAD.mnCurPos; +} + +fifo_buffer_t *audio_decoder_init (ao_instance_t *audio_out, + pthread_mutex_t xine_lock) { + + gAD.mAudioOut = audio_out; + gAD.mXineLock = xine_lock; + + gAD.mCurDecoder = NULL; + for (i=0; i<MAX_NUM_DECODERS; i++) + gAD.mDecoders[i] = NULL; + + gAD.mDecoders[BUF_AC3AUDIO] = init_audio_decoder_ac3dec (); + gAD.mDecoders[BUF_MPEGAUDIO] = init_audio_decoder_mpg123 (); + gAD.mDecoders[BUF_MSAUDIO] = init_audio_decoder_msaudio (); + gAD.mDecoders[BUF_LINEARPCM] = init_audio_decoder_linearpcm (); + + gAD.mBufAudio = fifo_buffer_new (); + + pthread_create (&gAD.mAudioThread, NULL, audio_decoder_loop, NULL) ; + + printf ("audio_decoder_init: audio thread created\n"); + + return gAD.mBufAudio; +} + +void audio_decoder_shutdown () { + + buf_element_t *pBuf; + + gAD.mBufAudio->fifo_buffer_clear(gAD.mBufAudio); + + pBuf = gAD.mBufAudio->buffer_pool_alloc (); + pBuf->nType = BUF_QUIT; + gAD.mBufAudio->fifo_buffer_put (gAD.mBufAudio, pBuf); + + pthread_join (gAD.mAudioThread, &p); +} + + diff --git a/src/xine-engine/audio_decoder.h b/src/xine-engine/audio_decoder.h new file mode 100644 index 000000000..b7d6e4243 --- /dev/null +++ b/src/xine-engine/audio_decoder.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: audio_decoder.h,v 1.1 2001/04/18 22:36:05 f1rmb Exp $ + * + * + * functions that implement audio decoding + */ + +#ifndef HAVE_VIDEO_DECODER_H +#define VIDEO_DECODER_H + +#include "buffer.h" + +/* + * generic xine audio decoder plugin interface + */ + +typedef struct audio_decoder_s +{ + + /* get interface version */ + int (*get_version) (void); + + int (*can_handle) (int buf_type); + + void (*init) (ao_instance_t *audio_out); + + void (*decode_data) (buf_element_t *buf); + + void (*close) (void); + +} audio_decoder_t; + +/* + * init audio decoders, allocate audio fifo, + * start audio decoder thread + */ + +fifo_buffer_t *audio_decoder_init (ao_instance_t *audio_out, + pthread_mutex_t xine_lock) ; + +/* + * quit audio thread + */ + +void audio_decoder_shutdown (); + + +#endif diff --git a/src/xine-engine/buffer.c b/src/xine-engine/buffer.c new file mode 100644 index 000000000..c45a93cb6 --- /dev/null +++ b/src/xine-engine/buffer.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: buffer.c,v 1.1 2001/04/18 22:36:01 f1rmb Exp $ + * + * + * contents: + * + * buffer_entry structure - serves as a transport encapsulation + * of the mpeg audio/video data through xine + * + * free buffer pool management routines + * + * FIFO buffer structures/routines + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "buffer.h" +#include "utils.h" + +/* + * global variables + */ + +buf_element_t *gBufferPoolTop; /* a stack actually */ +pthread_mutex_t gBufferPoolMutex; +pthread_cond_t gBufferPoolCondNotEmpty; +int gBufferPoolNumFree; + +/* + * put a previously allocated buffer element back into the buffer pool + */ +static void buffer_pool_free (buf_element_t *pBufElement) { + + pthread_mutex_lock (&gBufferPoolMutex); + + pBufElement->next = gBufferPoolTop; + gBufferPoolTop = pBufElement; + + gBufferPoolNumFree++; + + pthread_cond_signal (&gBufferPoolCondNotEmpty); + + pthread_mutex_unlock (&gBufferPoolMutex); +} + +/* + * check if there are no more free elements + */ +static int buffer_pool_isempty (void) { + return gBufferPoolNumFree<7; +} + +/* + * check if there are no more free elements + */ +static buf_element_t *buffer_pool_alloc (void) { + + buf_element_t *pBuf; + + pthread_mutex_lock (&gBufferPoolMutex); + + while (!gBufferPoolTop) { + pthread_cond_wait (&gBufferPoolCondNotEmpty, &gBufferPoolMutex); + } + + pBuf = gBufferPoolTop; + gBufferPoolTop = gBufferPoolTop->next; + gBufferPoolNumFree--; + + pthread_mutex_unlock (&gBufferPoolMutex); + + return pBuf; +} + +/* + * append buffer element to fifo buffer + */ +static void fifo_buffer_put (fifo_buffer_t *pFifo, buf_element_t *pBufElement) { + + pthread_mutex_lock (&pFifo->mMutex); + + if (pFifo->mpLast) + pFifo->mpLast->next = pBufElement; + else + pFifo->mpFirst = pBufElement; + + pFifo->mpLast = pBufElement; + pBufElement->next = NULL; + + pthread_cond_signal (&pFifo->mNotEmpty); + + pthread_mutex_unlock (&pFifo->mMutex); +} + +/* + * get element from fifo buffer + */ +static buf_element_t *fifo_buffer_get (fifo_buffer_t *pFifo) { + + buf_element_t *pBuf; + + pthread_mutex_lock (&pFifo->mMutex); + + while (pFifo->mpFirst==NULL) { + pthread_cond_wait (&pFifo->mNotEmpty, &pFifo->mMutex); + } + + pBuf = pFifo->mpFirst; + + pFifo->mpFirst = pFifo->mpFirst->next; + if (pFifo->mpFirst==NULL) + pFifo->mpLast = NULL; + + pthread_mutex_unlock (&pFifo->mMutex); + + return pBuf; +} + +/* + * clear buffer (put all contained buffer elements back into buffer pool) + */ +static void fifo_buffer_clear (fifo_buffer_t *pFifo) { + + buf_element_t *pBuf; + + pthread_mutex_lock (&pFifo->mMutex); + + while (pFifo->mpFirst != NULL) { + + pBuf = pFifo->mpFirst; + + pFifo->mpFirst = pFifo->mpFirst->next; + if (pFifo->mpFirst==NULL) + pFifo->mpLast = NULL; + + buffer_pool_free (pBuf); + } + + pthread_mutex_unlock (&pFifo->mMutex); +} + +/* + * allocate and initialize new (empty) fifo buffer + */ +static fifo_buffer_t *fifo_buffer_new (void) { + + fifo_buffer_t *pFifo; + + pFifo = xmalloc (sizeof (fifo_buffer_t)); + + pFifo->mpFirst = NULL; + pFifo->mpLast = NULL; + pFifo->fifo_buffer_put = fifo_buffer_put; + pFifo->fifo_buffer_get = fifo_buffer_get; + pFifo->fifo_buffer_clear = fifo_buffer_clear; + + pthread_mutex_init (&pFifo->mMutex, NULL); + pthread_cond_init (&pFifo->mNotEmpty, NULL); + + return pFifo; +} + +/* + * init buffer pool, allocate nNumBuffers of buf_size bytes each + */ +fifobuf_functions_t *buffer_pool_init (int nNumBuffers, uint32_t buf_size) { + + int i; + const int alignment = 2048; + char *pMultiBuffer = NULL; + + if ((buf_size % alignment) == 0) { + printf ("Allocating %d buffers of %ld bytes in one chunk (alignment = %d)\n", nNumBuffers, (long int)buf_size, alignment); + pMultiBuffer = xmalloc_aligned (alignment, nNumBuffers * buf_size); + } + + gBufferPoolTop = NULL; + + pthread_mutex_init (&gBufferPoolMutex, NULL); + pthread_cond_init (&gBufferPoolCondNotEmpty, NULL); + + for (i = 0; i<nNumBuffers; i++) { + buf_element_t *pBuf; + + pBuf = xmalloc (sizeof (buf_element_t)); + + if (pMultiBuffer != NULL) { + pBuf->pMem = pMultiBuffer; + pMultiBuffer += buf_size; + } + else + pBuf->pMem = malloc_aligned (buf_size, alignment); + + pBuf->nMaxSize = buf_size; + pBuf->free_buffer = buffer_pool_free; + + buffer_pool_free (pBuf); + } + gBufferPoolNumFree = nNumBuffers; + + return &fifobuf_op; +} diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h new file mode 100644 index 000000000..a57d219ba --- /dev/null +++ b/src/xine-engine/buffer.h @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: buffer.h,v 1.1 2001/04/18 22:36:05 f1rmb Exp $ + * + * + * contents: + * + * buffer_entry structure - serves as a transport encapsulation + * of the mpeg audio/video data through xine + * + * free buffer pool management routines + * + * FIFO buffer structures/routines + * + */ + +#ifndef HAVE_BUFFER_H +#define HAVE_BUFFER_H + +#include <stdio.h> +#include <pthread.h> +#include <inttypes.h> + +/* + * 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 0x01000001 +#define BUF_CONTROL_QUIT 0x01000002 + +/* video buffer types: */ + +#define BUF_VIDEO_BASE 0x02000000 +#define BUF_VIDEO_MPEG 0x02000000 +#define BUF_VIDEO_OPENDIVX 0x02010000 +#define BUF_VIDEO_QUICKTIME 0x02020000 +#define BUF_VIDEO_AVI 0x02030000 + +/* audio buffer types: */ + +#define BUF_AUDIO_BASE 0x03000000 +#define BUF_AUDIO_AC3 0x03000000 +#define BUF_AUDIO_MPEG 0x03010000 +#define BUF_AUDIO_LPCM 0x03020000 +#define BUF_AUDIO_AVI 0x03030000 + +/* spu buffer types: */ + +#define BUF_SPU_BASE 0x04000000 +#define BUF_SPU_CLUT 0x04000000 +#define BUF_SPU_PACKAGE 0x04010000 + + +typedef struct buf_element_s buf_element_t; +struct buf_element_s { + buf_element_t *next; + + unsigned char *mem; + unsigned char *content; /* start of raw content in pMem (without header etc) */ + + uint32_t size ; /* size of _content_ */ + uint32_t max_size; + uint32_t type; + uint32_t PTS, DTS; + off_t input_pos; /* remember where this buf came from in the input source */ + int frame_end; /* avi */ + + void (*free_buffer) (buf_element_t *buf); + +} ; + +typedef struct fifo_buffer_s fifo_buffer_t; +struct fifo_buffer_s +{ + buf_element_t *first, *last; + + pthread_mutex_t mutex; + pthread_cond_t not_empty; + + /* + * functions to access this fifo: + */ + + void (*put) (fifo_buffer_t *fifo, buf_element_t *buf); + + buf_element_t *(*get) (fifo_buffer_t *fifo); + + void (*clear) (fifo_buffer_t *fifo) ; + + /* + * alloc buffer for this fifo from global buf pool + * you don't have to use this function to allocate a buffer, + * an input plugin can decide to implement it's own + * buffer allocation functions + */ + + buf_element_t *(*buffer_pool_alloc) (void); + +} ; + +/* + * allocate and initialize new (empty) fifo buffer + */ + +fifo_buffer_t *fifo_buffer_new (void); + +/* + * init global buffer pool, + * allocate nNumBuffers of buf_size bytes each + */ + +void buffer_pool_init (int num_buffers, uint32_t buf_size); + +#endif diff --git a/src/xine-engine/configfile.c b/src/xine-engine/configfile.c new file mode 100644 index 000000000..1903db791 --- /dev/null +++ b/src/xine-engine/configfile.c @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: configfile.c,v 1.1 2001/04/18 22:36:01 f1rmb Exp $ + * + * config file management - implementation + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "configfile.h" +#include "utils.h" + +typedef struct cfg_entry_s { + struct cfg_entry_s *next; + char *key, *value; +} cfg_entry_t; + +struct cfg_data_s { + cfg_entry_t *gConfig, *gConfigLast; +}; + + + +/* + * internal utility functions + *******************************/ + +void config_file_add (config_values_t *this, char *key, char *value) { + + cfg_entry_t *entry; + int len; + + entry = (cfg_entry_t *) xmalloc (sizeof (cfg_entry_t)); + + len = strlen (key); + entry->key = (char *) xmalloc (len+2); + strncpy (entry->key, key, len+1); + + len = strlen (value); + entry->value = (char *) xmalloc (len+21); + strncpy (entry->value, value, len+1); + + entry->next = NULL; + + if (this->data->gConfigLast) + this->data->gConfigLast->next = entry; + else + this->data->gConfig = entry; + + this->data->gConfigLast = entry; + +} + + + + +cfg_entry_t *config_file_search (config_values_t *this, char *key) { + cfg_entry_t *entry; + + entry = this->data->gConfig; + + while (entry && strcmp (entry->key, key)) + entry = entry->next; + + return entry; +} + + + +/* + * external interface + ***********************/ + +static char *config_file_lookup_str (config_values_t *this, + char *key, char*str_default) { + cfg_entry_t *entry; + + entry = config_file_search (this, key); + + if (entry) + return entry->value; + + config_file_add (this, key, str_default); + + return str_default; +} + + + + +static int config_file_lookup_int (config_values_t *this, + char *key, int n_default) { + + cfg_entry_t *entry; + char str[25]; + + entry = config_file_search (this, key); + + if (entry) { + int n; + + if (sscanf (entry->value, "%d", &n) == 1) + return n; + } + + sprintf (str, "%d", n_default); + + config_file_add (this, key, str); + + return n_default; +} + + + + +static void config_file_set_int (config_values_t *this, + char *key, int value) { + + cfg_entry_t *entry; + + entry = config_file_search (this, key); + + if (entry) { + sprintf (entry->value, "%d", value); + } + else { + char str[25]; + sprintf (str, "%d", value); + + config_file_add (this, key, str); + } +} + + + + +static void config_file_set_str (config_values_t *this, + char *key, char *value) { + + cfg_entry_t *entry; + + entry = config_file_search (this, key); + + if (entry) { + int len; + + free (entry->value); + + len = strlen (value); + entry->value = (char *) xmalloc (len+20); + strncpy (entry->value, value, len); + + } + else { + config_file_add (this, key, value); + } +} + + + + +static void config_file_save (config_values_t *this) { + FILE *f_config; + char filename[1024]; + + sprintf (filename, "%s/.xinerc", get_homedir()); + + f_config = fopen (filename, "w"); + + if (f_config) { + + cfg_entry_t *entry; + + fprintf (f_config, "#\n# xine config file\n#\n"); + + entry = this->data->gConfig; + + while (entry) { + fprintf (f_config, "%s:%s\n",entry->key,entry->value); + entry = entry->next; + } + + fclose (f_config); + } +} + + + + +static void config_file_read (config_values_t *this, char *filename){ + + FILE *f_config; + + f_config = fopen (filename, "r"); + + if (f_config) { + + char line[1024]; + char *value; + + while (fgets (line, 1023, f_config)) { + line[strlen(line)-1]= (char) 0; /* eliminate lf */ + + if (line[0] == '#') + continue; + + if ((value = strchr (line, ':'))) { + *value = (char) 0; + value++; + + config_file_add (this, line, value); + } + + } + + fclose (f_config); + } +} + + + + +config_values_t *config_file_init (char *filename) { + + config_values_t *this; + cfg_data_t *data; + + if ( (this = xmalloc(sizeof(config_values_t))) ) { + if ( (data = xmalloc(sizeof(cfg_data_t))) ) { + data->gConfig = NULL; + data->gConfigLast = NULL; + this->data = data; + config_file_read (this, filename); + + } + else { + fprintf (stderr, "WARNING: could not allocate config data\n"); + } + } + else { + fprintf (stderr, "WARNING: could not allocate config values list\n"); + } + + this->lookup_str = config_file_lookup_str; + this->lookup_int = config_file_lookup_int; + this->set_str = config_file_set_str; + this->set_int = config_file_set_int; + this->save = config_file_save; + this->read = config_file_read; + + return this; +} + + +/* + * $Log: configfile.c,v $ + * Revision 1.1 2001/04/18 22:36:01 f1rmb + * Initial revision + * + * Revision 1.8 2001/03/31 03:42:25 guenter + * more cleanups, started xv driver + * + * Revision 1.7 2001/03/28 12:30:25 siggi + * fixed init function + * added read function (multiple config files now supported) + * + * Revision 1.6 2001/03/27 17:12:49 siggi + * made config file handler a dynamic "object" + * + */ diff --git a/src/xine-engine/configfile.h b/src/xine-engine/configfile.h new file mode 100644 index 000000000..1e5de7be9 --- /dev/null +++ b/src/xine-engine/configfile.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: configfile.h,v 1.1 2001/04/18 22:36:05 f1rmb Exp $ + * + * config file management + * + */ + + +#ifndef HAVE_CONFIGFILE_H +#define HAVE_CONFIGFILE_H + +#include <inttypes.h> + +typedef struct config_values_s config_values_t; +typedef struct cfg_data_s cfg_data_t; + +struct config_values_s { + /* + * lookup config values + */ + char* (*lookup_str) (config_values_t *this, + char *key, char *str_default); + + int (*lookup_int) (config_values_t *this, + char *key, int n_default); + + /* + * set config values + */ + + void (*set_str) (config_values_t *this, + char *key, char *value) ; + + void (*set_int) (config_values_t *this, + char *key, int value) ; + + /* + * write config file to disk + */ + void (*save) (config_values_t *this); + + /* + * read config file from disk, ovverriding values in memory + * if you also want to clear values that are not in the file, + * use _init instead! + */ + void (*read) (config_values_t *this, char *filename); + + /* + * contains private data of this config file + */ + cfg_data_t *data; +}; + +/* + * init internal data structures, read config file + * (if it exists) + */ +config_values_t *config_file_init (char *filename); + + +#endif + +/* + * $Log: configfile.h,v $ + * Revision 1.1 2001/04/18 22:36:05 f1rmb + * Initial revision + * + * Revision 1.6 2001/03/31 03:42:25 guenter + * more cleanups, started xv driver + * + * Revision 1.5 2001/03/28 12:30:25 siggi + * fixed init function + * added read function (multiple config files now supported) + * + * Revision 1.4 2001/03/27 21:49:02 siggi + * started touching demuxers + * + */ + + + + diff --git a/src/xine-engine/cpu_accel.c b/src/xine-engine/cpu_accel.c new file mode 100644 index 000000000..bd3a55fc0 --- /dev/null +++ b/src/xine-engine/cpu_accel.c @@ -0,0 +1,110 @@ +/* + * cpu_accel.c + * Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * + * mpeg2dec 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. + * + * mpeg2dec 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 "config.h" + +#include <inttypes.h> + +#include "attributes.h" +#include "cpu_accel.h" + +#ifdef ARCH_X86 +static uint32_t x86_accel (void) +{ + uint32_t eax, ebx, ecx, edx; + int AMD; + uint32_t caps; + +#define cpuid(op,eax,ebx,ecx,edx) \ + asm ("cpuid" \ + : "=a" (eax), \ + "=b" (ebx), \ + "=c" (ecx), \ + "=d" (edx) \ + : "a" (op) \ + : "cc") + + asm ("pushfl\n\t" + "popl %0\n\t" + "movl %0,%1\n\t" + "xorl $0x200000,%0\n\t" + "pushl %0\n\t" + "popfl\n\t" + "pushfl\n\t" + "popl %0" + : "=a" (eax), + "=b" (ebx) + : + : "cc"); + + if (eax == ebx) /* no cpuid */ + return 0; + + cpuid (0x00000000, eax, ebx, ecx, edx); + if (!eax) /* vendor string only */ + return 0; + + AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65); + + cpuid (0x00000001, eax, ebx, ecx, edx); + if (! (edx & 0x00800000)) /* no MMX */ + return 0; + + caps = MM_ACCEL_X86_MMX; + if (edx & 0x02000000) /* SSE - identical to AMD MMX extensions */ + caps = MM_ACCEL_X86_MMX | MM_ACCEL_X86_MMXEXT; + + cpuid (0x80000000, eax, ebx, ecx, edx); + if (eax < 0x80000001) /* no extended capabilities */ + return caps; + + cpuid (0x80000001, eax, ebx, ecx, edx); + + if (edx & 0x80000000) + caps |= MM_ACCEL_X86_3DNOW; + + if (AMD && (edx & 0x00400000)) /* AMD MMX extensions */ + caps |= MM_ACCEL_X86_MMXEXT; + + return caps; +} +#endif + +uint32_t mm_accel (void) +{ +#ifdef ARCH_X86 + static int got_accel = 0; + static uint32_t accel; + + if (!got_accel) { + got_accel = 1; + accel = x86_accel (); + } + + return accel; +#else +#ifdef HAVE_MLIB + return MM_ACCEL_MLIB; +#else + return 0; +#endif +#endif +} diff --git a/src/xine-engine/cpu_accel.h b/src/xine-engine/cpu_accel.h new file mode 100644 index 000000000..9583b6681 --- /dev/null +++ b/src/xine-engine/cpu_accel.h @@ -0,0 +1,514 @@ +/* + * cpu_accel.h - based on mmx.h, sse.h + * Copyright (C) 1997-1999 H. Dietz and R. Fisher + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * + * mpeg2dec 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. + * + * mpeg2dec 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 + * + * xine specific modifications 2001 by G. Bartsch + * + */ + +/* + * The type of an value that fits in an MMX register (note that long + * long constant values MUST be suffixed by LL and unsigned long long + * values by ULL, lest they be truncated by the compiler) + */ + +#ifndef _CPU_ACCEL_H +#define _CPU_ACCEL_H + +#include "attributes.h" + +/* generic accelerations */ +#define MM_ACCEL_MLIB 0x00000001 + +/* x86 accelerations */ +#define MM_ACCEL_X86_MMX 0x80000000 +#define MM_ACCEL_X86_3DNOW 0x40000000 +#define MM_ACCEL_X86_MMXEXT 0x20000000 + +uint32_t mm_accel (void) ; + +#ifdef ARCH_X86 + +typedef union { + long long q; /* Quadword (64-bit) value */ + unsigned long long uq; /* Unsigned Quadword */ + int d[2]; /* 2 Doubleword (32-bit) values */ + unsigned int ud[2]; /* 2 Unsigned Doubleword */ + short w[4]; /* 4 Word (16-bit) values */ + unsigned short uw[4]; /* 4 Unsigned Word */ + char b[8]; /* 8 Byte (8-bit) values */ + unsigned char ub[8]; /* 8 Unsigned Byte */ + float s[2]; /* Single-precision (32-bit) value */ +} ATTR_ALIGN(8) mmx_t; /* On an 8-byte (64-bit) boundary */ + + + +#define mmx_i2r(op,imm,reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "X" (imm) ) + +#define mmx_m2r(op,mem,reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "X" (mem)) + +#define mmx_r2m(op,reg,mem) \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=X" (mem) \ + : /* nothing */ ) + +#define mmx_r2r(op,regs,regd) \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd) + + +#define emms() __asm__ __volatile__ ("emms") + +#define movd_m2r(var,reg) mmx_m2r (movd, var, reg) +#define movd_r2m(reg,var) mmx_r2m (movd, reg, var) +#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd) + +#define movq_m2r(var,reg) mmx_m2r (movq, var, reg) +#define movq_r2m(reg,var) mmx_r2m (movq, reg, var) +#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd) + +#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg) +#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd) +#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg) +#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd) + +#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg) +#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd) + +#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg) +#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd) +#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg) +#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd) +#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg) +#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd) + +#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg) +#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd) +#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg) +#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd) + +#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg) +#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd) +#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg) +#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd) + +#define pand_m2r(var,reg) mmx_m2r (pand, var, reg) +#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd) + +#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg) +#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd) + +#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg) +#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd) +#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg) +#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd) +#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg) +#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd) + +#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg) +#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd) +#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg) +#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd) +#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg) +#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd) + +#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg) +#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd) + +#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg) +#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd) + +#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg) +#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd) + +#define por_m2r(var,reg) mmx_m2r (por, var, reg) +#define por_r2r(regs,regd) mmx_r2r (por, regs, regd) + +#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg) +#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg) +#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd) +#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg) +#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg) +#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd) +#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg) +#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg) +#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd) + +#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg) +#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg) +#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd) +#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg) +#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg) +#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd) + +#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg) +#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg) +#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd) +#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg) +#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg) +#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd) +#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg) +#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg) +#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd) + +#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg) +#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd) +#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg) +#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd) +#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg) +#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd) + +#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg) +#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd) +#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg) +#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd) + +#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg) +#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd) +#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg) +#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd) + +#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg) +#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd) +#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg) +#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd) +#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg) +#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd) + +#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg) +#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd) +#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg) +#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd) +#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg) +#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd) + +#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg) +#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd) + + +/* 3DNOW extensions */ + +#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg) +#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd) + + +/* AMD MMX extensions - also available in intel SSE */ + + +#define mmx_m2ri(op,mem,reg,imm) \ + __asm__ __volatile__ (#op " %1, %0, %%" #reg \ + : /* nothing */ \ + : "X" (mem), "X" (imm)) +#define mmx_r2ri(op,regs,regd,imm) \ + __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ + : /* nothing */ \ + : "X" (imm) ) + +#define mmx_fetch(mem,hint) \ + __asm__ __volatile__ ("prefetch" #hint " %0" \ + : /* nothing */ \ + : "X" (mem)) + + +#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg) + +#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var) + +#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg) +#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd) +#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg) +#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd) + +#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm) + +#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm) + +#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg) +#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd) + +#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg) +#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd) + +#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg) +#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd) + +#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg) +#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd) + +#define pmovmskb(mmreg,reg) \ + __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg) + +#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg) +#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd) + +#define prefetcht0(mem) mmx_fetch (mem, t0) +#define prefetcht1(mem) mmx_fetch (mem, t1) +#define prefetcht2(mem) mmx_fetch (mem, t2) +#define prefetchnta(mem) mmx_fetch (mem, nta) + +#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg) +#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd) + +#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm) +#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm) + +#define sfence() __asm__ __volatile__ ("sfence\n\t") + +typedef union { + float sf[4]; /* Single-precision (32-bit) value */ +} ATTR_ALIGN(16) sse_t; /* On a 16 byte (128-bit) boundary */ + + +#define sse_i2r(op, imm, reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "X" (imm) ) + +#define sse_m2r(op, mem, reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "X" (mem)) + +#define sse_r2m(op, reg, mem) \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=X" (mem) \ + : /* nothing */ ) + +#define sse_r2r(op, regs, regd) \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd) + +#define sse_r2ri(op, regs, regd, imm) \ + __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ + : /* nothing */ \ + : "X" (imm) ) + +#define sse_m2ri(op, mem, reg, subop) \ + __asm__ __volatile__ (#op " %0, %%" #reg ", " #subop \ + : /* nothing */ \ + : "X" (mem)) + + +#define movaps_m2r(var, reg) sse_m2r(movaps, var, reg) +#define movaps_r2m(reg, var) sse_r2m(movaps, reg, var) +#define movaps_r2r(regs, regd) sse_r2r(movaps, regs, regd) + +#define movntps_r2m(xmmreg, var) sse_r2m(movntps, xmmreg, var) + +#define movups_m2r(var, reg) sse_m2r(movups, var, reg) +#define movups_r2m(reg, var) sse_r2m(movups, reg, var) +#define movups_r2r(regs, regd) sse_r2r(movups, regs, regd) + +#define movhlps_r2r(regs, regd) sse_r2r(movhlps, regs, regd) + +#define movlhps_r2r(regs, regd) sse_r2r(movlhps, regs, regd) + +#define movhps_m2r(var, reg) sse_m2r(movhps, var, reg) +#define movhps_r2m(reg, var) sse_r2m(movhps, reg, var) + +#define movlps_m2r(var, reg) sse_m2r(movlps, var, reg) +#define movlps_r2m(reg, var) sse_r2m(movlps, reg, var) + +#define movss_m2r(var, reg) sse_m2r(movss, var, reg) +#define movss_r2m(reg, var) sse_r2m(movss, reg, var) +#define movss_r2r(regs, regd) sse_r2r(movss, regs, regd) + +#define shufps_m2r(var, reg, index) sse_m2ri(shufps, var, reg, index) +#define shufps_r2r(regs, regd, index) sse_r2ri(shufps, regs, regd, index) + +#define cvtpi2ps_m2r(var, xmmreg) sse_m2r(cvtpi2ps, var, xmmreg) +#define cvtpi2ps_r2r(mmreg, xmmreg) sse_r2r(cvtpi2ps, mmreg, xmmreg) + +#define cvtps2pi_m2r(var, mmreg) sse_m2r(cvtps2pi, var, mmreg) +#define cvtps2pi_r2r(xmmreg, mmreg) sse_r2r(cvtps2pi, mmreg, xmmreg) + +#define cvttps2pi_m2r(var, mmreg) sse_m2r(cvttps2pi, var, mmreg) +#define cvttps2pi_r2r(xmmreg, mmreg) sse_r2r(cvttps2pi, mmreg, xmmreg) + +#define cvtsi2ss_m2r(var, xmmreg) sse_m2r(cvtsi2ss, var, xmmreg) +#define cvtsi2ss_r2r(reg, xmmreg) sse_r2r(cvtsi2ss, reg, xmmreg) + +#define cvtss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) +#define cvtss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) + +#define cvttss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) +#define cvttss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) + +#define movmskps(xmmreg, reg) \ + __asm__ __volatile__ ("movmskps %" #xmmreg ", %" #reg) + +#define addps_m2r(var, reg) sse_m2r(addps, var, reg) +#define addps_r2r(regs, regd) sse_r2r(addps, regs, regd) + +#define addss_m2r(var, reg) sse_m2r(addss, var, reg) +#define addss_r2r(regs, regd) sse_r2r(addss, regs, regd) + +#define subps_m2r(var, reg) sse_m2r(subps, var, reg) +#define subps_r2r(regs, regd) sse_r2r(subps, regs, regd) + +#define subss_m2r(var, reg) sse_m2r(subss, var, reg) +#define subss_r2r(regs, regd) sse_r2r(subss, regs, regd) + +#define mulps_m2r(var, reg) sse_m2r(mulps, var, reg) +#define mulps_r2r(regs, regd) sse_r2r(mulps, regs, regd) + +#define mulss_m2r(var, reg) sse_m2r(mulss, var, reg) +#define mulss_r2r(regs, regd) sse_r2r(mulss, regs, regd) + +#define divps_m2r(var, reg) sse_m2r(divps, var, reg) +#define divps_r2r(regs, regd) sse_r2r(divps, regs, regd) + +#define divss_m2r(var, reg) sse_m2r(divss, var, reg) +#define divss_r2r(regs, regd) sse_r2r(divss, regs, regd) + +#define rcpps_m2r(var, reg) sse_m2r(rcpps, var, reg) +#define rcpps_r2r(regs, regd) sse_r2r(rcpps, regs, regd) + +#define rcpss_m2r(var, reg) sse_m2r(rcpss, var, reg) +#define rcpss_r2r(regs, regd) sse_r2r(rcpss, regs, regd) + +#define rsqrtps_m2r(var, reg) sse_m2r(rsqrtps, var, reg) +#define rsqrtps_r2r(regs, regd) sse_r2r(rsqrtps, regs, regd) + +#define rsqrtss_m2r(var, reg) sse_m2r(rsqrtss, var, reg) +#define rsqrtss_r2r(regs, regd) sse_r2r(rsqrtss, regs, regd) + +#define sqrtps_m2r(var, reg) sse_m2r(sqrtps, var, reg) +#define sqrtps_r2r(regs, regd) sse_r2r(sqrtps, regs, regd) + +#define sqrtss_m2r(var, reg) sse_m2r(sqrtss, var, reg) +#define sqrtss_r2r(regs, regd) sse_r2r(sqrtss, regs, regd) + +#define andps_m2r(var, reg) sse_m2r(andps, var, reg) +#define andps_r2r(regs, regd) sse_r2r(andps, regs, regd) + +#define andnps_m2r(var, reg) sse_m2r(andnps, var, reg) +#define andnps_r2r(regs, regd) sse_r2r(andnps, regs, regd) + +#define orps_m2r(var, reg) sse_m2r(orps, var, reg) +#define orps_r2r(regs, regd) sse_r2r(orps, regs, regd) + +#define xorps_m2r(var, reg) sse_m2r(xorps, var, reg) +#define xorps_r2r(regs, regd) sse_r2r(xorps, regs, regd) + +#define maxps_m2r(var, reg) sse_m2r(maxps, var, reg) +#define maxps_r2r(regs, regd) sse_r2r(maxps, regs, regd) + +#define maxss_m2r(var, reg) sse_m2r(maxss, var, reg) +#define maxss_r2r(regs, regd) sse_r2r(maxss, regs, regd) + +#define minps_m2r(var, reg) sse_m2r(minps, var, reg) +#define minps_r2r(regs, regd) sse_r2r(minps, regs, regd) + +#define minss_m2r(var, reg) sse_m2r(minss, var, reg) +#define minss_r2r(regs, regd) sse_r2r(minss, regs, regd) + +#define cmpps_m2r(var, reg, op) sse_m2ri(cmpps, var, reg, op) +#define cmpps_r2r(regs, regd, op) sse_r2ri(cmpps, regs, regd, op) + +#define cmpeqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 0) +#define cmpeqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 0) + +#define cmpltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 1) +#define cmpltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 1) + +#define cmpleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 2) +#define cmpleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 2) + +#define cmpunordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 3) +#define cmpunordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 3) + +#define cmpneqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 4) +#define cmpneqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 4) + +#define cmpnltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 5) +#define cmpnltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 5) + +#define cmpnleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 6) +#define cmpnleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 6) + +#define cmpordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 7) +#define cmpordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 7) + +#define cmpss_m2r(var, reg, op) sse_m2ri(cmpss, var, reg, op) +#define cmpss_r2r(regs, regd, op) sse_r2ri(cmpss, regs, regd, op) + +#define cmpeqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 0) +#define cmpeqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 0) + +#define cmpltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 1) +#define cmpltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 1) + +#define cmpless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 2) +#define cmpless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 2) + +#define cmpunordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 3) +#define cmpunordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 3) + +#define cmpneqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 4) +#define cmpneqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 4) + +#define cmpnltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 5) +#define cmpnltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 5) + +#define cmpnless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 6) +#define cmpnless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 6) + +#define cmpordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 7) +#define cmpordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 7) + +#define comiss_m2r(var, reg) sse_m2r(comiss, var, reg) +#define comiss_r2r(regs, regd) sse_r2r(comiss, regs, regd) + +#define ucomiss_m2r(var, reg) sse_m2r(ucomiss, var, reg) +#define ucomiss_r2r(regs, regd) sse_r2r(ucomiss, regs, regd) + +#define unpcklps_m2r(var, reg) sse_m2r(unpcklps, var, reg) +#define unpcklps_r2r(regs, regd) sse_r2r(unpcklps, regs, regd) + +#define unpckhps_m2r(var, reg) sse_m2r(unpckhps, var, reg) +#define unpckhps_r2r(regs, regd) sse_r2r(unpckhps, regs, regd) + +#define fxrstor(mem) \ + __asm__ __volatile__ ("fxrstor %0" \ + : /* nothing */ \ + : "X" (mem)) + +#define fxsave(mem) \ + __asm__ __volatile__ ("fxsave %0" \ + : /* nothing */ \ + : "X" (mem)) + +#define stmxcsr(mem) \ + __asm__ __volatile__ ("stmxcsr %0" \ + : /* nothing */ \ + : "X" (mem)) + +#define ldmxcsr(mem) \ + __asm__ __volatile__ ("ldmxcsr %0" \ + : /* nothing */ \ + : "X" (mem)) +#endif /*ARCH_X86 */ + +#endif + diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c new file mode 100644 index 000000000..4984566db --- /dev/null +++ b/src/xine-engine/load_plugins.c @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: load_plugins.c,v 1.1 2001/04/18 22:36:09 f1rmb Exp $ + * + * + * Load input/demux/audio_out/video_out plugins + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <inttypes.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#include <dlfcn.h> + +#include "xine.h" +#include "xine_internal.h" +#include "demuxers/demux.h" +#include "input/input_plugin.h" +#include "metronom.h" +#include "configfile.h" +#include "monitor.h" + +/* debugging purposes only */ +extern uint32_t xine_debug; + +/* + * + */ +void xine_load_demux_plugins (xine_t *this) { + DIR *dir; + + this->demuxer_plugins[0] = *(init_demux_mpeg (xine_debug)); + this->demuxer_plugins[1] = *(init_demux_mpeg_block (xine_debug)); + this->demuxer_plugins[2] = *(init_demux_avi (xine_debug)); + this->demuxer_plugins[3] = *(init_demux_mpeg_audio (xine_debug)); + this->demuxer_plugins[4] = *(init_demux_mpeg_elem (xine_debug)); + this->num_demuxer_plugins = 5; + + dir = opendir (XINE_DEMUXDIR) ; + + if (dir) { + struct dirent *pEntry; + + while ((pEntry = readdir (dir)) != NULL) { + char str[1024]; + void *plugin; + + int nLen = strlen (pEntry->d_name); + + if ((strncasecmp(pEntry->d_name, "demux_", 6) == 0) && + ((pEntry->d_name[nLen-3]=='.') + && (pEntry->d_name[nLen-2]=='s') + && (pEntry->d_name[nLen-1]=='o'))) { + + /* + * demux plugin found => load it + */ + + sprintf (str, "%s/%s", XINE_DEMUXDIR, pEntry->d_name); + + if(!(plugin = dlopen (str, RTLD_LAZY))) { + fprintf(stderr, "%s(%d): %s doesn't seem to be installed (%s)\n", + __FILE__, __LINE__, str, dlerror()); + exit(1); + } + else { + void *(*getinfo) (fifobuf_functions_t *, uint32_t); + + if((getinfo = dlsym(plugin, "demux_plugin_getinfo")) != NULL) { + demux_functions_t *dxp; + + dxp = (demux_functions_t *) getinfo(this->fifo_funcs, xine_debug); + dxp->handle = plugin; + dxp->filename = str; + this->demuxer_plugins[this->num_demuxer_plugins] = *dxp; + + + printf("demux plugin found : %s(%s)\n", + this->demuxer_plugins[this->num_demuxer_plugins].filename, + pEntry->d_name); + + this->num_demuxer_plugins++; + } + + if(this->num_demuxer_plugins > DEMUXER_PLUGIN_MAX) { + fprintf(stderr, "%s(%d): too many demux plugins installed, " + "exiting.\n", __FILE__, __LINE__); + exit(1); + } + } + } + } + } + + if (this->num_demuxer_plugins == 5) + printf ("No extra demux plugins found in %s\n", XINE_DEMUXDIR); + + /* + * init demuxer + */ + + this->cur_demuxer_plugin = NULL; +} + +/* + * + */ +void xine_load_input_plugins (xine_t *this) { + DIR *dir; + + this->num_input_plugins = 0; + + dir = opendir (XINE_PLUGINDIR) ; + + if (dir) { + struct dirent *pEntry; + + while ((pEntry = readdir (dir)) != NULL) { + + char str[1024]; + void *plugin; + + int nLen = strlen (pEntry->d_name); + + if ((strncasecmp(pEntry->d_name, "input_", 6) == 0) && + ((pEntry->d_name[nLen-3]=='.') + && (pEntry->d_name[nLen-2]=='s') + && (pEntry->d_name[nLen-1]=='o'))) { + + /* + * input plugin found => load it + */ + + sprintf (str, "%s/%s", XINE_PLUGINDIR, pEntry->d_name); + + if(!(plugin = dlopen (str, RTLD_LAZY))) { + fprintf(stderr, "%s(%d): %s doesn't seem to be installed (%s)\n", + __FILE__, __LINE__, str, dlerror()); + exit(1); + } + else { + void *(*getinfo) (uint32_t); + + if((getinfo = dlsym(plugin, "input_plugin_getinfo")) != NULL) { + input_plugin_t *ipp; + + ipp = (input_plugin_t *) getinfo(xine_debug); + ipp->handle = plugin; + ipp->filename = str; + this->input_plugins[this->num_input_plugins] = *ipp; + + this->input_plugins[this->num_input_plugins].init(); + + printf("input plugin found : %s(%s)\n", + this->input_plugins[this->num_input_plugins].filename, + pEntry->d_name); + + this->num_input_plugins++; + + } + + if(this->num_input_plugins > INPUT_PLUGIN_MAX) { + fprintf(stderr, "%s(%d): too many input plugins installed, " + "exiting.\n", __FILE__, __LINE__); + exit(1); + } + } + } + } + } + + if (this->num_input_plugins == 0) { + printf ("No input plugins found in %s! - " + "Did you install xine correctly??\n", XINE_PLUGINDIR); + exit (1); + } + +} diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c new file mode 100644 index 000000000..e71f2b8b6 --- /dev/null +++ b/src/xine-engine/metronom.c @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: metronom.c,v 1.1 2001/04/18 22:36:04 f1rmb Exp $ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/time.h> +#include <inttypes.h> +#include <stdio.h> +#include <unistd.h> +#include <math.h> + +#include "monitor.h" +#include "xine.h" +#include "xine_internal.h" +#include "metronom.h" +#include "utils.h" + +#define MAX_PTS_TOLERANCE 5000 +#define MAX_VIDEO_DELTA 1600 +#define AUDIO_SAMPLE_NUM 32768 + +static void metronom_reset (metronom_t *this) { + + this->video_vpts = 0; + this->audio_vpts = 0; + + this->video_pts_delta = 0; + this->audio_pts_delta = 0; + + this->last_video_pts = 0; + this->num_video_vpts_guessed = 1; + this->num_audio_samples_guessed = 1; + + this->sync_pts = 0; + this->sync_vpts = 0; + + this->av_offset = 0; + + this->stopped = 1; +} + +static void metronom_set_video_rate (metronom_t *this, uint32_t pts_per_frame) { + this->pts_per_frame = pts_per_frame; +} + +static uint32_t metronom_get_video_rate (metronom_t *this) { + return this->pts_per_frame + this->video_pts_delta; +} + +static void metronom_set_audio_rate (metronom_t *this, uint32_t pts_per_smpls) { + this->pts_per_smpls = pts_per_smpls; + + xprintf (METRONOM | VERBOSE, "metronom: %d pts per %d samples\n", pts_per_smpls, AUDIO_SAMPLE_NUM); + +} + +static uint32_t metronom_got_spu_packet (metronom_t *this, uint32_t pts) { + /* FIXME: Nasty hack */ + + return this->sync_pts; +} + +static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts) { + + uint32_t vpts; + + if (pts) { + + /* + * calc delta to compensate wrong framerates + */ + + if (this->last_video_vpts && (pts>this->last_video_pts)) { + int32_t vpts_diff; + uint32_t synced_vpts ; + int32_t diff; + + diff = pts - this->last_video_pts; + synced_vpts = this->last_video_vpts + diff; + vpts_diff = synced_vpts - this->video_vpts; + + this->video_pts_delta += vpts_diff / (this->num_video_vpts_guessed); + + if (abs(this->video_pts_delta) >= MAX_VIDEO_DELTA) + this->video_pts_delta = 0; + + this->num_video_vpts_guessed = 0; + /* printf ("delta: %d\n", this->video_pts_delta); */ + } + + /* + * sync if necessary and possible + */ + + if (this->sync_vpts && (pts>this->sync_pts)) { + + int32_t vpts_diff; + uint32_t synced_vpts ; + int32_t diff; + + diff = pts - this->sync_pts; + synced_vpts = this->sync_vpts + diff; + vpts_diff = synced_vpts - this->video_vpts; + + xprintf (METRONOM | VERBOSE, "metronom: video calced vpts : %d <=> synced vpts : %d (diff: %d, delta: %d)\n", + this->video_vpts, synced_vpts, vpts_diff, this->video_pts_delta); + + if (abs(vpts_diff)>MAX_PTS_TOLERANCE) { + if (synced_vpts>this->video_vpts) { + this->video_vpts = synced_vpts; + } + } else + xprintf (METRONOM | VERBOSE, "metronom: video tolerating diff\n"); + + } else + xprintf (METRONOM | VERBOSE, "metronom: video not synced on this one\n"); + + this->sync_pts = pts; + this->sync_vpts = this->video_vpts; + this->last_video_vpts = this->video_vpts; + this->last_video_pts = pts; + } + + vpts = this->video_vpts; + this->video_vpts += this->pts_per_frame + this->video_pts_delta; + this->num_video_vpts_guessed++ ; + + xprintf (METRONOM | VERBOSE, "metronom: video vpts for %10d : %10d\n", pts, vpts); + + return vpts + this->av_offset; +} + + +static uint32_t metronom_got_audio_samples (metronom_t *this, uint32_t pts, uint32_t nsamples) { + + uint32_t vpts; + + xprintf (METRONOM | VERBOSE, "metronom: got %d audio samples (pts=%d)\n", + nsamples,pts); + + if (pts) { + int32_t diff; + + diff = pts - this->sync_pts; + + if (this->sync_vpts && (pts>this->sync_pts)) { + + int32_t vpts_diff; + uint32_t synced_vpts = this->sync_vpts + diff; + + vpts_diff = synced_vpts - this->audio_vpts; + + xprintf (METRONOM | VERBOSE, "metronom: audio calced vpts : %d <=> synced vpts : %d (diff: %d, delta: %d)\n", + this->audio_vpts, synced_vpts, vpts_diff, this->audio_pts_delta); + if (abs(vpts_diff)>5000) { + + /* calc delta for wrong samplerates */ + + this->audio_pts_delta += vpts_diff*AUDIO_SAMPLE_NUM / (this->num_audio_samples_guessed); + + if (abs(this->audio_pts_delta) >= 10000) + this->audio_pts_delta = 0; + + if (synced_vpts>this->audio_vpts) + this->audio_vpts = synced_vpts; + + } else + xprintf (METRONOM | VERBOSE, "metronom: audio tolerating diff\n"); + + } else + xprintf (METRONOM | VERBOSE, "metronom: audio not synced on this one\n"); + + this->sync_pts = pts; + this->sync_vpts = this->audio_vpts; + this->num_audio_samples_guessed = 0; + } + + vpts = this->audio_vpts; + this->audio_vpts += nsamples * (this->audio_pts_delta + this->pts_per_smpls) / AUDIO_SAMPLE_NUM; + this->num_audio_samples_guessed += nsamples; + + xprintf (METRONOM | VERBOSE, "metronom: audio vpts for %10d : %10d\n", pts, vpts); + + return vpts; +} + +static void metronom_set_av_offset (metronom_t *this, int32_t pts) { + this->av_offset = pts; + printf ("metronom: av_offset=%d pts\n", pts); +} + +static int32_t metronom_get_av_offset (metronom_t *this) { + return this->av_offset; +} + + + +/* + * **************************************** + * master clock feature + * **************************************** + */ + + +static void metronom_start_clock (metronom_t *this, uint32_t pts) { + gettimeofday(&this->start_time, NULL); + this->last_pts = this->start_pts = pts; + this->stopped = 0; +} + + +static uint32_t metronom_get_current_time (metronom_t *this) { + + uint32_t pts; + struct timeval tv; + + gettimeofday(&tv, NULL); + pts = (tv.tv_sec - this->start_time.tv_sec) * 90000; + pts += (tv.tv_usec - this->start_time.tv_usec) / 10 * 9 / 10; + pts += this->start_pts; + + if (this->stopped || (this->last_pts > pts)) { + //printf("tm_current_pts(): timer STOPPED!\n"); + pts = this->last_pts; + } + + return pts; +} + + +static void metronom_stop_clock(metronom_t *this) { + this->stopped = 1; + this->last_pts = this->get_current_time(this); +} + + +static void metronom_resume_clock(metronom_t *this) { + this->start_clock(this, this->last_pts); +} + + + +static void metronom_adjust_clock(metronom_t *this, uint32_t desired_pts) +{ + int delta; + + /* FIXME: this should be softer than a brute force warp... */ + delta = desired_pts; + delta -= this->get_current_time(this); + this->start_pts += delta; + /* printf("adjusting start_pts to %d\n", this->start_pts); */ +} + +metronom_t * metronom_init () { + + metronom_t *this = xmalloc (sizeof (metronom_t)); + + this->reset = metronom_reset; + this->set_video_rate = metronom_set_video_rate; + this->get_video_rate = metronom_get_video_rate; + this->set_audio_rate = metronom_set_audio_rate; + this->got_video_frame = metronom_got_video_frame; + this->got_audio_samples = metronom_got_audio_samples; + this->got_spu_packet = metronom_got_spu_packet; + this->set_av_offset = metronom_set_av_offset; + this->get_av_offset = metronom_get_av_offset; + this->start_clock = metronom_start_clock; + this->stop_clock = metronom_stop_clock; + this->resume_clock = metronom_resume_clock; + this->get_current_time = metronom_get_current_time; + this->adjust_clock = metronom_adjust_clock; + + this->reset (this); + + return this; +} + diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h new file mode 100644 index 000000000..a16b9ef20 --- /dev/null +++ b/src/xine-engine/metronom.h @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: metronom.h,v 1.1 2001/04/18 22:36:07 f1rmb Exp $ + * + * metronom: general pts => virtual calculation/assoc + * + * virtual pts: unit 1/90000 sec, always increasing + * can be used for synchronization + * video/audio frame with same pts also have same vpts + * but pts is likely to differ from vpts + * + */ + + +#ifndef HAVE_METRONOM_H +#define HAVE_METRONOM_H + +#include <inttypes.h> +#include <sys/time.h> + +typedef struct metronom_s metronom_t ; + +struct metronom_s { + + /* + * clear all cached data, reset current vpts ... called if new input + * file is reached + */ + + void (*reset) (metronom_t *this); + + /* + * called by video output driver to inform metronom about current framerate + * + * parameter pts_per_frame : frame display duration in 1/90000 sec + */ + void (*set_video_rate) (metronom_t *this, uint32_t pts_per_frame); + + /* + * return current video rate (including delta corrections) + */ + + uint32_t (*get_video_rate) (metronom_t *this); + + /* + * called by audio output driver to inform metronom about current audio + * bitrate + * + * parameter pts_per_smpls : 1/90000 sec per 65536 samples + */ + void (*set_audio_rate) (metronom_t *this, uint32_t pts_per_smpls); + + /* + * called by video output driver for *every* frame + * + * parameter pts: pts for frame if known, 0 otherwise + * + * return value: virtual pts for frame + * + */ + + uint32_t (*got_video_frame) (metronom_t *this, uint32_t pts); + + /* + * called by audio output driver whenever audio samples are delivered to it + * + * parameter pts : pts for audio data if known, 0 otherwise + * nsamples : number of samples delivered + * + * return value: virtual pts for audio data + * + */ + + uint32_t (*got_audio_samples) (metronom_t *this, uint32_t pts, uint32_t nsamples); + + /* + * called by SPU decoder whenever a packet is delivered to it + * + * parameter pts : pts for SPU packet if known, 0 otherwise + * + * return value: virtual pts for SPU packet + * + */ + + uint32_t (*got_spu_packet) (metronom_t *this, uint32_t pts); + + /* + * manually correct audio <-> video sync + */ + void (*set_av_offset) (metronom_t *this, int32_t pts); + + int32_t (*get_av_offset) (metronom_t *this); + + /* + * **************************************** + * master clock functions + * **************************************** + */ + + /* + * start metronom clock (no clock reset) + */ + void (*start_clock) (metronom_t *this, uint32_t pts); + + + /* + * stop metronom clock + */ + void (*stop_clock) (metronom_t *this); + + + /* + * resume clock from where it was stopped + */ + void (*resume_clock) (metronom_t *this); + + + /* + * get current clock value in vpts + */ + uint32_t (*get_current_time) (metronom_t *this); + + + /* + * adjust master clock to external timer (e.g. audio hardware) + */ + void (*adjust_clock) (metronom_t *this, uint32_t desired_pts); + + /* + * metronom internal stuff + */ + + uint32_t pts_per_frame; + uint32_t pts_per_smpls; + + int32_t audio_pts_delta; + + uint32_t video_vpts; + uint32_t audio_vpts; + + uint32_t sync_pts; + uint32_t sync_vpts; + + /* video delta for wrong framerates */ + uint32_t last_video_pts; + uint32_t last_video_vpts; + int num_video_vpts_guessed; + int32_t video_pts_delta; + + int num_audio_samples_guessed; + + int32_t av_offset; + + struct timeval start_time; + uint32_t start_pts, last_pts; + int stopped ; +}; + +metronom_t *metronom_init (); + +#endif + diff --git a/src/xine-engine/monitor.c b/src/xine-engine/monitor.c new file mode 100644 index 000000000..6fb23340e --- /dev/null +++ b/src/xine-engine/monitor.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: monitor.c,v 1.1 2001/04/18 22:36:04 f1rmb Exp $ + * + * debug print and profiling functions - implementation + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "monitor.h" +#include <stdio.h> + +#define MAX_ID 5 + +#ifdef DEBUG + +long long int profiler_times[MAX_ID+1] ; +long long int profiler_start[MAX_ID+1] ; +char * profiler_label[MAX_ID+1] ; + +void profiler_init () { + int i; + for (i=0; i<MAX_ID; i++) { + profiler_times[i] = 0; + profiler_start[i] = 0; + profiler_label[i] = "??"; + } +} + +void profiler_set_label (int id, char *label) { + profiler_label[id] = label; +} + +#ifdef ARCH_X86 +__inline__ unsigned long long int rdtsc() +{ + unsigned long long int x; + __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); + return x; +} +#endif + +void profiler_start_count (int id) { +#ifdef ARCH_X86 + profiler_start[id] = rdtsc(); +#endif +} + +void profiler_stop_count (int id) { +#ifdef ARCH_X86 + profiler_times[id] += rdtsc() - profiler_start[id]; +#endif +} + +void profiler_print_results () { + int i; + + printf ("\n\nPerformance analysis (cpu cycles):\n\n"); + for (i=0; i<MAX_ID; i++) { + printf ("%d:\t%s\t%12lld\n", i, profiler_label[i], profiler_times[i]); + } +} + +#endif diff --git a/src/xine-engine/monitor.h b/src/xine-engine/monitor.h new file mode 100644 index 000000000..e338be535 --- /dev/null +++ b/src/xine-engine/monitor.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: monitor.h,v 1.1 2001/04/18 22:36:07 f1rmb Exp $ + * + * debug print and profiling functions + * + */ + +#ifndef HAVE_MONITOR_H +#define HAVE_MONITOR_H + +#include <inttypes.h> + +extern uint32_t xine_debug; + +#define VERBOSE (xine_debug & 0x8000>>1) +#define METRONOM (xine_debug & 0x8000>>2) +#define AUDIO (xine_debug & 0x8000>>3) +#define DEMUX (xine_debug & 0x8000>>4) +#define INPUT (xine_debug & 0x8000>>5) +#define VIDEO (xine_debug & 0x8000>>6) +#define VPTS (xine_debug & 0x8000>>7) +#define MPEG (xine_debug & 0x8000>>8) +#define VAVI (xine_debug & 0x8000>>9) +#define AC3 (xine_debug & 0x8000>>10) +#define LOOP (xine_debug & 0x8000>>11) +#define GUI (xine_debug & 0x8000>>12) + +#define perr(FMT,ARGS...) {fprintf(stderr, FMT, ##ARGS);fflush(stderr);} + +#ifdef DEBUG + +/* + * Debug stuff + */ + +//#define perr(FMT,ARGS...) {fprintf(stderr, FMT, ##ARGS);fflush(stderr);} + +#define xprintf(LVL, FMT, ARGS...) { \ + if(LVL) { \ + printf(FMT, ##ARGS); \ + } \ + } +/* + * profiling + */ + +void profiler_init (); + +void profiler_set_label (int id, char *label); + +void profiler_start_count (int id); + +void profiler_stop_count (int id); + +void profiler_print_results (); + +#else /* no DEBUG, release version */ + +//#define perr(FMT,ARGS...) + +#define xprintf(LVL, FMT, ARGS...) + +#define profiler_init() +#define profiler_set_label(id, label) +#define profiler_start_count(id) +#define profiler_stop_count(id) +#define profiler_print_results() + +#endif /* DEBUG*/ + +#endif /* HAVE_MONITOR_H */ diff --git a/src/xine-engine/utils.c b/src/xine-engine/utils.c new file mode 100644 index 000000000..3c6c0f532 --- /dev/null +++ b/src/xine-engine/utils.c @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: utils.c,v 1.1 2001/04/18 22:36:04 f1rmb Exp $ + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <pwd.h> +#include <sys/types.h> + +/* + * + */ +void *xmalloc(size_t size) { + void *ptrmalloc, *ptrmemset; + + if((ptrmalloc = malloc(size)) == NULL) { + fprintf(stderr, "%s: malloc() failed: %s.\n", + __FUNCTION__, strerror(errno)); + return NULL; + } + + if((ptrmemset = memset(ptrmalloc, 0, size)) == NULL) { + fprintf(stderr, "%s: memset() failed: %s.\n", + __FUNCTION__, strerror(errno)); + return NULL; + } + + return ptrmemset; +} + +/* + * + */ +void *xmalloc_aligned (size_t alignment, size_t size) { + void *pMem; + + pMem = xmalloc (size+alignment); + + while ((int) pMem % alignment) + pMem++; + + return pMem; +} + +/* + * + */ +const char *get_homedir(void) { + struct passwd *pw = NULL; + char *homedir = NULL; +#ifdef HAVE_GETPWUID_R + int ret; + struct passwd pwd; + char *buffer = NULL; + int bufsize = 128; + + buffer = (char *) xmalloc(bufsize); + + if((ret = getpwuid_r(getuid(), &pwd, buffer, bufsize, &pw)) < 0) { +#else + if((pw = getpwuid(getuid())) == NULL) { +#endif + if((homedir = getenv("HOME")) == NULL) { + fprintf(stderr, "Unable to get home directory, set it to /tmp.\n"); + homedir = strdup("/tmp"); + } + } + else { + if(pw) + homedir = strdup(pw->pw_dir); + } + + +#ifdef HAVE_GETPWUID_R + if(buffer) + free(buffer); +#endif + + return homedir; +} + +/* + * + */ +char *chomp(char *str) { + char *pbuf; + + pbuf = str; + + while(*pbuf != '\0') pbuf++; + + while(pbuf > str) { + if(*pbuf == '\r' || *pbuf == '\n' || *pbuf == '"') pbuf = '\0'; + pbuf--; + } + + while(*pbuf == '=' || *pbuf == '"') pbuf++; + + return pbuf; +} diff --git a/src/xine-engine/utils.h b/src/xine-engine/utils.h new file mode 100644 index 000000000..d68cd0999 --- /dev/null +++ b/src/xine-engine/utils.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: utils.h,v 1.1 2001/04/18 22:36:09 f1rmb Exp $ + * + */ +#ifndef HAVE_UTILS_H +#define HAVE_UTILS_H + +void *xmalloc(size_t size); + +void *xmalloc_aligned(size_t alignment, size_t size); + +const char *get_homedir(void); + +/* + * Clean a string (remove spaces and '=' at the begin, + * and '\n', '\r' and spaces at the end. + */ + +char *chomp (char *str); + +#endif diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c new file mode 100644 index 000000000..a3f5532ce --- /dev/null +++ b/src/xine-engine/video_decoder.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: video_decoder.c,v 1.1 2001/04/18 22:36:04 f1rmb Exp $ + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xine.h" +#include "xine_internal.h" +#include "video_out/video_out.h" +#include "video_decoder.h" + +#define MAX_NUM_DECODERS 10 + +typedef struct vd_globals_s { + + pthread_t mVideoThread; + + fifo_buffer_t *mBufVideo; + + video_decoder_t *mDecoders[MAX_NUM_DECODERS]; + video_decoder_t *mCurDecoder; + + uint32_t mnCurInputPos; + + vo_instance_t *mVideoOut; + + gui_status_callback_func_t gui_status_callback; + + int mbStreamFinished; + + pthread_mutex_t mXineLock; + +} vd_globals_t; + +static vd_globals_t gVD; + +void *video_decoder_loop () { + + buf_element_t *pBuf; + int bRunning = 1; + + while (bRunning) { + + pBuf = gVD.mBufVideo->fifo_buffer_get (gVD.mBufVideo); + + gVD.mnCurInputPos = pBuf->nInputPos; + + switch (pBuf->nType) { + case BUF_STREAMSTART: + if (gVD.mCurDecoder) { + gVD.mCurDecoder->close (); + gVD.mCurDecoder = NULL; + } + + pthread_mutex_lock (&gVD.mXineLock); + gVD.mbStreamFinished = 0; + pthread_mutex_unlock (&gVD.mXineLock); + + break; + + case BUF_MPEGVIDEO: + case BUF_AVIVIDEO: + + decoder = gVD.mDecoders [pBuf->nType]; + + if (decoder) { + if (gVD.mCurDecoder != decoder) { + + if (gVD.mCurDecoder) + gVD.mCurDecoder->close (); + + gVD.mCurDecoder = decoder; + gVD.mCurDecoder->init (gVD.mVideoOut); + + } + + decoder->decode_data (pBuf); + } + + break; + + case BUF_STREAMEND: + if (gVD.mCurDecoder) { + gVD.mCurDecoder->close (); + gVD.mCurDecoder = NULL; + } + + gVD.mbStreamFinished = 1; + + pthread_mutex_lock (&gVD.mXineLock); + + gVD.mbVideoFinished = 1; + + if (audio_decoder_is_stream_finished ()) { + pthread_mutex_unlock (&gVD.mXineLock); + xine_notify_stream_finished (); + } else + pthread_mutex_unlock (&gVD.mXineLock); + + break; + + case BUF_QUIT: + if (gVD.mCurDecoder) { + gVD.mCurDecoder->close (); + gVD.mCurDecoder = NULL; + } + bRunning = 0; + break; + + } + + pBuf->free_buffer (pBuf); + } + + return NULL; +} + +int video_decoder_is_stream_finished () { + return gVD.mbStreamFinished ; +} + +uint32_t video_decoder_get_pos () { + return gVD.mnCurPos; +} + +fifo_buffer_t *video_decoder_init (vo_instance_t *video_out, + pthread_mutex_t xine_lock) { + + gVD.mVideoOut = video_out; + gVD.mXineLock = xine_lock; + + gVD.mCurDecoder = NULL; + for (i=0; i<MAX_NUM_DECODERS; i++) + gVD.mDecoders[i] = NULL; + + gVD.mDecoders[BUF_MPEGVIDEO] = init_video_decoder_mpeg2dec (); + gVD.mDecoders[BUF_AVIVIDEO] = init_video_decoder_avi (); + + gVD.mBufVideo = fifo_buffer_new (); + + pthread_create (&gVD.mVideoThread, NULL, video_decoder_loop, NULL) ; + + printf ("video_decoder_init: video thread created\n"); + + return gVD.mBufVideo; +} + +void video_decoder_shutdown () { + + buf_element_t *pBuf; + + gVD.mBufVideo->fifo_buffer_clear(gVD.mBufVideo); + + pBuf = gVD.mBufVideo->buffer_pool_alloc (); + pBuf->nType = BUF_QUIT; + gVD.mBufVideo->fifo_buffer_put (gVD.mBufVideo, pBuf); + + pthread_join (gVD.mVideoThread, &p); +} diff --git a/src/xine-engine/video_decoder.h b/src/xine-engine/video_decoder.h new file mode 100644 index 000000000..ee9abfe33 --- /dev/null +++ b/src/xine-engine/video_decoder.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: video_decoder.h,v 1.1 2001/04/18 22:36:09 f1rmb Exp $ + * + * + * functions that implement video decoding + */ + +#ifndef HAVE_VIDEO_DECODER_H +#define VIDEO_DECODER_H + +#include <pthread.h> +#include "buffer.h" +#include "video_out.h" + +/* + * generic xine video decoder plugin interface + */ + +typedef struct video_decoder_s +{ + + /* get interface version */ + int (*get_version) (void); + + int (*can_handle) (int buf_type); + + void (*init) (vo_instance_t *video_out); + + void (*decode_data) (buf_element_t *buf); + + void (*release_img_buffers) (void); + + void (*close) (void); + +} video_decoder_t; + +/* + * init video decoders, allocate video fifo, + * start video decoder thread + */ + +fifo_buffer_t *video_decoder_init (vo_instance_t *video_out, + pthread_mutex_t xine_lock) ; + +/* + * quit video thread + */ + +void video_decoder_shutdown (); + +uint32_t video_decoder_get_pos (); + +int video_decoder_is_stream_finished (); + +#endif diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c new file mode 100644 index 000000000..9093e50ec --- /dev/null +++ b/src/xine-engine/xine.c @@ -0,0 +1,607 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: xine.c,v 1.1 2001/04/18 22:36:05 f1rmb Exp $ + * + * top-level xine functions + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <pthread.h> +#if defined (__linux__) +#include <endian.h> +#elif defined (__FreeBSD__) +#include <machine/endian.h> +#endif + +#include "xine.h" +#include "xine_internal.h" +#include "audio_out.h" +#include "video_out.h" +#include "demuxers/demux.h" +#include "buffer.h" +#include "libac3/ac3.h" +#include "libmpg123/mpg123.h" +#include "libmpg123/mpglib.h" +#include "libmpeg2/mpeg2.h" +#ifdef ARCH_X86 +#include "libw32dll/w32codec.h" +#endif +#include "libspudec/spudec.h" +#include "input/input_plugin.h" +#include "metronom.h" +#include "configfile.h" +#include "monitor.h" +#include "video_decoder.h" +#include "audio_decoder.h" + +/* debugging purposes only */ +uint32_t xine_debug; + +/* +#define TEST_FILE +*/ +#ifdef TEST_FILE +int gTestFile=-1; +#endif + +/* + * xine global variables + */ + +void xine_notify_stream_finished (xine_t *this) { + printf ("xine_notify_stream_finished\n"); + + xine_stop (this); + + this->status_callback (this->status); +} + +/* + * + */ +void *xine_spu_loop (xine_t *this, void *dummy) { + + buf_element_t *pBuf; + int bRunning = 1; + + while (bRunning) { + + pBuf = this->fifo_funcs->fifo_buffer_get (this->spu_fifo); + + switch (pBuf->nType) { + case BUF_QUIT: + bRunning = 0; + break; + case BUF_RESET: + spudec_reset (); + break; + case BUF_SPU: + spudec_decode(pBuf->pContent, pBuf->nSize, pBuf->nPTS); + break; + } + this->fifo_funcs->buffer_pool_free (pBuf); + } + + return NULL; +} + +/* + * + */ +void xine_stop (xine_t *this) { + + pthread_mutex_lock (&this->xine_lock); + + if (!this->cur_input_plugin) + return; + + this->mnStatus = XINE_STOP; + + if(this->cur_demuxer_plugin) { + this->cur_demuxer_plugin->demux_stop (); + this->cur_demuxer_plugin = NULL; + } + + // FIXME + this->fifo_funcs->fifo_buffer_clear(this->mBufVideo); + this->fifo_funcs->fifo_buffer_clear(this->mBufAudio); + this->fifo_funcs->fifo_buffer_clear(this->spu_fifo); + + if (gAudioOut) + gAudioOut->close (); + + metronom_reset(); + metronom_stop_clock (); + + vo_reset(); + + this->cur_input_plugin->close(); + this->cur_input_plugin = NULL; + + pthread_mutex_unlock (&this->xine_lock); +} + +/* + * ***** + * Demuxers probing stuff + */ +static int try_demux_with_stages(xine_t *this, const char *MRL, + int stage1, int stage2) { + int s = 0, i; + int stages[3] = { + stage1, stage2, -1 + }; + + if(stages[0] == -1) { + fprintf(stderr, "%s(%d) wrong first stage = %d !!\n", + __FUNCTION__, __LINE__, stage1); + return 0; + } + + while(stages[s] != -1) { + for(i = 0; i < this->num_demuxer_plugins; i++) { + if(this->demuxer_plugins[i].open(this->cur_input_plugin, + MRL, stages[s]) == DEMUX_CAN_HANDLE) { + + this->cur_demuxer_plugin = &this->demux_plugins[i]; + + xprintf(VERBOSE|DEMUX,"demuxer '%s' handle in stage '%s'.\n", + this->demux_plugins[i].get_identifier(), + (stages[s] == STAGE_BY_CONTENT) ? "STAGE_BY_CONTENT" + : ((stages[s] == STAGE_BY_EXTENSION) ? "STAGE_BY_EXTENSION" + : "UNKNOWN")); + return 1; + } +#ifdef DEBUG + else + xprintf(VERBOSE|DEMUX, "demuxer '%s' cannot handle in stage '%s'.\n", + this->demuxer_plugins[i].get_identifier(), + (stages[s] == STAGE_BY_CONTENT) ? "STAGE_BY_CONTENT" + : ((stages[s] == STAGE_BY_EXTENSION) ? "STAGE_BY_EXTENSION" + : "UNKNOWN")); +#endif + } + s++; + } + + return 0; +} +/* + * Try to find a demuxer which handle the MRL stream + */ +static int find_demuxer(xine_t *this, const char *MRL) { + + this->cur_demuxer_plugin = NULL; + + switch(this->demux_strategy) { + + case DEMUX_DEFAULT_STRATEGY: + if(try_demux_with_stages(this, MRL, STAGE_BY_CONTENT, STAGE_BY_EXTENSION)) + return 1; + break; + + case DEMUX_REVERT_STRATEGY: + if(try_demux_with_stages(this, MRL, STAGE_BY_EXTENSION, STAGE_BY_CONTENT)) + return 1; + break; + + case DEMUX_CONTENT_STRATEGY: + if(try_demux_with_stages(this, MRL, STAGE_BY_CONTENT, -1)) + return 1; + break; + + case DEMUX_EXTENSION_STRATEGY: + if(try_demux_with_stages(this, MRL, STAGE_BY_EXTENSION, -1)) + return 1; + break; + + } + + return 0; +} + +/* + * + */ +static void xine_play_internal (xine_t *this, char *MRL, + int spos, off_t pos) { + + double share ; + off_t len; + int i; + + xprintf (VERBOSE|LOOP, "xine open %s, start pos = %d\n",MRL, spos); + + if (this->status == XINE_PAUSE) { + xine_pause(); + return; + } + + if (this->status != XINE_STOP) { + xine_stop (); + } + + /* + * find input plugin + */ + + this->cur_input_plugin = NULL; + + for (i = 0; i < this->num_input_plugins; i++) { + if (this->input_plugins[i].open(MRL)) { + this->cur_input_plugin = &this->input_plugins[i]; + break; + } + } + + if (!this->cur_input_plugin) { + perror ("open input source"); + this->cur_demuxer_plugin = NULL; + return; + } + + /* + * find demuxer plugin + */ + + if(!find_demuxer(this, MRL)) { + printf ("error: couldn't find demuxer for >%s<\n", MRL); + return; + } + + vo_set_logo_mode (0); + + /* + * Init SPU decoder with colour lookup table. + */ + + if(this->cur_input_plugin->get_clut) + spudec_init(this->cur_input_plugin->get_clut()); + else + spudec_init(NULL); + + /* + * metronom + */ + + metronom_reset(); + + /* + * start demuxer + */ + + if (spos) { + len = this->cur_input_plugin->get_length (); + share = (double) spos / 65535; + pos = (off_t) (share * len) ; + } + + this->cur_demuxer_plugin->demux_select_audio_channel (this->audio_channel); + this->cur_demuxer_plugin->demux_select_spu_channel (this->spu_channel); + this->cur_demuxer_plugin->demux_start (this->cur_input_plugin, + this->mBufVideo, //FIXME + this->mBufAudio, + this->spu_fifo, pos); + + this->status = XINE_PLAY; + this->cur_input_pos = pos; + + /* + * remember MRL + */ + + strncpy (this->cur_mrl, MRL, 1024); + + /* + * start clock + */ + + metronom_start_clock (0); +} + +/* + * + */ +void xine_play (xine_t *this, char *MRL, int spos) { + + pthread_mutex_lock (&this->xine_lock); + + if (this->status != XINE_PLAY) + xine_play_internal (this, MRL, spos, (off_t) 0); + + pthread_mutex_unlock (&this->xine_lock); +} + +/* + * + */ +static int xine_eject (xine_t *this, char *MRL) { + int i; + + pthread_mutex_lock (&this->xine_lock); + + if(this->cur_input_plugin == NULL) { + + for (i = 0; i < this->num_input_plugins; i++) { + if (this->input_pluginss[i].open(MRL)) { + this->cur_input_plugin = &this->input_plugins[i]; + this->cur_input_plugin->close(); + break; + } + } + } + + if (this->status == XINE_STOP + && this->cur_input_plugin && this->cur_input_plugin->eject_media) { + + pthread_mutex_unlock (&this->xine_lock); + + return this->cur_input_plugin->eject_media (); + } + + pthread_mutex_unlock (&this->xine_lock); + return 0; +} + +/* + * + */ +void xine_exit (xine_t *this) { + + void *p; + buf_element_t *pBuf; + + /* + * stop decoder threads + */ + + if (this->cur_input_plugin) + this->cur_input_plugin->demux_stop (); + + this->fifo_funcs->fifo_buffer_clear(this->spu_fifo); + + audio_decoder_shutdown (); + video_decoder_shutdown (); + + this->status = XINE_QUIT; + + config_file_save (); +} + +/* + * + */ +static void xine_pause (xine_t *this) { + + pthread_mutex_lock (&this->xine_lock); + + if (this->status == XINE_PAUSE) { + + xprintf (VERBOSE, "xine play %s from %Ld\n", + this->cur_mrl, this->cur_input_pos); + + this->status = XINE_STOP; + + xine_play_internal (this, this->cur_mrl, 0, this->cur_input_pos); + /* this->mnPausePos = 0; */ + + } else if (this->status == XINE_PLAY) { + + if (!this->cur_input_plugin) { + pthread_mutex_unlock (&this->xine_lock); + return; + } + + this->status = XINE_PAUSE; + + this->cur_demuxer_plugin->demux_stop (); + this->cur_demuxer_plugin = NULL; + + //FIXME + this->fifo_funcs->fifo_buffer_clear(this->mBufVideo); + this->fifo_funcs->fifo_buffer_clear(this->mBufAudio); + this->fifo_funcs->fifo_buffer_clear(this->spu_fifo); + + if (gAudioOut) + gAudioOut->close (); + + metronom_reset(); + metronom_stop_clock (); + + vo_reset (); + + this->cur_input_plugin->close(); + } + + pthread_mutex_unlock (&this->xine_lock); +} + +/* + * + */ +xine_t *xine_init (vo_instance_t *vo, ao_instance_t *ao, + gui_status_callback_func_t gui_status_callback, + int demux_strategy, uint32_t debug_lvl) { + + xine_t *this = xmalloc (sizeof (xine_t)); + int err; + + this->status_callback = gui_status_callback; + this->demux_strategy = demux_strategy; + xine_debug = debug_lvl; + +#ifdef TEST_FILE + gTestFile = open ("/tmp/test.mp3", O_WRONLY | O_CREAT, 0644); +#endif + + /* + * init lock + */ + + pthread_mutex_init (&this->xine_lock, NULL); + + /* + * Init buffers + */ + + this->fifo_funcs = buffer_pool_init (2000, 4096); + this->spu_fifo = this->fifo_funcs->fifo_buffer_new (); + + /* + * init demuxer + */ + + xine_load_demux_plugins(); + + this->audio_channel = 0; + this->spu_channel = -1; + this->cur_input_pos = 0; + + printf ("xine_init: demuxer initialized\n"); + + /* + * init and start decoder threads + */ + + this->mBufVideo = video_decoder_init (vo); + + this->mBufAudio = audio_decoder_init (ao); + + /* + * init SPU decoder, start SPU thread + */ + + spudec_init(NULL); + + if((err = pthread_create (&this->spu_thread, NULL, + xine_spu_loop, NULL)) != 0) { + fprintf(stderr, "pthread_create failed: return code %d.\n", err); + exit(1); + } + else + printf ("xine_init: SPU thread created\n"); + + /* + * load input plugins + */ + + xine_load_input_plugins (); + + printf ("xine_init: plugins loaded\n"); + + return this; +} + +/* + * + */ +int xine_get_audio_channel (xine_t *this) { + + return this->audio_channel; +} + +/* + * + */ +void xine_select_audio_channel (xine_t *this, int nChannel) { + + pthread_mutex_lock (&this->xine_lock); + + this->audio_channel = nChannel; + + if (this->cur_demuxer_plugin) { + this->cur_demuxer_plugin->demux_select_audio_channel (this->audio_channel); + } + + pthread_mutex_unlock (&this->xine_lock); +} + +/* + * + */ +int xine_get_spu_channel (xine_t *this) { + + return this->spu_channel; +} + +/* + * + */ +void xine_select_spu_channel (xine_t *this, int nChannel) { + + pthread_mutex_lock (&this->xine_lock); + + this->spu_channel = (nChannel >= -1 ? nChannel : -1); + + if (this->cur_demuxer_plugin) + this->cur_demuxer_plugin->demux_select_spu_channel (this->spu_channel); + + pthread_mutex_unlock (&this->xine_lock); +} + +/* + * + */ +input_plugin_t* xine_get_input_plugin_list (xine_t *this, int *nInputPlugins) { + + *nInputPlugins = this->num_input_plugins; + return this->input_plugins; +} + +/* + * + */ +int xine_get_current_position (xine_t *this) { + + off_t len; + double share; + + pthread_mutex_lock (&this->xine_lock); + + if (!this->cur_input_plugin) { + xprintf (VERBOSE|INPUT, "xine_get_current_position: no input source\n"); + pthread_mutex_unlock (&this->xine_lock); + return 0; + } + + /* pos = this->mCurInput->seek (0, SEEK_CUR); */ + len = this->cur_input_plugin->get_length (); + + share = (double) this->cur_input_pos / (double) len * 65535; + + pthread_mutex_unlock (&this->xine_lock); + + return (int) share; +} + +/* + * + */ +int xine_get_status(xine_t *this) { + + return this->status; +} diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h new file mode 100644 index 000000000..c097158af --- /dev/null +++ b/src/xine-engine/xine_internal.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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 + * + * $Id: xine_internal.h,v 1.1 2001/04/18 22:36:09 f1rmb Exp $ + * + */ + +#ifndef HAVE_XINE_INTERNAL_H +#define HAVE_XINE_INTERNAL_H + +#include <inttypes.h> +#include "xine.h" +#include "input/input_plugin.h" +#include "demuxers/demux.h" +#include "video_out.h" +#include "audio_out.h" +#include "metronom.h" + +#define INPUT_PLUGIN_MAX 50 +#define DEMUXER_PLUGIN_MAX 50 + +typedef struct xine_s { + + /* private : */ + + metronom_t *metronom; + + input_plugin_t input_plugins[INPUT_PLUGIN_MAX]; + int num_input_plugins; + input_plugin_t *cur_input_plugin; + + demux_plugin_t demuxer_plugins[DEMUXER_PLUGIN_MAX]; + int num_demuxer_plugins; + demux_plugin_t *cur_demuxer_plugin; + int demux_stragegy; + + int status; + off_t cur_input_pos; + char cur_mrl[1024]; + + fifo_buffer_t *spu_fifo; + + int audio_channel; + int spu_channel; + + gui_status_callback_func_t status_callback; + + /* Lock for xine player functions */ + pthread_mutex_t xine_lock; + +} xine_t; + +/* + * Load input/demux/audio_out/video_out plugins + * prototypes of load_plugins.c functions. + */ +void xine_load_demux_plugins (xine_t *this); +void xine_load_input_plugins (xine_t *this); + +#endif |