From 25665d389818fca81eefaf83b217c0061b482551 Mon Sep 17 00:00:00 2001 From: Claudio Ciccani Date: Mon, 18 Dec 2006 21:31:47 +0000 Subject: Partially implemented RTSP seekability: support starting the playback at an optional time by delaying the PLAY request upon the first call to rtsp_session_read() and setting the playback start time via input_plugin->seek_time(). CVS patchset: 8422 CVS date: 2006/12/18 21:31:47 --- src/demuxers/demux_real.c | 16 +++++++++++++--- src/input/input_rtsp.c | 26 ++++++++++++++++++-------- src/input/libreal/real.c | 6 +----- src/input/librtsp/rtsp_session.c | 30 +++++++++++++++++++++++++++--- src/input/librtsp/rtsp_session.h | 4 +++- 5 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c index 7441c8619..90852c25c 100644 --- a/src/demuxers/demux_real.c +++ b/src/demuxers/demux_real.c @@ -31,7 +31,7 @@ * * Based on FFmpeg's libav/rm.c. * - * $Id: demux_real.c,v 1.109 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: demux_real.c,v 1.110 2006/12/18 21:31:47 klan Exp $ */ #ifdef HAVE_CONFIG_H @@ -1409,12 +1409,15 @@ static int demux_real_seek (demux_plugin_t *this_gen, real_index_entry_t *index, *other_index = NULL; int i = 0, entries; - start_pos = (off_t) ( (double) start_pos / 65535 * - this->input->get_length (this->input) ); + lprintf("seek start_pos=%d, start_time=%d, playing=%d\n", + (int)start_pos, start_time, playing); if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) && ((this->audio_stream && this->audio_stream->index) || (this->video_stream && this->video_stream->index))) { + + start_pos = (off_t) ( (double) start_pos / 65535 * + this->input->get_length (this->input) ); /* video index has priority over audio index */ if(this->video_stream && this->video_stream->index) { @@ -1453,6 +1456,13 @@ static int demux_real_seek (demux_plugin_t *this_gen, _x_demux_flush_engine(this->stream); } } + else if (this->input->seek_time != NULL) { + /* RTSP supports only time based seek */ + if (start_pos && !start_time) + start_time = (int64_t) this->duration * start_pos / 65535; + + this->input->seek_time(this->input, start_time, SEEK_SET); + } this->send_newpts = 1; this->old_seqnum = -1; diff --git a/src/input/input_rtsp.c b/src/input/input_rtsp.c index 0256edc8d..bcbc19555 100644 --- a/src/input/input_rtsp.c +++ b/src/input/input_rtsp.c @@ -134,6 +134,18 @@ static off_t rtsp_plugin_seek (input_plugin_t *this_gen, off_t offset, int origi return this->curpos; } +static off_t rtsp_plugin_seek_time (input_plugin_t *this_gen, int time_offset, int origin) { + + rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; + + lprintf ("seek_time %d msec, origin %d\n", time_offset, origin); + + if (origin == SEEK_SET) + rtsp_session_set_start_time (this->rtsp, time_offset); + + return this->curpos; +} + static off_t rtsp_plugin_get_length (input_plugin_t *this_gen) { /* @@ -145,7 +157,7 @@ static off_t rtsp_plugin_get_length (input_plugin_t *this_gen) { } static uint32_t rtsp_plugin_get_capabilities (input_plugin_t *this_gen) { - return INPUT_CAP_PREVIEW | INPUT_CAP_RIP_FORBIDDEN; + return INPUT_CAP_PREVIEW | INPUT_CAP_RIP_FORBIDDEN | INPUT_CAP_NOCACHE; } static uint32_t rtsp_plugin_get_blocksize (input_plugin_t *this_gen) { @@ -212,7 +224,7 @@ static int rtsp_plugin_open (input_plugin_t *this_gen) { lprintf ("trying to open '%s'\n", this->mrl); - rtsp = rtsp_session_start(this->stream,this->mrl); + rtsp = rtsp_session_start(this->stream, this->mrl); if (!rtsp) { lprintf ("returning null.\n"); @@ -226,22 +238,19 @@ static int rtsp_plugin_open (input_plugin_t *this_gen) { } static input_plugin_t *rtsp_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream, - const char *data) { + const char *mrl) { /* rtsp_input_class_t *cls = (rtsp_input_class_t *) cls_gen; */ rtsp_input_plugin_t *this; - char *mrl = strdup(data); - if (strncasecmp (mrl, "rtsp://", 6)) { - free (mrl); + if (strncasecmp (mrl, "rtsp://", 6)) return NULL; - } this = (rtsp_input_plugin_t *) xine_xmalloc (sizeof (rtsp_input_plugin_t)); this->stream = stream; this->rtsp = NULL; - this->mrl = mrl; + this->mrl = strdup (mrl); /* since we handle only real streams yet, we can savely add * an .rm extention to force handling by demux_real. */ @@ -255,6 +264,7 @@ static input_plugin_t *rtsp_class_get_instance (input_class_t *cls_gen, xine_str 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.seek_time = rtsp_plugin_seek_time; 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; diff --git a/src/input/libreal/real.c b/src/input/libreal/real.c index 270fd16e4..c3d39fab3 100644 --- a/src/input/libreal/real.c +++ b/src/input/libreal/real.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: real.c,v 1.24 2006/11/29 19:43:01 dgp85 Exp $ + * $Id: real.c,v 1.25 2006/12/18 21:31:47 klan Exp $ * * special functions for real streams. * adopted from joschkas real tools. @@ -715,10 +715,6 @@ rmff_header_t *real_setup_and_get_header(rtsp_t *rtsp_session, uint32_t bandwid rtsp_schedule_field(rtsp_session, subscribe); rtsp_request_setparameter(rtsp_session,NULL); - /* and finally send a play request */ - rtsp_schedule_field(rtsp_session, "Range: npt=0-"); - rtsp_request_play(rtsp_session,NULL); - xine_buffer_free(subscribe); xine_buffer_free(buf); return h; diff --git a/src/input/librtsp/rtsp_session.c b/src/input/librtsp/rtsp_session.c index 6f06693a9..8a5135ac3 100644 --- a/src/input/librtsp/rtsp_session.c +++ b/src/input/librtsp/rtsp_session.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: rtsp_session.c,v 1.16 2004/04/24 16:55:42 miguelfreitas Exp $ + * $Id: rtsp_session.c,v 1.17 2006/12/18 21:31:47 klan Exp $ * * high level interface to rtsp servers. */ @@ -53,7 +53,7 @@ struct rtsp_session_s { rtsp_t *s; /* receive buffer */ - uint8_t *recv; + uint8_t *recv; int recv_size; int recv_read; @@ -62,11 +62,13 @@ struct rtsp_session_s { int header_len; int header_read; + int playing; + int start_time; }; rtsp_session_t *rtsp_session_start(xine_stream_t *stream, char *mrl) { - rtsp_session_t *rtsp_session = malloc(sizeof(rtsp_session_t)); + rtsp_session_t *rtsp_session = xine_xmalloc(sizeof(rtsp_session_t)); char *server; char *mrl_line=strdup(mrl); rmff_header_t *h; @@ -144,6 +146,23 @@ connect: return rtsp_session; } +void rtsp_session_set_start_time (rtsp_session_t *this, int start_time) { + + if (start_time >= 0) + this->start_time = start_time; +} + +static void rtsp_session_play (rtsp_session_t *this) { + + char buf[256]; + + snprintf (buf, sizeof(buf), "Range: npt=%d.%03d-", + this->start_time/1000, this->start_time%1000); + + rtsp_schedule_field (this->s, buf); + rtsp_request_play (this->s,NULL); +} + int rtsp_session_read (rtsp_session_t *this, char *data, int len) { int to_copy=len; @@ -154,6 +173,11 @@ int rtsp_session_read (rtsp_session_t *this, char *data, int len) { if (len < 0) return 0; while (to_copy > fill) { + if (!this->playing) { + rtsp_session_play (this); + this->playing = 1; + } + memcpy(dest, source, fill); to_copy -= fill; dest += fill; diff --git a/src/input/librtsp/rtsp_session.h b/src/input/librtsp/rtsp_session.h index 140d09a0a..649842e7a 100644 --- a/src/input/librtsp/rtsp_session.h +++ b/src/input/librtsp/rtsp_session.h @@ -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: rtsp_session.h,v 1.6 2003/12/09 00:02:31 f1rmb Exp $ + * $Id: rtsp_session.h,v 1.7 2006/12/18 21:31:47 klan Exp $ * * high level interface to rtsp servers. */ @@ -29,6 +29,8 @@ typedef struct rtsp_session_s rtsp_session_t; rtsp_session_t *rtsp_session_start(xine_stream_t *stream, char *mrl); +void rtsp_session_set_start_time(rtsp_session_t *this, int start_time); + int rtsp_session_read(rtsp_session_t *session, char *data, int len); int rtsp_session_peek_header(rtsp_session_t *this, char *buf, int maxsize); -- cgit v1.2.3