Mercurial > libavformat.hg
comparison sdp.c @ 6405:1f6088eaa469 libavformat
Properly handle IPv6 addresses in the SDP generation
author | mstorsjo |
---|---|
date | Wed, 25 Aug 2010 12:29:32 +0000 |
parents | 0bcd6a8bc5d5 |
children | 189ff77baaf3 |
comparison
equal
deleted
inserted
replaced
6404:37944ce385a0 | 6405:1f6088eaa469 |
---|---|
42 int end_time; /**< session end time (NTP time, in seconds), | 42 int end_time; /**< session end time (NTP time, in seconds), |
43 or 0 if the session is not bounded */ | 43 or 0 if the session is not bounded */ |
44 int ttl; /**< TTL, in case of multicast stream */ | 44 int ttl; /**< TTL, in case of multicast stream */ |
45 const char *user; /**< username of the session's creator */ | 45 const char *user; /**< username of the session's creator */ |
46 const char *src_addr; /**< IP address of the machine from which the session was created */ | 46 const char *src_addr; /**< IP address of the machine from which the session was created */ |
47 const char *src_type; /**< address type of src_addr */ | |
47 const char *dst_addr; /**< destination IP address (can be multicast) */ | 48 const char *dst_addr; /**< destination IP address (can be multicast) */ |
49 const char *dst_type; /**< destination IP address type */ | |
48 const char *name; /**< session name (can be an empty string) */ | 50 const char *name; /**< session name (can be an empty string) */ |
49 }; | 51 }; |
50 | 52 |
51 static void sdp_write_address(char *buff, int size, const char *dest_addr, int ttl) | 53 static void sdp_write_address(char *buff, int size, const char *dest_addr, |
54 const char *dest_type, int ttl) | |
52 { | 55 { |
53 if (dest_addr) { | 56 if (dest_addr) { |
57 if (!dest_type) | |
58 dest_type = "IP4"; | |
54 if (ttl > 0) { | 59 if (ttl > 0) { |
55 av_strlcatf(buff, size, "c=IN IP4 %s/%d\r\n", dest_addr, ttl); | 60 av_strlcatf(buff, size, "c=IN %s %s/%d\r\n", dest_type, dest_addr, ttl); |
56 } else { | 61 } else { |
57 av_strlcatf(buff, size, "c=IN IP4 %s\r\n", dest_addr); | 62 av_strlcatf(buff, size, "c=IN %s %s\r\n", dest_type, dest_addr); |
58 } | 63 } |
59 } | 64 } |
60 } | 65 } |
61 | 66 |
62 static void sdp_write_header(char *buff, int size, struct sdp_session_level *s) | 67 static void sdp_write_header(char *buff, int size, struct sdp_session_level *s) |
63 { | 68 { |
64 av_strlcatf(buff, size, "v=%d\r\n" | 69 av_strlcatf(buff, size, "v=%d\r\n" |
65 "o=- %d %d IN IP4 %s\r\n" | 70 "o=- %d %d IN %s %s\r\n" |
66 "s=%s\r\n", | 71 "s=%s\r\n", |
67 s->sdp_version, | 72 s->sdp_version, |
68 s->id, s->version, s->src_addr, | 73 s->id, s->version, s->src_type, s->src_addr, |
69 s->name); | 74 s->name); |
70 sdp_write_address(buff, size, s->dst_addr, s->ttl); | 75 sdp_write_address(buff, size, s->dst_addr, s->dst_type, s->ttl); |
71 av_strlcatf(buff, size, "t=%d %d\r\n" | 76 av_strlcatf(buff, size, "t=%d %d\r\n" |
72 "a=tool:libavformat " AV_STRINGIFY(LIBAVFORMAT_VERSION) "\r\n", | 77 "a=tool:libavformat " AV_STRINGIFY(LIBAVFORMAT_VERSION) "\r\n", |
73 s->start_time, s->end_time); | 78 s->start_time, s->end_time); |
74 } | 79 } |
75 | 80 |
76 #if CONFIG_NETWORK | 81 #if CONFIG_NETWORK |
77 static void resolve_destination(char *dest_addr, int size) | 82 static void resolve_destination(char *dest_addr, int size, char *type, |
83 int type_size) | |
78 { | 84 { |
79 struct addrinfo hints, *ai, *cur; | 85 struct addrinfo hints, *ai, *cur; |
80 | 86 |
87 av_strlcpy(type, "IP4", type_size); | |
81 if (!dest_addr[0]) | 88 if (!dest_addr[0]) |
82 return; | 89 return; |
83 | 90 |
84 /* Resolve the destination, since it must be written | 91 /* Resolve the destination, since it must be written |
85 * as a numeric IP address in the SDP. */ | 92 * as a numeric IP address in the SDP. */ |
86 | 93 |
87 memset(&hints, 0, sizeof(hints)); | 94 memset(&hints, 0, sizeof(hints)); |
88 /* We only support IPv4 addresses in the SDP at the moment. */ | |
89 hints.ai_family = AF_INET; | |
90 if (getaddrinfo(dest_addr, NULL, &hints, &ai)) | 95 if (getaddrinfo(dest_addr, NULL, &hints, &ai)) |
91 return; | 96 return; |
92 for (cur = ai; cur; cur = cur->ai_next) { | 97 for (cur = ai; cur; cur = cur->ai_next) { |
93 if (cur->ai_family == AF_INET) { | |
94 getnameinfo(cur->ai_addr, cur->ai_addrlen, dest_addr, size, | 98 getnameinfo(cur->ai_addr, cur->ai_addrlen, dest_addr, size, |
95 NULL, 0, NI_NUMERICHOST); | 99 NULL, 0, NI_NUMERICHOST); |
96 break; | 100 if (cur->ai_family == AF_INET6) |
97 } | 101 av_strlcpy(type, "IP6", type_size); |
102 break; | |
98 } | 103 } |
99 freeaddrinfo(ai); | 104 freeaddrinfo(ai); |
100 } | 105 } |
101 #else | 106 #else |
102 static void resolve_destination(char *dest_addr, int size) | 107 static void resolve_destination(char *dest_addr, int size) |
424 av_free(config); | 429 av_free(config); |
425 | 430 |
426 return buff; | 431 return buff; |
427 } | 432 } |
428 | 433 |
429 void ff_sdp_write_media(char *buff, int size, AVCodecContext *c, const char *dest_addr, int port, int ttl) | 434 void ff_sdp_write_media(char *buff, int size, AVCodecContext *c, const char *dest_addr, const char *dest_type, int port, int ttl) |
430 { | 435 { |
431 const char *type; | 436 const char *type; |
432 int payload_type; | 437 int payload_type; |
433 | 438 |
434 payload_type = ff_rtp_get_payload_type(c); | 439 payload_type = ff_rtp_get_payload_type(c); |
442 case AVMEDIA_TYPE_SUBTITLE: type = "text" ; break; | 447 case AVMEDIA_TYPE_SUBTITLE: type = "text" ; break; |
443 default : type = "application"; break; | 448 default : type = "application"; break; |
444 } | 449 } |
445 | 450 |
446 av_strlcatf(buff, size, "m=%s %d RTP/AVP %d\r\n", type, port, payload_type); | 451 av_strlcatf(buff, size, "m=%s %d RTP/AVP %d\r\n", type, port, payload_type); |
447 sdp_write_address(buff, size, dest_addr, ttl); | 452 sdp_write_address(buff, size, dest_addr, dest_type, ttl); |
448 if (c->bit_rate) { | 453 if (c->bit_rate) { |
449 av_strlcatf(buff, size, "b=AS:%d\r\n", c->bit_rate / 1000); | 454 av_strlcatf(buff, size, "b=AS:%d\r\n", c->bit_rate / 1000); |
450 } | 455 } |
451 | 456 |
452 sdp_write_media_attributes(buff, size, c, payload_type); | 457 sdp_write_media_attributes(buff, size, c, payload_type); |
455 int avf_sdp_create(AVFormatContext *ac[], int n_files, char *buff, int size) | 460 int avf_sdp_create(AVFormatContext *ac[], int n_files, char *buff, int size) |
456 { | 461 { |
457 AVMetadataTag *title = av_metadata_get(ac[0]->metadata, "title", NULL, 0); | 462 AVMetadataTag *title = av_metadata_get(ac[0]->metadata, "title", NULL, 0); |
458 struct sdp_session_level s; | 463 struct sdp_session_level s; |
459 int i, j, port, ttl; | 464 int i, j, port, ttl; |
460 char dst[32]; | 465 char dst[32], dst_type[5]; |
461 | 466 |
462 memset(buff, 0, size); | 467 memset(buff, 0, size); |
463 memset(&s, 0, sizeof(struct sdp_session_level)); | 468 memset(&s, 0, sizeof(struct sdp_session_level)); |
464 s.user = "-"; | 469 s.user = "-"; |
465 s.src_addr = "127.0.0.1"; /* FIXME: Properly set this */ | 470 s.src_addr = "127.0.0.1"; /* FIXME: Properly set this */ |
471 s.src_type = "IP4"; | |
466 s.name = title ? title->value : "No Name"; | 472 s.name = title ? title->value : "No Name"; |
467 | 473 |
468 port = 0; | 474 port = 0; |
469 ttl = 0; | 475 ttl = 0; |
470 if (n_files == 1) { | 476 if (n_files == 1) { |
471 port = sdp_get_address(dst, sizeof(dst), &ttl, ac[0]->filename); | 477 port = sdp_get_address(dst, sizeof(dst), &ttl, ac[0]->filename); |
472 resolve_destination(dst, sizeof(dst)); | 478 resolve_destination(dst, sizeof(dst), dst_type, sizeof(dst_type)); |
473 if (dst[0]) { | 479 if (dst[0]) { |
474 s.dst_addr = dst; | 480 s.dst_addr = dst; |
481 s.dst_type = dst_type; | |
475 s.ttl = ttl; | 482 s.ttl = ttl; |
483 if (!strcmp(dst_type, "IP6")) { | |
484 s.src_addr = "::1"; | |
485 s.src_type = "IP6"; | |
486 } | |
476 } | 487 } |
477 } | 488 } |
478 sdp_write_header(buff, size, &s); | 489 sdp_write_header(buff, size, &s); |
479 | 490 |
480 dst[0] = 0; | 491 dst[0] = 0; |
481 for (i = 0; i < n_files; i++) { | 492 for (i = 0; i < n_files; i++) { |
482 if (n_files != 1) { | 493 if (n_files != 1) { |
483 port = sdp_get_address(dst, sizeof(dst), &ttl, ac[i]->filename); | 494 port = sdp_get_address(dst, sizeof(dst), &ttl, ac[i]->filename); |
484 resolve_destination(dst, sizeof(dst)); | 495 resolve_destination(dst, sizeof(dst), dst_type, sizeof(dst_type)); |
485 } | 496 } |
486 for (j = 0; j < ac[i]->nb_streams; j++) { | 497 for (j = 0; j < ac[i]->nb_streams; j++) { |
487 ff_sdp_write_media(buff, size, | 498 ff_sdp_write_media(buff, size, |
488 ac[i]->streams[j]->codec, dst[0] ? dst : NULL, | 499 ac[i]->streams[j]->codec, dst[0] ? dst : NULL, |
500 dst_type, | |
489 (port > 0) ? port + j * 2 : 0, ttl); | 501 (port > 0) ? port + j * 2 : 0, ttl); |
490 if (port <= 0) { | 502 if (port <= 0) { |
491 av_strlcatf(buff, size, | 503 av_strlcatf(buff, size, |
492 "a=control:streamid=%d\r\n", i + j); | 504 "a=control:streamid=%d\r\n", i + j); |
493 } | 505 } |