diff options
Diffstat (limited to 'src/input/input_rtsp.c')
-rw-r--r-- | src/input/input_rtsp.c | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/src/input/input_rtsp.c b/src/input/input_rtsp.c new file mode 100644 index 000000000..ad483bde8 --- /dev/null +++ b/src/input/input_rtsp.c @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2002 the xine project + * + * This file is part of xine, a free 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 + * + * rtsp input plugin + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unistd.h> +#include <stdio.h> +#include <assert.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include "bswap.h" + +#include "xine_internal.h" +#include "xineutils.h" +#include "input_plugin.h" + +#include "librtsp/rtsp_session.h" +#include "net_buf_ctrl.h" + +/* +#define LOG +*/ + +#define BUFSIZE 1025 + +extern int errno; + +#if !defined(NDELAY) && defined(O_NDELAY) +#define FNDELAY O_NDELAY +#endif + +typedef struct { + + input_class_t input_class; + + xine_t *xine; +} rtsp_input_class_t; + +typedef struct { + input_plugin_t input_plugin; + + rtsp_session_t *rtsp; + + char *mrl; + + off_t curpos; + + nbc_t *nbc; + + char scratch[BUFSIZE]; + +} rtsp_input_plugin_t; + + +static off_t rtsp_plugin_read (input_plugin_t *this_gen, + char *buf, off_t len) { + rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; + off_t n; + +#ifdef LOG + printf ("rtsp_plugin_read: %lld bytes ...\n", + len); +#endif + + nbc_check_buffers (this->nbc); + + n = rtsp_session_read (this->rtsp, buf, len); + this->curpos += n; + + return n; +} + +static buf_element_t *rtsp_plugin_read_block (input_plugin_t *this_gen, + fifo_buffer_t *fifo, off_t todo) { + /*rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; */ + buf_element_t *buf = fifo->buffer_pool_alloc (fifo); + int total_bytes; + +#ifdef LOG + printf ("rtsp_plugin_read_block: %lld bytes...\n", + todo); +#endif + + buf->content = buf->mem; + buf->type = BUF_DEMUX_BLOCK; + + total_bytes = rtsp_plugin_read (this_gen, buf->content, todo); + + if (total_bytes != todo) { + buf->free_buffer (buf); + return NULL; + } + + buf->size = total_bytes; + + return buf; +} + +static off_t rtsp_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) { + + rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; + + printf ("input_rtsp: seek %lld bytes, origin %d\n", + offset, origin); + + /* only realtive forward-seeking is implemented */ + + if ((origin == SEEK_CUR) && (offset >= 0)) { + + for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { + this->curpos += rtsp_plugin_read (this_gen, this->scratch, BUFSIZE); + } + + this->curpos += rtsp_plugin_read (this_gen, this->scratch, offset); + } + + return this->curpos; +} + +static off_t rtsp_plugin_get_length (input_plugin_t *this_gen) { + + /* + rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; + off_t length; + */ + + return -1; +} + +static uint32_t rtsp_plugin_get_capabilities (input_plugin_t *this_gen) { + return INPUT_CAP_NOCAP; +} + +static uint32_t rtsp_plugin_get_blocksize (input_plugin_t *this_gen) { + return 0; +} + +static off_t rtsp_plugin_get_current_pos (input_plugin_t *this_gen){ + rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; + + /* + printf ("current pos is %lld\n", this->curpos); + */ + + return this->curpos; +} + +static void rtsp_plugin_dispose (input_plugin_t *this_gen) { + rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; + + if (this->rtsp) { + rtsp_session_end (this->rtsp); + this->rtsp = NULL; + } + + if (this->nbc) { + nbc_close (this->nbc); + this->nbc = NULL; + } + + if(this->mrl) + free(this->mrl); + + free (this); +} + +static char* rtsp_plugin_get_mrl (input_plugin_t *this_gen) { + rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; + + return this->mrl; +} + +static int rtsp_plugin_get_optional_data (input_plugin_t *this_gen, + void *data, int data_type) { + /* rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; */ + + return INPUT_OPTIONAL_UNSUPPORTED; +} + +static input_plugin_t *open_plugin (input_class_t *cls_gen, xine_stream_t *stream, + const char *data) { + + /* rtsp_input_class_t *cls = (rtsp_input_class_t *) cls_gen; */ + rtsp_input_plugin_t *this; + rtsp_session_t *rtsp; + char *mrl = strdup(data); + +#ifdef LOG + printf ("input_rtsp: trying to open '%s'\n", mrl); +#endif + + if (strncasecmp (mrl, "rtsp://", 6)) { + free (mrl); + return NULL; + } + + rtsp = rtsp_session_start(mrl); + + if (!rtsp) { + free (mrl); + return NULL; + } + + this = (rtsp_input_plugin_t *) xine_xmalloc (sizeof (rtsp_input_plugin_t)); + + this->rtsp = rtsp; + this->mrl = mrl; + this->nbc = nbc_init (stream); + + this->input_plugin.get_capabilities = rtsp_plugin_get_capabilities; + this->input_plugin.read = rtsp_plugin_read; + this->input_plugin.read_block = rtsp_plugin_read_block; + this->input_plugin.seek = rtsp_plugin_seek; + this->input_plugin.get_current_pos = rtsp_plugin_get_current_pos; + this->input_plugin.get_length = rtsp_plugin_get_length; + this->input_plugin.get_blocksize = rtsp_plugin_get_blocksize; + this->input_plugin.get_mrl = rtsp_plugin_get_mrl; + this->input_plugin.dispose = rtsp_plugin_dispose; + this->input_plugin.get_optional_data = rtsp_plugin_get_optional_data; + this->input_plugin.input_class = cls_gen; + + return &this->input_plugin; +} + +/* + * rtsp input plugin class stuff + */ + +static char *rtsp_class_get_description (input_class_t *this_gen) { + return _("rtsp streaming input plugin"); +} + +static char *rtsp_class_get_identifier (input_class_t *this_gen) { + return "rtsp"; +} + +static void rtsp_class_dispose (input_class_t *this_gen) { + rtsp_input_class_t *this = (rtsp_input_class_t *) this_gen; + + free (this); +} + +static void *init_class (xine_t *xine, void *data) { + + rtsp_input_class_t *this; + + this = (rtsp_input_class_t *) xine_xmalloc (sizeof (rtsp_input_class_t)); + + this->xine = xine; + + this->input_class.open_plugin = open_plugin; + this->input_class.get_identifier = rtsp_class_get_identifier; + this->input_class.get_description = rtsp_class_get_description; + this->input_class.get_dir = NULL; + this->input_class.get_autoplay_list = NULL; + this->input_class.dispose = rtsp_class_dispose; + this->input_class.eject_media = NULL; + + return this; +} + +/* + * exported plugin catalog entry + */ + +plugin_info_t xine_plugin_info[] = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_INPUT, 10, "rtsp", XINE_VERSION_CODE, NULL, init_class }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; + |