diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/input/Makefile.am | 6 | ||||
-rw-r--r-- | src/input/dvd_udf.c | 2 | ||||
-rw-r--r-- | src/input/dvd_udf.h | 13 | ||||
-rw-r--r-- | src/input/input_dvd.c | 108 | ||||
-rw-r--r-- | src/input/read_cache.c | 273 | ||||
-rw-r--r-- | src/input/read_cache.h | 41 |
6 files changed, 365 insertions, 78 deletions
diff --git a/src/input/Makefile.am b/src/input/Makefile.am index 8d9546c01..470428383 100644 --- a/src/input/Makefile.am +++ b/src/input/Makefile.am @@ -26,7 +26,7 @@ lib_LTLIBRARIES = xineplug_inp_file.la $(in_dvd) $(in_vcd) \ xineplug_inp_file_la_SOURCES = input_file.c xineplug_inp_file_la_LDFLAGS = -avoid-version -module -xineplug_inp_dvd_la_SOURCES = input_dvd.c dvd_udf.c +xineplug_inp_dvd_la_SOURCES = input_dvd.c dvd_udf.c read_cache.c xineplug_inp_dvd_la_LDFLAGS = -avoid-version -module xineplug_inp_net_la_SOURCES = input_net.c @@ -42,8 +42,8 @@ xineplug_inp_rtp_la_SOURCES = input_rtp.c xineplug_inp_rtp_la_LDFLAGS = -avoid-version -module include_HEADERS = input_plugin.h -noinst_HEADERS = dvd_udf.h -EXTRA_DIST = input_dvd.c dvd_udf.c input_vcd.c +noinst_HEADERS = dvd_udf.h read_cache.h +EXTRA_DIST = input_dvd.c dvd_udf.c input_vcd.c read_cache.c ## diff --git a/src/input/dvd_udf.c b/src/input/dvd_udf.c index c8064b0eb..6a3d839c5 100644 --- a/src/input/dvd_udf.c +++ b/src/input/dvd_udf.c @@ -549,8 +549,6 @@ off_t UDFFindFile (int fd, char *filename, off_t *size) lb_number = partition.Start+File.Location ; - printf ("lb_number : %Ld\n", lb_number); - retval = lb_number; bail: diff --git a/src/input/dvd_udf.h b/src/input/dvd_udf.h index 77e8ed309..ec19af5ee 100644 --- a/src/input/dvd_udf.h +++ b/src/input/dvd_udf.h @@ -1,12 +1,14 @@ -/* - * Copyright (C) 2000-2001 plitsch-platsch +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. * - * xine_dvd_plugin is free software; you can redistribute it and/or modify + * 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_dvd_plugin is distributed in the hope that it will be useful, + * + * 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. @@ -15,6 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * + * $Id: dvd_udf.h,v 1.3 2001/09/11 00:57:11 guenter Exp $ */ #ifndef DVD_UDF_H diff --git a/src/input/input_dvd.c b/src/input/input_dvd.c index b891e0c83..239997f2e 100644 --- a/src/input/input_dvd.c +++ b/src/input/input_dvd.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: input_dvd.c,v 1.22 2001/09/10 00:47:37 miguelfreitas Exp $ + * $Id: input_dvd.c,v 1.23 2001/09/11 00:57:11 guenter Exp $ */ #ifdef HAVE_CONFIG_H @@ -48,6 +48,7 @@ #include "monitor.h" #include "input_plugin.h" #include "dvd_udf.h" +#include "read_cache.h" static uint32_t xine_debug; @@ -68,6 +69,7 @@ typedef struct { int dvd_fd; int raw_fd; + read_cache_t *read_cache; off_t file_size; off_t file_size_left; int file_lbstart; @@ -110,6 +112,9 @@ static int openDrive (dvd_input_plugin_t *this) { if (this->raw_fd < 0) { this->raw_fd = this->dvd_fd; } + + read_cache_set_fd (this->read_cache, this->raw_fd); + return this->raw_fd; } @@ -123,6 +128,7 @@ static void closeDrive (dvd_input_plugin_t *this) { close (this->raw_fd); this->dvd_fd = -1; + } /* @@ -206,20 +212,16 @@ static int dvd_plugin_open (input_plugin_t *this_gen, char *mrl) { return 1 ; } -/* - * - */ static off_t dvd_plugin_read (input_plugin_t *this_gen, char *buf, off_t nlen) { + dvd_input_plugin_t *this = (dvd_input_plugin_t *) this_gen; if (nlen != DVD_VIDEO_LB_LEN) { - /* - * Hide the error reporting now, demuxer try to read 6 bytes - * at STAGE_BY_CONTENT probe stage - */ - fprintf (stderr, "ERROR in input_dvd plugin read: %Ld bytes " - "is not a sector!\n", nlen); + + printf ("input_dvd: error read: %Ld bytes is not a sector!\n", + nlen); + return 0; } @@ -249,9 +251,6 @@ static void pool_release_buffer (void *arg) { } -/* - * - */ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t nlen) { dvd_input_plugin_t *this = (dvd_input_plugin_t *) this_gen; @@ -263,38 +262,34 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, * at STAGE_BY_CONTENT probe stage */ if(nlen != DVD_VIDEO_LB_LEN) - fprintf (stderr, "ERROR in input_dvd plugin read: %Ld bytes " + printf ("input_dvd: error in input_dvd plugin read: %Ld bytes " "is not a sector!\n", nlen); return NULL; } - buf = fifo->buffer_pool_alloc (fifo); - - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); - pthread_cleanup_push( pool_release_buffer, buf ); - - buf->content = buf->mem; + if ((buf = read_cache_read_block (this->read_cache, this->file_lbcur*DVD_VIDEO_LB_LEN))) { + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); + pthread_cleanup_push( pool_release_buffer, buf ); + + pthread_testcancel(); - pthread_testcancel(); - if ((buf->size = dvd_plugin_read (this_gen, buf->mem, DVD_VIDEO_LB_LEN)) > 0) { + buf->type = BUF_DEMUX_BLOCK; + this->file_lbcur++; this->file_size_left -= DVD_VIDEO_LB_LEN; buf->type = BUF_DEMUX_BLOCK; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); + pthread_cleanup_pop(0); } else { - buf->free_buffer (buf); - buf = NULL; - fprintf (stderr, "read error in input_dvd plugin\n"); + printf ("input_dvd: read error in input_dvd plugin\n"); } - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); - pthread_cleanup_pop(0); return buf; } -/* - * - */ + static off_t dvd_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) { dvd_input_plugin_t *this = (dvd_input_plugin_t *) this_gen; @@ -320,8 +315,7 @@ static off_t dvd_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin break; default: - fprintf (stderr, "error in input dvd plugin seek: %d is an unknown " - "origin\n", origin); + printf ("input_dvd: seek: %d is an unknown origin\n", origin); } return lseek (this->raw_fd, @@ -329,35 +323,27 @@ static off_t dvd_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin - this->file_lbstart * (off_t) DVD_VIDEO_LB_LEN; } -/* - * - */ + static off_t dvd_plugin_get_current_pos (input_plugin_t *this_gen){ dvd_input_plugin_t *this = (dvd_input_plugin_t *) this_gen; return ((this->file_lbcur - this->file_lbstart) * DVD_VIDEO_LB_LEN); } -/* - * - */ + static off_t dvd_plugin_get_length (input_plugin_t *this_gen) { dvd_input_plugin_t *this = (dvd_input_plugin_t *) this_gen; return this->file_size; } -/* - * - */ + static uint32_t dvd_plugin_get_blocksize (input_plugin_t *this_gen) { return DVD_VIDEO_LB_LEN; } -/* - * - */ + static int dvd_plugin_eject_media (input_plugin_t *this_gen) { dvd_input_plugin_t *this = (dvd_input_plugin_t *) this_gen; int ret, status; @@ -413,41 +399,31 @@ static int dvd_plugin_eject_media (input_plugin_t *this_gen) { return 1; } -/* - * - */ + static void dvd_plugin_close (input_plugin_t *this_gen) { dvd_input_plugin_t *this = (dvd_input_plugin_t *) this_gen; closeDrive (this); } -/* - * - */ + static void dvd_plugin_stop (input_plugin_t *this_gen) { dvd_plugin_close(this_gen); } -/* - * - */ + static char *dvd_plugin_get_description (input_plugin_t *this_gen) { return "dvd device input plugin as shipped with xine"; } -/* - * - */ + static char *dvd_plugin_get_identifier (input_plugin_t *this_gen) { return "DVD"; } -/* - * - */ + static mrl_t **dvd_plugin_get_dir (input_plugin_t *this_gen, char *filename, int *nEntries) { dvd_input_plugin_t *this = (dvd_input_plugin_t *) this_gen; @@ -537,9 +513,7 @@ static mrl_t **dvd_plugin_get_dir (input_plugin_t *this_gen, return this->mrls; } -/* - * - */ + static char **dvd_plugin_get_autoplay_list (input_plugin_t *this_gen, int *nFiles) { dvd_input_plugin_t *this = (dvd_input_plugin_t *) this_gen; @@ -583,9 +557,7 @@ static char **dvd_plugin_get_autoplay_list (input_plugin_t *this_gen, return this->filelist2; } -/* - * - */ + static char* dvd_plugin_get_mrl (input_plugin_t *this_gen) { dvd_input_plugin_t *this = (dvd_input_plugin_t *) this_gen; @@ -613,9 +585,7 @@ static int dvd_plugin_get_optional_data (input_plugin_t *this_gen, return INPUT_OPTIONAL_UNSUPPORTED; } -/* - * - */ + input_plugin_t *init_input_plugin (int iface, config_values_t *config) { dvd_input_plugin_t *this; @@ -671,6 +641,8 @@ input_plugin_t *init_input_plugin (int iface, config_values_t *config) { this->config = config; this->dvd_fd = -1; this->raw_fd = -1; + + this->read_cache = read_cache_new (); return (input_plugin_t *) this; } diff --git a/src/input/read_cache.c b/src/input/read_cache.c new file mode 100644 index 000000000..60a139d53 --- /dev/null +++ b/src/input/read_cache.c @@ -0,0 +1,273 @@ +/* + * 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: read_cache.c,v 1.1 2001/09/11 00:57:11 guenter Exp $ + */ + +#include <sys/types.h> +#include <stdlib.h> +#include <unistd.h> + +#include <xine/utils.h> + +#include "read_cache.h" + +#define NUM_BUFFERS 512 +#define NUM_MACRO_BUFFERS 32 + +typedef struct macro_buf_s macro_buf_t; + +struct macro_buf_s { + + macro_buf_t *next; + + int ref; + off_t adr; + + uint8_t *data; + read_cache_t *source; +}; + +struct read_cache_s { + + int fd; + + macro_buf_t *mbuf_pool_top; + char *multi_base; + buf_element_t *buf_pool_top; + + macro_buf_t *cur_mbuf; + + pthread_mutex_t lock; + pthread_cond_t buf_pool_not_empty; + pthread_cond_t mbuf_pool_not_empty; +}; + +/* + * helper function to release buffer pool lock + * in case demux thread is cancelled + */ + +static void cache_release_lock (void *arg) { + + pthread_mutex_t *mutex = (pthread_mutex_t *) arg; + + /* printf ("pool release lock\n"); */ + + pthread_mutex_unlock (mutex); + +} + +static void buf_free (buf_element_t *buf) { + + macro_buf_t *mbuf = (macro_buf_t *) buf->source; + read_cache_t *this = mbuf->source; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); + + pthread_cleanup_push( cache_release_lock, &this->lock); + + pthread_mutex_lock (&this->lock); + + /* free buffer */ + + buf->next = this->buf_pool_top; + this->buf_pool_top = buf; + + pthread_cond_signal (&this->buf_pool_not_empty); + + /* maybe free mbuf too */ + + mbuf->ref--; + + if (!mbuf->ref && (mbuf != this->cur_mbuf)) { + + mbuf->next = this->mbuf_pool_top; + this->mbuf_pool_top = mbuf; + + pthread_cond_signal (&this->mbuf_pool_not_empty); + } + + pthread_cleanup_pop (0); + pthread_mutex_unlock (&this->lock); + /* needed because cancellation points defined by POSIX + (eg. 'read') would leak allocated buffers */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); +} + +read_cache_t *read_cache_new () { + + read_cache_t *this; + int i; + char *multi_buffer = NULL; + int buf_size; + + this = (read_cache_t *) xmalloc (sizeof (read_cache_t)); + + pthread_mutex_init (&this->lock, NULL); + pthread_cond_init (&this->buf_pool_not_empty, NULL); + pthread_cond_init (&this->mbuf_pool_not_empty, NULL); + + /* init buffer pool */ + + this->buf_pool_top = NULL; + for (i = 0; i<NUM_BUFFERS; i++) { + buf_element_t *buf; + + buf = xmalloc (sizeof (buf_element_t)); + + buf->max_size = 2048; + buf->free_buffer = buf_free; + + buf->next = this->buf_pool_top; + this->buf_pool_top = buf; + } + + /* init macro buffer pool */ + + buf_size = NUM_MACRO_BUFFERS * 2048 * 16; + buf_size += 2048; /* alignment space */ + this->multi_base = xmalloc (buf_size); + multi_buffer = this->multi_base; + while ((int) multi_buffer % 2048) + multi_buffer++; + + this->mbuf_pool_top = NULL; + for (i = 0; i<NUM_MACRO_BUFFERS; i++) { + macro_buf_t *mbuf; + + mbuf = xmalloc (sizeof (macro_buf_t)); + + mbuf->data = multi_buffer; + multi_buffer += 2048*16; + mbuf->source = this; + + mbuf->next = this->mbuf_pool_top; + this->mbuf_pool_top = mbuf; + } + + return this; +} + +void read_cache_set_fd (read_cache_t *this, int fd) { + this->fd = fd; +} + + +buf_element_t *read_cache_read_block (read_cache_t *this, + off_t pos) { + + macro_buf_t *mbuf; + buf_element_t *buf; + off_t madr; + int badr; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); + + pthread_cleanup_push( cache_release_lock, &this->lock); + + pthread_mutex_lock (&this->lock); + + /* address calculations */ + + madr = pos & (~ (off_t) 0x7FFF); + badr = pos & ((off_t) 0x7FFF); + + /* find or create macroblock that contains this block */ + + if ( !this->cur_mbuf || (this->cur_mbuf->adr != madr) ) { + + if (this->cur_mbuf && (!this->cur_mbuf->ref)) { + + mbuf = this->cur_mbuf; + + } else { + + while (this->mbuf_pool_top==NULL) { + pthread_cond_wait (&this->mbuf_pool_not_empty, &this->lock); + } + + mbuf = this->mbuf_pool_top; + + this->mbuf_pool_top = this->mbuf_pool_top->next; + } + + mbuf->adr = madr; + mbuf->ref = 0; + + /* FIXME: error checking */ + lseek (this->fd, madr, SEEK_SET) ; + read ( this->fd, mbuf->data, 2048*16); + + this->cur_mbuf = mbuf; + + } else { + mbuf = this->cur_mbuf; + } + + + /* create buf */ + + while (this->buf_pool_top==NULL) { + pthread_cond_wait (&this->buf_pool_not_empty, &this->lock); + } + + buf = this->buf_pool_top; + + this->buf_pool_top = this->buf_pool_top->next; + + buf->mem = mbuf->data + badr; + buf->content = buf->mem; + buf->source = mbuf; + + mbuf->ref++; + + pthread_cleanup_pop (0); + pthread_mutex_unlock (&this->lock); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); + + return buf; +} + +void read_cache_free (read_cache_t *this) { + + buf_element_t *buf; + macro_buf_t *mbuf; + + buf = this->buf_pool_top; + while (buf) { + buf_element_t *next = buf->next; + + free(buf); + buf = next; + } + + mbuf = this->mbuf_pool_top; + while (mbuf) { + macro_buf_t *mnext = mbuf->next; + + free (mbuf); + mbuf = mnext; + } + + free (this->multi_base); + + free (this); +} + diff --git a/src/input/read_cache.h b/src/input/read_cache.h new file mode 100644 index 000000000..7cd3da4ac --- /dev/null +++ b/src/input/read_cache.h @@ -0,0 +1,41 @@ +/* + * 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: read_cache.h,v 1.1 2001/09/11 00:57:11 guenter Exp $ + */ + +#ifndef HAVE_READ_CACHE_H +#define HAVE_READ_CACHE_H + +#include <inttypes.h> +#include <sys/types.h> +#include <xine/buffer.h> + +typedef struct read_cache_s read_cache_t; + +read_cache_t *read_cache_new (); + +void read_cache_set_fd (read_cache_t *this, int fd); + +buf_element_t *read_cache_read_block (read_cache_t *this, + off_t pos); + +void read_cache_free (read_cache_t *this); + +#endif |