| OLD | NEW |
| 1 /* | 1 /* |
| 2 * RTSP/SDP client | 2 * RTSP/SDP client |
| 3 * Copyright (c) 2002 Fabrice Bellard | 3 * Copyright (c) 2002 Fabrice Bellard |
| 4 * | 4 * |
| 5 * This file is part of FFmpeg. | 5 * This file is part of FFmpeg. |
| 6 * | 6 * |
| 7 * FFmpeg is free software; you can redistribute it and/or | 7 * FFmpeg is free software; you can redistribute it and/or |
| 8 * modify it under the terms of the GNU Lesser General Public | 8 * modify it under the terms of the GNU Lesser General Public |
| 9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
| 10 * version 2.1 of the License, or (at your option) any later version. | 10 * version 2.1 of the License, or (at your option) any later version. |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 *start = parse_date(buf, 1); | 197 *start = parse_date(buf, 1); |
| 198 if (*p == '-') { | 198 if (*p == '-') { |
| 199 p++; | 199 p++; |
| 200 get_word_sep(buf, sizeof(buf), "-", &p); | 200 get_word_sep(buf, sizeof(buf), "-", &p); |
| 201 *end = parse_date(buf, 1); | 201 *end = parse_date(buf, 1); |
| 202 } | 202 } |
| 203 // av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start); | 203 // av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start); |
| 204 // av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end); | 204 // av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end); |
| 205 } | 205 } |
| 206 | 206 |
| 207 static int get_sockaddr(const char *buf, struct sockaddr_storage *sock) |
| 208 { |
| 209 struct addrinfo hints, *ai = NULL; |
| 210 memset(&hints, 0, sizeof(hints)); |
| 211 hints.ai_flags = AI_NUMERICHOST; |
| 212 if (getaddrinfo(buf, NULL, &hints, &ai)) |
| 213 return -1; |
| 214 memcpy(sock, ai->ai_addr, FFMIN(sizeof(*sock), ai->ai_addrlen)); |
| 215 freeaddrinfo(ai); |
| 216 return 0; |
| 217 } |
| 218 |
| 207 typedef struct SDPParseState { | 219 typedef struct SDPParseState { |
| 208 /* SDP only */ | 220 /* SDP only */ |
| 209 struct in_addr default_ip; | 221 struct sockaddr_storage default_ip; |
| 210 int default_ttl; | 222 int default_ttl; |
| 211 int skip_media; ///< set if an unknown m= line occurs | 223 int skip_media; ///< set if an unknown m= line occurs |
| 212 } SDPParseState; | 224 } SDPParseState; |
| 213 | 225 |
| 214 static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, | 226 static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, |
| 215 int letter, const char *buf) | 227 int letter, const char *buf) |
| 216 { | 228 { |
| 217 RTSPState *rt = s->priv_data; | 229 RTSPState *rt = s->priv_data; |
| 218 char buf1[64], st_type[64]; | 230 char buf1[64], st_type[64]; |
| 219 const char *p; | 231 const char *p; |
| 220 enum AVMediaType codec_type; | 232 enum AVMediaType codec_type; |
| 221 int payload_type, i; | 233 int payload_type, i; |
| 222 AVStream *st; | 234 AVStream *st; |
| 223 RTSPStream *rtsp_st; | 235 RTSPStream *rtsp_st; |
| 224 struct in_addr sdp_ip; | 236 struct sockaddr_storage sdp_ip; |
| 225 int ttl; | 237 int ttl; |
| 226 | 238 |
| 227 dprintf(s, "sdp: %c='%s'\n", letter, buf); | 239 dprintf(s, "sdp: %c='%s'\n", letter, buf); |
| 228 | 240 |
| 229 p = buf; | 241 p = buf; |
| 230 if (s1->skip_media && letter != 'm') | 242 if (s1->skip_media && letter != 'm') |
| 231 return; | 243 return; |
| 232 switch (letter) { | 244 switch (letter) { |
| 233 case 'c': | 245 case 'c': |
| 234 get_word(buf1, sizeof(buf1), &p); | 246 get_word(buf1, sizeof(buf1), &p); |
| 235 if (strcmp(buf1, "IN") != 0) | 247 if (strcmp(buf1, "IN") != 0) |
| 236 return; | 248 return; |
| 237 get_word(buf1, sizeof(buf1), &p); | 249 get_word(buf1, sizeof(buf1), &p); |
| 238 if (strcmp(buf1, "IP4") != 0) | 250 if (strcmp(buf1, "IP4") && strcmp(buf1, "IP6")) |
| 239 return; | 251 return; |
| 240 get_word_sep(buf1, sizeof(buf1), "/", &p); | 252 get_word_sep(buf1, sizeof(buf1), "/", &p); |
| 241 if (ff_inet_aton(buf1, &sdp_ip) == 0) | 253 if (get_sockaddr(buf1, &sdp_ip)) |
| 242 return; | 254 return; |
| 243 ttl = 16; | 255 ttl = 16; |
| 244 if (*p == '/') { | 256 if (*p == '/') { |
| 245 p++; | 257 p++; |
| 246 get_word_sep(buf1, sizeof(buf1), "/", &p); | 258 get_word_sep(buf1, sizeof(buf1), "/", &p); |
| 247 ttl = atoi(buf1); | 259 ttl = atoi(buf1); |
| 248 } | 260 } |
| 249 if (s->nb_streams == 0) { | 261 if (s->nb_streams == 0) { |
| 250 s1->default_ip = sdp_ip; | 262 s1->default_ip = sdp_ip; |
| 251 s1->default_ttl = ttl; | 263 s1->default_ttl = ttl; |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 677 } | 689 } |
| 678 } else if (!strcmp(parameter, "multicast")) { | 690 } else if (!strcmp(parameter, "multicast")) { |
| 679 if (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP) | 691 if (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP) |
| 680 th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST; | 692 th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST; |
| 681 } else if (!strcmp(parameter, "ttl")) { | 693 } else if (!strcmp(parameter, "ttl")) { |
| 682 if (*p == '=') { | 694 if (*p == '=') { |
| 683 p++; | 695 p++; |
| 684 th->ttl = strtol(p, (char **)&p, 10); | 696 th->ttl = strtol(p, (char **)&p, 10); |
| 685 } | 697 } |
| 686 } else if (!strcmp(parameter, "destination")) { | 698 } else if (!strcmp(parameter, "destination")) { |
| 687 struct in_addr ipaddr; | |
| 688 | |
| 689 if (*p == '=') { | 699 if (*p == '=') { |
| 690 p++; | 700 p++; |
| 691 get_word_sep(buf, sizeof(buf), ";,", &p); | 701 get_word_sep(buf, sizeof(buf), ";,", &p); |
| 692 if (ff_inet_aton(buf, &ipaddr)) | 702 get_sockaddr(buf, &th->destination); |
| 693 th->destination = ntohl(ipaddr.s_addr); | 703 } |
| 704 } else if (!strcmp(parameter, "source")) { |
| 705 if (*p == '=') { |
| 706 p++; |
| 707 get_word_sep(buf, sizeof(buf), ";,", &p); |
| 708 av_strlcpy(th->source, buf, sizeof(th->source)); |
| 694 } | 709 } |
| 695 } | 710 } |
| 711 |
| 696 while (*p != ';' && *p != '\0' && *p != ',') | 712 while (*p != ';' && *p != '\0' && *p != ',') |
| 697 p++; | 713 p++; |
| 698 if (*p == ';') | 714 if (*p == ';') |
| 699 p++; | 715 p++; |
| 700 } | 716 } |
| 701 if (*p == ',') | 717 if (*p == ',') |
| 702 p++; | 718 p++; |
| 703 | 719 |
| 704 reply->nb_transports++; | 720 reply->nb_transports++; |
| 705 } | 721 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 790 /* parse reply (XXX: use buffers) */ | 806 /* parse reply (XXX: use buffers) */ |
| 791 rt->last_reply[0] = '\0'; | 807 rt->last_reply[0] = '\0'; |
| 792 for (;;) { | 808 for (;;) { |
| 793 q = buf; | 809 q = buf; |
| 794 for (;;) { | 810 for (;;) { |
| 795 ret = url_read_complete(rt->rtsp_hd, &ch, 1); | 811 ret = url_read_complete(rt->rtsp_hd, &ch, 1); |
| 796 #ifdef DEBUG_RTP_TCP | 812 #ifdef DEBUG_RTP_TCP |
| 797 dprintf(s, "ret=%d c=%02x [%c]\n", ret, ch, ch); | 813 dprintf(s, "ret=%d c=%02x [%c]\n", ret, ch, ch); |
| 798 #endif | 814 #endif |
| 799 if (ret != 1) | 815 if (ret != 1) |
| 800 return -1; | 816 return AVERROR_EOF; |
| 801 if (ch == '\n') | 817 if (ch == '\n') |
| 802 break; | 818 break; |
| 803 if (ch == '$') { | 819 if (ch == '$') { |
| 804 /* XXX: only parse it if first char on line ? */ | 820 /* XXX: only parse it if first char on line ? */ |
| 805 if (return_on_interleaved_data) { | 821 if (return_on_interleaved_data) { |
| 806 return 1; | 822 return 1; |
| 807 } else | 823 } else |
| 808 ff_rtsp_skip_packet(s); | 824 ff_rtsp_skip_packet(s); |
| 809 } else if (ch != '\r') { | 825 } else if (ch != '\r') { |
| 810 if ((q - buf) < sizeof(buf) - 1) | 826 if ((q - buf) < sizeof(buf) - 1) |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1138 | 1154 |
| 1139 switch(reply->transports[0].lower_transport) { | 1155 switch(reply->transports[0].lower_transport) { |
| 1140 case RTSP_LOWER_TRANSPORT_TCP: | 1156 case RTSP_LOWER_TRANSPORT_TCP: |
| 1141 rtsp_st->interleaved_min = reply->transports[0].interleaved_min; | 1157 rtsp_st->interleaved_min = reply->transports[0].interleaved_min; |
| 1142 rtsp_st->interleaved_max = reply->transports[0].interleaved_max; | 1158 rtsp_st->interleaved_max = reply->transports[0].interleaved_max; |
| 1143 break; | 1159 break; |
| 1144 | 1160 |
| 1145 case RTSP_LOWER_TRANSPORT_UDP: { | 1161 case RTSP_LOWER_TRANSPORT_UDP: { |
| 1146 char url[1024]; | 1162 char url[1024]; |
| 1147 | 1163 |
| 1148 /* XXX: also use address if specified */ | 1164 /* Use source address if specified */ |
| 1149 ff_url_join(url, sizeof(url), "rtp", NULL, host, | 1165 if (reply->transports[0].source[0]) { |
| 1150 reply->transports[0].server_port_min, NULL); | 1166 ff_url_join(url, sizeof(url), "rtp", NULL, |
| 1167 reply->transports[0].source, |
| 1168 reply->transports[0].server_port_min, NULL); |
| 1169 } else { |
| 1170 ff_url_join(url, sizeof(url), "rtp", NULL, host, |
| 1171 reply->transports[0].server_port_min, NULL); |
| 1172 } |
| 1151 if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && | 1173 if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && |
| 1152 rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) { | 1174 rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) { |
| 1153 err = AVERROR_INVALIDDATA; | 1175 err = AVERROR_INVALIDDATA; |
| 1154 goto fail; | 1176 goto fail; |
| 1155 } | 1177 } |
| 1156 /* Try to initialize the connection state in a | 1178 /* Try to initialize the connection state in a |
| 1157 * potential NAT router by sending dummy packets. | 1179 * potential NAT router by sending dummy packets. |
| 1158 * RTP/RTCP dummy packets are used for RDT, too. | 1180 * RTP/RTCP dummy packets are used for RDT, too. |
| 1159 */ | 1181 */ |
| 1160 if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat) | 1182 if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat) |
| 1161 rtp_send_punch_packets(rtsp_st->rtp_handle); | 1183 rtp_send_punch_packets(rtsp_st->rtp_handle); |
| 1162 break; | 1184 break; |
| 1163 } | 1185 } |
| 1164 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: { | 1186 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: { |
| 1165 char url[1024]; | 1187 char url[1024], namebuf[50]; |
| 1166 struct in_addr in; | 1188 struct sockaddr_storage addr; |
| 1167 int port, ttl; | 1189 int port, ttl; |
| 1168 | 1190 |
| 1169 if (reply->transports[0].destination) { | 1191 if (reply->transports[0].destination.ss_family) { |
| 1170 in.s_addr = htonl(reply->transports[0].destination); | 1192 addr = reply->transports[0].destination; |
| 1171 port = reply->transports[0].port_min; | 1193 port = reply->transports[0].port_min; |
| 1172 ttl = reply->transports[0].ttl; | 1194 ttl = reply->transports[0].ttl; |
| 1173 } else { | 1195 } else { |
| 1174 in = rtsp_st->sdp_ip; | 1196 addr = rtsp_st->sdp_ip; |
| 1175 port = rtsp_st->sdp_port; | 1197 port = rtsp_st->sdp_port; |
| 1176 ttl = rtsp_st->sdp_ttl; | 1198 ttl = rtsp_st->sdp_ttl; |
| 1177 } | 1199 } |
| 1178 ff_url_join(url, sizeof(url), "rtp", NULL, inet_ntoa(in), | 1200 getnameinfo((struct sockaddr*) &addr, sizeof(addr), |
| 1201 namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); |
| 1202 ff_url_join(url, sizeof(url), "rtp", NULL, namebuf, |
| 1179 port, "?ttl=%d", ttl); | 1203 port, "?ttl=%d", ttl); |
| 1180 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { | 1204 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { |
| 1181 err = AVERROR_INVALIDDATA; | 1205 err = AVERROR_INVALIDDATA; |
| 1182 goto fail; | 1206 goto fail; |
| 1183 } | 1207 } |
| 1184 break; | 1208 break; |
| 1185 } | 1209 } |
| 1186 } | 1210 } |
| 1187 | 1211 |
| 1188 if ((err = rtsp_open_transport_ctx(s, rtsp_st))) | 1212 if ((err = rtsp_open_transport_ctx(s, rtsp_st))) |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1208 } | 1232 } |
| 1209 | 1233 |
| 1210 static int rtsp_read_play(AVFormatContext *s) | 1234 static int rtsp_read_play(AVFormatContext *s) |
| 1211 { | 1235 { |
| 1212 RTSPState *rt = s->priv_data; | 1236 RTSPState *rt = s->priv_data; |
| 1213 RTSPMessageHeader reply1, *reply = &reply1; | 1237 RTSPMessageHeader reply1, *reply = &reply1; |
| 1214 int i; | 1238 int i; |
| 1215 char cmd[1024]; | 1239 char cmd[1024]; |
| 1216 | 1240 |
| 1217 av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state); | 1241 av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state); |
| 1242 rt->nb_byes = 0; |
| 1218 | 1243 |
| 1219 if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) { | 1244 if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) { |
| 1220 if (rt->state == RTSP_STATE_PAUSED) { | 1245 if (rt->state == RTSP_STATE_PAUSED) { |
| 1221 cmd[0] = 0; | 1246 cmd[0] = 0; |
| 1222 } else { | 1247 } else { |
| 1223 snprintf(cmd, sizeof(cmd), | 1248 snprintf(cmd, sizeof(cmd), |
| 1224 "Range: npt=%0.3f-\r\n", | 1249 "Range: npt=%0.3f-\r\n", |
| 1225 (double)rt->seek_timestamp / AV_TIME_BASE); | 1250 (double)rt->seek_timestamp / AV_TIME_BASE); |
| 1226 } | 1251 } |
| 1227 ff_rtsp_send_cmd(s, "PLAY", rt->control_uri, cmd, reply, NULL); | 1252 ff_rtsp_send_cmd(s, "PLAY", rt->control_uri, cmd, reply, NULL); |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1604 } | 1629 } |
| 1605 ff_network_close(); | 1630 ff_network_close(); |
| 1606 return err; | 1631 return err; |
| 1607 } | 1632 } |
| 1608 #endif | 1633 #endif |
| 1609 | 1634 |
| 1610 #if CONFIG_RTSP_DEMUXER | 1635 #if CONFIG_RTSP_DEMUXER |
| 1611 static int rtsp_read_header(AVFormatContext *s, | 1636 static int rtsp_read_header(AVFormatContext *s, |
| 1612 AVFormatParameters *ap) | 1637 AVFormatParameters *ap) |
| 1613 { | 1638 { |
| 1639 RTSPState *rt = s->priv_data; |
| 1614 int ret; | 1640 int ret; |
| 1615 | 1641 |
| 1616 ret = ff_rtsp_connect(s); | 1642 ret = ff_rtsp_connect(s); |
| 1617 if (ret) | 1643 if (ret) |
| 1618 return ret; | 1644 return ret; |
| 1619 | 1645 |
| 1646 rt->real_setup_cache = av_mallocz(2 * s->nb_streams * sizeof(*rt->real_setup
_cache)); |
| 1647 if (!rt->real_setup_cache) |
| 1648 return AVERROR(ENOMEM); |
| 1649 rt->real_setup = rt->real_setup_cache + s->nb_streams * sizeof(*rt->real_set
up); |
| 1650 |
| 1620 if (ap->initial_pause) { | 1651 if (ap->initial_pause) { |
| 1621 /* do not start immediately */ | 1652 /* do not start immediately */ |
| 1622 } else { | 1653 } else { |
| 1623 if (rtsp_read_play(s) < 0) { | 1654 if (rtsp_read_play(s) < 0) { |
| 1624 ff_rtsp_close_streams(s); | 1655 ff_rtsp_close_streams(s); |
| 1625 ff_rtsp_close_connections(s); | 1656 ff_rtsp_close_connections(s); |
| 1626 return AVERROR_INVALIDDATA; | 1657 return AVERROR_INVALIDDATA; |
| 1627 } | 1658 } |
| 1628 } | 1659 } |
| 1629 | 1660 |
| 1630 return 0; | 1661 return 0; |
| 1631 } | 1662 } |
| 1632 | 1663 |
| 1633 static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, | 1664 static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, |
| 1634 uint8_t *buf, int buf_size) | 1665 uint8_t *buf, int buf_size) |
| 1635 { | 1666 { |
| 1636 RTSPState *rt = s->priv_data; | 1667 RTSPState *rt = s->priv_data; |
| 1637 RTSPStream *rtsp_st; | 1668 RTSPStream *rtsp_st; |
| 1638 fd_set rfds; | 1669 fd_set rfds; |
| 1639 int fd, fd_max, n, i, ret, tcp_fd, timeout_cnt = 0; | 1670 int fd, fd_rtcp, fd_max, n, i, ret, tcp_fd, timeout_cnt = 0; |
| 1640 struct timeval tv; | 1671 struct timeval tv; |
| 1641 | 1672 |
| 1642 for (;;) { | 1673 for (;;) { |
| 1643 if (url_interrupt_cb()) | 1674 if (url_interrupt_cb()) |
| 1644 return AVERROR(EINTR); | 1675 return AVERROR(EINTR); |
| 1645 FD_ZERO(&rfds); | 1676 FD_ZERO(&rfds); |
| 1646 if (rt->rtsp_hd) { | 1677 if (rt->rtsp_hd) { |
| 1647 tcp_fd = fd_max = url_get_file_handle(rt->rtsp_hd); | 1678 tcp_fd = fd_max = url_get_file_handle(rt->rtsp_hd); |
| 1648 FD_SET(tcp_fd, &rfds); | 1679 FD_SET(tcp_fd, &rfds); |
| 1649 } else { | 1680 } else { |
| 1650 fd_max = 0; | 1681 fd_max = 0; |
| 1651 tcp_fd = -1; | 1682 tcp_fd = -1; |
| 1652 } | 1683 } |
| 1653 for (i = 0; i < rt->nb_rtsp_streams; i++) { | 1684 for (i = 0; i < rt->nb_rtsp_streams; i++) { |
| 1654 rtsp_st = rt->rtsp_streams[i]; | 1685 rtsp_st = rt->rtsp_streams[i]; |
| 1655 if (rtsp_st->rtp_handle) { | 1686 if (rtsp_st->rtp_handle) { |
| 1656 /* currently, we cannot probe RTCP handle because of | |
| 1657 * blocking restrictions */ | |
| 1658 fd = url_get_file_handle(rtsp_st->rtp_handle); | 1687 fd = url_get_file_handle(rtsp_st->rtp_handle); |
| 1659 if (fd > fd_max) | 1688 fd_rtcp = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle); |
| 1660 fd_max = fd; | 1689 if (FFMAX(fd, fd_rtcp) > fd_max) |
| 1690 fd_max = FFMAX(fd, fd_rtcp); |
| 1661 FD_SET(fd, &rfds); | 1691 FD_SET(fd, &rfds); |
| 1692 FD_SET(fd_rtcp, &rfds); |
| 1662 } | 1693 } |
| 1663 } | 1694 } |
| 1664 tv.tv_sec = 0; | 1695 tv.tv_sec = 0; |
| 1665 tv.tv_usec = SELECT_TIMEOUT_MS * 1000; | 1696 tv.tv_usec = SELECT_TIMEOUT_MS * 1000; |
| 1666 n = select(fd_max + 1, &rfds, NULL, NULL, &tv); | 1697 n = select(fd_max + 1, &rfds, NULL, NULL, &tv); |
| 1667 if (n > 0) { | 1698 if (n > 0) { |
| 1668 timeout_cnt = 0; | 1699 timeout_cnt = 0; |
| 1669 for (i = 0; i < rt->nb_rtsp_streams; i++) { | 1700 for (i = 0; i < rt->nb_rtsp_streams; i++) { |
| 1670 rtsp_st = rt->rtsp_streams[i]; | 1701 rtsp_st = rt->rtsp_streams[i]; |
| 1671 if (rtsp_st->rtp_handle) { | 1702 if (rtsp_st->rtp_handle) { |
| 1672 fd = url_get_file_handle(rtsp_st->rtp_handle); | 1703 fd = url_get_file_handle(rtsp_st->rtp_handle); |
| 1673 if (FD_ISSET(fd, &rfds)) { | 1704 fd_rtcp = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle); |
| 1705 if (FD_ISSET(fd_rtcp, &rfds) || FD_ISSET(fd, &rfds)) { |
| 1674 ret = url_read(rtsp_st->rtp_handle, buf, buf_size); | 1706 ret = url_read(rtsp_st->rtp_handle, buf, buf_size); |
| 1675 if (ret > 0) { | 1707 if (ret > 0) { |
| 1676 *prtsp_st = rtsp_st; | 1708 *prtsp_st = rtsp_st; |
| 1677 return ret; | 1709 return ret; |
| 1678 } | 1710 } |
| 1679 } | 1711 } |
| 1680 } | 1712 } |
| 1681 } | 1713 } |
| 1682 #if CONFIG_RTSP_DEMUXER | 1714 #if CONFIG_RTSP_DEMUXER |
| 1683 if (tcp_fd != -1 && FD_ISSET(tcp_fd, &rfds)) { | 1715 if (tcp_fd != -1 && FD_ISSET(tcp_fd, &rfds)) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1706 RTSPStream *rtsp_st; | 1738 RTSPStream *rtsp_st; |
| 1707 | 1739 |
| 1708 #ifdef DEBUG_RTP_TCP | 1740 #ifdef DEBUG_RTP_TCP |
| 1709 dprintf(s, "tcp_read_packet:\n"); | 1741 dprintf(s, "tcp_read_packet:\n"); |
| 1710 #endif | 1742 #endif |
| 1711 redo: | 1743 redo: |
| 1712 for (;;) { | 1744 for (;;) { |
| 1713 RTSPMessageHeader reply; | 1745 RTSPMessageHeader reply; |
| 1714 | 1746 |
| 1715 ret = ff_rtsp_read_reply(s, &reply, NULL, 1); | 1747 ret = ff_rtsp_read_reply(s, &reply, NULL, 1); |
| 1716 if (ret == -1) | 1748 if (ret < 0) |
| 1717 return -1; | 1749 return ret; |
| 1718 if (ret == 1) /* received '$' */ | 1750 if (ret == 1) /* received '$' */ |
| 1719 break; | 1751 break; |
| 1720 /* XXX: parse message */ | 1752 /* XXX: parse message */ |
| 1721 if (rt->state != RTSP_STATE_STREAMING) | 1753 if (rt->state != RTSP_STATE_STREAMING) |
| 1722 return 0; | 1754 return 0; |
| 1723 } | 1755 } |
| 1724 ret = url_read_complete(rt->rtsp_hd, buf, 3); | 1756 ret = url_read_complete(rt->rtsp_hd, buf, 3); |
| 1725 if (ret != 3) | 1757 if (ret != 3) |
| 1726 return -1; | 1758 return -1; |
| 1727 id = buf[0]; | 1759 id = buf[0]; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1752 return len; | 1784 return len; |
| 1753 } | 1785 } |
| 1754 | 1786 |
| 1755 static int rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt) | 1787 static int rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt) |
| 1756 { | 1788 { |
| 1757 RTSPState *rt = s->priv_data; | 1789 RTSPState *rt = s->priv_data; |
| 1758 int ret, len; | 1790 int ret, len; |
| 1759 uint8_t buf[10 * RTP_MAX_PACKET_LENGTH]; | 1791 uint8_t buf[10 * RTP_MAX_PACKET_LENGTH]; |
| 1760 RTSPStream *rtsp_st; | 1792 RTSPStream *rtsp_st; |
| 1761 | 1793 |
| 1794 if (rt->nb_byes == rt->nb_rtsp_streams) |
| 1795 return AVERROR_EOF; |
| 1796 |
| 1762 /* get next frames from the same RTP packet */ | 1797 /* get next frames from the same RTP packet */ |
| 1763 if (rt->cur_transport_priv) { | 1798 if (rt->cur_transport_priv) { |
| 1764 if (rt->transport == RTSP_TRANSPORT_RDT) { | 1799 if (rt->transport == RTSP_TRANSPORT_RDT) { |
| 1765 ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0); | 1800 ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0); |
| 1766 } else | 1801 } else |
| 1767 ret = rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0); | 1802 ret = rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0); |
| 1768 if (ret == 0) { | 1803 if (ret == 0) { |
| 1769 rt->cur_transport_priv = NULL; | 1804 rt->cur_transport_priv = NULL; |
| 1770 return 0; | 1805 return 0; |
| 1771 } else if (ret == 1) { | 1806 } else if (ret == 1) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1802 /* Either bad packet, or a RTCP packet. Check if the | 1837 /* Either bad packet, or a RTCP packet. Check if the |
| 1803 * first_rtcp_ntp_time field was initialized. */ | 1838 * first_rtcp_ntp_time field was initialized. */ |
| 1804 RTPDemuxContext *rtpctx = rtsp_st->transport_priv; | 1839 RTPDemuxContext *rtpctx = rtsp_st->transport_priv; |
| 1805 if (rtpctx->first_rtcp_ntp_time != AV_NOPTS_VALUE) { | 1840 if (rtpctx->first_rtcp_ntp_time != AV_NOPTS_VALUE) { |
| 1806 /* first_rtcp_ntp_time has been initialized for this stream, | 1841 /* first_rtcp_ntp_time has been initialized for this stream, |
| 1807 * copy the same value to all other uninitialized streams, | 1842 * copy the same value to all other uninitialized streams, |
| 1808 * in order to map their timestamp origin to the same ntp time | 1843 * in order to map their timestamp origin to the same ntp time |
| 1809 * as this one. */ | 1844 * as this one. */ |
| 1810 int i; | 1845 int i; |
| 1811 for (i = 0; i < rt->nb_rtsp_streams; i++) { | 1846 for (i = 0; i < rt->nb_rtsp_streams; i++) { |
| 1812 RTPDemuxContext *rtpctx2 = rtsp_st->transport_priv; | 1847 RTPDemuxContext *rtpctx2 = rt->rtsp_streams[i]->transport_pr
iv; |
| 1813 if (rtpctx2 && | 1848 if (rtpctx2 && |
| 1814 rtpctx2->first_rtcp_ntp_time == AV_NOPTS_VALUE) | 1849 rtpctx2->first_rtcp_ntp_time == AV_NOPTS_VALUE) |
| 1815 rtpctx2->first_rtcp_ntp_time = rtpctx->first_rtcp_ntp_ti
me; | 1850 rtpctx2->first_rtcp_ntp_time = rtpctx->first_rtcp_ntp_ti
me; |
| 1816 } | 1851 } |
| 1817 } | 1852 } |
| 1853 if (ret == -RTCP_BYE) { |
| 1854 rt->nb_byes++; |
| 1855 |
| 1856 av_log(s, AV_LOG_DEBUG, "Received BYE for stream %d (%d/%d)\n", |
| 1857 rtsp_st->stream_index, rt->nb_byes, rt->nb_rtsp_streams); |
| 1858 |
| 1859 if (rt->nb_byes == rt->nb_rtsp_streams) |
| 1860 return AVERROR_EOF; |
| 1861 } |
| 1818 } | 1862 } |
| 1819 } | 1863 } |
| 1820 if (ret < 0) | 1864 if (ret < 0) |
| 1821 goto redo; | 1865 goto redo; |
| 1822 if (ret == 1) | 1866 if (ret == 1) |
| 1823 /* more packets may follow, so we save the RTP context */ | 1867 /* more packets may follow, so we save the RTP context */ |
| 1824 rt->cur_transport_priv = rtsp_st->transport_priv; | 1868 rt->cur_transport_priv = rtsp_st->transport_priv; |
| 1825 | 1869 |
| 1826 return ret; | 1870 return ret; |
| 1827 } | 1871 } |
| 1828 | 1872 |
| 1829 static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt) | 1873 static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt) |
| 1830 { | 1874 { |
| 1831 RTSPState *rt = s->priv_data; | 1875 RTSPState *rt = s->priv_data; |
| 1832 int ret; | 1876 int ret; |
| 1833 RTSPMessageHeader reply1, *reply = &reply1; | 1877 RTSPMessageHeader reply1, *reply = &reply1; |
| 1834 char cmd[1024]; | 1878 char cmd[1024]; |
| 1835 | 1879 |
| 1836 if (rt->server_type == RTSP_SERVER_REAL) { | 1880 if (rt->server_type == RTSP_SERVER_REAL) { |
| 1837 int i; | 1881 int i; |
| 1838 enum AVDiscard cache[MAX_STREAMS]; | |
| 1839 | 1882 |
| 1840 for (i = 0; i < s->nb_streams; i++) | 1883 for (i = 0; i < s->nb_streams; i++) |
| 1841 cache[i] = s->streams[i]->discard; | 1884 rt->real_setup[i] = s->streams[i]->discard; |
| 1842 | 1885 |
| 1843 if (!rt->need_subscription) { | 1886 if (!rt->need_subscription) { |
| 1844 if (memcmp (cache, rt->real_setup_cache, | 1887 if (memcmp (rt->real_setup, rt->real_setup_cache, |
| 1845 sizeof(enum AVDiscard) * s->nb_streams)) { | 1888 sizeof(enum AVDiscard) * s->nb_streams)) { |
| 1846 snprintf(cmd, sizeof(cmd), | 1889 snprintf(cmd, sizeof(cmd), |
| 1847 "Unsubscribe: %s\r\n", | 1890 "Unsubscribe: %s\r\n", |
| 1848 rt->last_subscription); | 1891 rt->last_subscription); |
| 1849 ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri, | 1892 ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri, |
| 1850 cmd, reply, NULL); | 1893 cmd, reply, NULL); |
| 1851 if (reply->status_code != RTSP_STATUS_OK) | 1894 if (reply->status_code != RTSP_STATUS_OK) |
| 1852 return AVERROR_INVALIDDATA; | 1895 return AVERROR_INVALIDDATA; |
| 1853 rt->need_subscription = 1; | 1896 rt->need_subscription = 1; |
| 1854 } | 1897 } |
| 1855 } | 1898 } |
| 1856 | 1899 |
| 1857 if (rt->need_subscription) { | 1900 if (rt->need_subscription) { |
| 1858 int r, rule_nr, first = 1; | 1901 int r, rule_nr, first = 1; |
| 1859 | 1902 |
| 1860 memcpy(rt->real_setup_cache, cache, | 1903 memcpy(rt->real_setup_cache, rt->real_setup, |
| 1861 sizeof(enum AVDiscard) * s->nb_streams); | 1904 sizeof(enum AVDiscard) * s->nb_streams); |
| 1862 rt->last_subscription[0] = 0; | 1905 rt->last_subscription[0] = 0; |
| 1863 | 1906 |
| 1864 snprintf(cmd, sizeof(cmd), | 1907 snprintf(cmd, sizeof(cmd), |
| 1865 "Subscribe: "); | 1908 "Subscribe: "); |
| 1866 for (i = 0; i < rt->nb_rtsp_streams; i++) { | 1909 for (i = 0; i < rt->nb_rtsp_streams; i++) { |
| 1867 rule_nr = 0; | 1910 rule_nr = 0; |
| 1868 for (r = 0; r < s->nb_streams; r++) { | 1911 for (r = 0; r < s->nb_streams; r++) { |
| 1869 if (s->streams[r]->priv_data == rt->rtsp_streams[i]) { | 1912 if (s->streams[r]->priv_data == rt->rtsp_streams[i]) { |
| 1870 if (s->streams[r]->discard != AVDISCARD_ALL) { | 1913 if (s->streams[r]->discard != AVDISCARD_ALL) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1890 if (rt->state == RTSP_STATE_STREAMING) | 1933 if (rt->state == RTSP_STATE_STREAMING) |
| 1891 rtsp_read_play (s); | 1934 rtsp_read_play (s); |
| 1892 } | 1935 } |
| 1893 } | 1936 } |
| 1894 | 1937 |
| 1895 ret = rtsp_fetch_packet(s, pkt); | 1938 ret = rtsp_fetch_packet(s, pkt); |
| 1896 if (ret < 0) | 1939 if (ret < 0) |
| 1897 return ret; | 1940 return ret; |
| 1898 | 1941 |
| 1899 /* send dummy request to keep TCP connection alive */ | 1942 /* send dummy request to keep TCP connection alive */ |
| 1900 if ((rt->server_type == RTSP_SERVER_WMS || | 1943 if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) { |
| 1901 rt->server_type == RTSP_SERVER_REAL) && | |
| 1902 (av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) { | |
| 1903 if (rt->server_type == RTSP_SERVER_WMS) { | 1944 if (rt->server_type == RTSP_SERVER_WMS) { |
| 1904 ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL); | 1945 ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL); |
| 1905 } else { | 1946 } else { |
| 1906 ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL); | 1947 ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL); |
| 1907 } | 1948 } |
| 1908 } | 1949 } |
| 1909 | 1950 |
| 1910 return 0; | 1951 return 0; |
| 1911 } | 1952 } |
| 1912 | 1953 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1962 /* NOTE: it is valid to flush the buffer here */ | 2003 /* NOTE: it is valid to flush the buffer here */ |
| 1963 if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) { | 2004 if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) { |
| 1964 url_fclose(&rt->rtsp_gb); | 2005 url_fclose(&rt->rtsp_gb); |
| 1965 } | 2006 } |
| 1966 #endif | 2007 #endif |
| 1967 ff_rtsp_send_cmd_async(s, "TEARDOWN", rt->control_uri, NULL); | 2008 ff_rtsp_send_cmd_async(s, "TEARDOWN", rt->control_uri, NULL); |
| 1968 | 2009 |
| 1969 ff_rtsp_close_streams(s); | 2010 ff_rtsp_close_streams(s); |
| 1970 ff_rtsp_close_connections(s); | 2011 ff_rtsp_close_connections(s); |
| 1971 ff_network_close(); | 2012 ff_network_close(); |
| 2013 rt->real_setup = NULL; |
| 2014 av_freep(&rt->real_setup_cache); |
| 1972 return 0; | 2015 return 0; |
| 1973 } | 2016 } |
| 1974 | 2017 |
| 1975 AVInputFormat rtsp_demuxer = { | 2018 AVInputFormat rtsp_demuxer = { |
| 1976 "rtsp", | 2019 "rtsp", |
| 1977 NULL_IF_CONFIG_SMALL("RTSP input format"), | 2020 NULL_IF_CONFIG_SMALL("RTSP input format"), |
| 1978 sizeof(RTSPState), | 2021 sizeof(RTSPState), |
| 1979 rtsp_probe, | 2022 rtsp_probe, |
| 1980 rtsp_read_header, | 2023 rtsp_read_header, |
| 1981 rtsp_read_packet, | 2024 rtsp_read_packet, |
| 1982 rtsp_read_close, | 2025 rtsp_read_close, |
| 1983 rtsp_read_seek, | 2026 rtsp_read_seek, |
| 1984 .flags = AVFMT_NOFILE, | 2027 .flags = AVFMT_NOFILE, |
| 1985 .read_play = rtsp_read_play, | 2028 .read_play = rtsp_read_play, |
| 1986 .read_pause = rtsp_read_pause, | 2029 .read_pause = rtsp_read_pause, |
| 1987 }; | 2030 }; |
| 1988 #endif | 2031 #endif |
| 1989 | 2032 |
| 1990 static int sdp_probe(AVProbeData *p1) | 2033 static int sdp_probe(AVProbeData *p1) |
| 1991 { | 2034 { |
| 1992 const char *p = p1->buf, *p_end = p1->buf + p1->buf_size; | 2035 const char *p = p1->buf, *p_end = p1->buf + p1->buf_size; |
| 1993 | 2036 |
| 1994 /* we look for a line beginning "c=IN IP4" */ | 2037 /* we look for a line beginning "c=IN IP" */ |
| 1995 while (p < p_end && *p != '\0') { | 2038 while (p < p_end && *p != '\0') { |
| 1996 if (p + sizeof("c=IN IP4") - 1 < p_end && | 2039 if (p + sizeof("c=IN IP") - 1 < p_end && |
| 1997 av_strstart(p, "c=IN IP4", NULL)) | 2040 av_strstart(p, "c=IN IP", NULL)) |
| 1998 return AVPROBE_SCORE_MAX / 2; | 2041 return AVPROBE_SCORE_MAX / 2; |
| 1999 | 2042 |
| 2000 while (p < p_end - 1 && *p != '\n') p++; | 2043 while (p < p_end - 1 && *p != '\n') p++; |
| 2001 if (++p >= p_end) | 2044 if (++p >= p_end) |
| 2002 break; | 2045 break; |
| 2003 if (*p == '\r') | 2046 if (*p == '\r') |
| 2004 p++; | 2047 p++; |
| 2005 } | 2048 } |
| 2006 return 0; | 2049 return 0; |
| 2007 } | 2050 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2025 av_free(content); | 2068 av_free(content); |
| 2026 return AVERROR_INVALIDDATA; | 2069 return AVERROR_INVALIDDATA; |
| 2027 } | 2070 } |
| 2028 content[size] ='\0'; | 2071 content[size] ='\0'; |
| 2029 | 2072 |
| 2030 sdp_parse(s, content); | 2073 sdp_parse(s, content); |
| 2031 av_free(content); | 2074 av_free(content); |
| 2032 | 2075 |
| 2033 /* open each RTP stream */ | 2076 /* open each RTP stream */ |
| 2034 for (i = 0; i < rt->nb_rtsp_streams; i++) { | 2077 for (i = 0; i < rt->nb_rtsp_streams; i++) { |
| 2078 char namebuf[50]; |
| 2035 rtsp_st = rt->rtsp_streams[i]; | 2079 rtsp_st = rt->rtsp_streams[i]; |
| 2036 | 2080 |
| 2081 getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, sizeof(rtsp_st->sdp_ip)
, |
| 2082 namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); |
| 2037 ff_url_join(url, sizeof(url), "rtp", NULL, | 2083 ff_url_join(url, sizeof(url), "rtp", NULL, |
| 2038 inet_ntoa(rtsp_st->sdp_ip), rtsp_st->sdp_port, | 2084 namebuf, rtsp_st->sdp_port, |
| 2039 "?localport=%d&ttl=%d", rtsp_st->sdp_port, | 2085 "?localport=%d&ttl=%d", rtsp_st->sdp_port, |
| 2040 rtsp_st->sdp_ttl); | 2086 rtsp_st->sdp_ttl); |
| 2041 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { | 2087 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { |
| 2042 err = AVERROR_INVALIDDATA; | 2088 err = AVERROR_INVALIDDATA; |
| 2043 goto fail; | 2089 goto fail; |
| 2044 } | 2090 } |
| 2045 if ((err = rtsp_open_transport_ctx(s, rtsp_st))) | 2091 if ((err = rtsp_open_transport_ctx(s, rtsp_st))) |
| 2046 goto fail; | 2092 goto fail; |
| 2047 } | 2093 } |
| 2048 return 0; | 2094 return 0; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2061 | 2107 |
| 2062 AVInputFormat sdp_demuxer = { | 2108 AVInputFormat sdp_demuxer = { |
| 2063 "sdp", | 2109 "sdp", |
| 2064 NULL_IF_CONFIG_SMALL("SDP"), | 2110 NULL_IF_CONFIG_SMALL("SDP"), |
| 2065 sizeof(RTSPState), | 2111 sizeof(RTSPState), |
| 2066 sdp_probe, | 2112 sdp_probe, |
| 2067 sdp_read_header, | 2113 sdp_read_header, |
| 2068 rtsp_fetch_packet, | 2114 rtsp_fetch_packet, |
| 2069 sdp_read_close, | 2115 sdp_read_close, |
| 2070 }; | 2116 }; |
| OLD | NEW |