Add support for domain names, for multiple source addresses,
for exclusions, and for session level specification of addresses.
Signed-off-by: Martin Storsjö <martin@martin.st>
... | ... |
@@ -286,8 +286,27 @@ typedef struct SDPParseState { |
286 | 286 |
struct sockaddr_storage default_ip; |
287 | 287 |
int default_ttl; |
288 | 288 |
int skip_media; ///< set if an unknown m= line occurs |
289 |
+ int nb_default_include_source_addrs; /**< Number of source-specific multicast include source IP address (from SDP content) */ |
|
290 |
+ struct RTSPSource **default_include_source_addrs; /**< Source-specific multicast include source IP address (from SDP content) */ |
|
291 |
+ int nb_default_exclude_source_addrs; /**< Number of source-specific multicast exclude source IP address (from SDP content) */ |
|
292 |
+ struct RTSPSource **default_exclude_source_addrs; /**< Source-specific multicast exclude source IP address (from SDP content) */ |
|
289 | 293 |
} SDPParseState; |
290 | 294 |
|
295 |
+static void copy_default_source_addrs(struct RTSPSource **addrs, int count, |
|
296 |
+ struct RTSPSource ***dest, int *dest_count) |
|
297 |
+{ |
|
298 |
+ RTSPSource *rtsp_src, *rtsp_src2; |
|
299 |
+ int i; |
|
300 |
+ for (i = 0; i < count; i++) { |
|
301 |
+ rtsp_src = addrs[i]; |
|
302 |
+ rtsp_src2 = av_malloc(sizeof(*rtsp_src2)); |
|
303 |
+ if (!rtsp_src2) |
|
304 |
+ continue; |
|
305 |
+ memcpy(rtsp_src2, rtsp_src, sizeof(*rtsp_src)); |
|
306 |
+ dynarray_add(dest, dest_count, rtsp_src2); |
|
307 |
+ } |
|
308 |
+} |
|
309 |
+ |
|
291 | 310 |
static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, |
292 | 311 |
int letter, const char *buf) |
293 | 312 |
{ |
... | ... |
@@ -298,6 +317,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, |
298 | 298 |
int payload_type, i; |
299 | 299 |
AVStream *st; |
300 | 300 |
RTSPStream *rtsp_st; |
301 |
+ RTSPSource *rtsp_src; |
|
301 | 302 |
struct sockaddr_storage sdp_ip; |
302 | 303 |
int ttl; |
303 | 304 |
|
... | ... |
@@ -366,6 +386,15 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, |
366 | 366 |
rtsp_st->sdp_ip = s1->default_ip; |
367 | 367 |
rtsp_st->sdp_ttl = s1->default_ttl; |
368 | 368 |
|
369 |
+ copy_default_source_addrs(s1->default_include_source_addrs, |
|
370 |
+ s1->nb_default_include_source_addrs, |
|
371 |
+ &rtsp_st->include_source_addrs, |
|
372 |
+ &rtsp_st->nb_include_source_addrs); |
|
373 |
+ copy_default_source_addrs(s1->default_exclude_source_addrs, |
|
374 |
+ s1->nb_default_exclude_source_addrs, |
|
375 |
+ &rtsp_st->exclude_source_addrs, |
|
376 |
+ &rtsp_st->nb_exclude_source_addrs); |
|
377 |
+ |
|
369 | 378 |
get_word(buf1, sizeof(buf1), &p); /* port */ |
370 | 379 |
rtsp_st->sdp_port = atoi(buf1); |
371 | 380 |
|
... | ... |
@@ -495,22 +524,43 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, |
495 | 495 |
p += strspn(p, SPACE_CHARS); |
496 | 496 |
if (av_strstart(p, "inline:", &p)) |
497 | 497 |
get_word(rtsp_st->crypto_params, sizeof(rtsp_st->crypto_params), &p); |
498 |
- } else if (av_strstart(p, "source-filter:", &p) && s->nb_streams > 0) { |
|
498 |
+ } else if (av_strstart(p, "source-filter:", &p)) { |
|
499 |
+ int exclude = 0; |
|
499 | 500 |
get_word(buf1, sizeof(buf1), &p); |
500 |
- if (strcmp(buf1, "incl")) |
|
501 |
+ if (strcmp(buf1, "incl") && strcmp(buf1, "excl")) |
|
501 | 502 |
return; |
503 |
+ exclude = !strcmp(buf1, "excl"); |
|
502 | 504 |
|
503 | 505 |
get_word(buf1, sizeof(buf1), &p); |
504 | 506 |
if (strcmp(buf1, "IN") != 0) |
505 | 507 |
return; |
506 | 508 |
get_word(buf1, sizeof(buf1), &p); |
507 |
- if (strcmp(buf1, "IP4") && strcmp(buf1, "IP6")) |
|
509 |
+ if (strcmp(buf1, "IP4") && strcmp(buf1, "IP6") && strcmp(buf1, "*")) |
|
508 | 510 |
return; |
509 |
- // not checking that the destination address actually matches |
|
511 |
+ // not checking that the destination address actually matches or is wildcard |
|
510 | 512 |
get_word(buf1, sizeof(buf1), &p); |
511 | 513 |
|
512 |
- rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1]; |
|
513 |
- get_word(rtsp_st->source_addr, sizeof(rtsp_st->source_addr), &p); |
|
514 |
+ while (*p != '\0') { |
|
515 |
+ rtsp_src = av_mallocz(sizeof(*rtsp_src)); |
|
516 |
+ if (!rtsp_src) |
|
517 |
+ return; |
|
518 |
+ get_word(rtsp_src->addr, sizeof(rtsp_src->addr), &p); |
|
519 |
+ if (exclude) { |
|
520 |
+ if (s->nb_streams == 0) { |
|
521 |
+ dynarray_add(&s1->default_exclude_source_addrs, &s1->nb_default_exclude_source_addrs, rtsp_src); |
|
522 |
+ } else { |
|
523 |
+ rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1]; |
|
524 |
+ dynarray_add(&rtsp_st->exclude_source_addrs, &rtsp_st->nb_exclude_source_addrs, rtsp_src); |
|
525 |
+ } |
|
526 |
+ } else { |
|
527 |
+ if (s->nb_streams == 0) { |
|
528 |
+ dynarray_add(&s1->default_include_source_addrs, &s1->nb_default_include_source_addrs, rtsp_src); |
|
529 |
+ } else { |
|
530 |
+ rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1]; |
|
531 |
+ dynarray_add(&rtsp_st->include_source_addrs, &rtsp_st->nb_include_source_addrs, rtsp_src); |
|
532 |
+ } |
|
533 |
+ } |
|
534 |
+ } |
|
514 | 535 |
} else { |
515 | 536 |
if (rt->server_type == RTSP_SERVER_WMS) |
516 | 537 |
ff_wms_parse_sdp_a_line(s, p); |
... | ... |
@@ -535,7 +585,7 @@ int ff_sdp_parse(AVFormatContext *s, const char *content) |
535 | 535 |
{ |
536 | 536 |
RTSPState *rt = s->priv_data; |
537 | 537 |
const char *p; |
538 |
- int letter; |
|
538 |
+ int letter, i; |
|
539 | 539 |
/* Some SDP lines, particularly for Realmedia or ASF RTSP streams, |
540 | 540 |
* contain long SDP lines containing complete ASF Headers (several |
541 | 541 |
* kB) or arrays of MDPR (RM stream descriptor) headers plus |
... | ... |
@@ -572,6 +622,14 @@ int ff_sdp_parse(AVFormatContext *s, const char *content) |
572 | 572 |
if (*p == '\n') |
573 | 573 |
p++; |
574 | 574 |
} |
575 |
+ |
|
576 |
+ for (i = 0; i < s1->nb_default_include_source_addrs; i++) |
|
577 |
+ av_free(s1->default_include_source_addrs[i]); |
|
578 |
+ av_freep(&s1->default_include_source_addrs); |
|
579 |
+ for (i = 0; i < s1->nb_default_exclude_source_addrs; i++) |
|
580 |
+ av_free(s1->default_exclude_source_addrs[i]); |
|
581 |
+ av_freep(&s1->default_exclude_source_addrs); |
|
582 |
+ |
|
575 | 583 |
rt->p = av_malloc(sizeof(struct pollfd)*2*(rt->nb_rtsp_streams+1)); |
576 | 584 |
if (!rt->p) return AVERROR(ENOMEM); |
577 | 585 |
return 0; |
... | ... |
@@ -615,7 +673,7 @@ void ff_rtsp_undo_setup(AVFormatContext *s) |
615 | 615 |
void ff_rtsp_close_streams(AVFormatContext *s) |
616 | 616 |
{ |
617 | 617 |
RTSPState *rt = s->priv_data; |
618 |
- int i; |
|
618 |
+ int i, j; |
|
619 | 619 |
RTSPStream *rtsp_st; |
620 | 620 |
|
621 | 621 |
ff_rtsp_undo_setup(s); |
... | ... |
@@ -625,6 +683,13 @@ void ff_rtsp_close_streams(AVFormatContext *s) |
625 | 625 |
if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context) |
626 | 626 |
rtsp_st->dynamic_handler->free( |
627 | 627 |
rtsp_st->dynamic_protocol_context); |
628 |
+ for (j = 0; j < rtsp_st->nb_include_source_addrs; j++) |
|
629 |
+ av_free(rtsp_st->include_source_addrs[j]); |
|
630 |
+ av_freep(&rtsp_st->include_source_addrs); |
|
631 |
+ for (j = 0; j < rtsp_st->nb_exclude_source_addrs; j++) |
|
632 |
+ av_free(rtsp_st->exclude_source_addrs[j]); |
|
633 |
+ av_freep(&rtsp_st->exclude_source_addrs); |
|
634 |
+ |
|
628 | 635 |
av_free(rtsp_st); |
629 | 636 |
} |
630 | 637 |
} |
... | ... |
@@ -2058,6 +2123,17 @@ static int sdp_probe(AVProbeData *p1) |
2058 | 2058 |
return 0; |
2059 | 2059 |
} |
2060 | 2060 |
|
2061 |
+static void append_source_addrs(char *buf, int size, const char *name, |
|
2062 |
+ int count, struct RTSPSource **addrs) |
|
2063 |
+{ |
|
2064 |
+ int i; |
|
2065 |
+ if (!count) |
|
2066 |
+ return; |
|
2067 |
+ av_strlcatf(buf, size, "&%s=%s", name, addrs[0]->addr); |
|
2068 |
+ for (i = 1; i < count; i++) |
|
2069 |
+ av_strlcatf(buf, size, ",%s", addrs[i]->addr); |
|
2070 |
+} |
|
2071 |
+ |
|
2061 | 2072 |
static int sdp_read_header(AVFormatContext *s) |
2062 | 2073 |
{ |
2063 | 2074 |
RTSPState *rt = s->priv_data; |
... | ... |
@@ -2101,8 +2177,13 @@ static int sdp_read_header(AVFormatContext *s) |
2101 | 2101 |
"?localport=%d&ttl=%d&connect=%d", rtsp_st->sdp_port, |
2102 | 2102 |
rtsp_st->sdp_ttl, |
2103 | 2103 |
rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0); |
2104 |
- if (rtsp_st->source_addr[0]) |
|
2105 |
- av_strlcatf(url, sizeof(url), "&sources=%s", rtsp_st->source_addr); |
|
2104 |
+ |
|
2105 |
+ append_source_addrs(url, sizeof(url), "sources", |
|
2106 |
+ rtsp_st->nb_include_source_addrs, |
|
2107 |
+ rtsp_st->include_source_addrs); |
|
2108 |
+ append_source_addrs(url, sizeof(url), "block", |
|
2109 |
+ rtsp_st->nb_exclude_source_addrs, |
|
2110 |
+ rtsp_st->exclude_source_addrs); |
|
2106 | 2111 |
if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, |
2107 | 2112 |
&s->interrupt_callback, NULL) < 0) { |
2108 | 2113 |
err = AVERROR_INVALIDDATA; |
... | ... |
@@ -402,6 +402,10 @@ typedef struct RTSPState { |
402 | 402 |
#define RTSP_FLAG_LISTEN 0x2 /**< Wait for incoming connections. */ |
403 | 403 |
#define RTSP_FLAG_CUSTOM_IO 0x4 /**< Do all IO via the AVIOContext. */ |
404 | 404 |
|
405 |
+typedef struct RTSPSource { |
|
406 |
+ char addr[128]; /**< Source-specific multicast include source IP address (from SDP content) */ |
|
407 |
+} RTSPSource; |
|
408 |
+ |
|
405 | 409 |
/** |
406 | 410 |
* Describe a single stream, as identified by a single m= line block in the |
407 | 411 |
* SDP content. In the case of RDT, one RTSPStream can represent multiple |
... | ... |
@@ -425,7 +429,10 @@ typedef struct RTSPStream { |
425 | 425 |
//@{ |
426 | 426 |
int sdp_port; /**< port (from SDP content) */ |
427 | 427 |
struct sockaddr_storage sdp_ip; /**< IP address (from SDP content) */ |
428 |
- char source_addr[100]; /**< Source-specific multicast source IP address (from SDP content) */ |
|
428 |
+ int nb_include_source_addrs; /**< Number of source-specific multicast include source IP addresses (from SDP content) */ |
|
429 |
+ struct RTSPSource **include_source_addrs; /**< Source-specific multicast include source IP addresses (from SDP content) */ |
|
430 |
+ int nb_exclude_source_addrs; /**< Number of source-specific multicast exclude source IP addresses (from SDP content) */ |
|
431 |
+ struct RTSPSource **exclude_source_addrs; /**< Source-specific multicast exclude source IP addresses (from SDP content) */ |
|
429 | 432 |
int sdp_ttl; /**< IP Time-To-Live (from SDP content) */ |
430 | 433 |
int sdp_payload_type; /**< payload type */ |
431 | 434 |
//@} |