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
);
135 free (st
->control_url
);
140 rtp_session_set_fd (struct rtp_rtsp_session_t
*st
,
141 int rtp_sock
, int rtcp_sock
)
146 st
->rtp_socket
= rtp_sock
;
147 st
->rtcp_socket
= rtcp_sock
;
151 parse_port (const char *line
, const char *param
,
152 int *rtp_port
, int *rtcp_port
)
158 char *line_copy
= strdup (line
);
160 parse1
= strstr (line_copy
, param
);
164 parse2
= strstr (parse1
, "-");
168 parse3
= strstr (parse2
, ";");
187 *rtp_port
= atoi (parse1
+ strlen (param
));
188 *rtcp_port
= atoi (parse2
+ 1);
196 parse_destination (const char *line
)
202 char *line_copy
= strdup (line
);
205 parse1
= strstr (line_copy
, RTSP_SETUP_DESTINATION
);
212 parse2
= strstr (parse1
, ";");
219 len
= strlen (parse1
) - strlen (parse2
)
220 - strlen (RTSP_SETUP_DESTINATION
) + 1;
221 dest
= (char *) malloc (len
+ 1);
222 av_strlcpy (dest
, parse1
+ strlen (RTSP_SETUP_DESTINATION
), len
);
229 rtcp_connect (int client_port
, int server_port
, const char* server_hostname
)
231 struct sockaddr_in sin
;
235 if (client_port
<= 1023)
238 s
= socket (PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
242 hp
= gethostbyname (server_hostname
);
249 memset(&sin
, 0, sizeof(sin
));
250 sin
.sin_family
= AF_INET
;
251 sin
.sin_addr
.s_addr
= INADDR_ANY
;
252 sin
.sin_port
= htons (client_port
);
254 if (bind (s
, (struct sockaddr
*) &sin
, sizeof (sin
)))
257 if (errno
!= EINPROGRESS
)
259 if (WSAGetLastError() != WSAEINPROGRESS
)
267 sin
.sin_family
= AF_INET
;
268 memcpy (&(sin
.sin_addr
.s_addr
), hp
->h_addr
, sizeof (hp
->h_addr
));
269 sin
.sin_port
= htons (server_port
);
271 /* datagram socket */
272 if (connect (s
, (struct sockaddr
*) &sin
, sizeof (sin
)) < 0)
282 rtp_connect (char *hostname
, int port
)
284 struct sockaddr_in sin
;
294 s
= socket (PF_INET
, SOCK_DGRAM
, 0);
298 memset(&sin
, 0, sizeof(sin
));
299 sin
.sin_family
= AF_INET
;
300 if (!hostname
|| !strcmp (hostname
, "0.0.0.0"))
301 sin
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
304 inet_pton (AF_INET
, hostname
, &sin
.sin_addr
);
306 inet_aton (hostname
, &sin
.sin_addr
);
307 #elif HAVE_WINSOCK2_H
308 sin
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
310 sin
.sin_port
= htons (port
);
312 /* Increase the socket rx buffer size to maximum -- this is UDP */
313 rxsockbufsz
= 240 * 1024;
314 if (setsockopt (s
, SOL_SOCKET
, SO_RCVBUF
,
315 &rxsockbufsz
, sizeof (rxsockbufsz
)))
316 mp_msg (MSGT_OPEN
, MSGL_ERR
, "Couldn't set receive socket buffer size\n");
318 /* if multicast address, add membership */
319 if ((ntohl (sin
.sin_addr
.s_addr
) >> 28) == 0xe)
321 struct ip_mreq mcast
;
322 mcast
.imr_multiaddr
.s_addr
= sin
.sin_addr
.s_addr
;
323 mcast
.imr_interface
.s_addr
= 0;
325 if (setsockopt (s
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
, &mcast
, sizeof (mcast
)))
327 mp_msg (MSGT_OPEN
, MSGL_ERR
, "IP_ADD_MEMBERSHIP failed\n");
333 /* datagram socket */
334 if (bind (s
, (struct sockaddr
*) &sin
, sizeof (sin
)))
337 if (errno
!= EINPROGRESS
)
339 if (WSAGetLastError() != WSAEINPROGRESS
)
342 mp_msg (MSGT_OPEN
, MSGL_ERR
, "bind: %s\n", strerror (errno
));
348 tv
.tv_sec
= 1; /* 1 second timeout */
354 err
= select (s
+ 1, &set
, NULL
, NULL
, &tv
);
357 mp_msg (MSGT_OPEN
, MSGL_ERR
, "Select failed: %s\n", strerror (errno
));
363 mp_msg (MSGT_OPEN
, MSGL_ERR
, "Timeout! No data from host %s\n", hostname
);
368 err_len
= sizeof (err
);
369 getsockopt (s
, SOL_SOCKET
, SO_ERROR
, &err
, (socklen_t
*) &err_len
);
372 mp_msg (MSGT_OPEN
, MSGL_ERR
, "Socket error: %d\n", err
);
381 is_multicast_address (char *addr
)
383 struct sockaddr_in sin
;
388 sin
.sin_family
= AF_INET
;
391 inet_pton (AF_INET
, addr
, &sin
.sin_addr
);
393 inet_aton (addr
, &sin
.sin_addr
);
394 #elif HAVE_WINSOCK2_H
395 sin
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
398 if ((ntohl (sin
.sin_addr
.s_addr
) >> 28) == 0xe)
404 struct rtp_rtsp_session_t
*
405 rtp_setup_and_play (rtsp_t
*rtsp_session
)
407 struct rtp_rtsp_session_t
* rtp_session
= NULL
;
408 const fsdp_media_description_t
*med_dsc
= NULL
;
409 char temp_buf
[MAX_LENGTH
+ 1];
414 char *server_addr
= NULL
;
415 char *destination
= NULL
;
418 int content_length
= 0;
419 int is_multicast
= 0;
421 fsdp_description_t
*dsc
= NULL
;
424 int client_rtp_port
= -1;
425 int client_rtcp_port
= -1;
426 int server_rtp_port
= -1;
427 int server_rtcp_port
= -1;
431 /* 1. send a RTSP DESCRIBE request to server */
432 rtsp_schedule_field (rtsp_session
, RTSP_ACCEPT_SDP
);
433 statut
= rtsp_request_describe (rtsp_session
, NULL
);
434 if (statut
< 200 || statut
> 299)
437 answer
= rtsp_search_answers (rtsp_session
, RTSP_CONTENT_LENGTH
);
439 content_length
= atoi (answer
);
443 answer
= rtsp_search_answers (rtsp_session
, RTSP_CONTENT_TYPE
);
444 if (!answer
|| !strstr (answer
, RTSP_APPLICATION_SDP
))
447 /* 2. read SDP message from server */
448 sdp
= (char *) malloc (content_length
+ 1);
449 if (rtsp_read_data (rtsp_session
, sdp
, content_length
) <= 0)
454 sdp
[content_length
] = 0;
456 /* 3. parse SDP message */
457 dsc
= fsdp_description_new ();
458 result
= fsdp_parse (sdp
, dsc
);
459 if (result
!= FSDPE_OK
)
462 fsdp_description_delete (dsc
);
465 mp_msg (MSGT_OPEN
, MSGL_V
, "SDP:\n%s\n", sdp
);
468 /* 4. check for number of media streams: only one is supported */
469 if (fsdp_get_media_count (dsc
) != 1)
471 mp_msg (MSGT_OPEN
, MSGL_ERR
,
472 "A single media stream only is supported atm.\n");
473 fsdp_description_delete (dsc
);
477 /* 5. set the Normal Play Time parameter
478 * use range provided by server in SDP or start now if empty */
479 sprintf (npt
, RTSP_RANGE
);
480 if (fsdp_get_range (dsc
))
481 strcat (npt
, fsdp_get_range (dsc
));
483 strcat (npt
, RTSP_NPT_NOW
);
485 /* 5. check for a valid media stream */
486 med_dsc
= fsdp_get_media (dsc
, 0);
489 fsdp_description_delete (dsc
);
493 /* 6. parse the `m=<media> <port> <transport> <fmt list>' line */
495 /* check for an A/V media */
496 if (fsdp_get_media_type (med_dsc
) != FSDP_MEDIA_VIDEO
&&
497 fsdp_get_media_type (med_dsc
) != FSDP_MEDIA_AUDIO
)
499 fsdp_description_delete (dsc
);
503 /* only RTP/AVP transport method is supported right now */
504 if (fsdp_get_media_transport_protocol (med_dsc
) != FSDP_TP_RTP_AVP
)
506 fsdp_description_delete (dsc
);
510 /* only MPEG-TS is supported at the moment */
511 if (!fsdp_get_media_format (med_dsc
, 0) ||
512 !strstr (fsdp_get_media_format (med_dsc
, 0),
513 RTSP_MEDIA_CONTAINER_MPEG_TS
))
515 fsdp_description_delete (dsc
);
519 /* get client port (if any) advised by server */
520 client_rtp_port
= fsdp_get_media_port (med_dsc
);
521 if (client_rtp_port
== -1)
523 fsdp_description_delete (dsc
);
527 /* if client_rtp_port = 0 => let client randomly pick one */
528 if (client_rtp_port
== 0)
530 /* TODO: we should check if the port is in use first */
532 client_rtp_port
= rtsp_port
;
534 client_rtp_port
= RTSP_DEFAULT_PORT
;
537 /* RTCP port generally is RTP port + 1 */
538 client_rtcp_port
= client_rtp_port
+ 1;
540 mp_msg (MSGT_OPEN
, MSGL_V
,
541 "RTP Port from SDP appears to be: %d\n", client_rtp_port
);
542 mp_msg (MSGT_OPEN
, MSGL_V
,
543 "RTCP Port from SDP appears to be: %d\n", client_rtcp_port
);
545 /* 7. parse the `c=<network type> <addr type> <connection address>' line */
547 /* check for a valid media network type (inet) */
548 if (fsdp_get_media_network_type (med_dsc
) != FSDP_NETWORK_TYPE_INET
)
550 /* no control for media: try global one instead */
551 if (fsdp_get_global_conn_network_type (dsc
) != FSDP_NETWORK_TYPE_INET
)
553 fsdp_description_delete (dsc
);
558 /* only IPv4 is supported atm. */
559 if (fsdp_get_media_address_type (med_dsc
) != FSDP_ADDRESS_TYPE_IPV4
)
561 /* no control for media: try global one instead */
562 if (fsdp_get_global_conn_address_type (dsc
) != FSDP_ADDRESS_TYPE_IPV4
)
564 fsdp_description_delete (dsc
);
569 /* get the media server address to connect to */
570 if (fsdp_get_media_address (med_dsc
))
571 server_addr
= strdup (fsdp_get_media_address (med_dsc
));
572 else if (fsdp_get_global_conn_address (dsc
))
574 /* no control for media: try global one instead */
575 server_addr
= strdup (fsdp_get_global_conn_address (dsc
));
580 fsdp_description_delete (dsc
);
584 /* check for a UNICAST or MULTICAST address to connect to */
585 is_multicast
= is_multicast_address (server_addr
);
587 /* 8. initiate an RTP session */
588 rtp_session
= rtp_session_new ();
592 fsdp_description_delete (dsc
);
596 /* get the media control URL */
597 if (fsdp_get_media_control (med_dsc
, 0))
598 rtp_session
->control_url
= strdup (fsdp_get_media_control (med_dsc
, 0));
599 fsdp_description_delete (dsc
);
600 if (!rtp_session
->control_url
)
603 rtp_session_free (rtp_session
);
607 /* 9. create the payload for RTSP SETUP request */
608 memset (temp_buf
, '\0', MAX_LENGTH
);
609 snprintf (temp_buf
, MAX_LENGTH
,
610 RTSP_TRANSPORT_REQUEST
,
611 is_multicast
? RTSP_TRANSPORT_MULTICAST
: RTSP_TRANSPORT_UNICAST
,
612 is_multicast
? RTSP_MULTICAST_PORT
: RTSP_UNICAST_CLIENT_PORT
,
613 client_rtp_port
, client_rtcp_port
);
614 mp_msg (MSGT_OPEN
, MSGL_V
, "RTSP Transport: %s\n", temp_buf
);
616 rtsp_unschedule_field (rtsp_session
, RTSP_SESSION
);
617 rtsp_schedule_field (rtsp_session
, temp_buf
);
619 /* 10. check for the media control URL type and initiate RTSP SETUP */
620 if (!strncmp (rtp_session
->control_url
, "rtsp://", 7)) /* absolute URL */
621 statut
= rtsp_request_setup (rtsp_session
,
622 rtp_session
->control_url
, NULL
);
623 else /* relative URL */
624 statut
= rtsp_request_setup (rtsp_session
,
625 NULL
, rtp_session
->control_url
);
627 if (statut
< 200 || statut
> 299)
630 rtp_session_free (rtp_session
);
634 /* 11. parse RTSP SETUP response: we need it to actually determine
635 * the real address and port to connect to */
636 answer
= rtsp_search_answers (rtsp_session
, RTSP_TRANSPORT
);
640 rtp_session_free (rtp_session
);
644 /* check for RTP and RTCP ports to bind according to how request was done */
646 if (strstr (answer
, RTSP_TRANSPORT_MULTICAST
))
650 parse_port (answer
, RTSP_MULTICAST_PORT
,
651 &client_rtp_port
, &client_rtcp_port
);
654 parse_port (answer
, RTSP_UNICAST_CLIENT_PORT
,
655 &client_rtp_port
, &client_rtcp_port
);
656 parse_port (answer
, RTSP_UNICAST_SERVER_PORT
,
657 &server_rtp_port
, &server_rtcp_port
);
660 /* now check network settings as determined by server */
661 if (rtsp_destination
)
662 destination
= strdup (rtsp_destination
);
664 destination
= parse_destination (answer
);
666 destination
= strdup (server_addr
);
669 mp_msg (MSGT_OPEN
, MSGL_V
, "RTSP Destination: %s\n", destination
);
670 mp_msg (MSGT_OPEN
, MSGL_V
, "Client RTP port : %d\n", client_rtp_port
);
671 mp_msg (MSGT_OPEN
, MSGL_V
, "Client RTCP port : %d\n", client_rtcp_port
);
672 mp_msg (MSGT_OPEN
, MSGL_V
, "Server RTP port : %d\n", server_rtp_port
);
673 mp_msg (MSGT_OPEN
, MSGL_V
, "Server RTCP port : %d\n", server_rtcp_port
);
675 /* 12. performs RTSP PLAY request */
676 rtsp_schedule_field (rtsp_session
, npt
);
677 statut
= rtsp_request_play (rtsp_session
, NULL
);
678 if (statut
< 200 || statut
> 299)
681 rtp_session_free (rtp_session
);
685 /* 13. create RTP and RTCP connections */
686 rtp_sock
= rtp_connect (destination
, client_rtp_port
);
687 rtcp_sock
= rtcp_connect (client_rtcp_port
, server_rtcp_port
, destination
);
688 rtp_session_set_fd (rtp_session
, rtp_sock
, rtcp_sock
);
691 mp_msg (MSGT_OPEN
, MSGL_V
, "RTP Sock : %d\nRTCP Sock : %d\n",
692 rtp_session
->rtp_socket
, rtp_session
->rtcp_socket
);
694 if (rtp_session
->rtp_socket
== -1)
696 rtp_session_free (rtp_session
);