2 * Copyright (C) 2006 Benjamin Zores
3 * based on the Freebox patch for xine by Vincent Mussard
4 * but with many enhancements for better RTSP RFC compliance.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include <sys/types.h>
33 #include <netinet/in.h>
34 #include <sys/socket.h>
35 #include <arpa/inet.h>
44 #include "rtsp_session.h"
45 #include "stream/network.h"
46 #include "stream/freesdp/common.h"
47 #include "stream/freesdp/parser.h"
48 #include "libavutil/avstring.h"
50 #define RTSP_DEFAULT_PORT 31336
51 #define MAX_LENGTH 256
53 #define RTSP_ACCEPT_SDP "Accept: application/sdp"
54 #define RTSP_CONTENT_LENGTH "Content-length"
55 #define RTSP_CONTENT_TYPE "Content-Type"
56 #define RTSP_APPLICATION_SDP "application/sdp"
57 #define RTSP_RANGE "Range: "
58 #define RTSP_NPT_NOW "npt=now-"
59 #define RTSP_MEDIA_CONTAINER_MPEG_TS "33"
60 #define RTSP_TRANSPORT_REQUEST "Transport: RTP/AVP;%s;%s%i-%i;mode=\"PLAY\""
62 #define RTSP_TRANSPORT_MULTICAST "multicast"
63 #define RTSP_TRANSPORT_UNICAST "unicast"
65 #define RTSP_MULTICAST_PORT "port="
66 #define RTSP_UNICAST_CLIENT_PORT "client_port="
67 #define RTSP_UNICAST_SERVER_PORT "server_port="
68 #define RTSP_SETUP_DESTINATION "destination="
70 #define RTSP_SESSION "Session"
71 #define RTSP_TRANSPORT "Transport"
73 /* hardcoded RTCP RR - this is _NOT_ RFC compliant */
74 #define RTCP_RR_SIZE 32
75 #define RTCP_RR "\201\311\0\7(.JD\31+\306\343\0\0\0\0\0\0/E\0\0\2&\0\0\0\0\0\0\0\0\201"
76 #define RTCP_SEND_FREQUENCY 1024
79 char *rtsp_destination
= NULL
;
82 rtcp_send_rr (rtsp_t
*s
, struct rtp_rtsp_session_t
*st
)
84 if (st
->rtcp_socket
== -1)
87 /* send RTCP RR every RTCP_SEND_FREQUENCY packets
88 * FIXME : NOT CORRECT, HARDCODED, BUT MAKES SOME SERVERS HAPPY
90 * http://www.faqs.org/rfcs/rfc1889.html chapter 6 for RTCP
93 if (st
->count
== RTCP_SEND_FREQUENCY
)
95 char rtcp_content
[RTCP_RR_SIZE
];
96 strcpy (rtcp_content
, RTCP_RR
);
97 send (st
->rtcp_socket
, rtcp_content
, RTCP_RR_SIZE
, DEFAULT_SEND_FLAGS
);
99 /* ping RTSP server to keep connection alive.
100 we use OPTIONS instead of PING as not all servers support it */
101 rtsp_request_options (s
, "*");
108 static struct rtp_rtsp_session_t
*
109 rtp_session_new (void)
111 struct rtp_rtsp_session_t
*st
= NULL
;
113 st
= malloc (sizeof (struct rtp_rtsp_session_t
));
116 st
->rtcp_socket
= -1;
117 st
->control_url
= NULL
;
124 rtp_session_free (struct rtp_rtsp_session_t
*st
)
129 if (st
->rtp_socket
!= -1)
130 close (st
->rtp_socket
);
131 if (st
->rtcp_socket
!= -1)
132 close (st
->rtcp_socket
);
134 free (st
->control_url
);
139 rtp_session_set_fd (struct rtp_rtsp_session_t
*st
,
140 int rtp_sock
, int rtcp_sock
)
145 st
->rtp_socket
= rtp_sock
;
146 st
->rtcp_socket
= rtcp_sock
;
150 parse_port (const char *line
, const char *param
,
151 int *rtp_port
, int *rtcp_port
)
157 char *line_copy
= strdup (line
);
159 parse1
= strstr (line_copy
, param
);
163 parse2
= strstr (parse1
, "-");
167 parse3
= strstr (parse2
, ";");
186 *rtp_port
= atoi (parse1
+ strlen (param
));
187 *rtcp_port
= atoi (parse2
+ 1);
195 parse_destination (const char *line
)
201 char *line_copy
= strdup (line
);
204 parse1
= strstr (line_copy
, RTSP_SETUP_DESTINATION
);
211 parse2
= strstr (parse1
, ";");
218 len
= strlen (parse1
) - strlen (parse2
)
219 - strlen (RTSP_SETUP_DESTINATION
) + 1;
220 dest
= (char *) malloc (len
+ 1);
221 av_strlcpy (dest
, parse1
+ strlen (RTSP_SETUP_DESTINATION
), len
);
228 rtcp_connect (int client_port
, int server_port
, const char* server_hostname
)
230 struct sockaddr_in sin
;
234 if (client_port
<= 1023)
237 s
= socket (PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
241 hp
= gethostbyname (server_hostname
);
248 memset(&sin
, 0, sizeof(sin
));
249 sin
.sin_family
= AF_INET
;
250 sin
.sin_addr
.s_addr
= INADDR_ANY
;
251 sin
.sin_port
= htons (client_port
);
253 if (bind (s
, (struct sockaddr
*) &sin
, sizeof (sin
)))
256 if (errno
!= EINPROGRESS
)
258 if (WSAGetLastError() != WSAEINPROGRESS
)
266 sin
.sin_family
= AF_INET
;
267 memcpy (&(sin
.sin_addr
.s_addr
), hp
->h_addr
, sizeof (hp
->h_addr
));
268 sin
.sin_port
= htons (server_port
);
270 /* datagram socket */
271 if (connect (s
, (struct sockaddr
*) &sin
, sizeof (sin
)) < 0)
281 rtp_connect (char *hostname
, int port
)
283 struct sockaddr_in sin
;
293 s
= socket (PF_INET
, SOCK_DGRAM
, 0);
297 memset(&sin
, 0, sizeof(sin
));
298 sin
.sin_family
= AF_INET
;
299 if (!hostname
|| !strcmp (hostname
, "0.0.0.0"))
300 sin
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
303 inet_pton (AF_INET
, hostname
, &sin
.sin_addr
);
305 inet_aton (hostname
, &sin
.sin_addr
);
306 #elif HAVE_WINSOCK2_H
307 sin
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
309 sin
.sin_port
= htons (port
);
311 /* Increase the socket rx buffer size to maximum -- this is UDP */
312 rxsockbufsz
= 240 * 1024;
313 if (setsockopt (s
, SOL_SOCKET
, SO_RCVBUF
,
314 &rxsockbufsz
, sizeof (rxsockbufsz
)))
315 mp_msg (MSGT_OPEN
, MSGL_ERR
, "Couldn't set receive socket buffer size\n");
317 /* if multicast address, add membership */
318 if ((ntohl (sin
.sin_addr
.s_addr
) >> 28) == 0xe)
320 struct ip_mreq mcast
;
321 mcast
.imr_multiaddr
.s_addr
= sin
.sin_addr
.s_addr
;
322 mcast
.imr_interface
.s_addr
= 0;
324 if (setsockopt (s
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
, &mcast
, sizeof (mcast
)))
326 mp_msg (MSGT_OPEN
, MSGL_ERR
, "IP_ADD_MEMBERSHIP failed\n");
332 /* datagram socket */
333 if (bind (s
, (struct sockaddr
*) &sin
, sizeof (sin
)))
336 if (errno
!= EINPROGRESS
)
338 if (WSAGetLastError() != WSAEINPROGRESS
)
341 mp_msg (MSGT_OPEN
, MSGL_ERR
, "bind: %s\n", strerror (errno
));
347 tv
.tv_sec
= 1; /* 1 second timeout */
353 err
= select (s
+ 1, &set
, NULL
, NULL
, &tv
);
356 mp_msg (MSGT_OPEN
, MSGL_ERR
, "Select failed: %s\n", strerror (errno
));
362 mp_msg (MSGT_OPEN
, MSGL_ERR
, "Timeout! No data from host %s\n", hostname
);
367 err_len
= sizeof (err
);
368 getsockopt (s
, SOL_SOCKET
, SO_ERROR
, &err
, (socklen_t
*) &err_len
);
371 mp_msg (MSGT_OPEN
, MSGL_ERR
, "Socket error: %d\n", err
);
380 is_multicast_address (char *addr
)
382 struct sockaddr_in sin
;
387 sin
.sin_family
= AF_INET
;
390 inet_pton (AF_INET
, addr
, &sin
.sin_addr
);
392 inet_aton (addr
, &sin
.sin_addr
);
393 #elif HAVE_WINSOCK2_H
394 sin
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
397 if ((ntohl (sin
.sin_addr
.s_addr
) >> 28) == 0xe)
403 struct rtp_rtsp_session_t
*
404 rtp_setup_and_play (rtsp_t
*rtsp_session
)
406 struct rtp_rtsp_session_t
* rtp_session
= NULL
;
407 const fsdp_media_description_t
*med_dsc
= NULL
;
408 char temp_buf
[MAX_LENGTH
+ 1];
413 char *server_addr
= NULL
;
414 char *destination
= NULL
;
417 int content_length
= 0;
418 int is_multicast
= 0;
420 fsdp_description_t
*dsc
= NULL
;
423 int client_rtp_port
= -1;
424 int client_rtcp_port
= -1;
425 int server_rtp_port
= -1;
426 int server_rtcp_port
= -1;
430 /* 1. send a RTSP DESCRIBE request to server */
431 rtsp_schedule_field (rtsp_session
, RTSP_ACCEPT_SDP
);
432 statut
= rtsp_request_describe (rtsp_session
, NULL
);
433 if (statut
< 200 || statut
> 299)
436 answer
= rtsp_search_answers (rtsp_session
, RTSP_CONTENT_LENGTH
);
438 content_length
= atoi (answer
);
442 answer
= rtsp_search_answers (rtsp_session
, RTSP_CONTENT_TYPE
);
443 if (!answer
|| !strstr (answer
, RTSP_APPLICATION_SDP
))
446 /* 2. read SDP message from server */
447 sdp
= (char *) malloc (content_length
+ 1);
448 if (rtsp_read_data (rtsp_session
, sdp
, content_length
) <= 0)
453 sdp
[content_length
] = 0;
455 /* 3. parse SDP message */
456 dsc
= fsdp_description_new ();
457 result
= fsdp_parse (sdp
, dsc
);
458 if (result
!= FSDPE_OK
)
461 fsdp_description_delete (dsc
);
464 mp_msg (MSGT_OPEN
, MSGL_V
, "SDP:\n%s\n", sdp
);
467 /* 4. check for number of media streams: only one is supported */
468 if (fsdp_get_media_count (dsc
) != 1)
470 mp_msg (MSGT_OPEN
, MSGL_ERR
,
471 "A single media stream only is supported atm.\n");
472 fsdp_description_delete (dsc
);
476 /* 5. set the Normal Play Time parameter
477 * use range provided by server in SDP or start now if empty */
478 sprintf (npt
, RTSP_RANGE
);
479 if (fsdp_get_range (dsc
))
480 strcat (npt
, fsdp_get_range (dsc
));
482 strcat (npt
, RTSP_NPT_NOW
);
484 /* 5. check for a valid media stream */
485 med_dsc
= fsdp_get_media (dsc
, 0);
488 fsdp_description_delete (dsc
);
492 /* 6. parse the `m=<media> <port> <transport> <fmt list>' line */
494 /* check for an A/V media */
495 if (fsdp_get_media_type (med_dsc
) != FSDP_MEDIA_VIDEO
&&
496 fsdp_get_media_type (med_dsc
) != FSDP_MEDIA_AUDIO
)
498 fsdp_description_delete (dsc
);
502 /* only RTP/AVP transport method is supported right now */
503 if (fsdp_get_media_transport_protocol (med_dsc
) != FSDP_TP_RTP_AVP
)
505 fsdp_description_delete (dsc
);
509 /* only MPEG-TS is supported at the moment */
510 if (!fsdp_get_media_format (med_dsc
, 0) ||
511 !strstr (fsdp_get_media_format (med_dsc
, 0),
512 RTSP_MEDIA_CONTAINER_MPEG_TS
))
514 fsdp_description_delete (dsc
);
518 /* get client port (if any) advised by server */
519 client_rtp_port
= fsdp_get_media_port (med_dsc
);
520 if (client_rtp_port
== -1)
522 fsdp_description_delete (dsc
);
526 /* if client_rtp_port = 0 => let client randomly pick one */
527 if (client_rtp_port
== 0)
529 /* TODO: we should check if the port is in use first */
531 client_rtp_port
= rtsp_port
;
533 client_rtp_port
= RTSP_DEFAULT_PORT
;
536 /* RTCP port generally is RTP port + 1 */
537 client_rtcp_port
= client_rtp_port
+ 1;
539 mp_msg (MSGT_OPEN
, MSGL_V
,
540 "RTP Port from SDP appears to be: %d\n", client_rtp_port
);
541 mp_msg (MSGT_OPEN
, MSGL_V
,
542 "RTCP Port from SDP appears to be: %d\n", client_rtcp_port
);
544 /* 7. parse the `c=<network type> <addr type> <connection address>' line */
546 /* check for a valid media network type (inet) */
547 if (fsdp_get_media_network_type (med_dsc
) != FSDP_NETWORK_TYPE_INET
)
549 /* no control for media: try global one instead */
550 if (fsdp_get_global_conn_network_type (dsc
) != FSDP_NETWORK_TYPE_INET
)
552 fsdp_description_delete (dsc
);
557 /* only IPv4 is supported atm. */
558 if (fsdp_get_media_address_type (med_dsc
) != FSDP_ADDRESS_TYPE_IPV4
)
560 /* no control for media: try global one instead */
561 if (fsdp_get_global_conn_address_type (dsc
) != FSDP_ADDRESS_TYPE_IPV4
)
563 fsdp_description_delete (dsc
);
568 /* get the media server address to connect to */
569 if (fsdp_get_media_address (med_dsc
))
570 server_addr
= strdup (fsdp_get_media_address (med_dsc
));
571 else if (fsdp_get_global_conn_address (dsc
))
573 /* no control for media: try global one instead */
574 server_addr
= strdup (fsdp_get_global_conn_address (dsc
));
579 fsdp_description_delete (dsc
);
583 /* check for a UNICAST or MULTICAST address to connect to */
584 is_multicast
= is_multicast_address (server_addr
);
586 /* 8. initiate an RTP session */
587 rtp_session
= rtp_session_new ();
591 fsdp_description_delete (dsc
);
595 /* get the media control URL */
596 if (fsdp_get_media_control (med_dsc
, 0))
597 rtp_session
->control_url
= strdup (fsdp_get_media_control (med_dsc
, 0));
598 fsdp_description_delete (dsc
);
599 if (!rtp_session
->control_url
)
602 rtp_session_free (rtp_session
);
606 /* 9. create the payload for RTSP SETUP request */
607 memset (temp_buf
, '\0', MAX_LENGTH
);
608 snprintf (temp_buf
, MAX_LENGTH
,
609 RTSP_TRANSPORT_REQUEST
,
610 is_multicast
? RTSP_TRANSPORT_MULTICAST
: RTSP_TRANSPORT_UNICAST
,
611 is_multicast
? RTSP_MULTICAST_PORT
: RTSP_UNICAST_CLIENT_PORT
,
612 client_rtp_port
, client_rtcp_port
);
613 mp_msg (MSGT_OPEN
, MSGL_V
, "RTSP Transport: %s\n", temp_buf
);
615 rtsp_unschedule_field (rtsp_session
, RTSP_SESSION
);
616 rtsp_schedule_field (rtsp_session
, temp_buf
);
618 /* 10. check for the media control URL type and initiate RTSP SETUP */
619 if (!strncmp (rtp_session
->control_url
, "rtsp://", 7)) /* absolute URL */
620 statut
= rtsp_request_setup (rtsp_session
,
621 rtp_session
->control_url
, NULL
);
622 else /* relative URL */
623 statut
= rtsp_request_setup (rtsp_session
,
624 NULL
, rtp_session
->control_url
);
626 if (statut
< 200 || statut
> 299)
629 rtp_session_free (rtp_session
);
633 /* 11. parse RTSP SETUP response: we need it to actually determine
634 * the real address and port to connect to */
635 answer
= rtsp_search_answers (rtsp_session
, RTSP_TRANSPORT
);
639 rtp_session_free (rtp_session
);
643 /* check for RTP and RTCP ports to bind according to how request was done */
645 if (strstr (answer
, RTSP_TRANSPORT_MULTICAST
))
649 parse_port (answer
, RTSP_MULTICAST_PORT
,
650 &client_rtp_port
, &client_rtcp_port
);
653 parse_port (answer
, RTSP_UNICAST_CLIENT_PORT
,
654 &client_rtp_port
, &client_rtcp_port
);
655 parse_port (answer
, RTSP_UNICAST_SERVER_PORT
,
656 &server_rtp_port
, &server_rtcp_port
);
659 /* now check network settings as determined by server */
660 if (rtsp_destination
)
661 destination
= strdup (rtsp_destination
);
663 destination
= parse_destination (answer
);
665 destination
= strdup (server_addr
);
668 mp_msg (MSGT_OPEN
, MSGL_V
, "RTSP Destination: %s\n", destination
);
669 mp_msg (MSGT_OPEN
, MSGL_V
, "Client RTP port : %d\n", client_rtp_port
);
670 mp_msg (MSGT_OPEN
, MSGL_V
, "Client RTCP port : %d\n", client_rtcp_port
);
671 mp_msg (MSGT_OPEN
, MSGL_V
, "Server RTP port : %d\n", server_rtp_port
);
672 mp_msg (MSGT_OPEN
, MSGL_V
, "Server RTCP port : %d\n", server_rtcp_port
);
674 /* 12. performs RTSP PLAY request */
675 rtsp_schedule_field (rtsp_session
, npt
);
676 statut
= rtsp_request_play (rtsp_session
, NULL
);
677 if (statut
< 200 || statut
> 299)
680 rtp_session_free (rtp_session
);
684 /* 13. create RTP and RTCP connections */
685 rtp_sock
= rtp_connect (destination
, client_rtp_port
);
686 rtcp_sock
= rtcp_connect (client_rtcp_port
, server_rtcp_port
, destination
);
687 rtp_session_set_fd (rtp_session
, rtp_sock
, rtcp_sock
);
690 mp_msg (MSGT_OPEN
, MSGL_V
, "RTP Sock : %d\nRTCP Sock : %d\n",
691 rtp_session
->rtp_socket
, rtp_session
->rtcp_socket
);
693 if (rtp_session
->rtp_socket
== -1)
695 rtp_session_free (rtp_session
);