1 /*
2 * Session Announcement Protocol (RFC 2974) muxer
3 * Copyright (c) 2010 Martin Storsjo
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
36
42 };
43
45 {
48
49 for (
i = 0;
i <
s->nb_streams;
i++) {
51 if (!rtpctx)
52 continue;
56 s->streams[
i]->priv_data =
NULL;
57 }
58
60 sap->
ann[0] |= 4;
/* Session deletion*/
62 }
63
67 return 0;
68 }
69
71 {
73 char host[1024], path[1024], url[1024], announce_addr[50] = "";
74 char *option_list;
75 int port = 9875, base_port = 5004,
i,
pos = 0, same_port = 0, ttl = 255;
79 socklen_t addrlen = sizeof(localaddr);
80 int udp_fd;
82
85
86 /* extract hostname and port */
88 path,
sizeof(path),
s->url);
89 if (base_port < 0)
90 base_port = 5004;
91
92 /* search for options */
93 option_list = strrchr(path, '?');
94 if (option_list) {
95 char buf[50];
97 port = strtol(buf,
NULL, 10);
98 }
100 same_port = strtol(buf,
NULL, 10);
101 }
103 ttl = strtol(buf,
NULL, 10);
104 }
106 av_strlcpy(announce_addr, buf,
sizeof(announce_addr));
107 }
108 }
109
110 if (!announce_addr[0]) {
117 }
118 if (ai->ai_family == AF_INET) {
119 /* Also known as sap.mcast.net */
120 av_strlcpy(announce_addr,
"224.2.127.254",
sizeof(announce_addr));
121 #if HAVE_STRUCT_SOCKADDR_IN6
122 } else if (ai->ai_family == AF_INET6) {
123 /* With IPv6, you can use the same destination in many different
124 * multicast subnets, to choose how far you want it routed.
125 * This one is intended to be routed globally. */
126 av_strlcpy(announce_addr,
"ff0e::2:7ffe",
sizeof(announce_addr));
127 #endif
128 } else {
131 "address family\n", host);
134 }
136 }
137
138 contexts =
av_calloc(
s->nb_streams,
sizeof(*contexts));
139 if (!contexts) {
142 }
143
144 if (
s->start_time_realtime == 0 ||
s->start_time_realtime ==
AV_NOPTS_VALUE)
146 for (
i = 0;
i <
s->nb_streams;
i++) {
148 char *new_url;
149
151 "?ttl=%d", ttl);
152 if (!same_port)
153 base_port += 2;
155 &
s->interrupt_callback,
NULL,
156 s->protocol_whitelist,
s->protocol_blacklist,
NULL);
160 }
164 s->streams[
i]->priv_data = contexts[
i];
167 if (!new_url) {
170 }
172 }
173
174 if (
s->nb_streams > 0 && title)
176
178 "?ttl=%d&connect=1", ttl);
180 &
s->interrupt_callback,
NULL,
181 s->protocol_whitelist,
s->protocol_blacklist,
NULL);
185 }
186
188 if (getsockname(udp_fd, (struct sockaddr*) &localaddr, &addrlen)) {
191 }
192 if (localaddr.ss_family != AF_INET
193 #if HAVE_STRUCT_SOCKADDR_IN6
194 && localaddr.ss_family != AF_INET6
195 #endif
196 ) {
200 }
206 }
208 #if HAVE_STRUCT_SOCKADDR_IN6
209 if (localaddr.ss_family == AF_INET6)
211 #endif
213 sap->
ann[
pos++] = 0;
/* Authentication length */
216 if (localaddr.ss_family == AF_INET) {
217 memcpy(&sap->
ann[
pos], &((
struct sockaddr_in*)&localaddr)->sin_addr,
218 sizeof(struct in_addr));
219 pos +=
sizeof(
struct in_addr);
220 #if HAVE_STRUCT_SOCKADDR_IN6
221 } else {
222 memcpy(&sap->
ann[
pos], &((
struct sockaddr_in6*)&localaddr)->sin6_addr,
223 sizeof(struct in6_addr));
224 pos +=
sizeof(
struct in6_addr);
225 #endif
226 }
227
230
235 }
240
243 "packet\n");
245 }
246
247 return 0;
248
253 }
254
256 {
260
263 /* Don't abort even if we get "Destination unreachable" */
267 }
270 }
271
275 .priv_data_size =
sizeof(
struct SAPState),
282 };