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
34
40 };
41
43 {
46
47 for (
i = 0;
i <
s->nb_streams;
i++) {
49 if (!rtpctx)
50 continue;
54 s->streams[
i]->priv_data =
NULL;
55 }
56
58 sap->
ann[0] |= 4;
/* Session deletion*/
60 }
61
65 return 0;
66 }
67
69 {
71 char host[1024], path[1024], url[1024], announce_addr[50] = "";
72 char *option_list;
73 int port = 9875, base_port = 5004,
i,
pos = 0, same_port = 0, ttl = 255;
77 socklen_t addrlen = sizeof(localaddr);
78 int udp_fd;
80
83
84 /* extract hostname and port */
86 path,
sizeof(path),
s->url);
87 if (base_port < 0)
88 base_port = 5004;
89
90 /* search for options */
91 option_list = strrchr(path, '?');
92 if (option_list) {
93 char buf[50];
95 port = strtol(buf,
NULL, 10);
96 }
98 same_port = strtol(buf,
NULL, 10);
99 }
101 ttl = strtol(buf,
NULL, 10);
102 }
104 av_strlcpy(announce_addr, buf,
sizeof(announce_addr));
105 }
106 }
107
108 if (!announce_addr[0]) {
115 }
116 if (ai->ai_family == AF_INET) {
117 /* Also known as sap.mcast.net */
118 av_strlcpy(announce_addr,
"224.2.127.254",
sizeof(announce_addr));
119 #if HAVE_STRUCT_SOCKADDR_IN6
120 } else if (ai->ai_family == AF_INET6) {
121 /* With IPv6, you can use the same destination in many different
122 * multicast subnets, to choose how far you want it routed.
123 * This one is intended to be routed globally. */
124 av_strlcpy(announce_addr,
"ff0e::2:7ffe",
sizeof(announce_addr));
125 #endif
126 } else {
129 "address family\n", host);
132 }
134 }
135
136 contexts =
av_calloc(
s->nb_streams,
sizeof(*contexts));
137 if (!contexts) {
140 }
141
142 if (
s->start_time_realtime == 0 ||
s->start_time_realtime ==
AV_NOPTS_VALUE)
144 for (
i = 0;
i <
s->nb_streams;
i++) {
146 char *new_url;
147
149 "?ttl=%d", ttl);
150 if (!same_port)
151 base_port += 2;
153 &
s->interrupt_callback,
NULL,
154 s->protocol_whitelist,
s->protocol_blacklist,
NULL);
158 }
162 s->streams[
i]->priv_data = contexts[
i];
165 if (!new_url) {
168 }
170 }
171
172 if (
s->nb_streams > 0 && title)
174
176 "?ttl=%d&connect=1", ttl);
178 &
s->interrupt_callback,
NULL,
179 s->protocol_whitelist,
s->protocol_blacklist,
NULL);
183 }
184
186 if (getsockname(udp_fd, (struct sockaddr*) &localaddr, &addrlen)) {
189 }
190 if (localaddr.ss_family != AF_INET
191 #if HAVE_STRUCT_SOCKADDR_IN6
192 && localaddr.ss_family != AF_INET6
193 #endif
194 ) {
198 }
204 }
206 #if HAVE_STRUCT_SOCKADDR_IN6
207 if (localaddr.ss_family == AF_INET6)
209 #endif
211 sap->
ann[
pos++] = 0;
/* Authentication length */
214 if (localaddr.ss_family == AF_INET) {
215 memcpy(&sap->
ann[
pos], &((
struct sockaddr_in*)&localaddr)->sin_addr,
216 sizeof(struct in_addr));
217 pos +=
sizeof(
struct in_addr);
218 #if HAVE_STRUCT_SOCKADDR_IN6
219 } else {
220 memcpy(&sap->
ann[
pos], &((
struct sockaddr_in6*)&localaddr)->sin6_addr,
221 sizeof(struct in6_addr));
222 pos +=
sizeof(
struct in6_addr);
223 #endif
224 }
225
228
233 }
238
241 "packet\n");
243 }
244
245 return 0;
246
251 }
252
254 {
258
261 /* Don't abort even if we get "Destination unreachable" */
265 }
268 }
269
273 .priv_data_size =
sizeof(
struct SAPState),
280 };