changeset 18799:e16345b97dab

moved generic rtsp related files from realrtsp to librtsp
author ben
date Fri, 23 Jun 2006 21:38:28 +0000
parents a738f1e0224f
children 1cd24dd02261
files libmpdemux/Makefile libmpdemux/librtsp/rtsp.c libmpdemux/librtsp/rtsp.h libmpdemux/librtsp/rtsp_session.c libmpdemux/librtsp/rtsp_session.h libmpdemux/realrtsp/real.h libmpdemux/realrtsp/rtsp.c libmpdemux/realrtsp/rtsp.h libmpdemux/realrtsp/rtsp_session.c libmpdemux/realrtsp/rtsp_session.h libmpdemux/realrtsp/sdpplin.c libmpdemux/realrtsp/sdpplin.h libmpdemux/rtsp.c
diffstat 13 files changed, 1223 insertions(+), 1220 deletions(-) [+]
line wrap: on
line diff
--- a/libmpdemux/Makefile	Fri Jun 23 20:32:32 2006 +0000
+++ b/libmpdemux/Makefile	Fri Jun 23 21:38:28 2006 +0000
@@ -135,11 +135,12 @@
 SRCS += realrtsp/asmrp.c \
         realrtsp/real.c \
         realrtsp/rmff.c \
-        realrtsp/rtsp.c \
-        realrtsp/rtsp_session.c \
         realrtsp/sdpplin.c \
         realrtsp/xbuffer.c \
 
+SRCS += librtsp/rtsp.c \
+        librtsp/rtsp_session.c \
+
 ifeq ($(STREAMING_LIVE555),yes)
 CPLUSPLUSSRCS = demux_rtp.cpp demux_rtp_codec.cpp
 CPLUSPLUSINCLUDE = $(LIVE_INCLUDES)
@@ -185,7 +186,9 @@
 	  $(ALSA_LIB) $(VORBIS_LIB) $(CDPARANOIA_LIB) -lz -lpthread
 
 clean:
-	rm -f *.o *.a *~ realrtsp/*.o realrtsp/*.a realrtsp/*~
+	rm -f *.o *.a *~ \
+	realrtsp/*.o realrtsp/*.a realrtsp/*~ \
+	librtsp/*.o librtsp/*.a librtsp/*~
 
 distclean: clean
 	rm -f .depend test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmpdemux/librtsp/rtsp.c	Fri Jun 23 21:38:28 2006 +0000
@@ -0,0 +1,889 @@
+/*
+ * This file was ported to MPlayer from xine CVS rtsp.c,v 1.9 2003/04/10 02:30:48
+ */
+
+/*
+ * Copyright (C) 2000-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
+ *
+ *
+ * a minimalistic implementation of rtsp protocol,
+ * *not* RFC 2326 compilant yet.
+ *
+ *    2006, Benjamin Zores and Vincent Mussard
+ *      fixed a lot of RFC compliance issues.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <assert.h>
+#include "config.h"
+#ifndef HAVE_WINSOCK2
+#define closesocket close
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#else
+#include <winsock2.h>
+#endif
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include "mp_msg.h"
+#include "rtsp.h"
+#include "rtsp_session.h"
+#include "osdep/timer.h"
+
+/*
+#define LOG
+*/
+
+#define BUF_SIZE 4096
+#define HEADER_SIZE 1024
+#define MAX_FIELDS 256
+
+struct rtsp_s {
+
+  int           s;
+
+  char         *host;
+  int           port;
+  char         *path;
+  char         *param;
+  char         *mrl;
+  char         *user_agent;
+
+  char         *server;
+  unsigned int  server_state;
+  uint32_t      server_caps;
+  
+  unsigned int  cseq;
+  char         *session;
+
+  char        *answers[MAX_FIELDS];   /* data of last message */
+  char        *scheduled[MAX_FIELDS]; /* will be sent with next message */
+};
+
+/*
+ * constants
+ */
+
+#define RTSP_PROTOCOL_VERSION "RTSP/1.0"
+
+/* server states */
+#define RTSP_CONNECTED 1
+#define RTSP_INIT      2
+#define RTSP_READY     4
+#define RTSP_PLAYING   8
+#define RTSP_RECORDING 16
+
+/* server capabilities */
+#define RTSP_OPTIONS       0x001
+#define RTSP_DESCRIBE      0x002
+#define RTSP_ANNOUNCE      0x004
+#define RTSP_SETUP         0x008
+#define RTSP_GET_PARAMETER 0x010
+#define RTSP_SET_PARAMETER 0x020
+#define RTSP_TEARDOWN      0x040
+#define RTSP_PLAY          0x080
+#define RTSP_RECORD        0x100
+
+/*
+ * network utilities
+ */
+ 
+static int host_connect_attempt(struct in_addr ia, int port) {
+
+  int                s;
+  struct sockaddr_in sin;
+
+  s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);  
+  if (s == -1) {
+    mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: socket(): %s\n", strerror(errno));
+    return -1;
+  }
+
+  sin.sin_family = AF_INET;
+  sin.sin_addr   = ia;
+  sin.sin_port   = htons(port);
+  
+  if (connect(s, (struct sockaddr *)&sin, sizeof(sin))==-1 
+#ifndef HAVE_WINSOCK2
+      && errno != EINPROGRESS) {
+#else
+      && WSAGetLastError() == WSAEINPROGRESS) {
+#endif
+    mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: connect(): %s\n", strerror(errno));
+    closesocket(s);
+    return -1;
+  }
+
+  return s;
+}
+
+static int host_connect(const char *host, int port) {
+
+  struct hostent *h;
+  int             i, s;
+  
+  h = gethostbyname(host);
+  if (h == NULL) {
+    mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: unable to resolve '%s'.\n", host);
+    return -1;
+  }
+
+  for (i = 0; h->h_addr_list[i]; i++) {
+    struct in_addr ia;
+
+    memcpy (&ia, h->h_addr_list[i], 4);
+    s = host_connect_attempt(ia, port);
+    if(s != -1)
+      return s;
+  }
+  mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: unable to connect to '%s'.\n", host);
+  return -1;
+}
+
+static int write_stream(int s, const char *buf, int len) {
+  int total, timeout;
+
+  total = 0; timeout = 30;
+  while (total < len){ 
+    int n;
+
+    n = send (s, &buf[total], len - total, 0);
+
+    if (n > 0)
+      total += n;
+    else if (n < 0) {
+#ifndef HAVE_WINSOCK2
+      if ((timeout>0) && ((errno == EAGAIN) || (errno == EINPROGRESS))) {
+#else
+      if ((timeout>0) && ((errno == EAGAIN) || (WSAGetLastError() == WSAEINPROGRESS))) {
+#endif
+        usec_sleep (1000000); timeout--;
+      } else
+        return -1;
+    }
+  }
+
+  return total;
+}
+
+static ssize_t read_stream(int fd, void *buf, size_t count) {
+  
+  ssize_t ret, total;
+
+  total = 0;
+
+  while (total < count) {
+  
+    ret=recv (fd, ((uint8_t*)buf)+total, count-total, 0);
+
+    if (ret<0) {
+      if(errno == EAGAIN) {
+        fd_set rset;
+        struct timeval timeout;
+    
+        FD_ZERO (&rset);
+        FD_SET  (fd, &rset);
+        
+        timeout.tv_sec  = 30;
+        timeout.tv_usec = 0;
+        
+        if (select (fd+1, &rset, NULL, NULL, &timeout) <= 0) {
+          return -1;
+        }
+        continue;
+      }
+      
+      mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: read error.\n");
+      return ret;
+    } else
+      total += ret;
+    
+    /* end of stream */
+    if (!ret) break;
+  }
+
+  return total;
+}
+
+/*
+ * debugging utilities
+ */
+#if 0 
+static void hexdump (char *buf, int length) {
+
+  int i;
+
+  mp_msg(MSGT_OPEN, MSGL_INFO, "rtsp: ascii>");
+  for (i = 0; i < length; i++) {
+    unsigned char c = buf[i];
+
+    if ((c >= 32) && (c <= 128))
+      mp_msg(MSGT_OPEN, MSGL_INFO, "%c", c);
+    else
+      mp_msg(MSGT_OPEN, MSGL_INFO, ".");
+  }
+  mp_msg(MSGT_OPEN, MSGL_INFO, "\n");
+
+  mp_msg(MSGT_OPEN, MSGL_INFO, "rtsp: hexdump> ");
+  for (i = 0; i < length; i++) {
+    unsigned char c = buf[i];
+
+    mp_msg(MSGT_OPEN, MSGL_INFO, "%02x", c);
+
+    if ((i % 16) == 15)
+      mp_msg(MSGT_OPEN, MSGL_INFO, "\nrtsp:         ");
+
+    if ((i % 2) == 1)
+      mp_msg(MSGT_OPEN, MSGL_INFO, " ");
+
+  }
+  mp_msg(MSGT_OPEN, MSGL_INFO, "\n");
+}
+#endif
+
+/*
+ * rtsp_get gets a line from stream
+ * and returns a null terminated string.
+ */
+ 
+static char *rtsp_get(rtsp_t *s) {
+
+  int n=1;
+  char *buffer = malloc(BUF_SIZE);
+  char *string = NULL;
+
+  read_stream(s->s, buffer, 1);
+  while (n<BUF_SIZE) {
+    read_stream(s->s, &(buffer[n]), 1);
+    if ((buffer[n-1]==0x0d)&&(buffer[n]==0x0a)) break;
+    n++;
+  }
+
+  if (n>=BUF_SIZE) {
+    mp_msg(MSGT_OPEN, MSGL_FATAL, "librtsp: buffer overflow in rtsp_get\n");
+    exit(1);
+  }
+  string=malloc(sizeof(char)*n);
+  memcpy(string,buffer,n-1);
+  string[n-1]=0;
+
+#ifdef LOG
+  mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: << '%s'\n", string);
+#endif
+  
+
+  free(buffer);
+  return string;
+}
+
+/*
+ * rtsp_put puts a line on stream
+ */
+ 
+static void rtsp_put(rtsp_t *s, const char *string) {
+
+  int len=strlen(string);
+  char *buf=malloc(sizeof(char)*len+2);
+
+#ifdef LOG
+  mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: >> '%s'", string);
+#endif
+
+  memcpy(buf,string,len);
+  buf[len]=0x0d;
+  buf[len+1]=0x0a;
+
+  write_stream(s->s, buf, len+2);
+  
+#ifdef LOG
+  mp_msg(MSGT_OPEN, MSGL_INFO, " done.\n");
+#endif
+
+  free(buf);
+}
+
+/*
+ * extract server status code
+ */
+
+static int rtsp_get_code(const char *string) {
+
+  char buf[4];
+  int code=0;
+ 
+  if (!strncmp(string, RTSP_PROTOCOL_VERSION, strlen(RTSP_PROTOCOL_VERSION)))
+  {
+    memcpy(buf, string+strlen(RTSP_PROTOCOL_VERSION)+1, 3);
+    buf[3]=0;
+    code=atoi(buf);
+  } else if (!strncmp(string, RTSP_METHOD_SET_PARAMETER,8))
+  {
+    return RTSP_STATUS_SET_PARAMETER;
+  }
+
+  if(code != RTSP_STATUS_OK) mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: server responds: '%s'\n",string);
+
+  return code;
+}
+
+/*
+ * send a request
+ */
+
+static void rtsp_send_request(rtsp_t *s, const char *type, const char *what) {
+
+  char **payload=s->scheduled;
+  char *buf;
+  
+  buf = malloc(strlen(type)+strlen(what)+strlen(RTSP_PROTOCOL_VERSION)+3);
+  
+  sprintf(buf,"%s %s %s",type, what, RTSP_PROTOCOL_VERSION);
+  rtsp_put(s,buf);
+  free(buf);
+  if (payload)
+    while (*payload) {
+      rtsp_put(s,*payload);
+      payload++;
+    }
+  rtsp_put(s,"");
+  rtsp_unschedule_all(s);
+}
+
+/*
+ * schedule standard fields
+ */
+
+static void rtsp_schedule_standard(rtsp_t *s) {
+
+  char tmp[16];
+  
+  snprintf(tmp, 16, "CSeq: %u", s->cseq);
+  rtsp_schedule_field(s, tmp);
+  
+  if (s->session) {
+    char *buf;
+    buf = malloc(strlen(s->session)+15);
+    sprintf(buf, "Session: %s", s->session);
+    rtsp_schedule_field(s, buf);
+    free(buf);
+  }
+}
+/*
+ * get the answers, if server responses with something != 200, return NULL
+ */
+ 
+static int rtsp_get_answers(rtsp_t *s) {
+
+  char *answer=NULL;
+  unsigned int answer_seq;
+  char **answer_ptr=s->answers;
+  int code;
+  int ans_count = 0;
+  
+  answer=rtsp_get(s);
+  if (!answer)
+    return 0;
+  code=rtsp_get_code(answer);
+  free(answer);
+
+  rtsp_free_answers(s);
+  
+  do { /* while we get answer lines */
+  
+    answer=rtsp_get(s);
+    if (!answer)
+      return 0;
+    
+    if (!strncmp(answer,"CSeq:",5)) {
+      sscanf(answer,"CSeq: %u",&answer_seq);
+      if (s->cseq != answer_seq) {
+#ifdef LOG
+        mp_msg(MSGT_OPEN, MSGL_WARN, "librtsp: warning: CSeq mismatch. got %u, assumed %u", answer_seq, s->cseq);
+#endif
+        s->cseq=answer_seq;
+      }
+    }
+    if (!strncmp(answer,"Server:",7)) {
+      char *buf = malloc(strlen(answer));
+      sscanf(answer,"Server: %s",buf);
+      if (s->server) free(s->server);
+      s->server=strdup(buf);
+      free(buf);
+    }
+    if (!strncmp(answer,"Session:",8)) {
+      char *buf = calloc(1, strlen(answer));
+      sscanf(answer,"Session: %s",buf);
+      if (s->session) {
+        if (strcmp(buf, s->session)) {
+          mp_msg(MSGT_OPEN, MSGL_WARN, "rtsp: warning: setting NEW session: %s\n", buf);
+          free(s->session);
+          s->session=strdup(buf);
+        }
+      } else
+      {
+#ifdef LOG
+        mp_msg(MSGT_OPEN, MSGL_INFO, "rtsp: setting session id to: %s\n", buf);
+#endif
+        s->session=strdup(buf);
+      }
+      free(buf);
+    }
+    *answer_ptr=answer;
+    answer_ptr++;
+  } while ((strlen(answer)!=0) && (++ans_count < MAX_FIELDS));
+  
+  s->cseq++;
+  
+  *answer_ptr=NULL;
+  rtsp_schedule_standard(s);
+    
+  return code;
+}
+
+/*
+ * send an ok message
+ */
+
+int rtsp_send_ok(rtsp_t *s) {
+  char cseq[16];
+  
+  rtsp_put(s, "RTSP/1.0 200 OK");
+  sprintf(cseq,"CSeq: %u", s->cseq);
+  rtsp_put(s, cseq);
+  rtsp_put(s, "");
+  return 0;
+}
+
+/*
+ * implementation of must-have rtsp requests; functions return
+ * server status code.
+ */
+
+int rtsp_request_options(rtsp_t *s, const char *what) {
+
+  char *buf;
+
+  if (what) {
+    buf=strdup(what);
+  } else
+  {
+    buf=malloc(sizeof(char)*(strlen(s->host)+16));
+    sprintf(buf,"rtsp://%s:%i", s->host, s->port);
+  }
+  rtsp_send_request(s,RTSP_METHOD_OPTIONS,buf);
+  free(buf);
+
+  return rtsp_get_answers(s);
+}
+
+int rtsp_request_describe(rtsp_t *s, const char *what) {
+
+  char *buf;
+
+  if (what) {
+    buf=strdup(what);
+  } else
+  {
+    buf=malloc(sizeof(char)*(strlen(s->host)+strlen(s->path)+16));
+    sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path);
+  }
+  rtsp_send_request(s,RTSP_METHOD_DESCRIBE,buf);
+  free(buf);
+  
+  return rtsp_get_answers(s);
+}
+
+int rtsp_request_setup(rtsp_t *s, const char *what, char *control) {
+
+  char *buf = NULL;
+
+  if (what)
+    buf = strdup (what);
+  else
+  {
+    int len = strlen (s->host) + strlen (s->path) + 16;
+    if (control)
+      len += strlen (control) + 1;
+    
+    buf = malloc (len);
+    sprintf (buf, "rtsp://%s:%i/%s%s%s", s->host, s->port, s->path,
+             control ? "/" : "", control ? control : "");
+  }
+  
+  rtsp_send_request (s, RTSP_METHOD_SETUP, buf);
+  free (buf);
+  return rtsp_get_answers (s);
+}
+
+int rtsp_request_setparameter(rtsp_t *s, const char *what) {
+
+  char *buf;
+
+  if (what) {
+    buf=strdup(what);
+  } else
+  {
+    buf=malloc(sizeof(char)*(strlen(s->host)+strlen(s->path)+16));
+    sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path);
+  }
+  rtsp_send_request(s,RTSP_METHOD_SET_PARAMETER,buf);
+  free(buf);
+  
+  return rtsp_get_answers(s);
+}
+
+int rtsp_request_play(rtsp_t *s, const char *what) {
+
+  char *buf;
+  int ret;
+  
+  if (what) {
+    buf=strdup(what);
+  } else
+  {
+    buf=malloc(sizeof(char)*(strlen(s->host)+strlen(s->path)+16));
+    sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path);
+  }
+  rtsp_send_request(s,RTSP_METHOD_PLAY,buf);
+  free(buf);
+  
+  ret = rtsp_get_answers (s);
+  if (ret == RTSP_STATUS_OK)
+    s->server_state = RTSP_PLAYING;
+
+  return ret;
+}
+
+int rtsp_request_teardown(rtsp_t *s, const char *what) {
+
+  char *buf;
+  
+  if (what)
+    buf = strdup (what);
+  else
+  {
+    buf =
+      malloc (strlen (s->host) + strlen (s->path) + 16);
+    sprintf (buf, "rtsp://%s:%i/%s", s->host, s->port, s->path);
+  }
+  rtsp_send_request (s, RTSP_METHOD_TEARDOWN, buf);
+  free (buf);
+ 
+  return rtsp_get_answers(s);
+}
+
+/*
+ * read opaque data from stream
+ */
+
+int rtsp_read_data(rtsp_t *s, char *buffer, unsigned int size) {
+
+  int i,seq;
+
+  if (size>=4) {
+    i=read_stream(s->s, buffer, 4);
+    if (i<4) return i;
+    if (((buffer[0]=='S')&&(buffer[1]=='E')&&(buffer[2]=='T')&&(buffer[3]=='_')) ||
+        ((buffer[0]=='O')&&(buffer[1]=='P')&&(buffer[2]=='T')&&(buffer[3]=='I'))) // OPTIONS
+    {
+      char *rest=rtsp_get(s);
+      if (!rest)
+        return -1;      
+
+      seq=-1;
+      do {
+        free(rest);
+        rest=rtsp_get(s);
+        if (!rest)
+          return -1;
+        if (!strncmp(rest,"CSeq:",5))
+          sscanf(rest,"CSeq: %u",&seq);
+      } while (strlen(rest)!=0);
+      free(rest);
+      if (seq<0) {
+#ifdef LOG
+        mp_msg(MSGT_OPEN, MSGL_WARN, "rtsp: warning: CSeq not recognized!\n");
+#endif
+        seq=1;
+      }
+      /* let's make the server happy */
+      rtsp_put(s, "RTSP/1.0 451 Parameter Not Understood");
+      rest=malloc(sizeof(char)*16);
+      sprintf(rest,"CSeq: %u", seq);
+      rtsp_put(s, rest);
+      rtsp_put(s, "");
+      i=read_stream(s->s, buffer, size);
+    } else
+    {
+      i=read_stream(s->s, buffer+4, size-4);
+      i+=4;
+    }
+  } else
+    i=read_stream(s->s, buffer, size);
+#ifdef LOG
+  mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: << %d of %d bytes\n", i, size);
+#endif
+
+  return i;
+}
+
+/*
+ * connect to a rtsp server
+ */
+
+//rtsp_t *rtsp_connect(const char *mrl, const char *user_agent) {
+rtsp_t *rtsp_connect(int fd, char* mrl, char *path, char *host, int port, char *user_agent) {
+
+  rtsp_t *s=malloc(sizeof(rtsp_t));
+  int i;
+  
+  for (i=0; i<MAX_FIELDS; i++) {
+    s->answers[i]=NULL;
+    s->scheduled[i]=NULL;
+  }
+
+  s->server=NULL;
+  s->server_state=0;
+  s->server_caps=0;
+  
+  s->cseq=0;
+  s->session=NULL;
+  
+  if (user_agent)
+    s->user_agent=strdup(user_agent);
+  else
+    s->user_agent=strdup("User-Agent: RealMedia Player Version 6.0.9.1235 (linux-2.0-libc6-i386-gcc2.95)");
+
+  s->mrl = strdup(mrl);
+  s->host = strdup(host);
+  s->port = port;
+  s->path = strdup(path);
+  while (*path == '/')
+    path++;
+  if ((s->param = strchr(s->path, '?')) != NULL)
+    s->param++;
+  //mp_msg(MSGT_OPEN, MSGL_INFO, "path=%s\n", s->path);
+  //mp_msg(MSGT_OPEN, MSGL_INFO, "param=%s\n", s->param ? s->param : "NULL");
+  s->s = fd;
+
+  if (s->s < 0) {
+    mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: failed to connect to '%s'\n", s->host);
+    rtsp_close(s);
+    return NULL;
+  }
+
+  s->server_state=RTSP_CONNECTED;
+
+  /* now let's send an options request. */
+  rtsp_schedule_field(s, "CSeq: 1");
+  rtsp_schedule_field(s, s->user_agent);
+  rtsp_schedule_field(s, "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7");
+  rtsp_schedule_field(s, "PlayerStarttime: [28/03/2003:22:50:23 00:00]");
+  rtsp_schedule_field(s, "CompanyID: KnKV4M4I/B2FjJ1TToLycw==");
+  rtsp_schedule_field(s, "GUID: 00000000-0000-0000-0000-000000000000");
+  rtsp_schedule_field(s, "RegionData: 0");
+  rtsp_schedule_field(s, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586");
+  /*rtsp_schedule_field(s, "Pragma: initiate-session");*/
+  rtsp_request_options(s, NULL);
+
+  return s;
+}
+
+
+/*
+ * closes an rtsp connection 
+ */
+
+void rtsp_close(rtsp_t *s) {
+
+  if (s->server_state)
+  {
+    if (s->server_state == RTSP_PLAYING)
+      rtsp_request_teardown (s, NULL);
+    closesocket (s->s);
+  }
+
+  if (s->path) free(s->path);
+  if (s->host) free(s->host);
+  if (s->mrl) free(s->mrl);
+  if (s->session) free(s->session);
+  if (s->user_agent) free(s->user_agent);
+  rtsp_free_answers(s);
+  rtsp_unschedule_all(s);
+  free(s);  
+}
+
+/*
+ * search in answers for tags. returns a pointer to the content
+ * after the first matched tag. returns NULL if no match found.
+ */
+
+char *rtsp_search_answers(rtsp_t *s, const char *tag) {
+
+  char **answer;
+  char *ptr;
+  
+  if (!s->answers) return NULL;
+  answer=s->answers;
+
+  while (*answer) {
+    if (!strncasecmp(*answer,tag,strlen(tag))) {
+      ptr=strchr(*answer,':');
+      if (!ptr) return NULL;
+      ptr++;
+      while(*ptr==' ') ptr++;
+      return ptr;
+    }
+    answer++;
+  }
+
+  return NULL;
+}
+
+/*
+ * session id management
+ */
+
+void rtsp_set_session(rtsp_t *s, const char *id) {
+
+  if (s->session) free(s->session);
+
+  s->session=strdup(id);
+
+}
+
+char *rtsp_get_session(rtsp_t *s) {
+
+  return s->session;
+
+}
+
+char *rtsp_get_mrl(rtsp_t *s) {
+
+  return s->mrl;
+
+}
+
+char *rtsp_get_param(rtsp_t *s, char *p) {
+  int len;
+  char *param;
+  if (!s->param)
+    return NULL;
+  if (!p)
+    return strdup(s->param);
+  len = strlen(p);
+  param = s->param;
+  while (param && *param) {
+    char *nparam = strchr(param, '&');
+    if (strncmp(param, p, len) == 0 && param[len] == '=') {
+      param += len + 1;
+      len = nparam ? nparam - param : strlen(param);
+      nparam = malloc(len + 1);
+      memcpy(nparam, param, len);
+      nparam[len] = 0;
+      return nparam;
+    }
+    param = nparam ? nparam + 1 : NULL;
+  }
+  return NULL;
+}
+  
+/*
+ * schedules a field for transmission
+ */
+
+void rtsp_schedule_field(rtsp_t *s, const char *string) {
+
+  int i=0;
+  
+  if (!string) return;
+
+  while(s->scheduled[i]) {
+    i++;
+  }
+  s->scheduled[i]=strdup(string);
+}
+
+/*
+ * removes the first scheduled field which prefix matches string. 
+ */
+
+void rtsp_unschedule_field(rtsp_t *s, const char *string) {
+
+  char **ptr=s->scheduled;
+  
+  if (!string) return;
+
+  while(*ptr) {
+    if (!strncmp(*ptr, string, strlen(string)))
+      break;
+    else
+      ptr++;
+  }
+  if (*ptr) free(*ptr);
+  ptr++;
+  do {
+    *(ptr-1)=*ptr;
+  } while(*ptr);
+}
+
+/*
+ * unschedule all fields
+ */
+
+void rtsp_unschedule_all(rtsp_t *s) {
+
+  char **ptr;
+  
+  if (!s->scheduled) return;
+  ptr=s->scheduled;
+
+  while (*ptr) {
+    free(*ptr);
+    *ptr=NULL;
+    ptr++;
+  }
+}
+/*
+ * free answers
+ */
+
+void rtsp_free_answers(rtsp_t *s) {
+
+  char **answer;
+  
+  if (!s->answers) return;
+  answer=s->answers;
+
+  while (*answer) {
+    free(*answer);
+    *answer=NULL;
+    answer++;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmpdemux/librtsp/rtsp.h	Fri Jun 23 21:38:28 2006 +0000
@@ -0,0 +1,84 @@
+/*
+ * This file was ported to MPlayer from xine CVS rtsp.h,v 1.2 2002/12/16 21:50:55
+ */
+
+/*
+ * 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
+ *
+ *
+ * a minimalistic implementation of rtsp protocol,
+ * *not* RFC 2326 compilant yet.
+ *
+ *    2006, Benjamin Zores and Vincent Mussard
+ *      fixed a lot of RFC compliance issues.
+ */
+ 
+#ifndef HAVE_RTSP_H
+#define HAVE_RTSP_H
+
+
+/* some codes returned by rtsp_request_* functions */
+
+#define RTSP_STATUS_SET_PARAMETER  10
+#define RTSP_STATUS_OK            200
+
+#define RTSP_METHOD_OPTIONS "OPTIONS"
+#define RTSP_METHOD_DESCRIBE "DESCRIBE"
+#define RTSP_METHOD_SETUP "SETUP"
+#define RTSP_METHOD_PLAY "PLAY"
+#define RTSP_METHOD_TEARDOWN "TEARDOWN"
+#define RTSP_METHOD_SET_PARAMETER "SET_PARAMETER"
+
+typedef struct rtsp_s rtsp_t;
+
+rtsp_t*  rtsp_connect (int fd, char *mrl, char *path, char *host, int port, char *user_agent);
+
+int rtsp_request_options(rtsp_t *s, const char *what);
+int rtsp_request_describe(rtsp_t *s, const char *what);
+int rtsp_request_setup(rtsp_t *s, const char *what, char *control);
+int rtsp_request_setparameter(rtsp_t *s, const char *what);
+int rtsp_request_play(rtsp_t *s, const char *what);
+int rtsp_request_teardown(rtsp_t *s, const char *what);
+
+int rtsp_send_ok(rtsp_t *s);
+
+int rtsp_read_data(rtsp_t *s, char *buffer, unsigned int size);
+
+char* rtsp_search_answers(rtsp_t *s, const char *tag);
+void rtsp_add_to_payload(char **payload, const char *string);
+
+void rtsp_free_answers(rtsp_t *this);
+
+int      rtsp_read (rtsp_t *this, char *data, int len);
+void     rtsp_close (rtsp_t *this);
+
+void  rtsp_set_session(rtsp_t *s, const char *id);
+char *rtsp_get_session(rtsp_t *s);
+
+char *rtsp_get_mrl(rtsp_t *s);
+char *rtsp_get_param(rtsp_t *s, char *param);
+
+/*int      rtsp_peek_header (rtsp_t *this, char *data); */
+
+void rtsp_schedule_field(rtsp_t *s, const char *string);
+void rtsp_unschedule_field(rtsp_t *s, const char *string);
+void rtsp_unschedule_all(rtsp_t *s);
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmpdemux/librtsp/rtsp_session.c	Fri Jun 23 21:38:28 2006 +0000
@@ -0,0 +1,200 @@
+/*
+ * This file was ported to MPlayer from xine CVS rtsp_session.c,v 1.9 2003/02/11 16:20:40
+ */
+
+/*
+ * Copyright (C) 2000-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
+ *
+ *
+ * high level interface to rtsp servers.
+ */
+
+#include <sys/types.h>
+#include "config.h"
+#ifndef HAVE_WINSOCK2
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#else
+#include <winsock2.h>
+#endif
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "mp_msg.h"
+#include "rtsp.h"
+#include "rtsp_session.h"
+#include "../realrtsp/real.h"
+#include "../realrtsp/rmff.h"
+#include "../realrtsp/asmrp.h"
+#include "../realrtsp/xbuffer.h"
+
+/*
+#define LOG
+*/
+
+struct rtsp_session_s {
+  rtsp_t       *s;
+  struct real_rtsp_session_t* real_session;
+};
+
+//rtsp_session_t *rtsp_session_start(char *mrl) {
+rtsp_session_t *rtsp_session_start(int fd, char **mrl, char *path, char *host, int port, int *redir, uint32_t bandwidth) {
+
+  rtsp_session_t *rtsp_session = NULL;
+  char *server;
+  char *mrl_line = NULL;
+  rmff_header_t *h;
+
+  rtsp_session = malloc (sizeof (rtsp_session_t));
+  rtsp_session->s = NULL;
+  rtsp_session->real_session = NULL;
+ 
+//connect:
+  *redir = 0;
+
+  /* connect to server */
+  rtsp_session->s=rtsp_connect(fd,*mrl,path,host,port,NULL);
+  if (!rtsp_session->s)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,"rtsp_session: failed to connect to server %s\n", path);
+    free(rtsp_session);
+    return NULL;
+  }
+
+  /* looking for server type */
+  if (rtsp_search_answers(rtsp_session->s,"Server"))
+    server=strdup(rtsp_search_answers(rtsp_session->s,"Server"));
+  else {
+    if (rtsp_search_answers(rtsp_session->s,"RealChallenge1"))
+      server=strdup("Real");
+    else
+      server=strdup("unknown");
+  }
+  if (strstr(server,"Real") || strstr(server,"Helix"))
+  {
+    /* we are talking to a real server ... */
+
+    h=real_setup_and_get_header(rtsp_session->s, bandwidth);
+    if (!h) {
+      /* got an redirect? */
+      if (rtsp_search_answers(rtsp_session->s, "Location"))
+      {
+        free(mrl_line);
+	mrl_line=strdup(rtsp_search_answers(rtsp_session->s, "Location"));
+        mp_msg (MSGT_OPEN, MSGL_INFO,"rtsp_session: redirected to %s\n", mrl_line);
+	rtsp_close(rtsp_session->s);
+	free(server);
+        free(*mrl);
+        free(rtsp_session);
+        /* tell the caller to redirect, return url to redirect to in mrl */
+        *mrl = mrl_line;
+        *redir = 1;
+        return NULL;
+//	goto connect; /* *shudder* i made a design mistake somewhere */
+      } else
+      {
+        mp_msg (MSGT_OPEN, MSGL_ERR,"rtsp_session: session can not be established.\n");
+        rtsp_close(rtsp_session->s);
+        free (server);
+        free(rtsp_session);
+        return NULL;
+      }
+    }
+	
+    rtsp_session->real_session = init_real_rtsp_session ();
+    rtsp_session->real_session->header_len =
+      rmff_dump_header (h, (char *) rtsp_session->real_session->header, 1024);
+
+    rtsp_session->real_session->recv =
+      xbuffer_copyin (rtsp_session->real_session->recv, 0,
+                      rtsp_session->real_session->header,
+                      rtsp_session->real_session->header_len);
+
+    rtsp_session->real_session->recv_size =
+      rtsp_session->real_session->header_len;
+    rtsp_session->real_session->recv_read = 0;
+  } else
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,"rtsp_session: Not a Real server. Server type is '%s'.\n",server);
+    rtsp_close(rtsp_session->s);
+    free(server);
+    free(rtsp_session);
+    return NULL;
+  }
+  free(server);
+  
+  return rtsp_session;
+}
+
+int rtsp_session_read (rtsp_session_t *this, char *data, int len) {
+  
+  if (this->real_session) {
+  int to_copy=len;
+  char *dest=data;
+  char *source =
+    (char *) (this->real_session->recv + this->real_session->recv_read);
+  int fill = this->real_session->recv_size - this->real_session->recv_read;
+
+  if (len < 0) return 0;
+  while (to_copy > fill) {
+    
+    memcpy(dest, source, fill);
+    to_copy -= fill;
+    dest += fill;
+    this->real_session->recv_read = 0;
+    this->real_session->recv_size =
+      real_get_rdt_chunk (this->s, (char **)&(this->real_session->recv));
+    if (this->real_session->recv_size < 0)
+      return -1;
+    source = (char *) this->real_session->recv;
+    fill = this->real_session->recv_size;
+
+    if (this->real_session->recv_size == 0) {
+#ifdef LOG
+      mp_msg (MSGT_OPEN, MSGL_INFO, "librtsp: %d of %d bytes provided\n", len-to_copy, len);
+#endif
+      return len-to_copy;
+    }
+  }
+  
+  memcpy(dest, source, to_copy);
+  this->real_session->recv_read += to_copy;
+
+#ifdef LOG
+  mp_msg (MSGT_OPEN, MSGL_INFO, "librtsp: %d bytes provided\n", len);
+#endif
+
+  return len;
+  }
+
+  return 0;
+}
+
+void rtsp_session_end(rtsp_session_t *session) {
+
+  rtsp_close(session->s);
+  if (session->real_session)
+    free_real_rtsp_session (session->real_session);
+  free(session);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmpdemux/librtsp/rtsp_session.h	Fri Jun 23 21:38:28 2006 +0000
@@ -0,0 +1,39 @@
+/*
+ * This file was ported to MPlayer from xine CVS rtsp_session.h,v 1.4 2003/01/31 14:06:18
+ */
+
+/*
+ * Copyright (C) 2000-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
+ *
+ *
+ * high level interface to rtsp servers.
+ */
+
+#ifndef HAVE_RTSP_SESSION_H
+#define HAVE_RTSP_SESSION_H
+
+typedef struct rtsp_session_s rtsp_session_t;
+
+rtsp_session_t *rtsp_session_start(int fd, char **mrl, char *path, char *host, int port, int *redir, uint32_t bandwidth);
+
+int rtsp_session_read(rtsp_session_t *session, char *data, int len);
+
+void rtsp_session_end(rtsp_session_t *session);
+
+#endif
--- a/libmpdemux/realrtsp/real.h	Fri Jun 23 20:32:32 2006 +0000
+++ b/libmpdemux/realrtsp/real.h	Fri Jun 23 21:38:28 2006 +0000
@@ -31,7 +31,7 @@
 #define HAVE_REAL_H
 
 #include "rmff.h"
-#include "rtsp.h"
+#include "../librtsp/rtsp.h"
 
 #define HEADER_SIZE 4096
 
--- a/libmpdemux/realrtsp/rtsp.c	Fri Jun 23 20:32:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,889 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS rtsp.c,v 1.9 2003/04/10 02:30:48
- */
-
-/*
- * Copyright (C) 2000-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
- *
- *
- * a minimalistic implementation of rtsp protocol,
- * *not* RFC 2326 compilant yet.
- *
- *    2006, Benjamin Zores and Vincent Mussard
- *      fixed a lot of RFC compliance issues.
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <assert.h>
-#include "config.h"
-#ifndef HAVE_WINSOCK2
-#define closesocket close
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#else
-#include <winsock2.h>
-#endif
-#include <string.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <time.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <inttypes.h>
-
-#include "mp_msg.h"
-#include "rtsp.h"
-#include "rtsp_session.h"
-#include "osdep/timer.h"
-
-/*
-#define LOG
-*/
-
-#define BUF_SIZE 4096
-#define HEADER_SIZE 1024
-#define MAX_FIELDS 256
-
-struct rtsp_s {
-
-  int           s;
-
-  char         *host;
-  int           port;
-  char         *path;
-  char         *param;
-  char         *mrl;
-  char         *user_agent;
-
-  char         *server;
-  unsigned int  server_state;
-  uint32_t      server_caps;
-  
-  unsigned int  cseq;
-  char         *session;
-
-  char        *answers[MAX_FIELDS];   /* data of last message */
-  char        *scheduled[MAX_FIELDS]; /* will be sent with next message */
-};
-
-/*
- * constants
- */
-
-#define RTSP_PROTOCOL_VERSION "RTSP/1.0"
-
-/* server states */
-#define RTSP_CONNECTED 1
-#define RTSP_INIT      2
-#define RTSP_READY     4
-#define RTSP_PLAYING   8
-#define RTSP_RECORDING 16
-
-/* server capabilities */
-#define RTSP_OPTIONS       0x001
-#define RTSP_DESCRIBE      0x002
-#define RTSP_ANNOUNCE      0x004
-#define RTSP_SETUP         0x008
-#define RTSP_GET_PARAMETER 0x010
-#define RTSP_SET_PARAMETER 0x020
-#define RTSP_TEARDOWN      0x040
-#define RTSP_PLAY          0x080
-#define RTSP_RECORD        0x100
-
-/*
- * network utilities
- */
- 
-static int host_connect_attempt(struct in_addr ia, int port) {
-
-  int                s;
-  struct sockaddr_in sin;
-
-  s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);  
-  if (s == -1) {
-    mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: socket(): %s\n", strerror(errno));
-    return -1;
-  }
-
-  sin.sin_family = AF_INET;
-  sin.sin_addr   = ia;
-  sin.sin_port   = htons(port);
-  
-  if (connect(s, (struct sockaddr *)&sin, sizeof(sin))==-1 
-#ifndef HAVE_WINSOCK2
-      && errno != EINPROGRESS) {
-#else
-      && WSAGetLastError() == WSAEINPROGRESS) {
-#endif
-    mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: connect(): %s\n", strerror(errno));
-    closesocket(s);
-    return -1;
-  }
-
-  return s;
-}
-
-static int host_connect(const char *host, int port) {
-
-  struct hostent *h;
-  int             i, s;
-  
-  h = gethostbyname(host);
-  if (h == NULL) {
-    mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: unable to resolve '%s'.\n", host);
-    return -1;
-  }
-
-  for (i = 0; h->h_addr_list[i]; i++) {
-    struct in_addr ia;
-
-    memcpy (&ia, h->h_addr_list[i], 4);
-    s = host_connect_attempt(ia, port);
-    if(s != -1)
-      return s;
-  }
-  mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: unable to connect to '%s'.\n", host);
-  return -1;
-}
-
-static int write_stream(int s, const char *buf, int len) {
-  int total, timeout;
-
-  total = 0; timeout = 30;
-  while (total < len){ 
-    int n;
-
-    n = send (s, &buf[total], len - total, 0);
-
-    if (n > 0)
-      total += n;
-    else if (n < 0) {
-#ifndef HAVE_WINSOCK2
-      if ((timeout>0) && ((errno == EAGAIN) || (errno == EINPROGRESS))) {
-#else
-      if ((timeout>0) && ((errno == EAGAIN) || (WSAGetLastError() == WSAEINPROGRESS))) {
-#endif
-        usec_sleep (1000000); timeout--;
-      } else
-        return -1;
-    }
-  }
-
-  return total;
-}
-
-static ssize_t read_stream(int fd, void *buf, size_t count) {
-  
-  ssize_t ret, total;
-
-  total = 0;
-
-  while (total < count) {
-  
-    ret=recv (fd, ((uint8_t*)buf)+total, count-total, 0);
-
-    if (ret<0) {
-      if(errno == EAGAIN) {
-        fd_set rset;
-        struct timeval timeout;
-    
-        FD_ZERO (&rset);
-        FD_SET  (fd, &rset);
-        
-        timeout.tv_sec  = 30;
-        timeout.tv_usec = 0;
-        
-        if (select (fd+1, &rset, NULL, NULL, &timeout) <= 0) {
-          return -1;
-        }
-        continue;
-      }
-      
-      mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: read error.\n");
-      return ret;
-    } else
-      total += ret;
-    
-    /* end of stream */
-    if (!ret) break;
-  }
-
-  return total;
-}
-
-/*
- * debugging utilities
- */
-#if 0 
-static void hexdump (char *buf, int length) {
-
-  int i;
-
-  mp_msg(MSGT_OPEN, MSGL_INFO, "rtsp: ascii>");
-  for (i = 0; i < length; i++) {
-    unsigned char c = buf[i];
-
-    if ((c >= 32) && (c <= 128))
-      mp_msg(MSGT_OPEN, MSGL_INFO, "%c", c);
-    else
-      mp_msg(MSGT_OPEN, MSGL_INFO, ".");
-  }
-  mp_msg(MSGT_OPEN, MSGL_INFO, "\n");
-
-  mp_msg(MSGT_OPEN, MSGL_INFO, "rtsp: hexdump> ");
-  for (i = 0; i < length; i++) {
-    unsigned char c = buf[i];
-
-    mp_msg(MSGT_OPEN, MSGL_INFO, "%02x", c);
-
-    if ((i % 16) == 15)
-      mp_msg(MSGT_OPEN, MSGL_INFO, "\nrtsp:         ");
-
-    if ((i % 2) == 1)
-      mp_msg(MSGT_OPEN, MSGL_INFO, " ");
-
-  }
-  mp_msg(MSGT_OPEN, MSGL_INFO, "\n");
-}
-#endif
-
-/*
- * rtsp_get gets a line from stream
- * and returns a null terminated string.
- */
- 
-static char *rtsp_get(rtsp_t *s) {
-
-  int n=1;
-  char *buffer = malloc(BUF_SIZE);
-  char *string = NULL;
-
-  read_stream(s->s, buffer, 1);
-  while (n<BUF_SIZE) {
-    read_stream(s->s, &(buffer[n]), 1);
-    if ((buffer[n-1]==0x0d)&&(buffer[n]==0x0a)) break;
-    n++;
-  }
-
-  if (n>=BUF_SIZE) {
-    mp_msg(MSGT_OPEN, MSGL_FATAL, "librtsp: buffer overflow in rtsp_get\n");
-    exit(1);
-  }
-  string=malloc(sizeof(char)*n);
-  memcpy(string,buffer,n-1);
-  string[n-1]=0;
-
-#ifdef LOG
-  mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: << '%s'\n", string);
-#endif
-  
-
-  free(buffer);
-  return string;
-}
-
-/*
- * rtsp_put puts a line on stream
- */
- 
-static void rtsp_put(rtsp_t *s, const char *string) {
-
-  int len=strlen(string);
-  char *buf=malloc(sizeof(char)*len+2);
-
-#ifdef LOG
-  mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: >> '%s'", string);
-#endif
-
-  memcpy(buf,string,len);
-  buf[len]=0x0d;
-  buf[len+1]=0x0a;
-
-  write_stream(s->s, buf, len+2);
-  
-#ifdef LOG
-  mp_msg(MSGT_OPEN, MSGL_INFO, " done.\n");
-#endif
-
-  free(buf);
-}
-
-/*
- * extract server status code
- */
-
-static int rtsp_get_code(const char *string) {
-
-  char buf[4];
-  int code=0;
- 
-  if (!strncmp(string, RTSP_PROTOCOL_VERSION, strlen(RTSP_PROTOCOL_VERSION)))
-  {
-    memcpy(buf, string+strlen(RTSP_PROTOCOL_VERSION)+1, 3);
-    buf[3]=0;
-    code=atoi(buf);
-  } else if (!strncmp(string, RTSP_METHOD_SET_PARAMETER,8))
-  {
-    return RTSP_STATUS_SET_PARAMETER;
-  }
-
-  if(code != RTSP_STATUS_OK) mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: server responds: '%s'\n",string);
-
-  return code;
-}
-
-/*
- * send a request
- */
-
-static void rtsp_send_request(rtsp_t *s, const char *type, const char *what) {
-
-  char **payload=s->scheduled;
-  char *buf;
-  
-  buf = malloc(strlen(type)+strlen(what)+strlen(RTSP_PROTOCOL_VERSION)+3);
-  
-  sprintf(buf,"%s %s %s",type, what, RTSP_PROTOCOL_VERSION);
-  rtsp_put(s,buf);
-  free(buf);
-  if (payload)
-    while (*payload) {
-      rtsp_put(s,*payload);
-      payload++;
-    }
-  rtsp_put(s,"");
-  rtsp_unschedule_all(s);
-}
-
-/*
- * schedule standard fields
- */
-
-static void rtsp_schedule_standard(rtsp_t *s) {
-
-  char tmp[16];
-  
-  snprintf(tmp, 16, "CSeq: %u", s->cseq);
-  rtsp_schedule_field(s, tmp);
-  
-  if (s->session) {
-    char *buf;
-    buf = malloc(strlen(s->session)+15);
-    sprintf(buf, "Session: %s", s->session);
-    rtsp_schedule_field(s, buf);
-    free(buf);
-  }
-}
-/*
- * get the answers, if server responses with something != 200, return NULL
- */
- 
-static int rtsp_get_answers(rtsp_t *s) {
-
-  char *answer=NULL;
-  unsigned int answer_seq;
-  char **answer_ptr=s->answers;
-  int code;
-  int ans_count = 0;
-  
-  answer=rtsp_get(s);
-  if (!answer)
-    return 0;
-  code=rtsp_get_code(answer);
-  free(answer);
-
-  rtsp_free_answers(s);
-  
-  do { /* while we get answer lines */
-  
-    answer=rtsp_get(s);
-    if (!answer)
-      return 0;
-    
-    if (!strncmp(answer,"CSeq:",5)) {
-      sscanf(answer,"CSeq: %u",&answer_seq);
-      if (s->cseq != answer_seq) {
-#ifdef LOG
-        mp_msg(MSGT_OPEN, MSGL_WARN, "librtsp: warning: CSeq mismatch. got %u, assumed %u", answer_seq, s->cseq);
-#endif
-        s->cseq=answer_seq;
-      }
-    }
-    if (!strncmp(answer,"Server:",7)) {
-      char *buf = malloc(strlen(answer));
-      sscanf(answer,"Server: %s",buf);
-      if (s->server) free(s->server);
-      s->server=strdup(buf);
-      free(buf);
-    }
-    if (!strncmp(answer,"Session:",8)) {
-      char *buf = calloc(1, strlen(answer));
-      sscanf(answer,"Session: %s",buf);
-      if (s->session) {
-        if (strcmp(buf, s->session)) {
-          mp_msg(MSGT_OPEN, MSGL_WARN, "rtsp: warning: setting NEW session: %s\n", buf);
-          free(s->session);
-          s->session=strdup(buf);
-        }
-      } else
-      {
-#ifdef LOG
-        mp_msg(MSGT_OPEN, MSGL_INFO, "rtsp: setting session id to: %s\n", buf);
-#endif
-        s->session=strdup(buf);
-      }
-      free(buf);
-    }
-    *answer_ptr=answer;
-    answer_ptr++;
-  } while ((strlen(answer)!=0) && (++ans_count < MAX_FIELDS));
-  
-  s->cseq++;
-  
-  *answer_ptr=NULL;
-  rtsp_schedule_standard(s);
-    
-  return code;
-}
-
-/*
- * send an ok message
- */
-
-int rtsp_send_ok(rtsp_t *s) {
-  char cseq[16];
-  
-  rtsp_put(s, "RTSP/1.0 200 OK");
-  sprintf(cseq,"CSeq: %u", s->cseq);
-  rtsp_put(s, cseq);
-  rtsp_put(s, "");
-  return 0;
-}
-
-/*
- * implementation of must-have rtsp requests; functions return
- * server status code.
- */
-
-int rtsp_request_options(rtsp_t *s, const char *what) {
-
-  char *buf;
-
-  if (what) {
-    buf=strdup(what);
-  } else
-  {
-    buf=malloc(sizeof(char)*(strlen(s->host)+16));
-    sprintf(buf,"rtsp://%s:%i", s->host, s->port);
-  }
-  rtsp_send_request(s,RTSP_METHOD_OPTIONS,buf);
-  free(buf);
-
-  return rtsp_get_answers(s);
-}
-
-int rtsp_request_describe(rtsp_t *s, const char *what) {
-
-  char *buf;
-
-  if (what) {
-    buf=strdup(what);
-  } else
-  {
-    buf=malloc(sizeof(char)*(strlen(s->host)+strlen(s->path)+16));
-    sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path);
-  }
-  rtsp_send_request(s,RTSP_METHOD_DESCRIBE,buf);
-  free(buf);
-  
-  return rtsp_get_answers(s);
-}
-
-int rtsp_request_setup(rtsp_t *s, const char *what, char *control) {
-
-  char *buf = NULL;
-
-  if (what)
-    buf = strdup (what);
-  else
-  {
-    int len = strlen (s->host) + strlen (s->path) + 16;
-    if (control)
-      len += strlen (control) + 1;
-    
-    buf = malloc (len);
-    sprintf (buf, "rtsp://%s:%i/%s%s%s", s->host, s->port, s->path,
-             control ? "/" : "", control ? control : "");
-  }
-  
-  rtsp_send_request (s, RTSP_METHOD_SETUP, buf);
-  free (buf);
-  return rtsp_get_answers (s);
-}
-
-int rtsp_request_setparameter(rtsp_t *s, const char *what) {
-
-  char *buf;
-
-  if (what) {
-    buf=strdup(what);
-  } else
-  {
-    buf=malloc(sizeof(char)*(strlen(s->host)+strlen(s->path)+16));
-    sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path);
-  }
-  rtsp_send_request(s,RTSP_METHOD_SET_PARAMETER,buf);
-  free(buf);
-  
-  return rtsp_get_answers(s);
-}
-
-int rtsp_request_play(rtsp_t *s, const char *what) {
-
-  char *buf;
-  int ret;
-  
-  if (what) {
-    buf=strdup(what);
-  } else
-  {
-    buf=malloc(sizeof(char)*(strlen(s->host)+strlen(s->path)+16));
-    sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path);
-  }
-  rtsp_send_request(s,RTSP_METHOD_PLAY,buf);
-  free(buf);
-  
-  ret = rtsp_get_answers (s);
-  if (ret == RTSP_STATUS_OK)
-    s->server_state = RTSP_PLAYING;
-
-  return ret;
-}
-
-int rtsp_request_teardown(rtsp_t *s, const char *what) {
-
-  char *buf;
-  
-  if (what)
-    buf = strdup (what);
-  else
-  {
-    buf =
-      malloc (strlen (s->host) + strlen (s->path) + 16);
-    sprintf (buf, "rtsp://%s:%i/%s", s->host, s->port, s->path);
-  }
-  rtsp_send_request (s, RTSP_METHOD_TEARDOWN, buf);
-  free (buf);
- 
-  return rtsp_get_answers(s);
-}
-
-/*
- * read opaque data from stream
- */
-
-int rtsp_read_data(rtsp_t *s, char *buffer, unsigned int size) {
-
-  int i,seq;
-
-  if (size>=4) {
-    i=read_stream(s->s, buffer, 4);
-    if (i<4) return i;
-    if (((buffer[0]=='S')&&(buffer[1]=='E')&&(buffer[2]=='T')&&(buffer[3]=='_')) ||
-        ((buffer[0]=='O')&&(buffer[1]=='P')&&(buffer[2]=='T')&&(buffer[3]=='I'))) // OPTIONS
-    {
-      char *rest=rtsp_get(s);
-      if (!rest)
-        return -1;      
-
-      seq=-1;
-      do {
-        free(rest);
-        rest=rtsp_get(s);
-        if (!rest)
-          return -1;
-        if (!strncmp(rest,"CSeq:",5))
-          sscanf(rest,"CSeq: %u",&seq);
-      } while (strlen(rest)!=0);
-      free(rest);
-      if (seq<0) {
-#ifdef LOG
-        mp_msg(MSGT_OPEN, MSGL_WARN, "rtsp: warning: CSeq not recognized!\n");
-#endif
-        seq=1;
-      }
-      /* let's make the server happy */
-      rtsp_put(s, "RTSP/1.0 451 Parameter Not Understood");
-      rest=malloc(sizeof(char)*16);
-      sprintf(rest,"CSeq: %u", seq);
-      rtsp_put(s, rest);
-      rtsp_put(s, "");
-      i=read_stream(s->s, buffer, size);
-    } else
-    {
-      i=read_stream(s->s, buffer+4, size-4);
-      i+=4;
-    }
-  } else
-    i=read_stream(s->s, buffer, size);
-#ifdef LOG
-  mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: << %d of %d bytes\n", i, size);
-#endif
-
-  return i;
-}
-
-/*
- * connect to a rtsp server
- */
-
-//rtsp_t *rtsp_connect(const char *mrl, const char *user_agent) {
-rtsp_t *rtsp_connect(int fd, char* mrl, char *path, char *host, int port, char *user_agent) {
-
-  rtsp_t *s=malloc(sizeof(rtsp_t));
-  int i;
-  
-  for (i=0; i<MAX_FIELDS; i++) {
-    s->answers[i]=NULL;
-    s->scheduled[i]=NULL;
-  }
-
-  s->server=NULL;
-  s->server_state=0;
-  s->server_caps=0;
-  
-  s->cseq=0;
-  s->session=NULL;
-  
-  if (user_agent)
-    s->user_agent=strdup(user_agent);
-  else
-    s->user_agent=strdup("User-Agent: RealMedia Player Version 6.0.9.1235 (linux-2.0-libc6-i386-gcc2.95)");
-
-  s->mrl = strdup(mrl);
-  s->host = strdup(host);
-  s->port = port;
-  s->path = strdup(path);
-  while (*path == '/')
-    path++;
-  if ((s->param = strchr(s->path, '?')) != NULL)
-    s->param++;
-  //mp_msg(MSGT_OPEN, MSGL_INFO, "path=%s\n", s->path);
-  //mp_msg(MSGT_OPEN, MSGL_INFO, "param=%s\n", s->param ? s->param : "NULL");
-  s->s = fd;
-
-  if (s->s < 0) {
-    mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: failed to connect to '%s'\n", s->host);
-    rtsp_close(s);
-    return NULL;
-  }
-
-  s->server_state=RTSP_CONNECTED;
-
-  /* now let's send an options request. */
-  rtsp_schedule_field(s, "CSeq: 1");
-  rtsp_schedule_field(s, s->user_agent);
-  rtsp_schedule_field(s, "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7");
-  rtsp_schedule_field(s, "PlayerStarttime: [28/03/2003:22:50:23 00:00]");
-  rtsp_schedule_field(s, "CompanyID: KnKV4M4I/B2FjJ1TToLycw==");
-  rtsp_schedule_field(s, "GUID: 00000000-0000-0000-0000-000000000000");
-  rtsp_schedule_field(s, "RegionData: 0");
-  rtsp_schedule_field(s, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586");
-  /*rtsp_schedule_field(s, "Pragma: initiate-session");*/
-  rtsp_request_options(s, NULL);
-
-  return s;
-}
-
-
-/*
- * closes an rtsp connection 
- */
-
-void rtsp_close(rtsp_t *s) {
-
-  if (s->server_state)
-  {
-    if (s->server_state == RTSP_PLAYING)
-      rtsp_request_teardown (s, NULL);
-    closesocket (s->s);
-  }
-
-  if (s->path) free(s->path);
-  if (s->host) free(s->host);
-  if (s->mrl) free(s->mrl);
-  if (s->session) free(s->session);
-  if (s->user_agent) free(s->user_agent);
-  rtsp_free_answers(s);
-  rtsp_unschedule_all(s);
-  free(s);  
-}
-
-/*
- * search in answers for tags. returns a pointer to the content
- * after the first matched tag. returns NULL if no match found.
- */
-
-char *rtsp_search_answers(rtsp_t *s, const char *tag) {
-
-  char **answer;
-  char *ptr;
-  
-  if (!s->answers) return NULL;
-  answer=s->answers;
-
-  while (*answer) {
-    if (!strncasecmp(*answer,tag,strlen(tag))) {
-      ptr=strchr(*answer,':');
-      if (!ptr) return NULL;
-      ptr++;
-      while(*ptr==' ') ptr++;
-      return ptr;
-    }
-    answer++;
-  }
-
-  return NULL;
-}
-
-/*
- * session id management
- */
-
-void rtsp_set_session(rtsp_t *s, const char *id) {
-
-  if (s->session) free(s->session);
-
-  s->session=strdup(id);
-
-}
-
-char *rtsp_get_session(rtsp_t *s) {
-
-  return s->session;
-
-}
-
-char *rtsp_get_mrl(rtsp_t *s) {
-
-  return s->mrl;
-
-}
-
-char *rtsp_get_param(rtsp_t *s, char *p) {
-  int len;
-  char *param;
-  if (!s->param)
-    return NULL;
-  if (!p)
-    return strdup(s->param);
-  len = strlen(p);
-  param = s->param;
-  while (param && *param) {
-    char *nparam = strchr(param, '&');
-    if (strncmp(param, p, len) == 0 && param[len] == '=') {
-      param += len + 1;
-      len = nparam ? nparam - param : strlen(param);
-      nparam = malloc(len + 1);
-      memcpy(nparam, param, len);
-      nparam[len] = 0;
-      return nparam;
-    }
-    param = nparam ? nparam + 1 : NULL;
-  }
-  return NULL;
-}
-  
-/*
- * schedules a field for transmission
- */
-
-void rtsp_schedule_field(rtsp_t *s, const char *string) {
-
-  int i=0;
-  
-  if (!string) return;
-
-  while(s->scheduled[i]) {
-    i++;
-  }
-  s->scheduled[i]=strdup(string);
-}
-
-/*
- * removes the first scheduled field which prefix matches string. 
- */
-
-void rtsp_unschedule_field(rtsp_t *s, const char *string) {
-
-  char **ptr=s->scheduled;
-  
-  if (!string) return;
-
-  while(*ptr) {
-    if (!strncmp(*ptr, string, strlen(string)))
-      break;
-    else
-      ptr++;
-  }
-  if (*ptr) free(*ptr);
-  ptr++;
-  do {
-    *(ptr-1)=*ptr;
-  } while(*ptr);
-}
-
-/*
- * unschedule all fields
- */
-
-void rtsp_unschedule_all(rtsp_t *s) {
-
-  char **ptr;
-  
-  if (!s->scheduled) return;
-  ptr=s->scheduled;
-
-  while (*ptr) {
-    free(*ptr);
-    *ptr=NULL;
-    ptr++;
-  }
-}
-/*
- * free answers
- */
-
-void rtsp_free_answers(rtsp_t *s) {
-
-  char **answer;
-  
-  if (!s->answers) return;
-  answer=s->answers;
-
-  while (*answer) {
-    free(*answer);
-    *answer=NULL;
-    answer++;
-  }
-}
--- a/libmpdemux/realrtsp/rtsp.h	Fri Jun 23 20:32:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS rtsp.h,v 1.2 2002/12/16 21:50:55
- */
-
-/*
- * 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
- *
- *
- * a minimalistic implementation of rtsp protocol,
- * *not* RFC 2326 compilant yet.
- *
- *    2006, Benjamin Zores and Vincent Mussard
- *      fixed a lot of RFC compliance issues.
- */
- 
-#ifndef HAVE_RTSP_H
-#define HAVE_RTSP_H
-
-
-/* some codes returned by rtsp_request_* functions */
-
-#define RTSP_STATUS_SET_PARAMETER  10
-#define RTSP_STATUS_OK            200
-
-#define RTSP_METHOD_OPTIONS "OPTIONS"
-#define RTSP_METHOD_DESCRIBE "DESCRIBE"
-#define RTSP_METHOD_SETUP "SETUP"
-#define RTSP_METHOD_PLAY "PLAY"
-#define RTSP_METHOD_TEARDOWN "TEARDOWN"
-#define RTSP_METHOD_SET_PARAMETER "SET_PARAMETER"
-
-typedef struct rtsp_s rtsp_t;
-
-rtsp_t*  rtsp_connect (int fd, char *mrl, char *path, char *host, int port, char *user_agent);
-
-int rtsp_request_options(rtsp_t *s, const char *what);
-int rtsp_request_describe(rtsp_t *s, const char *what);
-int rtsp_request_setup(rtsp_t *s, const char *what, char *control);
-int rtsp_request_setparameter(rtsp_t *s, const char *what);
-int rtsp_request_play(rtsp_t *s, const char *what);
-int rtsp_request_teardown(rtsp_t *s, const char *what);
-
-int rtsp_send_ok(rtsp_t *s);
-
-int rtsp_read_data(rtsp_t *s, char *buffer, unsigned int size);
-
-char* rtsp_search_answers(rtsp_t *s, const char *tag);
-void rtsp_add_to_payload(char **payload, const char *string);
-
-void rtsp_free_answers(rtsp_t *this);
-
-int      rtsp_read (rtsp_t *this, char *data, int len);
-void     rtsp_close (rtsp_t *this);
-
-void  rtsp_set_session(rtsp_t *s, const char *id);
-char *rtsp_get_session(rtsp_t *s);
-
-char *rtsp_get_mrl(rtsp_t *s);
-char *rtsp_get_param(rtsp_t *s, char *param);
-
-/*int      rtsp_peek_header (rtsp_t *this, char *data); */
-
-void rtsp_schedule_field(rtsp_t *s, const char *string);
-void rtsp_unschedule_field(rtsp_t *s, const char *string);
-void rtsp_unschedule_all(rtsp_t *s);
-
-#endif
-
--- a/libmpdemux/realrtsp/rtsp_session.c	Fri Jun 23 20:32:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS rtsp_session.c,v 1.9 2003/02/11 16:20:40
- */
-
-/*
- * Copyright (C) 2000-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
- *
- *
- * high level interface to rtsp servers.
- */
-
-#include <sys/types.h>
-#include "config.h"
-#ifndef HAVE_WINSOCK2
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#else
-#include <winsock2.h>
-#endif
-#include <unistd.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <inttypes.h>
-
-#include "mp_msg.h"
-#include "rtsp.h"
-#include "rtsp_session.h"
-#include "real.h"
-#include "rmff.h"
-#include "asmrp.h"
-#include "xbuffer.h"
-
-/*
-#define LOG
-*/
-
-struct rtsp_session_s {
-  rtsp_t       *s;
-  struct real_rtsp_session_t* real_session;
-};
-
-//rtsp_session_t *rtsp_session_start(char *mrl) {
-rtsp_session_t *rtsp_session_start(int fd, char **mrl, char *path, char *host, int port, int *redir, uint32_t bandwidth) {
-
-  rtsp_session_t *rtsp_session = NULL;
-  char *server;
-  char *mrl_line = NULL;
-  rmff_header_t *h;
-
-  rtsp_session = malloc (sizeof (rtsp_session_t));
-  rtsp_session->s = NULL;
-  rtsp_session->real_session = NULL;
- 
-//connect:
-  *redir = 0;
-
-  /* connect to server */
-  rtsp_session->s=rtsp_connect(fd,*mrl,path,host,port,NULL);
-  if (!rtsp_session->s)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,"rtsp_session: failed to connect to server %s\n", path);
-    free(rtsp_session);
-    return NULL;
-  }
-
-  /* looking for server type */
-  if (rtsp_search_answers(rtsp_session->s,"Server"))
-    server=strdup(rtsp_search_answers(rtsp_session->s,"Server"));
-  else {
-    if (rtsp_search_answers(rtsp_session->s,"RealChallenge1"))
-      server=strdup("Real");
-    else
-      server=strdup("unknown");
-  }
-  if (strstr(server,"Real") || strstr(server,"Helix"))
-  {
-    /* we are talking to a real server ... */
-
-    h=real_setup_and_get_header(rtsp_session->s, bandwidth);
-    if (!h) {
-      /* got an redirect? */
-      if (rtsp_search_answers(rtsp_session->s, "Location"))
-      {
-        free(mrl_line);
-	mrl_line=strdup(rtsp_search_answers(rtsp_session->s, "Location"));
-        mp_msg (MSGT_OPEN, MSGL_INFO,"rtsp_session: redirected to %s\n", mrl_line);
-	rtsp_close(rtsp_session->s);
-	free(server);
-        free(*mrl);
-        free(rtsp_session);
-        /* tell the caller to redirect, return url to redirect to in mrl */
-        *mrl = mrl_line;
-        *redir = 1;
-        return NULL;
-//	goto connect; /* *shudder* i made a design mistake somewhere */
-      } else
-      {
-        mp_msg (MSGT_OPEN, MSGL_ERR,"rtsp_session: session can not be established.\n");
-        rtsp_close(rtsp_session->s);
-        free (server);
-        free(rtsp_session);
-        return NULL;
-      }
-    }
-	
-    rtsp_session->real_session = init_real_rtsp_session ();
-    rtsp_session->real_session->header_len =
-      rmff_dump_header (h, (char *) rtsp_session->real_session->header, 1024);
-
-    rtsp_session->real_session->recv =
-      xbuffer_copyin (rtsp_session->real_session->recv, 0,
-                      rtsp_session->real_session->header,
-                      rtsp_session->real_session->header_len);
-
-    rtsp_session->real_session->recv_size =
-      rtsp_session->real_session->header_len;
-    rtsp_session->real_session->recv_read = 0;
-  } else
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,"rtsp_session: Not a Real server. Server type is '%s'.\n",server);
-    rtsp_close(rtsp_session->s);
-    free(server);
-    free(rtsp_session);
-    return NULL;
-  }
-  free(server);
-  
-  return rtsp_session;
-}
-
-int rtsp_session_read (rtsp_session_t *this, char *data, int len) {
-  
-  if (this->real_session) {
-  int to_copy=len;
-  char *dest=data;
-  char *source =
-    (char *) (this->real_session->recv + this->real_session->recv_read);
-  int fill = this->real_session->recv_size - this->real_session->recv_read;
-
-  if (len < 0) return 0;
-  while (to_copy > fill) {
-    
-    memcpy(dest, source, fill);
-    to_copy -= fill;
-    dest += fill;
-    this->real_session->recv_read = 0;
-    this->real_session->recv_size =
-      real_get_rdt_chunk (this->s, (char **)&(this->real_session->recv));
-    if (this->real_session->recv_size < 0)
-      return -1;
-    source = (char *) this->real_session->recv;
-    fill = this->real_session->recv_size;
-
-    if (this->real_session->recv_size == 0) {
-#ifdef LOG
-      mp_msg (MSGT_OPEN, MSGL_INFO, "librtsp: %d of %d bytes provided\n", len-to_copy, len);
-#endif
-      return len-to_copy;
-    }
-  }
-  
-  memcpy(dest, source, to_copy);
-  this->real_session->recv_read += to_copy;
-
-#ifdef LOG
-  mp_msg (MSGT_OPEN, MSGL_INFO, "librtsp: %d bytes provided\n", len);
-#endif
-
-  return len;
-  }
-
-  return 0;
-}
-
-void rtsp_session_end(rtsp_session_t *session) {
-
-  rtsp_close(session->s);
-  if (session->real_session)
-    free_real_rtsp_session (session->real_session);
-  free(session);
-}
--- a/libmpdemux/realrtsp/rtsp_session.h	Fri Jun 23 20:32:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS rtsp_session.h,v 1.4 2003/01/31 14:06:18
- */
-
-/*
- * Copyright (C) 2000-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
- *
- *
- * high level interface to rtsp servers.
- */
-
-#ifndef HAVE_RTSP_SESSION_H
-#define HAVE_RTSP_SESSION_H
-
-typedef struct rtsp_session_s rtsp_session_t;
-
-rtsp_session_t *rtsp_session_start(int fd, char **mrl, char *path, char *host, int port, int *redir, uint32_t bandwidth);
-
-int rtsp_session_read(rtsp_session_t *session, char *data, int len);
-
-void rtsp_session_end(rtsp_session_t *session);
-
-#endif
--- a/libmpdemux/realrtsp/sdpplin.c	Fri Jun 23 20:32:32 2006 +0000
+++ b/libmpdemux/realrtsp/sdpplin.c	Fri Jun 23 21:38:28 2006 +0000
@@ -28,7 +28,7 @@
  
 #include "config.h"
 #include "rmff.h"
-#include "rtsp.h"
+#include "../librtsp/rtsp.h"
 #include "sdpplin.h"
 #include "xbuffer.h"
 #include "mp_msg.h"
--- a/libmpdemux/realrtsp/sdpplin.h	Fri Jun 23 20:32:32 2006 +0000
+++ b/libmpdemux/realrtsp/sdpplin.h	Fri Jun 23 21:38:28 2006 +0000
@@ -30,7 +30,7 @@
 #define HAVE_SDPPLIN_H
 
 #include "rmff.h"
-#include "rtsp.h"
+#include "../librtsp/rtsp.h"
 
 typedef struct {
 
--- a/libmpdemux/rtsp.c	Fri Jun 23 20:32:32 2006 +0000
+++ b/libmpdemux/rtsp.c	Fri Jun 23 21:38:28 2006 +0000
@@ -37,8 +37,8 @@
 #include <errno.h>
 
 #include "stream.h"
-#include "realrtsp/rtsp.h"
-#include "realrtsp/rtsp_session.h"
+#include "librtsp/rtsp.h"
+#include "librtsp/rtsp_session.h"
 
 #define RTSP_DEFAULT_PORT 554