| 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 26 matching lines...) Expand all  Loading... | 
| 37 #include "rtsp.h" | 37 #include "rtsp.h" | 
| 38 | 38 | 
| 39 #include "rtpdec.h" | 39 #include "rtpdec.h" | 
| 40 #include "rdt.h" | 40 #include "rdt.h" | 
| 41 #include "rtpdec_formats.h" | 41 #include "rtpdec_formats.h" | 
| 42 #include "rtpenc_chain.h" | 42 #include "rtpenc_chain.h" | 
| 43 | 43 | 
| 44 //#define DEBUG | 44 //#define DEBUG | 
| 45 //#define DEBUG_RTP_TCP | 45 //#define DEBUG_RTP_TCP | 
| 46 | 46 | 
| 47 #if LIBAVFORMAT_VERSION_INT < (53 << 16) |  | 
| 48 int rtsp_default_protocols = (1 << RTSP_LOWER_TRANSPORT_UDP); |  | 
| 49 #endif |  | 
| 50 |  | 
| 51 /* Timeout values for socket select, in ms, | 47 /* Timeout values for socket select, in ms, | 
| 52  * and read_packet(), in seconds  */ | 48  * and read_packet(), in seconds  */ | 
| 53 #define SELECT_TIMEOUT_MS 100 | 49 #define SELECT_TIMEOUT_MS 100 | 
| 54 #define READ_PACKET_TIMEOUT_S 10 | 50 #define READ_PACKET_TIMEOUT_S 10 | 
| 55 #define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / SELECT_TIMEOUT_MS | 51 #define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / SELECT_TIMEOUT_MS | 
| 56 #define SDP_MAX_SIZE 16384 | 52 #define SDP_MAX_SIZE 16384 | 
| 57 #define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH | 53 #define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH | 
| 58 | 54 | 
| 59 static void get_word_until_chars(char *buf, int buf_size, | 55 static void get_word_until_chars(char *buf, int buf_size, | 
| 60                                  const char *sep, const char **pp) | 56                                  const char *sep, const char **pp) | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 80 { | 76 { | 
| 81     if (**pp == '/') (*pp)++; | 77     if (**pp == '/') (*pp)++; | 
| 82     get_word_until_chars(buf, buf_size, sep, pp); | 78     get_word_until_chars(buf, buf_size, sep, pp); | 
| 83 } | 79 } | 
| 84 | 80 | 
| 85 static void get_word(char *buf, int buf_size, const char **pp) | 81 static void get_word(char *buf, int buf_size, const char **pp) | 
| 86 { | 82 { | 
| 87     get_word_until_chars(buf, buf_size, SPACE_CHARS, pp); | 83     get_word_until_chars(buf, buf_size, SPACE_CHARS, pp); | 
| 88 } | 84 } | 
| 89 | 85 | 
|  | 86 /** Parse a string p in the form of Range:npt=xx-xx, and determine the start | 
|  | 87  *  and end time. | 
|  | 88  *  Used for seeking in the rtp stream. | 
|  | 89  */ | 
|  | 90 static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end) | 
|  | 91 { | 
|  | 92     char buf[256]; | 
|  | 93 | 
|  | 94     p += strspn(p, SPACE_CHARS); | 
|  | 95     if (!av_stristart(p, "npt=", &p)) | 
|  | 96         return; | 
|  | 97 | 
|  | 98     *start = AV_NOPTS_VALUE; | 
|  | 99     *end = AV_NOPTS_VALUE; | 
|  | 100 | 
|  | 101     get_word_sep(buf, sizeof(buf), "-", &p); | 
|  | 102     *start = parse_date(buf, 1); | 
|  | 103     if (*p == '-') { | 
|  | 104         p++; | 
|  | 105         get_word_sep(buf, sizeof(buf), "-", &p); | 
|  | 106         *end = parse_date(buf, 1); | 
|  | 107     } | 
|  | 108 //    av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start); | 
|  | 109 //    av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end); | 
|  | 110 } | 
|  | 111 | 
|  | 112 static int get_sockaddr(const char *buf, struct sockaddr_storage *sock) | 
|  | 113 { | 
|  | 114     struct addrinfo hints, *ai = NULL; | 
|  | 115     memset(&hints, 0, sizeof(hints)); | 
|  | 116     hints.ai_flags = AI_NUMERICHOST; | 
|  | 117     if (getaddrinfo(buf, NULL, &hints, &ai)) | 
|  | 118         return -1; | 
|  | 119     memcpy(sock, ai->ai_addr, FFMIN(sizeof(*sock), ai->ai_addrlen)); | 
|  | 120     freeaddrinfo(ai); | 
|  | 121     return 0; | 
|  | 122 } | 
|  | 123 | 
|  | 124 #if CONFIG_RTPDEC | 
| 90 /* parse the rtpmap description: <codec_name>/<clock_rate>[/<other params>] */ | 125 /* parse the rtpmap description: <codec_name>/<clock_rate>[/<other params>] */ | 
| 91 static int sdp_parse_rtpmap(AVFormatContext *s, | 126 static int sdp_parse_rtpmap(AVFormatContext *s, | 
| 92                             AVCodecContext *codec, RTSPStream *rtsp_st, | 127                             AVCodecContext *codec, RTSPStream *rtsp_st, | 
| 93                             int payload_type, const char *p) | 128                             int payload_type, const char *p) | 
| 94 { | 129 { | 
| 95     char buf[256]; | 130     char buf[256]; | 
| 96     int i; | 131     int i; | 
| 97     AVCodec *c; | 132     AVCodec *c; | 
| 98     const char *c_name; | 133     const char *c_name; | 
| 99 | 134 | 
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 179         if (**p == '=') | 214         if (**p == '=') | 
| 180             (*p)++; | 215             (*p)++; | 
| 181         get_word_sep(value, value_size, ";", p); | 216         get_word_sep(value, value_size, ";", p); | 
| 182         if (**p == ';') | 217         if (**p == ';') | 
| 183             (*p)++; | 218             (*p)++; | 
| 184         return 1; | 219         return 1; | 
| 185     } | 220     } | 
| 186     return 0; | 221     return 0; | 
| 187 } | 222 } | 
| 188 | 223 | 
| 189 /** Parse a string p in the form of Range:npt=xx-xx, and determine the start |  | 
| 190  *  and end time. |  | 
| 191  *  Used for seeking in the rtp stream. |  | 
| 192  */ |  | 
| 193 static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end) |  | 
| 194 { |  | 
| 195     char buf[256]; |  | 
| 196 |  | 
| 197     p += strspn(p, SPACE_CHARS); |  | 
| 198     if (!av_stristart(p, "npt=", &p)) |  | 
| 199         return; |  | 
| 200 |  | 
| 201     *start = AV_NOPTS_VALUE; |  | 
| 202     *end = AV_NOPTS_VALUE; |  | 
| 203 |  | 
| 204     get_word_sep(buf, sizeof(buf), "-", &p); |  | 
| 205     *start = parse_date(buf, 1); |  | 
| 206     if (*p == '-') { |  | 
| 207         p++; |  | 
| 208         get_word_sep(buf, sizeof(buf), "-", &p); |  | 
| 209         *end = parse_date(buf, 1); |  | 
| 210     } |  | 
| 211 //    av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start); |  | 
| 212 //    av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end); |  | 
| 213 } |  | 
| 214 |  | 
| 215 static int get_sockaddr(const char *buf, struct sockaddr_storage *sock) |  | 
| 216 { |  | 
| 217     struct addrinfo hints, *ai = NULL; |  | 
| 218     memset(&hints, 0, sizeof(hints)); |  | 
| 219     hints.ai_flags = AI_NUMERICHOST; |  | 
| 220     if (getaddrinfo(buf, NULL, &hints, &ai)) |  | 
| 221         return -1; |  | 
| 222     memcpy(sock, ai->ai_addr, FFMIN(sizeof(*sock), ai->ai_addrlen)); |  | 
| 223     freeaddrinfo(ai); |  | 
| 224     return 0; |  | 
| 225 } |  | 
| 226 |  | 
| 227 typedef struct SDPParseState { | 224 typedef struct SDPParseState { | 
| 228     /* SDP only */ | 225     /* SDP only */ | 
| 229     struct sockaddr_storage default_ip; | 226     struct sockaddr_storage default_ip; | 
| 230     int            default_ttl; | 227     int            default_ttl; | 
| 231     int            skip_media;  ///< set if an unknown m= line occurs | 228     int            skip_media;  ///< set if an unknown m= line occurs | 
| 232 } SDPParseState; | 229 } SDPParseState; | 
| 233 | 230 | 
| 234 static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, | 231 static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, | 
| 235                            int letter, const char *buf) | 232                            int letter, const char *buf) | 
| 236 { | 233 { | 
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 450         *q = '\0'; | 447         *q = '\0'; | 
| 451         sdp_parse_line(s, s1, letter, buf); | 448         sdp_parse_line(s, s1, letter, buf); | 
| 452     next_line: | 449     next_line: | 
| 453         while (*p != '\n' && *p != '\0') | 450         while (*p != '\n' && *p != '\0') | 
| 454             p++; | 451             p++; | 
| 455         if (*p == '\n') | 452         if (*p == '\n') | 
| 456             p++; | 453             p++; | 
| 457     } | 454     } | 
| 458     return 0; | 455     return 0; | 
| 459 } | 456 } | 
|  | 457 #endif /* CONFIG_RTPDEC */ | 
| 460 | 458 | 
| 461 /* close and free RTSP streams */ | 459 /* close and free RTSP streams */ | 
| 462 void ff_rtsp_close_streams(AVFormatContext *s) | 460 void ff_rtsp_close_streams(AVFormatContext *s) | 
| 463 { | 461 { | 
| 464     RTSPState *rt = s->priv_data; | 462     RTSPState *rt = s->priv_data; | 
| 465     int i; | 463     int i; | 
| 466     RTSPStream *rtsp_st; | 464     RTSPStream *rtsp_st; | 
| 467 | 465 | 
| 468     for (i = 0; i < rt->nb_rtsp_streams; i++) { | 466     for (i = 0; i < rt->nb_rtsp_streams; i++) { | 
| 469         rtsp_st = rt->rtsp_streams[i]; | 467         rtsp_st = rt->rtsp_streams[i]; | 
| 470         if (rtsp_st) { | 468         if (rtsp_st) { | 
| 471             if (rtsp_st->transport_priv) { | 469             if (rtsp_st->transport_priv) { | 
| 472                 if (s->oformat) { | 470                 if (s->oformat) { | 
| 473                     AVFormatContext *rtpctx = rtsp_st->transport_priv; | 471                     AVFormatContext *rtpctx = rtsp_st->transport_priv; | 
| 474                     av_write_trailer(rtpctx); | 472                     av_write_trailer(rtpctx); | 
| 475                     if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) { | 473                     if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) { | 
| 476                         uint8_t *ptr; | 474                         uint8_t *ptr; | 
| 477                         url_close_dyn_buf(rtpctx->pb, &ptr); | 475                         url_close_dyn_buf(rtpctx->pb, &ptr); | 
| 478                         av_free(ptr); | 476                         av_free(ptr); | 
| 479                     } else { | 477                     } else { | 
| 480                         url_fclose(rtpctx->pb); | 478                         url_fclose(rtpctx->pb); | 
| 481                     } | 479                     } | 
| 482                     av_metadata_free(&rtpctx->streams[0]->metadata); | 480                     av_metadata_free(&rtpctx->streams[0]->metadata); | 
| 483                     av_metadata_free(&rtpctx->metadata); | 481                     av_metadata_free(&rtpctx->metadata); | 
| 484                     av_free(rtpctx->streams[0]); | 482                     av_free(rtpctx->streams[0]); | 
| 485                     av_free(rtpctx); | 483                     av_free(rtpctx); | 
| 486                 } else if (rt->transport == RTSP_TRANSPORT_RDT) | 484                 } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC) | 
| 487                     ff_rdt_parse_close(rtsp_st->transport_priv); | 485                     ff_rdt_parse_close(rtsp_st->transport_priv); | 
| 488                 else | 486                 else if (CONFIG_RTPDEC) | 
| 489                     rtp_parse_close(rtsp_st->transport_priv); | 487                     rtp_parse_close(rtsp_st->transport_priv); | 
| 490             } | 488             } | 
| 491             if (rtsp_st->rtp_handle) | 489             if (rtsp_st->rtp_handle) | 
| 492                 url_close(rtsp_st->rtp_handle); | 490                 url_close(rtsp_st->rtp_handle); | 
| 493             if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context) | 491             if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context) | 
| 494                 rtsp_st->dynamic_handler->close( | 492                 rtsp_st->dynamic_handler->close( | 
| 495                     rtsp_st->dynamic_protocol_context); | 493                     rtsp_st->dynamic_protocol_context); | 
| 496         } | 494         } | 
| 497     } | 495     } | 
| 498     av_free(rt->rtsp_streams); | 496     av_free(rt->rtsp_streams); | 
| 499     if (rt->asf_ctx) { | 497     if (rt->asf_ctx) { | 
| 500         av_close_input_stream (rt->asf_ctx); | 498         av_close_input_stream (rt->asf_ctx); | 
| 501         rt->asf_ctx = NULL; | 499         rt->asf_ctx = NULL; | 
| 502     } | 500     } | 
| 503     av_free(rt->recvbuf); | 501     av_free(rt->recvbuf); | 
| 504 } | 502 } | 
| 505 | 503 | 
| 506 static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st) | 504 static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st) | 
| 507 { | 505 { | 
| 508     RTSPState *rt = s->priv_data; | 506     RTSPState *rt = s->priv_data; | 
| 509     AVStream *st = NULL; | 507     AVStream *st = NULL; | 
| 510 | 508 | 
| 511     /* open the RTP context */ | 509     /* open the RTP context */ | 
| 512     if (rtsp_st->stream_index >= 0) | 510     if (rtsp_st->stream_index >= 0) | 
| 513         st = s->streams[rtsp_st->stream_index]; | 511         st = s->streams[rtsp_st->stream_index]; | 
| 514     if (!st) | 512     if (!st) | 
| 515         s->ctx_flags |= AVFMTCTX_NOHEADER; | 513         s->ctx_flags |= AVFMTCTX_NOHEADER; | 
| 516 | 514 | 
| 517     if (s->oformat) { | 515     if (s->oformat && CONFIG_RTSP_MUXER) { | 
| 518         rtsp_st->transport_priv = ff_rtp_chain_mux_open(s, st, | 516         rtsp_st->transport_priv = ff_rtp_chain_mux_open(s, st, | 
| 519                                       rtsp_st->rtp_handle, | 517                                       rtsp_st->rtp_handle, | 
| 520                                       RTSP_TCP_MAX_PACKET_SIZE); | 518                                       RTSP_TCP_MAX_PACKET_SIZE); | 
| 521         /* Ownership of rtp_handle is passed to the rtp mux context */ | 519         /* Ownership of rtp_handle is passed to the rtp mux context */ | 
| 522         rtsp_st->rtp_handle = NULL; | 520         rtsp_st->rtp_handle = NULL; | 
| 523     } else if (rt->transport == RTSP_TRANSPORT_RDT) | 521     } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC) | 
| 524         rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index, | 522         rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index, | 
| 525                                             rtsp_st->dynamic_protocol_context, | 523                                             rtsp_st->dynamic_protocol_context, | 
| 526                                             rtsp_st->dynamic_handler); | 524                                             rtsp_st->dynamic_handler); | 
| 527     else | 525     else if (CONFIG_RTPDEC) | 
| 528         rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle, | 526         rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle, | 
| 529                                          rtsp_st->sdp_payload_type, | 527                                          rtsp_st->sdp_payload_type, | 
| 530             (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP || !s->max_delay) | 528             (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP || !s->max_delay) | 
| 531             ? 0 : RTP_REORDER_QUEUE_DEFAULT_SIZE); | 529             ? 0 : RTP_REORDER_QUEUE_DEFAULT_SIZE); | 
| 532 | 530 | 
| 533     if (!rtsp_st->transport_priv) { | 531     if (!rtsp_st->transport_priv) { | 
| 534          return AVERROR(ENOMEM); | 532          return AVERROR(ENOMEM); | 
| 535     } else if (rt->transport != RTSP_TRANSPORT_RDT) { | 533     } else if (rt->transport != RTSP_TRANSPORT_RDT && CONFIG_RTPDEC) { | 
| 536         if (rtsp_st->dynamic_handler) { | 534         if (rtsp_st->dynamic_handler) { | 
| 537             rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv, | 535             rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv, | 
| 538                                            rtsp_st->dynamic_protocol_context, | 536                                            rtsp_st->dynamic_protocol_context, | 
| 539                                            rtsp_st->dynamic_handler); | 537                                            rtsp_st->dynamic_handler); | 
| 540         } | 538         } | 
| 541     } | 539     } | 
| 542 | 540 | 
| 543     return 0; | 541     return 0; | 
| 544 } | 542 } | 
| 545 | 543 | 
| 546 #if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER | 544 #if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER | 
| 547 static int rtsp_probe(AVProbeData *p) |  | 
| 548 { |  | 
| 549     if (av_strstart(p->filename, "rtsp:", NULL)) |  | 
| 550         return AVPROBE_SCORE_MAX; |  | 
| 551     return 0; |  | 
| 552 } |  | 
| 553 |  | 
| 554 static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp) | 545 static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp) | 
| 555 { | 546 { | 
| 556     const char *p; | 547     const char *p; | 
| 557     int v; | 548     int v; | 
| 558 | 549 | 
| 559     p = *pp; | 550     p = *pp; | 
| 560     p += strspn(p, SPACE_CHARS); | 551     p += strspn(p, SPACE_CHARS); | 
| 561     v = strtol(p, (char **)&p, 10); | 552     v = strtol(p, (char **)&p, 10); | 
| 562     if (*p == '-') { | 553     if (*p == '-') { | 
| 563         p++; | 554         p++; | 
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1017 | 1008 | 
| 1018 #if 0 | 1009 #if 0 | 
| 1019             /* then try on any port */ | 1010             /* then try on any port */ | 
| 1020             if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) { | 1011             if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) { | 
| 1021                 err = AVERROR_INVALIDDATA; | 1012                 err = AVERROR_INVALIDDATA; | 
| 1022                 goto fail; | 1013                 goto fail; | 
| 1023             } | 1014             } | 
| 1024 #endif | 1015 #endif | 
| 1025 | 1016 | 
| 1026         rtp_opened: | 1017         rtp_opened: | 
| 1027             port = rtp_get_local_port(rtsp_st->rtp_handle); | 1018             port = rtp_get_local_rtp_port(rtsp_st->rtp_handle); | 
| 1028         have_port: | 1019         have_port: | 
| 1029             snprintf(transport, sizeof(transport) - 1, | 1020             snprintf(transport, sizeof(transport) - 1, | 
| 1030                      "%s/UDP;", trans_pref); | 1021                      "%s/UDP;", trans_pref); | 
| 1031             if (rt->server_type != RTSP_SERVER_REAL) | 1022             if (rt->server_type != RTSP_SERVER_REAL) | 
| 1032                 av_strlcat(transport, "unicast;", sizeof(transport)); | 1023                 av_strlcat(transport, "unicast;", sizeof(transport)); | 
| 1033             av_strlcatf(transport, sizeof(transport), | 1024             av_strlcatf(transport, sizeof(transport), | 
| 1034                      "client_port=%d", port); | 1025                      "client_port=%d", port); | 
| 1035             if (rt->transport == RTSP_TRANSPORT_RTP && | 1026             if (rt->transport == RTSP_TRANSPORT_RTP && | 
| 1036                 !(rt->server_type == RTSP_SERVER_WMS && i > 0)) | 1027                 !(rt->server_type == RTSP_SERVER_WMS && i > 0)) | 
| 1037                 av_strlcatf(transport, sizeof(transport), "-%d", port + 1); | 1028                 av_strlcatf(transport, sizeof(transport), "-%d", port + 1); | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 1061                      "%s/UDP;multicast", trans_pref); | 1052                      "%s/UDP;multicast", trans_pref); | 
| 1062         } | 1053         } | 
| 1063         if (s->oformat) { | 1054         if (s->oformat) { | 
| 1064             av_strlcat(transport, ";mode=receive", sizeof(transport)); | 1055             av_strlcat(transport, ";mode=receive", sizeof(transport)); | 
| 1065         } else if (rt->server_type == RTSP_SERVER_REAL || | 1056         } else if (rt->server_type == RTSP_SERVER_REAL || | 
| 1066                    rt->server_type == RTSP_SERVER_WMS) | 1057                    rt->server_type == RTSP_SERVER_WMS) | 
| 1067             av_strlcat(transport, ";mode=play", sizeof(transport)); | 1058             av_strlcat(transport, ";mode=play", sizeof(transport)); | 
| 1068         snprintf(cmd, sizeof(cmd), | 1059         snprintf(cmd, sizeof(cmd), | 
| 1069                  "Transport: %s\r\n", | 1060                  "Transport: %s\r\n", | 
| 1070                  transport); | 1061                  transport); | 
| 1071         if (i == 0 && rt->server_type == RTSP_SERVER_REAL) { | 1062         if (i == 0 && rt->server_type == RTSP_SERVER_REAL && CONFIG_RTPDEC) { | 
| 1072             char real_res[41], real_csum[9]; | 1063             char real_res[41], real_csum[9]; | 
| 1073             ff_rdt_calc_response_and_checksum(real_res, real_csum, | 1064             ff_rdt_calc_response_and_checksum(real_res, real_csum, | 
| 1074                                               real_challenge); | 1065                                               real_challenge); | 
| 1075             av_strlcatf(cmd, sizeof(cmd), | 1066             av_strlcatf(cmd, sizeof(cmd), | 
| 1076                         "If-Match: %s\r\n" | 1067                         "If-Match: %s\r\n" | 
| 1077                         "RealChallenge2: %s, sd=%s\r\n", | 1068                         "RealChallenge2: %s, sd=%s\r\n", | 
| 1078                         rt->session_id, real_res, real_csum); | 1069                         rt->session_id, real_res, real_csum); | 
| 1079         } | 1070         } | 
| 1080         ff_rtsp_send_cmd(s, "SETUP", rtsp_st->control_url, cmd, reply, NULL); | 1071         ff_rtsp_send_cmd(s, "SETUP", rtsp_st->control_url, cmd, reply, NULL); | 
| 1081         if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) { | 1072         if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) { | 
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1126             } | 1117             } | 
| 1127             if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && | 1118             if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && | 
| 1128                 rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) { | 1119                 rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) { | 
| 1129                 err = AVERROR_INVALIDDATA; | 1120                 err = AVERROR_INVALIDDATA; | 
| 1130                 goto fail; | 1121                 goto fail; | 
| 1131             } | 1122             } | 
| 1132             /* Try to initialize the connection state in a | 1123             /* Try to initialize the connection state in a | 
| 1133              * potential NAT router by sending dummy packets. | 1124              * potential NAT router by sending dummy packets. | 
| 1134              * RTP/RTCP dummy packets are used for RDT, too. | 1125              * RTP/RTCP dummy packets are used for RDT, too. | 
| 1135              */ | 1126              */ | 
| 1136             if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat) | 1127             if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat && | 
|  | 1128                 CONFIG_RTPDEC) | 
| 1137                 rtp_send_punch_packets(rtsp_st->rtp_handle); | 1129                 rtp_send_punch_packets(rtsp_st->rtp_handle); | 
| 1138             break; | 1130             break; | 
| 1139         } | 1131         } | 
| 1140         case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: { | 1132         case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: { | 
| 1141             char url[1024], namebuf[50]; | 1133             char url[1024], namebuf[50]; | 
| 1142             struct sockaddr_storage addr; | 1134             struct sockaddr_storage addr; | 
| 1143             int port, ttl; | 1135             int port, ttl; | 
| 1144 | 1136 | 
| 1145             if (reply->transports[0].destination.ss_family) { | 1137             if (reply->transports[0].destination.ss_family) { | 
| 1146                 addr      = reply->transports[0].destination; | 1138                 addr      = reply->transports[0].destination; | 
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1225                             av_rescale_q(reply->range_start, AV_TIME_BASE_Q, | 1217                             av_rescale_q(reply->range_start, AV_TIME_BASE_Q, | 
| 1226                                          st->time_base); | 1218                                          st->time_base); | 
| 1227                 } | 1219                 } | 
| 1228             } | 1220             } | 
| 1229         } | 1221         } | 
| 1230     } | 1222     } | 
| 1231     rt->state = RTSP_STATE_STREAMING; | 1223     rt->state = RTSP_STATE_STREAMING; | 
| 1232     return 0; | 1224     return 0; | 
| 1233 } | 1225 } | 
| 1234 | 1226 | 
|  | 1227 #if CONFIG_RTSP_DEMUXER | 
| 1235 static int rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply
      ) | 1228 static int rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply
      ) | 
| 1236 { | 1229 { | 
| 1237     RTSPState *rt = s->priv_data; | 1230     RTSPState *rt = s->priv_data; | 
| 1238     char cmd[1024]; | 1231     char cmd[1024]; | 
| 1239     unsigned char *content = NULL; | 1232     unsigned char *content = NULL; | 
| 1240     int ret; | 1233     int ret; | 
| 1241 | 1234 | 
| 1242     /* describe the stream */ | 1235     /* describe the stream */ | 
| 1243     snprintf(cmd, sizeof(cmd), | 1236     snprintf(cmd, sizeof(cmd), | 
| 1244              "Accept: application/sdp\r\n"); | 1237              "Accept: application/sdp\r\n"); | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 1261 | 1254 | 
| 1262     av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", content); | 1255     av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", content); | 
| 1263     /* now we got the SDP description, we parse it */ | 1256     /* now we got the SDP description, we parse it */ | 
| 1264     ret = sdp_parse(s, (const char *)content); | 1257     ret = sdp_parse(s, (const char *)content); | 
| 1265     av_freep(&content); | 1258     av_freep(&content); | 
| 1266     if (ret < 0) | 1259     if (ret < 0) | 
| 1267         return AVERROR_INVALIDDATA; | 1260         return AVERROR_INVALIDDATA; | 
| 1268 | 1261 | 
| 1269     return 0; | 1262     return 0; | 
| 1270 } | 1263 } | 
|  | 1264 #endif /* CONFIG_RTSP_DEMUXER */ | 
| 1271 | 1265 | 
|  | 1266 #if CONFIG_RTSP_MUXER | 
| 1272 static int rtsp_setup_output_streams(AVFormatContext *s, const char *addr) | 1267 static int rtsp_setup_output_streams(AVFormatContext *s, const char *addr) | 
| 1273 { | 1268 { | 
| 1274     RTSPState *rt = s->priv_data; | 1269     RTSPState *rt = s->priv_data; | 
| 1275     RTSPMessageHeader reply1, *reply = &reply1; | 1270     RTSPMessageHeader reply1, *reply = &reply1; | 
| 1276     int i; | 1271     int i; | 
| 1277     char *sdp; | 1272     char *sdp; | 
| 1278     AVFormatContext sdp_ctx, *ctx_array[1]; | 1273     AVFormatContext sdp_ctx, *ctx_array[1]; | 
| 1279 | 1274 | 
| 1280     s->start_time_realtime = av_gettime(); | 1275     s->start_time_realtime = av_gettime(); | 
| 1281 | 1276 | 
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1325         rtsp_st->stream_index = i; | 1320         rtsp_st->stream_index = i; | 
| 1326 | 1321 | 
| 1327         av_strlcpy(rtsp_st->control_url, rt->control_uri, sizeof(rtsp_st->contro
      l_url)); | 1322         av_strlcpy(rtsp_st->control_url, rt->control_uri, sizeof(rtsp_st->contro
      l_url)); | 
| 1328         /* Note, this must match the relative uri set in the sdp content */ | 1323         /* Note, this must match the relative uri set in the sdp content */ | 
| 1329         av_strlcatf(rtsp_st->control_url, sizeof(rtsp_st->control_url), | 1324         av_strlcatf(rtsp_st->control_url, sizeof(rtsp_st->control_url), | 
| 1330                     "/streamid=%d", i); | 1325                     "/streamid=%d", i); | 
| 1331     } | 1326     } | 
| 1332 | 1327 | 
| 1333     return 0; | 1328     return 0; | 
| 1334 } | 1329 } | 
|  | 1330 #endif /* CONFIG_RTSP_MUXER */ | 
| 1335 | 1331 | 
| 1336 void ff_rtsp_close_connections(AVFormatContext *s) | 1332 void ff_rtsp_close_connections(AVFormatContext *s) | 
| 1337 { | 1333 { | 
| 1338     RTSPState *rt = s->priv_data; | 1334     RTSPState *rt = s->priv_data; | 
| 1339     if (rt->rtsp_hd_out != rt->rtsp_hd) url_close(rt->rtsp_hd_out); | 1335     if (rt->rtsp_hd_out != rt->rtsp_hd) url_close(rt->rtsp_hd_out); | 
| 1340     url_close(rt->rtsp_hd); | 1336     url_close(rt->rtsp_hd); | 
| 1341     rt->rtsp_hd = rt->rtsp_hd_out = NULL; | 1337     rt->rtsp_hd = rt->rtsp_hd_out = NULL; | 
| 1342 } | 1338 } | 
| 1343 | 1339 | 
| 1344 int ff_rtsp_connect(AVFormatContext *s) | 1340 int ff_rtsp_connect(AVFormatContext *s) | 
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1541         if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) { | 1537         if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) { | 
| 1542             rt->server_type = RTSP_SERVER_REAL; | 1538             rt->server_type = RTSP_SERVER_REAL; | 
| 1543             continue; | 1539             continue; | 
| 1544         } else if (!strncasecmp(reply->server, "WMServer/", 9)) { | 1540         } else if (!strncasecmp(reply->server, "WMServer/", 9)) { | 
| 1545             rt->server_type = RTSP_SERVER_WMS; | 1541             rt->server_type = RTSP_SERVER_WMS; | 
| 1546         } else if (rt->server_type == RTSP_SERVER_REAL) | 1542         } else if (rt->server_type == RTSP_SERVER_REAL) | 
| 1547             strcpy(real_challenge, reply->real_challenge); | 1543             strcpy(real_challenge, reply->real_challenge); | 
| 1548         break; | 1544         break; | 
| 1549     } | 1545     } | 
| 1550 | 1546 | 
| 1551     if (s->iformat) | 1547     if (s->iformat && CONFIG_RTSP_DEMUXER) | 
| 1552         err = rtsp_setup_input_streams(s, reply); | 1548         err = rtsp_setup_input_streams(s, reply); | 
| 1553     else | 1549     else if (CONFIG_RTSP_MUXER) | 
| 1554         err = rtsp_setup_output_streams(s, host); | 1550         err = rtsp_setup_output_streams(s, host); | 
| 1555     if (err) | 1551     if (err) | 
| 1556         goto fail; | 1552         goto fail; | 
| 1557 | 1553 | 
| 1558     do { | 1554     do { | 
| 1559         int lower_transport = ff_log2_tab[lower_transport_mask & | 1555         int lower_transport = ff_log2_tab[lower_transport_mask & | 
| 1560                                   ~(lower_transport_mask - 1)]; | 1556                                   ~(lower_transport_mask - 1)]; | 
| 1561 | 1557 | 
| 1562         err = make_setup_request(s, host, port, lower_transport, | 1558         err = make_setup_request(s, host, port, lower_transport, | 
| 1563                                  rt->server_type == RTSP_SERVER_REAL ? | 1559                                  rt->server_type == RTSP_SERVER_REAL ? | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 1582         av_log(s, AV_LOG_INFO, "Status %d: Redirecting to %s\n", | 1578         av_log(s, AV_LOG_INFO, "Status %d: Redirecting to %s\n", | 
| 1583                reply->status_code, | 1579                reply->status_code, | 
| 1584                s->filename); | 1580                s->filename); | 
| 1585         goto redirect; | 1581         goto redirect; | 
| 1586     } | 1582     } | 
| 1587     ff_network_close(); | 1583     ff_network_close(); | 
| 1588     return err; | 1584     return err; | 
| 1589 } | 1585 } | 
| 1590 #endif /* CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER */ | 1586 #endif /* CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER */ | 
| 1591 | 1587 | 
|  | 1588 #if CONFIG_RTPDEC | 
| 1592 static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, | 1589 static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, | 
| 1593                            uint8_t *buf, int buf_size, int64_t wait_end) | 1590                            uint8_t *buf, int buf_size, int64_t wait_end) | 
| 1594 { | 1591 { | 
| 1595     RTSPState *rt = s->priv_data; | 1592     RTSPState *rt = s->priv_data; | 
| 1596     RTSPStream *rtsp_st; | 1593     RTSPStream *rtsp_st; | 
| 1597     fd_set rfds; | 1594     fd_set rfds; | 
| 1598     int fd, fd_rtcp, fd_max, n, i, ret, tcp_fd, timeout_cnt = 0; | 1595     int fd, fd_rtcp, fd_max, n, i, ret, tcp_fd, timeout_cnt = 0; | 
| 1599     struct timeval tv; | 1596     struct timeval tv; | 
| 1600 | 1597 | 
| 1601     for (;;) { | 1598     for (;;) { | 
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1770     } | 1767     } | 
| 1771 end: | 1768 end: | 
| 1772     if (ret < 0) | 1769     if (ret < 0) | 
| 1773         goto redo; | 1770         goto redo; | 
| 1774     if (ret == 1) | 1771     if (ret == 1) | 
| 1775         /* more packets may follow, so we save the RTP context */ | 1772         /* more packets may follow, so we save the RTP context */ | 
| 1776         rt->cur_transport_priv = rtsp_st->transport_priv; | 1773         rt->cur_transport_priv = rtsp_st->transport_priv; | 
| 1777 | 1774 | 
| 1778     return ret; | 1775     return ret; | 
| 1779 } | 1776 } | 
|  | 1777 #endif /* CONFIG_RTPDEC */ | 
| 1780 | 1778 | 
| 1781 #if CONFIG_RTSP_DEMUXER | 1779 #if CONFIG_RTSP_DEMUXER | 
|  | 1780 static int rtsp_probe(AVProbeData *p) | 
|  | 1781 { | 
|  | 1782     if (av_strstart(p->filename, "rtsp:", NULL)) | 
|  | 1783         return AVPROBE_SCORE_MAX; | 
|  | 1784     return 0; | 
|  | 1785 } | 
|  | 1786 | 
| 1782 static int rtsp_read_header(AVFormatContext *s, | 1787 static int rtsp_read_header(AVFormatContext *s, | 
| 1783                             AVFormatParameters *ap) | 1788                             AVFormatParameters *ap) | 
| 1784 { | 1789 { | 
| 1785     RTSPState *rt = s->priv_data; | 1790     RTSPState *rt = s->priv_data; | 
| 1786     int ret; | 1791     int ret; | 
| 1787 | 1792 | 
| 1788     ret = ff_rtsp_connect(s); | 1793     ret = ff_rtsp_connect(s); | 
| 1789     if (ret) | 1794     if (ret) | 
| 1790         return ret; | 1795         return ret; | 
| 1791 | 1796 | 
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2013     rtsp_read_header, | 2018     rtsp_read_header, | 
| 2014     rtsp_read_packet, | 2019     rtsp_read_packet, | 
| 2015     rtsp_read_close, | 2020     rtsp_read_close, | 
| 2016     rtsp_read_seek, | 2021     rtsp_read_seek, | 
| 2017     .flags = AVFMT_NOFILE, | 2022     .flags = AVFMT_NOFILE, | 
| 2018     .read_play = rtsp_read_play, | 2023     .read_play = rtsp_read_play, | 
| 2019     .read_pause = rtsp_read_pause, | 2024     .read_pause = rtsp_read_pause, | 
| 2020 }; | 2025 }; | 
| 2021 #endif /* CONFIG_RTSP_DEMUXER */ | 2026 #endif /* CONFIG_RTSP_DEMUXER */ | 
| 2022 | 2027 | 
|  | 2028 #if CONFIG_SDP_DEMUXER | 
| 2023 static int sdp_probe(AVProbeData *p1) | 2029 static int sdp_probe(AVProbeData *p1) | 
| 2024 { | 2030 { | 
| 2025     const char *p = p1->buf, *p_end = p1->buf + p1->buf_size; | 2031     const char *p = p1->buf, *p_end = p1->buf + p1->buf_size; | 
| 2026 | 2032 | 
| 2027     /* we look for a line beginning "c=IN IP" */ | 2033     /* we look for a line beginning "c=IN IP" */ | 
| 2028     while (p < p_end && *p != '\0') { | 2034     while (p < p_end && *p != '\0') { | 
| 2029         if (p + sizeof("c=IN IP") - 1 < p_end && | 2035         if (p + sizeof("c=IN IP") - 1 < p_end && | 
| 2030             av_strstart(p, "c=IN IP", NULL)) | 2036             av_strstart(p, "c=IN IP", NULL)) | 
| 2031             return AVPROBE_SCORE_MAX / 2; | 2037             return AVPROBE_SCORE_MAX / 2; | 
| 2032 | 2038 | 
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2097 | 2103 | 
| 2098 AVInputFormat sdp_demuxer = { | 2104 AVInputFormat sdp_demuxer = { | 
| 2099     "sdp", | 2105     "sdp", | 
| 2100     NULL_IF_CONFIG_SMALL("SDP"), | 2106     NULL_IF_CONFIG_SMALL("SDP"), | 
| 2101     sizeof(RTSPState), | 2107     sizeof(RTSPState), | 
| 2102     sdp_probe, | 2108     sdp_probe, | 
| 2103     sdp_read_header, | 2109     sdp_read_header, | 
| 2104     rtsp_fetch_packet, | 2110     rtsp_fetch_packet, | 
| 2105     sdp_read_close, | 2111     sdp_read_close, | 
| 2106 }; | 2112 }; | 
|  | 2113 #endif /* CONFIG_SDP_DEMUXER */ | 
|  | 2114 | 
|  | 2115 #if CONFIG_RTP_DEMUXER | 
|  | 2116 static int rtp_probe(AVProbeData *p) | 
|  | 2117 { | 
|  | 2118     if (av_strstart(p->filename, "rtp:", NULL)) | 
|  | 2119         return AVPROBE_SCORE_MAX; | 
|  | 2120     return 0; | 
|  | 2121 } | 
|  | 2122 | 
|  | 2123 static int rtp_read_header(AVFormatContext *s, | 
|  | 2124                            AVFormatParameters *ap) | 
|  | 2125 { | 
|  | 2126     uint8_t recvbuf[1500]; | 
|  | 2127     char host[500], sdp[500]; | 
|  | 2128     int ret, port; | 
|  | 2129     URLContext* in = NULL; | 
|  | 2130     int payload_type; | 
|  | 2131     AVCodecContext codec; | 
|  | 2132     struct sockaddr_storage addr; | 
|  | 2133     ByteIOContext pb; | 
|  | 2134     socklen_t addrlen = sizeof(addr); | 
|  | 2135 | 
|  | 2136     if (!ff_network_init()) | 
|  | 2137         return AVERROR(EIO); | 
|  | 2138 | 
|  | 2139     ret = url_open(&in, s->filename, URL_RDONLY); | 
|  | 2140     if (ret) | 
|  | 2141         goto fail; | 
|  | 2142 | 
|  | 2143     while (1) { | 
|  | 2144         ret = url_read(in, recvbuf, sizeof(recvbuf)); | 
|  | 2145         if (ret == AVERROR(EAGAIN)) | 
|  | 2146             continue; | 
|  | 2147         if (ret < 0) | 
|  | 2148             goto fail; | 
|  | 2149         if (ret < 12) { | 
|  | 2150             av_log(s, AV_LOG_WARNING, "Received too short packet\n"); | 
|  | 2151             continue; | 
|  | 2152         } | 
|  | 2153 | 
|  | 2154         if ((recvbuf[0] & 0xc0) != 0x80) { | 
|  | 2155             av_log(s, AV_LOG_WARNING, "Unsupported RTP version packet " | 
|  | 2156                                       "received\n"); | 
|  | 2157             continue; | 
|  | 2158         } | 
|  | 2159 | 
|  | 2160         payload_type = recvbuf[1] & 0x7f; | 
|  | 2161         break; | 
|  | 2162     } | 
|  | 2163     getsockname(url_get_file_handle(in), (struct sockaddr*) &addr, &addrlen); | 
|  | 2164     url_close(in); | 
|  | 2165     in = NULL; | 
|  | 2166 | 
|  | 2167     memset(&codec, 0, sizeof(codec)); | 
|  | 2168     if (ff_rtp_get_codec_info(&codec, payload_type)) { | 
|  | 2169         av_log(s, AV_LOG_ERROR, "Unable to receive RTP payload type %d " | 
|  | 2170                                 "without an SDP file describing it\n", | 
|  | 2171                                  payload_type); | 
|  | 2172         goto fail; | 
|  | 2173     } | 
|  | 2174     if (codec.codec_type != AVMEDIA_TYPE_DATA) { | 
|  | 2175         av_log(s, AV_LOG_WARNING, "Guessing on RTP content - if not received " | 
|  | 2176                                   "properly you need an SDP file " | 
|  | 2177                                   "describing it\n"); | 
|  | 2178     } | 
|  | 2179 | 
|  | 2180     av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, | 
|  | 2181                  NULL, 0, s->filename); | 
|  | 2182 | 
|  | 2183     snprintf(sdp, sizeof(sdp), | 
|  | 2184              "v=0\r\nc=IN IP%d %s\r\nm=%s %d RTP/AVP %d\r\n", | 
|  | 2185              addr.ss_family == AF_INET ? 4 : 6, host, | 
|  | 2186              codec.codec_type == AVMEDIA_TYPE_DATA  ? "application" : | 
|  | 2187              codec.codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio", | 
|  | 2188              port, payload_type); | 
|  | 2189     av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sdp); | 
|  | 2190 | 
|  | 2191     init_put_byte(&pb, sdp, strlen(sdp), 0, NULL, NULL, NULL, NULL); | 
|  | 2192     s->pb = &pb; | 
|  | 2193 | 
|  | 2194     /* sdp_read_header initializes this again */ | 
|  | 2195     ff_network_close(); | 
|  | 2196 | 
|  | 2197     ret = sdp_read_header(s, ap); | 
|  | 2198     s->pb = NULL; | 
|  | 2199     return ret; | 
|  | 2200 | 
|  | 2201 fail: | 
|  | 2202     if (in) | 
|  | 2203         url_close(in); | 
|  | 2204     ff_network_close(); | 
|  | 2205     return ret; | 
|  | 2206 } | 
|  | 2207 | 
|  | 2208 AVInputFormat rtp_demuxer = { | 
|  | 2209     "rtp", | 
|  | 2210     NULL_IF_CONFIG_SMALL("RTP input format"), | 
|  | 2211     sizeof(RTSPState), | 
|  | 2212     rtp_probe, | 
|  | 2213     rtp_read_header, | 
|  | 2214     rtsp_fetch_packet, | 
|  | 2215     sdp_read_close, | 
|  | 2216     .flags = AVFMT_NOFILE, | 
|  | 2217 }; | 
|  | 2218 #endif /* CONFIG_RTP_DEMUXER */ | 
|  | 2219 | 
| OLD | NEW | 
|---|