1 /*
2 * based on previous Real RTSP support from Roberto Togni and xine team.
3 *
4 * Copyright (C) 2006 Benjamin Zores
5 *
6 * This file is part of MPlayer.
7 *
8 * MPlayer is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <ctype.h>
30 #include "config.h"
31 #if !HAVE_WINSOCK2_H
32 #include <netinet/in.h>
33 #include <sys/socket.h>
34 #include <arpa/inet.h>
35 #else
36 #include <winsock2.h>
37 #include <ws2tcpip.h>
38 #endif
39 #include <errno.h>
40
41 #include "libmpdemux/demuxer.h"
42 #include "network.h"
43 #include "stream.h"
44 #include "tcp.h"
45 #include "librtsp/rtsp.h"
46 #include "librtsp/rtsp_session.h"
47
48 #define RTSP_DEFAULT_PORT 554
49
50 static int
rtsp_streaming_read(int fd,char * buffer,int size,streaming_ctrl_t * stream_ctrl)51 rtsp_streaming_read (int fd, char *buffer,
52 int size, streaming_ctrl_t *stream_ctrl)
53 {
54 return rtsp_session_read (stream_ctrl->data, buffer, size);
55 }
56
57 static int
rtsp_streaming_start(stream_t * stream)58 rtsp_streaming_start (stream_t *stream)
59 {
60 int fd;
61 rtsp_session_t *rtsp;
62 char *mrl;
63 char *file;
64 int port;
65 int redirected, temp;
66
67 if (!stream)
68 return -1;
69
70 /* counter so we don't get caught in infinite redirections */
71 temp = 5;
72
73 do {
74 redirected = 0;
75
76 fd = connect2Server (stream->streaming_ctrl->url->hostname,
77 port = (stream->streaming_ctrl->url->port ?
78 stream->streaming_ctrl->url->port :
79 RTSP_DEFAULT_PORT), 1);
80
81 if (fd < 0 && !stream->streaming_ctrl->url->port)
82 fd = connect2Server (stream->streaming_ctrl->url->hostname,
83 port = 7070, 1);
84
85 if (fd < 0)
86 return -1;
87
88 file = stream->streaming_ctrl->url->file;
89 if (file[0] == '/')
90 file++;
91
92 mrl = malloc (strlen (stream->streaming_ctrl->url->hostname)
93 + strlen (file) + 16);
94
95 sprintf (mrl, "rtsp://%s:%i/%s",
96 stream->streaming_ctrl->url->hostname, port, file);
97
98 rtsp = rtsp_session_start (fd, &mrl, file,
99 stream->streaming_ctrl->url->hostname,
100 port, &redirected,
101 stream->streaming_ctrl->bandwidth,
102 stream->streaming_ctrl->url->username,
103 stream->streaming_ctrl->url->password);
104
105 if (redirected == 1)
106 {
107 url_free (stream->streaming_ctrl->url);
108 stream->streaming_ctrl->url = url_new (mrl);
109 closesocket (fd);
110 }
111
112 free (mrl);
113 temp--;
114 } while ((redirected != 0) && (temp > 0));
115
116 if (!rtsp)
117 return -1;
118
119 stream->fd = fd;
120 stream->streaming_ctrl->data = rtsp;
121
122 stream->streaming_ctrl->streaming_read = rtsp_streaming_read;
123 stream->streaming_ctrl->streaming_seek = NULL;
124 stream->streaming_ctrl->prebuffer_size = 128*1024; // 640 KBytes
125 stream->streaming_ctrl->buffering = 1;
126 stream->streaming_ctrl->status = streaming_playing_e;
127
128 return 0;
129 }
130
131 static void
rtsp_streaming_close(struct stream * s)132 rtsp_streaming_close (struct stream *s)
133 {
134 rtsp_session_t *rtsp = NULL;
135
136 rtsp = (rtsp_session_t *) s->streaming_ctrl->data;
137 if (rtsp)
138 rtsp_session_end (rtsp);
139 }
140
141 static int
rtsp_streaming_open(stream_t * stream,int mode,void * opts,int * file_format)142 rtsp_streaming_open (stream_t *stream, int mode, void *opts, int *file_format)
143 {
144 mp_msg (MSGT_OPEN, MSGL_V, "STREAM_RTSP, URL: %s\n", stream->url);
145 stream->streaming_ctrl = streaming_ctrl_new ();
146 if (!stream->streaming_ctrl)
147 return STREAM_ERROR;
148
149 stream->streaming_ctrl->bandwidth = network_bandwidth;
150 stream->streaming_ctrl->url = url_new_with_proxy(stream->url);
151
152 stream->fd = -1;
153 index_mode = -1; /* prevent most RTSP streams from locking due to -idx */
154 if (rtsp_streaming_start (stream) < 0)
155 {
156 streaming_ctrl_free (stream->streaming_ctrl);
157 stream->streaming_ctrl = NULL;
158 return STREAM_UNSUPPORTED;
159 }
160
161 fixup_network_stream_cache (stream);
162 stream->type = STREAMTYPE_STREAM;
163 stream->close = rtsp_streaming_close;
164
165 return STREAM_OK;
166 }
167
168 const stream_info_t stream_info_rtsp = {
169 "RTSP streaming",
170 "rtsp",
171 "Benjamin Zores, Roberto Togni",
172 "ported from xine",
173 rtsp_streaming_open,
174 {"rtsp", NULL},
175 NULL,
176 0 /* Urls are an option string */
177 };
178