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
35
41 };
42
44 {
47
48 for (
i = 0;
i <
s->nb_streams;
i++) {
50 if (!rtpctx)
51 continue;
55 s->streams[
i]->priv_data =
NULL;
56 }
57
59 sap->
ann[0] |= 4;
/* Session deletion*/
61 }
62
66 return 0;
67 }
68
70 {
72 char host[1024], path[1024], url[1024], announce_addr[50] = "";
73 char *option_list;
74 int port = 9875, base_port = 5004,
i,
pos = 0, same_port = 0, ttl = 255;
78 socklen_t addrlen = sizeof(localaddr);
79 int udp_fd;
81
84
85 /* extract hostname and port */
87 path,
sizeof(path),
s->url);
88 if (base_port < 0)
89 base_port = 5004;
90
91 /* search for options */
92 option_list = strrchr(path, '?');
93 if (option_list) {
94 char buf[50];
96 port = strtol(buf,
NULL, 10);
97 }
99 same_port = strtol(buf,
NULL, 10);
100 }
102 ttl = strtol(buf,
NULL, 10);
103 }
105 av_strlcpy(announce_addr, buf,
sizeof(announce_addr));
106 }
107 }
108
109 if (!announce_addr[0]) {
116 }
117 if (ai->ai_family == AF_INET) {
118 /* Also known as sap.mcast.net */
119 av_strlcpy(announce_addr,
"224.2.127.254",
sizeof(announce_addr));
120 #if HAVE_STRUCT_SOCKADDR_IN6
121 } else if (ai->ai_family == AF_INET6) {
122 /* With IPv6, you can use the same destination in many different
123 * multicast subnets, to choose how far you want it routed.
124 * This one is intended to be routed globally. */
125 av_strlcpy(announce_addr,
"ff0e::2:7ffe",
sizeof(announce_addr));
126 #endif
127 } else {
130 "address family\n", host);
133 }
135 }
136
137 contexts =
av_calloc(
s->nb_streams,
sizeof(*contexts));
138 if (!contexts) {
141 }
142
143 if (
s->start_time_realtime == 0 ||
s->start_time_realtime ==
AV_NOPTS_VALUE)
145 for (
i = 0;
i <
s->nb_streams;
i++) {
147 char *new_url;
148
150 "?ttl=%d", ttl);
151 if (!same_port)
152 base_port += 2;
154 &
s->interrupt_callback,
NULL,
155 s->protocol_whitelist,
s->protocol_blacklist,
NULL);
159 }
163 s->streams[
i]->priv_data = contexts[
i];
166 if (!new_url) {
169 }
171 }
172
173 if (
s->nb_streams > 0 && title)
175
177 "?ttl=%d&connect=1", ttl);
179 &
s->interrupt_callback,
NULL,
180 s->protocol_whitelist,
s->protocol_blacklist,
NULL);
184 }
185
187 if (getsockname(udp_fd, (struct sockaddr*) &localaddr, &addrlen)) {
190 }
191 if (localaddr.ss_family != AF_INET
192 #if HAVE_STRUCT_SOCKADDR_IN6
193 && localaddr.ss_family != AF_INET6
194 #endif
195 ) {
199 }
205 }
207 #if HAVE_STRUCT_SOCKADDR_IN6
208 if (localaddr.ss_family == AF_INET6)
210 #endif
212 sap->
ann[
pos++] = 0;
/* Authentication length */
215 if (localaddr.ss_family == AF_INET) {
216 memcpy(&sap->
ann[
pos], &((
struct sockaddr_in*)&localaddr)->sin_addr,
217 sizeof(struct in_addr));
218 pos +=
sizeof(
struct in_addr);
219 #if HAVE_STRUCT_SOCKADDR_IN6
220 } else {
221 memcpy(&sap->
ann[
pos], &((
struct sockaddr_in6*)&localaddr)->sin6_addr,
222 sizeof(struct in6_addr));
223 pos +=
sizeof(
struct in6_addr);
224 #endif
225 }
226
229
234 }
239
242 "packet\n");
244 }
245
246 return 0;
247
252 }
253
255 {
259
262 /* Don't abort even if we get "Destination unreachable" */
266 }
269 }
270
274 .priv_data_size =
sizeof(
struct SAPState),
281 };