• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavformat/rtsp.c

Go to the documentation of this file.
00001 /*
00002  * RTSP/SDP client
00003  * Copyright (c) 2002 Fabrice Bellard
00004  *
00005  * This file is part of Libav.
00006  *
00007  * Libav is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * Libav is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with Libav; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include "libavutil/base64.h"
00023 #include "libavutil/avstring.h"
00024 #include "libavutil/intreadwrite.h"
00025 #include "libavutil/mathematics.h"
00026 #include "libavutil/parseutils.h"
00027 #include "libavutil/random_seed.h"
00028 #include "libavutil/dict.h"
00029 #include "libavutil/opt.h"
00030 #include "avformat.h"
00031 #include "avio_internal.h"
00032 
00033 #include <sys/time.h>
00034 #if HAVE_POLL_H
00035 #include <poll.h>
00036 #endif
00037 #include "internal.h"
00038 #include "network.h"
00039 #include "os_support.h"
00040 #include "http.h"
00041 #include "rtsp.h"
00042 
00043 #include "rtpdec.h"
00044 #include "rdt.h"
00045 #include "rtpdec_formats.h"
00046 #include "rtpenc_chain.h"
00047 #include "url.h"
00048 #include "rtpenc.h"
00049 
00050 //#define DEBUG
00051 
00052 /* Timeout values for socket poll, in ms,
00053  * and read_packet(), in seconds  */
00054 #define POLL_TIMEOUT_MS 100
00055 #define READ_PACKET_TIMEOUT_S 10
00056 #define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / POLL_TIMEOUT_MS
00057 #define SDP_MAX_SIZE 16384
00058 #define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH
00059 
00060 #define OFFSET(x) offsetof(RTSPState, x)
00061 #define DEC AV_OPT_FLAG_DECODING_PARAM
00062 #define ENC AV_OPT_FLAG_ENCODING_PARAM
00063 
00064 #define RTSP_FLAG_OPTS(name, longname) \
00065     { name, longname, OFFSET(rtsp_flags), AV_OPT_TYPE_FLAGS, {0}, INT_MIN, INT_MAX, DEC, "rtsp_flags" }, \
00066     { "filter_src", "Only receive packets from the negotiated peer IP", 0, AV_OPT_TYPE_CONST, {RTSP_FLAG_FILTER_SRC}, 0, 0, DEC, "rtsp_flags" }
00067 
00068 #define RTSP_MEDIATYPE_OPTS(name, longname) \
00069     { name, longname, OFFSET(media_type_mask), AV_OPT_TYPE_FLAGS, { (1 << (AVMEDIA_TYPE_DATA+1)) - 1 }, INT_MIN, INT_MAX, DEC, "allowed_media_types" }, \
00070     { "video", "Video", 0, AV_OPT_TYPE_CONST, {1 << AVMEDIA_TYPE_VIDEO}, 0, 0, DEC, "allowed_media_types" }, \
00071     { "audio", "Audio", 0, AV_OPT_TYPE_CONST, {1 << AVMEDIA_TYPE_AUDIO}, 0, 0, DEC, "allowed_media_types" }, \
00072     { "data", "Data", 0, AV_OPT_TYPE_CONST, {1 << AVMEDIA_TYPE_DATA}, 0, 0, DEC, "allowed_media_types" }
00073 
00074 const AVOption ff_rtsp_options[] = {
00075     { "initial_pause",  "Don't start playing the stream immediately", OFFSET(initial_pause), AV_OPT_TYPE_INT, {0}, 0, 1, DEC },
00076     FF_RTP_FLAG_OPTS(RTSPState, rtp_muxer_flags),
00077     { "rtsp_transport", "RTSP transport protocols", OFFSET(lower_transport_mask), AV_OPT_TYPE_FLAGS, {0}, INT_MIN, INT_MAX, DEC|ENC, "rtsp_transport" }, \
00078     { "udp", "UDP", 0, AV_OPT_TYPE_CONST, {1 << RTSP_LOWER_TRANSPORT_UDP}, 0, 0, DEC|ENC, "rtsp_transport" }, \
00079     { "tcp", "TCP", 0, AV_OPT_TYPE_CONST, {1 << RTSP_LOWER_TRANSPORT_TCP}, 0, 0, DEC|ENC, "rtsp_transport" }, \
00080     { "udp_multicast", "UDP multicast", 0, AV_OPT_TYPE_CONST, {1 << RTSP_LOWER_TRANSPORT_UDP_MULTICAST}, 0, 0, DEC, "rtsp_transport" },
00081     { "http", "HTTP tunneling", 0, AV_OPT_TYPE_CONST, {(1 << RTSP_LOWER_TRANSPORT_HTTP)}, 0, 0, DEC, "rtsp_transport" },
00082     RTSP_FLAG_OPTS("rtsp_flags", "RTSP flags"),
00083     RTSP_MEDIATYPE_OPTS("allowed_media_types", "Media types to accept from the server"),
00084     { NULL },
00085 };
00086 
00087 static const AVOption sdp_options[] = {
00088     RTSP_FLAG_OPTS("sdp_flags", "SDP flags"),
00089     RTSP_MEDIATYPE_OPTS("allowed_media_types", "Media types to accept from the server"),
00090     { NULL },
00091 };
00092 
00093 static const AVOption rtp_options[] = {
00094     RTSP_FLAG_OPTS("rtp_flags", "RTP flags"),
00095     { NULL },
00096 };
00097 
00098 static void get_word_until_chars(char *buf, int buf_size,
00099                                  const char *sep, const char **pp)
00100 {
00101     const char *p;
00102     char *q;
00103 
00104     p = *pp;
00105     p += strspn(p, SPACE_CHARS);
00106     q = buf;
00107     while (!strchr(sep, *p) && *p != '\0') {
00108         if ((q - buf) < buf_size - 1)
00109             *q++ = *p;
00110         p++;
00111     }
00112     if (buf_size > 0)
00113         *q = '\0';
00114     *pp = p;
00115 }
00116 
00117 static void get_word_sep(char *buf, int buf_size, const char *sep,
00118                          const char **pp)
00119 {
00120     if (**pp == '/') (*pp)++;
00121     get_word_until_chars(buf, buf_size, sep, pp);
00122 }
00123 
00124 static void get_word(char *buf, int buf_size, const char **pp)
00125 {
00126     get_word_until_chars(buf, buf_size, SPACE_CHARS, pp);
00127 }
00128 
00133 static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end)
00134 {
00135     char buf[256];
00136 
00137     p += strspn(p, SPACE_CHARS);
00138     if (!av_stristart(p, "npt=", &p))
00139         return;
00140 
00141     *start = AV_NOPTS_VALUE;
00142     *end = AV_NOPTS_VALUE;
00143 
00144     get_word_sep(buf, sizeof(buf), "-", &p);
00145     av_parse_time(start, buf, 1);
00146     if (*p == '-') {
00147         p++;
00148         get_word_sep(buf, sizeof(buf), "-", &p);
00149         av_parse_time(end, buf, 1);
00150     }
00151 //    av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start);
00152 //    av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end);
00153 }
00154 
00155 static int get_sockaddr(const char *buf, struct sockaddr_storage *sock)
00156 {
00157     struct addrinfo hints, *ai = NULL;
00158     memset(&hints, 0, sizeof(hints));
00159     hints.ai_flags = AI_NUMERICHOST;
00160     if (getaddrinfo(buf, NULL, &hints, &ai))
00161         return -1;
00162     memcpy(sock, ai->ai_addr, FFMIN(sizeof(*sock), ai->ai_addrlen));
00163     freeaddrinfo(ai);
00164     return 0;
00165 }
00166 
00167 #if CONFIG_RTPDEC
00168 static void init_rtp_handler(RTPDynamicProtocolHandler *handler,
00169                              RTSPStream *rtsp_st, AVCodecContext *codec)
00170 {
00171     if (!handler)
00172         return;
00173     codec->codec_id          = handler->codec_id;
00174     rtsp_st->dynamic_handler = handler;
00175     if (handler->alloc) {
00176         rtsp_st->dynamic_protocol_context = handler->alloc();
00177         if (!rtsp_st->dynamic_protocol_context)
00178             rtsp_st->dynamic_handler = NULL;
00179     }
00180 }
00181 
00182 /* parse the rtpmap description: <codec_name>/<clock_rate>[/<other params>] */
00183 static int sdp_parse_rtpmap(AVFormatContext *s,
00184                             AVStream *st, RTSPStream *rtsp_st,
00185                             int payload_type, const char *p)
00186 {
00187     AVCodecContext *codec = st->codec;
00188     char buf[256];
00189     int i;
00190     AVCodec *c;
00191     const char *c_name;
00192 
00193     /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and
00194      * see if we can handle this kind of payload.
00195      * The space should normally not be there but some Real streams or
00196      * particular servers ("RealServer Version 6.1.3.970", see issue 1658)
00197      * have a trailing space. */
00198     get_word_sep(buf, sizeof(buf), "/ ", &p);
00199     if (payload_type >= RTP_PT_PRIVATE) {
00200         RTPDynamicProtocolHandler *handler =
00201             ff_rtp_handler_find_by_name(buf, codec->codec_type);
00202         init_rtp_handler(handler, rtsp_st, codec);
00203         /* If no dynamic handler was found, check with the list of standard
00204          * allocated types, if such a stream for some reason happens to
00205          * use a private payload type. This isn't handled in rtpdec.c, since
00206          * the format name from the rtpmap line never is passed into rtpdec. */
00207         if (!rtsp_st->dynamic_handler)
00208             codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
00209     } else {
00210         /* We are in a standard case
00211          * (from http://www.iana.org/assignments/rtp-parameters). */
00212         /* search into AVRtpPayloadTypes[] */
00213         codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
00214     }
00215 
00216     c = avcodec_find_decoder(codec->codec_id);
00217     if (c && c->name)
00218         c_name = c->name;
00219     else
00220         c_name = "(null)";
00221 
00222     get_word_sep(buf, sizeof(buf), "/", &p);
00223     i = atoi(buf);
00224     switch (codec->codec_type) {
00225     case AVMEDIA_TYPE_AUDIO:
00226         av_log(s, AV_LOG_DEBUG, "audio codec set to: %s\n", c_name);
00227         codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE;
00228         codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS;
00229         if (i > 0) {
00230             codec->sample_rate = i;
00231             avpriv_set_pts_info(st, 32, 1, codec->sample_rate);
00232             get_word_sep(buf, sizeof(buf), "/", &p);
00233             i = atoi(buf);
00234             if (i > 0)
00235                 codec->channels = i;
00236             // TODO: there is a bug here; if it is a mono stream, and
00237             // less than 22000Hz, faad upconverts to stereo and twice
00238             // the frequency.  No problem, but the sample rate is being
00239             // set here by the sdp line. Patch on its way. (rdm)
00240         }
00241         av_log(s, AV_LOG_DEBUG, "audio samplerate set to: %i\n",
00242                codec->sample_rate);
00243         av_log(s, AV_LOG_DEBUG, "audio channels set to: %i\n",
00244                codec->channels);
00245         break;
00246     case AVMEDIA_TYPE_VIDEO:
00247         av_log(s, AV_LOG_DEBUG, "video codec set to: %s\n", c_name);
00248         if (i > 0)
00249             avpriv_set_pts_info(st, 32, 1, i);
00250         break;
00251     default:
00252         break;
00253     }
00254     if (rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->init)
00255         rtsp_st->dynamic_handler->init(s, st->index,
00256                                        rtsp_st->dynamic_protocol_context);
00257     return 0;
00258 }
00259 
00260 /* parse the attribute line from the fmtp a line of an sdp response. This
00261  * is broken out as a function because it is used in rtp_h264.c, which is
00262  * forthcoming. */
00263 int ff_rtsp_next_attr_and_value(const char **p, char *attr, int attr_size,
00264                                 char *value, int value_size)
00265 {
00266     *p += strspn(*p, SPACE_CHARS);
00267     if (**p) {
00268         get_word_sep(attr, attr_size, "=", p);
00269         if (**p == '=')
00270             (*p)++;
00271         get_word_sep(value, value_size, ";", p);
00272         if (**p == ';')
00273             (*p)++;
00274         return 1;
00275     }
00276     return 0;
00277 }
00278 
00279 typedef struct SDPParseState {
00280     /* SDP only */
00281     struct sockaddr_storage default_ip;
00282     int            default_ttl;
00283     int            skip_media;  
00284 } SDPParseState;
00285 
00286 static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
00287                            int letter, const char *buf)
00288 {
00289     RTSPState *rt = s->priv_data;
00290     char buf1[64], st_type[64];
00291     const char *p;
00292     enum AVMediaType codec_type;
00293     int payload_type, i;
00294     AVStream *st;
00295     RTSPStream *rtsp_st;
00296     struct sockaddr_storage sdp_ip;
00297     int ttl;
00298 
00299     av_dlog(s, "sdp: %c='%s'\n", letter, buf);
00300 
00301     p = buf;
00302     if (s1->skip_media && letter != 'm')
00303         return;
00304     switch (letter) {
00305     case 'c':
00306         get_word(buf1, sizeof(buf1), &p);
00307         if (strcmp(buf1, "IN") != 0)
00308             return;
00309         get_word(buf1, sizeof(buf1), &p);
00310         if (strcmp(buf1, "IP4") && strcmp(buf1, "IP6"))
00311             return;
00312         get_word_sep(buf1, sizeof(buf1), "/", &p);
00313         if (get_sockaddr(buf1, &sdp_ip))
00314             return;
00315         ttl = 16;
00316         if (*p == '/') {
00317             p++;
00318             get_word_sep(buf1, sizeof(buf1), "/", &p);
00319             ttl = atoi(buf1);
00320         }
00321         if (s->nb_streams == 0) {
00322             s1->default_ip = sdp_ip;
00323             s1->default_ttl = ttl;
00324         } else {
00325             rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
00326             rtsp_st->sdp_ip = sdp_ip;
00327             rtsp_st->sdp_ttl = ttl;
00328         }
00329         break;
00330     case 's':
00331         av_dict_set(&s->metadata, "title", p, 0);
00332         break;
00333     case 'i':
00334         if (s->nb_streams == 0) {
00335             av_dict_set(&s->metadata, "comment", p, 0);
00336             break;
00337         }
00338         break;
00339     case 'm':
00340         /* new stream */
00341         s1->skip_media = 0;
00342         codec_type = AVMEDIA_TYPE_UNKNOWN;
00343         get_word(st_type, sizeof(st_type), &p);
00344         if (!strcmp(st_type, "audio")) {
00345             codec_type = AVMEDIA_TYPE_AUDIO;
00346         } else if (!strcmp(st_type, "video")) {
00347             codec_type = AVMEDIA_TYPE_VIDEO;
00348         } else if (!strcmp(st_type, "application")) {
00349             codec_type = AVMEDIA_TYPE_DATA;
00350         }
00351         if (codec_type == AVMEDIA_TYPE_UNKNOWN || !(rt->media_type_mask & (1 << codec_type))) {
00352             s1->skip_media = 1;
00353             return;
00354         }
00355         rtsp_st = av_mallocz(sizeof(RTSPStream));
00356         if (!rtsp_st)
00357             return;
00358         rtsp_st->stream_index = -1;
00359         dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st);
00360 
00361         rtsp_st->sdp_ip = s1->default_ip;
00362         rtsp_st->sdp_ttl = s1->default_ttl;
00363 
00364         get_word(buf1, sizeof(buf1), &p); /* port */
00365         rtsp_st->sdp_port = atoi(buf1);
00366 
00367         get_word(buf1, sizeof(buf1), &p); /* protocol (ignored) */
00368 
00369         /* XXX: handle list of formats */
00370         get_word(buf1, sizeof(buf1), &p); /* format list */
00371         rtsp_st->sdp_payload_type = atoi(buf1);
00372 
00373         if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
00374             /* no corresponding stream */
00375         } else {
00376             st = avformat_new_stream(s, NULL);
00377             if (!st)
00378                 return;
00379             st->id = rt->nb_rtsp_streams - 1;
00380             rtsp_st->stream_index = st->index;
00381             st->codec->codec_type = codec_type;
00382             if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) {
00383                 RTPDynamicProtocolHandler *handler;
00384                 /* if standard payload type, we can find the codec right now */
00385                 ff_rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type);
00386                 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
00387                     st->codec->sample_rate > 0)
00388                     avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate);
00389                 /* Even static payload types may need a custom depacketizer */
00390                 handler = ff_rtp_handler_find_by_id(
00391                               rtsp_st->sdp_payload_type, st->codec->codec_type);
00392                 init_rtp_handler(handler, rtsp_st, st->codec);
00393                 if (handler && handler->init)
00394                     handler->init(s, st->index,
00395                                   rtsp_st->dynamic_protocol_context);
00396             }
00397         }
00398         /* put a default control url */
00399         av_strlcpy(rtsp_st->control_url, rt->control_uri,
00400                    sizeof(rtsp_st->control_url));
00401         break;
00402     case 'a':
00403         if (av_strstart(p, "control:", &p)) {
00404             if (s->nb_streams == 0) {
00405                 if (!strncmp(p, "rtsp://", 7))
00406                     av_strlcpy(rt->control_uri, p,
00407                                sizeof(rt->control_uri));
00408             } else {
00409                 char proto[32];
00410                 /* get the control url */
00411                 rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
00412 
00413                 /* XXX: may need to add full url resolution */
00414                 av_url_split(proto, sizeof(proto), NULL, 0, NULL, 0,
00415                              NULL, NULL, 0, p);
00416                 if (proto[0] == '\0') {
00417                     /* relative control URL */
00418                     if (rtsp_st->control_url[strlen(rtsp_st->control_url)-1]!='/')
00419                     av_strlcat(rtsp_st->control_url, "/",
00420                                sizeof(rtsp_st->control_url));
00421                     av_strlcat(rtsp_st->control_url, p,
00422                                sizeof(rtsp_st->control_url));
00423                 } else
00424                     av_strlcpy(rtsp_st->control_url, p,
00425                                sizeof(rtsp_st->control_url));
00426             }
00427         } else if (av_strstart(p, "rtpmap:", &p) && s->nb_streams > 0) {
00428             /* NOTE: rtpmap is only supported AFTER the 'm=' tag */
00429             get_word(buf1, sizeof(buf1), &p);
00430             payload_type = atoi(buf1);
00431             st = s->streams[s->nb_streams - 1];
00432             rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
00433             sdp_parse_rtpmap(s, st, rtsp_st, payload_type, p);
00434         } else if (av_strstart(p, "fmtp:", &p) ||
00435                    av_strstart(p, "framesize:", &p)) {
00436             /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */
00437             // let dynamic protocol handlers have a stab at the line.
00438             get_word(buf1, sizeof(buf1), &p);
00439             payload_type = atoi(buf1);
00440             for (i = 0; i < rt->nb_rtsp_streams; i++) {
00441                 rtsp_st = rt->rtsp_streams[i];
00442                 if (rtsp_st->sdp_payload_type == payload_type &&
00443                     rtsp_st->dynamic_handler &&
00444                     rtsp_st->dynamic_handler->parse_sdp_a_line)
00445                     rtsp_st->dynamic_handler->parse_sdp_a_line(s, i,
00446                         rtsp_st->dynamic_protocol_context, buf);
00447             }
00448         } else if (av_strstart(p, "range:", &p)) {
00449             int64_t start, end;
00450 
00451             // this is so that seeking on a streamed file can work.
00452             rtsp_parse_range_npt(p, &start, &end);
00453             s->start_time = start;
00454             /* AV_NOPTS_VALUE means live broadcast (and can't seek) */
00455             s->duration   = (end == AV_NOPTS_VALUE) ?
00456                             AV_NOPTS_VALUE : end - start;
00457         } else if (av_strstart(p, "IsRealDataType:integer;",&p)) {
00458             if (atoi(p) == 1)
00459                 rt->transport = RTSP_TRANSPORT_RDT;
00460         } else if (av_strstart(p, "SampleRate:integer;", &p) &&
00461                    s->nb_streams > 0) {
00462             st = s->streams[s->nb_streams - 1];
00463             st->codec->sample_rate = atoi(p);
00464         } else {
00465             if (rt->server_type == RTSP_SERVER_WMS)
00466                 ff_wms_parse_sdp_a_line(s, p);
00467             if (s->nb_streams > 0) {
00468                 if (rt->server_type == RTSP_SERVER_REAL)
00469                     ff_real_parse_sdp_a_line(s, s->nb_streams - 1, p);
00470 
00471                 rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
00472                 if (rtsp_st->dynamic_handler &&
00473                     rtsp_st->dynamic_handler->parse_sdp_a_line)
00474                     rtsp_st->dynamic_handler->parse_sdp_a_line(s,
00475                         s->nb_streams - 1,
00476                         rtsp_st->dynamic_protocol_context, buf);
00477             }
00478         }
00479         break;
00480     }
00481 }
00482 
00483 int ff_sdp_parse(AVFormatContext *s, const char *content)
00484 {
00485     RTSPState *rt = s->priv_data;
00486     const char *p;
00487     int letter;
00488     /* Some SDP lines, particularly for Realmedia or ASF RTSP streams,
00489      * contain long SDP lines containing complete ASF Headers (several
00490      * kB) or arrays of MDPR (RM stream descriptor) headers plus
00491      * "rulebooks" describing their properties. Therefore, the SDP line
00492      * buffer is large.
00493      *
00494      * The Vorbis FMTP line can be up to 16KB - see xiph_parse_sdp_line
00495      * in rtpdec_xiph.c. */
00496     char buf[16384], *q;
00497     SDPParseState sdp_parse_state, *s1 = &sdp_parse_state;
00498 
00499     memset(s1, 0, sizeof(SDPParseState));
00500     p = content;
00501     for (;;) {
00502         p += strspn(p, SPACE_CHARS);
00503         letter = *p;
00504         if (letter == '\0')
00505             break;
00506         p++;
00507         if (*p != '=')
00508             goto next_line;
00509         p++;
00510         /* get the content */
00511         q = buf;
00512         while (*p != '\n' && *p != '\r' && *p != '\0') {
00513             if ((q - buf) < sizeof(buf) - 1)
00514                 *q++ = *p;
00515             p++;
00516         }
00517         *q = '\0';
00518         sdp_parse_line(s, s1, letter, buf);
00519     next_line:
00520         while (*p != '\n' && *p != '\0')
00521             p++;
00522         if (*p == '\n')
00523             p++;
00524     }
00525     rt->p = av_malloc(sizeof(struct pollfd)*2*(rt->nb_rtsp_streams+1));
00526     if (!rt->p) return AVERROR(ENOMEM);
00527     return 0;
00528 }
00529 #endif /* CONFIG_RTPDEC */
00530 
00531 void ff_rtsp_undo_setup(AVFormatContext *s)
00532 {
00533     RTSPState *rt = s->priv_data;
00534     int i;
00535 
00536     for (i = 0; i < rt->nb_rtsp_streams; i++) {
00537         RTSPStream *rtsp_st = rt->rtsp_streams[i];
00538         if (!rtsp_st)
00539             continue;
00540         if (rtsp_st->transport_priv) {
00541             if (s->oformat) {
00542                 AVFormatContext *rtpctx = rtsp_st->transport_priv;
00543                 av_write_trailer(rtpctx);
00544                 if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
00545                     uint8_t *ptr;
00546                     avio_close_dyn_buf(rtpctx->pb, &ptr);
00547                     av_free(ptr);
00548                 } else {
00549                     avio_close(rtpctx->pb);
00550                 }
00551                 avformat_free_context(rtpctx);
00552             } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC)
00553                 ff_rdt_parse_close(rtsp_st->transport_priv);
00554             else if (CONFIG_RTPDEC)
00555                 ff_rtp_parse_close(rtsp_st->transport_priv);
00556         }
00557         rtsp_st->transport_priv = NULL;
00558         if (rtsp_st->rtp_handle)
00559             ffurl_close(rtsp_st->rtp_handle);
00560         rtsp_st->rtp_handle = NULL;
00561     }
00562 }
00563 
00564 /* close and free RTSP streams */
00565 void ff_rtsp_close_streams(AVFormatContext *s)
00566 {
00567     RTSPState *rt = s->priv_data;
00568     int i;
00569     RTSPStream *rtsp_st;
00570 
00571     ff_rtsp_undo_setup(s);
00572     for (i = 0; i < rt->nb_rtsp_streams; i++) {
00573         rtsp_st = rt->rtsp_streams[i];
00574         if (rtsp_st) {
00575             if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context)
00576                 rtsp_st->dynamic_handler->free(
00577                     rtsp_st->dynamic_protocol_context);
00578             av_free(rtsp_st);
00579         }
00580     }
00581     av_free(rt->rtsp_streams);
00582     if (rt->asf_ctx) {
00583         avformat_close_input(&rt->asf_ctx);
00584     }
00585     av_free(rt->p);
00586     av_free(rt->recvbuf);
00587 }
00588 
00589 static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
00590 {
00591     RTSPState *rt = s->priv_data;
00592     AVStream *st = NULL;
00593 
00594     /* open the RTP context */
00595     if (rtsp_st->stream_index >= 0)
00596         st = s->streams[rtsp_st->stream_index];
00597     if (!st)
00598         s->ctx_flags |= AVFMTCTX_NOHEADER;
00599 
00600     if (s->oformat && CONFIG_RTSP_MUXER) {
00601         rtsp_st->transport_priv = ff_rtp_chain_mux_open(s, st,
00602                                       rtsp_st->rtp_handle,
00603                                       RTSP_TCP_MAX_PACKET_SIZE);
00604         /* Ownership of rtp_handle is passed to the rtp mux context */
00605         rtsp_st->rtp_handle = NULL;
00606     } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC)
00607         rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
00608                                             rtsp_st->dynamic_protocol_context,
00609                                             rtsp_st->dynamic_handler);
00610     else if (CONFIG_RTPDEC)
00611         rtsp_st->transport_priv = ff_rtp_parse_open(s, st, rtsp_st->rtp_handle,
00612                                          rtsp_st->sdp_payload_type,
00613             (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP || !s->max_delay)
00614             ? 0 : RTP_REORDER_QUEUE_DEFAULT_SIZE);
00615 
00616     if (!rtsp_st->transport_priv) {
00617          return AVERROR(ENOMEM);
00618     } else if (rt->transport != RTSP_TRANSPORT_RDT && CONFIG_RTPDEC) {
00619         if (rtsp_st->dynamic_handler) {
00620             ff_rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
00621                                               rtsp_st->dynamic_protocol_context,
00622                                               rtsp_st->dynamic_handler);
00623         }
00624     }
00625 
00626     return 0;
00627 }
00628 
00629 #if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER
00630 static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
00631 {
00632     const char *p;
00633     int v;
00634 
00635     p = *pp;
00636     p += strspn(p, SPACE_CHARS);
00637     v = strtol(p, (char **)&p, 10);
00638     if (*p == '-') {
00639         p++;
00640         *min_ptr = v;
00641         v = strtol(p, (char **)&p, 10);
00642         *max_ptr = v;
00643     } else {
00644         *min_ptr = v;
00645         *max_ptr = v;
00646     }
00647     *pp = p;
00648 }
00649 
00650 /* XXX: only one transport specification is parsed */
00651 static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p)
00652 {
00653     char transport_protocol[16];
00654     char profile[16];
00655     char lower_transport[16];
00656     char parameter[16];
00657     RTSPTransportField *th;
00658     char buf[256];
00659 
00660     reply->nb_transports = 0;
00661 
00662     for (;;) {
00663         p += strspn(p, SPACE_CHARS);
00664         if (*p == '\0')
00665             break;
00666 
00667         th = &reply->transports[reply->nb_transports];
00668 
00669         get_word_sep(transport_protocol, sizeof(transport_protocol),
00670                      "/", &p);
00671         if (!av_strcasecmp (transport_protocol, "rtp")) {
00672             get_word_sep(profile, sizeof(profile), "/;,", &p);
00673             lower_transport[0] = '\0';
00674             /* rtp/avp/<protocol> */
00675             if (*p == '/') {
00676                 get_word_sep(lower_transport, sizeof(lower_transport),
00677                              ";,", &p);
00678             }
00679             th->transport = RTSP_TRANSPORT_RTP;
00680         } else if (!av_strcasecmp (transport_protocol, "x-pn-tng") ||
00681                    !av_strcasecmp (transport_protocol, "x-real-rdt")) {
00682             /* x-pn-tng/<protocol> */
00683             get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p);
00684             profile[0] = '\0';
00685             th->transport = RTSP_TRANSPORT_RDT;
00686         }
00687         if (!av_strcasecmp(lower_transport, "TCP"))
00688             th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
00689         else
00690             th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
00691 
00692         if (*p == ';')
00693             p++;
00694         /* get each parameter */
00695         while (*p != '\0' && *p != ',') {
00696             get_word_sep(parameter, sizeof(parameter), "=;,", &p);
00697             if (!strcmp(parameter, "port")) {
00698                 if (*p == '=') {
00699                     p++;
00700                     rtsp_parse_range(&th->port_min, &th->port_max, &p);
00701                 }
00702             } else if (!strcmp(parameter, "client_port")) {
00703                 if (*p == '=') {
00704                     p++;
00705                     rtsp_parse_range(&th->client_port_min,
00706                                      &th->client_port_max, &p);
00707                 }
00708             } else if (!strcmp(parameter, "server_port")) {
00709                 if (*p == '=') {
00710                     p++;
00711                     rtsp_parse_range(&th->server_port_min,
00712                                      &th->server_port_max, &p);
00713                 }
00714             } else if (!strcmp(parameter, "interleaved")) {
00715                 if (*p == '=') {
00716                     p++;
00717                     rtsp_parse_range(&th->interleaved_min,
00718                                      &th->interleaved_max, &p);
00719                 }
00720             } else if (!strcmp(parameter, "multicast")) {
00721                 if (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP)
00722                     th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST;
00723             } else if (!strcmp(parameter, "ttl")) {
00724                 if (*p == '=') {
00725                     p++;
00726                     th->ttl = strtol(p, (char **)&p, 10);
00727                 }
00728             } else if (!strcmp(parameter, "destination")) {
00729                 if (*p == '=') {
00730                     p++;
00731                     get_word_sep(buf, sizeof(buf), ";,", &p);
00732                     get_sockaddr(buf, &th->destination);
00733                 }
00734             } else if (!strcmp(parameter, "source")) {
00735                 if (*p == '=') {
00736                     p++;
00737                     get_word_sep(buf, sizeof(buf), ";,", &p);
00738                     av_strlcpy(th->source, buf, sizeof(th->source));
00739                 }
00740             }
00741 
00742             while (*p != ';' && *p != '\0' && *p != ',')
00743                 p++;
00744             if (*p == ';')
00745                 p++;
00746         }
00747         if (*p == ',')
00748             p++;
00749 
00750         reply->nb_transports++;
00751     }
00752 }
00753 
00754 static void handle_rtp_info(RTSPState *rt, const char *url,
00755                             uint32_t seq, uint32_t rtptime)
00756 {
00757     int i;
00758     if (!rtptime || !url[0])
00759         return;
00760     if (rt->transport != RTSP_TRANSPORT_RTP)
00761         return;
00762     for (i = 0; i < rt->nb_rtsp_streams; i++) {
00763         RTSPStream *rtsp_st = rt->rtsp_streams[i];
00764         RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
00765         if (!rtpctx)
00766             continue;
00767         if (!strcmp(rtsp_st->control_url, url)) {
00768             rtpctx->base_timestamp = rtptime;
00769             break;
00770         }
00771     }
00772 }
00773 
00774 static void rtsp_parse_rtp_info(RTSPState *rt, const char *p)
00775 {
00776     int read = 0;
00777     char key[20], value[1024], url[1024] = "";
00778     uint32_t seq = 0, rtptime = 0;
00779 
00780     for (;;) {
00781         p += strspn(p, SPACE_CHARS);
00782         if (!*p)
00783             break;
00784         get_word_sep(key, sizeof(key), "=", &p);
00785         if (*p != '=')
00786             break;
00787         p++;
00788         get_word_sep(value, sizeof(value), ";, ", &p);
00789         read++;
00790         if (!strcmp(key, "url"))
00791             av_strlcpy(url, value, sizeof(url));
00792         else if (!strcmp(key, "seq"))
00793             seq = strtoul(value, NULL, 10);
00794         else if (!strcmp(key, "rtptime"))
00795             rtptime = strtoul(value, NULL, 10);
00796         if (*p == ',') {
00797             handle_rtp_info(rt, url, seq, rtptime);
00798             url[0] = '\0';
00799             seq = rtptime = 0;
00800             read = 0;
00801         }
00802         if (*p)
00803             p++;
00804     }
00805     if (read > 0)
00806         handle_rtp_info(rt, url, seq, rtptime);
00807 }
00808 
00809 void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf,
00810                         RTSPState *rt, const char *method)
00811 {
00812     const char *p;
00813 
00814     /* NOTE: we do case independent match for broken servers */
00815     p = buf;
00816     if (av_stristart(p, "Session:", &p)) {
00817         int t;
00818         get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
00819         if (av_stristart(p, ";timeout=", &p) &&
00820             (t = strtol(p, NULL, 10)) > 0) {
00821             reply->timeout = t;
00822         }
00823     } else if (av_stristart(p, "Content-Length:", &p)) {
00824         reply->content_length = strtol(p, NULL, 10);
00825     } else if (av_stristart(p, "Transport:", &p)) {
00826         rtsp_parse_transport(reply, p);
00827     } else if (av_stristart(p, "CSeq:", &p)) {
00828         reply->seq = strtol(p, NULL, 10);
00829     } else if (av_stristart(p, "Range:", &p)) {
00830         rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end);
00831     } else if (av_stristart(p, "RealChallenge1:", &p)) {
00832         p += strspn(p, SPACE_CHARS);
00833         av_strlcpy(reply->real_challenge, p, sizeof(reply->real_challenge));
00834     } else if (av_stristart(p, "Server:", &p)) {
00835         p += strspn(p, SPACE_CHARS);
00836         av_strlcpy(reply->server, p, sizeof(reply->server));
00837     } else if (av_stristart(p, "Notice:", &p) ||
00838                av_stristart(p, "X-Notice:", &p)) {
00839         reply->notice = strtol(p, NULL, 10);
00840     } else if (av_stristart(p, "Location:", &p)) {
00841         p += strspn(p, SPACE_CHARS);
00842         av_strlcpy(reply->location, p , sizeof(reply->location));
00843     } else if (av_stristart(p, "WWW-Authenticate:", &p) && rt) {
00844         p += strspn(p, SPACE_CHARS);
00845         ff_http_auth_handle_header(&rt->auth_state, "WWW-Authenticate", p);
00846     } else if (av_stristart(p, "Authentication-Info:", &p) && rt) {
00847         p += strspn(p, SPACE_CHARS);
00848         ff_http_auth_handle_header(&rt->auth_state, "Authentication-Info", p);
00849     } else if (av_stristart(p, "Content-Base:", &p) && rt) {
00850         p += strspn(p, SPACE_CHARS);
00851         if (method && !strcmp(method, "DESCRIBE"))
00852             av_strlcpy(rt->control_uri, p , sizeof(rt->control_uri));
00853     } else if (av_stristart(p, "RTP-Info:", &p) && rt) {
00854         p += strspn(p, SPACE_CHARS);
00855         if (method && !strcmp(method, "PLAY"))
00856             rtsp_parse_rtp_info(rt, p);
00857     } else if (av_stristart(p, "Public:", &p) && rt) {
00858         if (strstr(p, "GET_PARAMETER") &&
00859             method && !strcmp(method, "OPTIONS"))
00860             rt->get_parameter_supported = 1;
00861     } else if (av_stristart(p, "x-Accept-Dynamic-Rate:", &p) && rt) {
00862         p += strspn(p, SPACE_CHARS);
00863         rt->accept_dynamic_rate = atoi(p);
00864     }
00865 }
00866 
00867 /* skip a RTP/TCP interleaved packet */
00868 void ff_rtsp_skip_packet(AVFormatContext *s)
00869 {
00870     RTSPState *rt = s->priv_data;
00871     int ret, len, len1;
00872     uint8_t buf[1024];
00873 
00874     ret = ffurl_read_complete(rt->rtsp_hd, buf, 3);
00875     if (ret != 3)
00876         return;
00877     len = AV_RB16(buf + 1);
00878 
00879     av_dlog(s, "skipping RTP packet len=%d\n", len);
00880 
00881     /* skip payload */
00882     while (len > 0) {
00883         len1 = len;
00884         if (len1 > sizeof(buf))
00885             len1 = sizeof(buf);
00886         ret = ffurl_read_complete(rt->rtsp_hd, buf, len1);
00887         if (ret != len1)
00888             return;
00889         len -= len1;
00890     }
00891 }
00892 
00893 int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
00894                        unsigned char **content_ptr,
00895                        int return_on_interleaved_data, const char *method)
00896 {
00897     RTSPState *rt = s->priv_data;
00898     char buf[4096], buf1[1024], *q;
00899     unsigned char ch;
00900     const char *p;
00901     int ret, content_length, line_count = 0;
00902     unsigned char *content = NULL;
00903 
00904     memset(reply, 0, sizeof(*reply));
00905 
00906     /* parse reply (XXX: use buffers) */
00907     rt->last_reply[0] = '\0';
00908     for (;;) {
00909         q = buf;
00910         for (;;) {
00911             ret = ffurl_read_complete(rt->rtsp_hd, &ch, 1);
00912             av_dlog(s, "ret=%d c=%02x [%c]\n", ret, ch, ch);
00913             if (ret != 1)
00914                 return AVERROR_EOF;
00915             if (ch == '\n')
00916                 break;
00917             if (ch == '$') {
00918                 /* XXX: only parse it if first char on line ? */
00919                 if (return_on_interleaved_data) {
00920                     return 1;
00921                 } else
00922                     ff_rtsp_skip_packet(s);
00923             } else if (ch != '\r') {
00924                 if ((q - buf) < sizeof(buf) - 1)
00925                     *q++ = ch;
00926             }
00927         }
00928         *q = '\0';
00929 
00930         av_dlog(s, "line='%s'\n", buf);
00931 
00932         /* test if last line */
00933         if (buf[0] == '\0')
00934             break;
00935         p = buf;
00936         if (line_count == 0) {
00937             /* get reply code */
00938             get_word(buf1, sizeof(buf1), &p);
00939             get_word(buf1, sizeof(buf1), &p);
00940             reply->status_code = atoi(buf1);
00941             av_strlcpy(reply->reason, p, sizeof(reply->reason));
00942         } else {
00943             ff_rtsp_parse_line(reply, p, rt, method);
00944             av_strlcat(rt->last_reply, p,    sizeof(rt->last_reply));
00945             av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply));
00946         }
00947         line_count++;
00948     }
00949 
00950     if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
00951         av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id));
00952 
00953     content_length = reply->content_length;
00954     if (content_length > 0) {
00955         /* leave some room for a trailing '\0' (useful for simple parsing) */
00956         content = av_malloc(content_length + 1);
00957         ffurl_read_complete(rt->rtsp_hd, content, content_length);
00958         content[content_length] = '\0';
00959     }
00960     if (content_ptr)
00961         *content_ptr = content;
00962     else
00963         av_free(content);
00964 
00965     if (rt->seq != reply->seq) {
00966         av_log(s, AV_LOG_WARNING, "CSeq %d expected, %d received.\n",
00967             rt->seq, reply->seq);
00968     }
00969 
00970     /* EOS */
00971     if (reply->notice == 2101 /* End-of-Stream Reached */      ||
00972         reply->notice == 2104 /* Start-of-Stream Reached */    ||
00973         reply->notice == 2306 /* Continuous Feed Terminated */) {
00974         rt->state = RTSP_STATE_IDLE;
00975     } else if (reply->notice >= 4400 && reply->notice < 5500) {
00976         return AVERROR(EIO); /* data or server error */
00977     } else if (reply->notice == 2401 /* Ticket Expired */ ||
00978              (reply->notice >= 5500 && reply->notice < 5600) /* end of term */ )
00979         return AVERROR(EPERM);
00980 
00981     return 0;
00982 }
00983 
00997 static int ff_rtsp_send_cmd_with_content_async(AVFormatContext *s,
00998                                                const char *method, const char *url,
00999                                                const char *headers,
01000                                                const unsigned char *send_content,
01001                                                int send_content_length)
01002 {
01003     RTSPState *rt = s->priv_data;
01004     char buf[4096], *out_buf;
01005     char base64buf[AV_BASE64_SIZE(sizeof(buf))];
01006 
01007     /* Add in RTSP headers */
01008     out_buf = buf;
01009     rt->seq++;
01010     snprintf(buf, sizeof(buf), "%s %s RTSP/1.0\r\n", method, url);
01011     if (headers)
01012         av_strlcat(buf, headers, sizeof(buf));
01013     av_strlcatf(buf, sizeof(buf), "CSeq: %d\r\n", rt->seq);
01014     if (rt->session_id[0] != '\0' && (!headers ||
01015         !strstr(headers, "\nIf-Match:"))) {
01016         av_strlcatf(buf, sizeof(buf), "Session: %s\r\n", rt->session_id);
01017     }
01018     if (rt->auth[0]) {
01019         char *str = ff_http_auth_create_response(&rt->auth_state,
01020                                                  rt->auth, url, method);
01021         if (str)
01022             av_strlcat(buf, str, sizeof(buf));
01023         av_free(str);
01024     }
01025     if (send_content_length > 0 && send_content)
01026         av_strlcatf(buf, sizeof(buf), "Content-Length: %d\r\n", send_content_length);
01027     av_strlcat(buf, "\r\n", sizeof(buf));
01028 
01029     /* base64 encode rtsp if tunneling */
01030     if (rt->control_transport == RTSP_MODE_TUNNEL) {
01031         av_base64_encode(base64buf, sizeof(base64buf), buf, strlen(buf));
01032         out_buf = base64buf;
01033     }
01034 
01035     av_dlog(s, "Sending:\n%s--\n", buf);
01036 
01037     ffurl_write(rt->rtsp_hd_out, out_buf, strlen(out_buf));
01038     if (send_content_length > 0 && send_content) {
01039         if (rt->control_transport == RTSP_MODE_TUNNEL) {
01040             av_log(s, AV_LOG_ERROR, "tunneling of RTSP requests "
01041                                     "with content data not supported\n");
01042             return AVERROR_PATCHWELCOME;
01043         }
01044         ffurl_write(rt->rtsp_hd_out, send_content, send_content_length);
01045     }
01046     rt->last_cmd_time = av_gettime();
01047 
01048     return 0;
01049 }
01050 
01051 int ff_rtsp_send_cmd_async(AVFormatContext *s, const char *method,
01052                            const char *url, const char *headers)
01053 {
01054     return ff_rtsp_send_cmd_with_content_async(s, method, url, headers, NULL, 0);
01055 }
01056 
01057 int ff_rtsp_send_cmd(AVFormatContext *s, const char *method, const char *url,
01058                      const char *headers, RTSPMessageHeader *reply,
01059                      unsigned char **content_ptr)
01060 {
01061     return ff_rtsp_send_cmd_with_content(s, method, url, headers, reply,
01062                                          content_ptr, NULL, 0);
01063 }
01064 
01065 int ff_rtsp_send_cmd_with_content(AVFormatContext *s,
01066                                   const char *method, const char *url,
01067                                   const char *header,
01068                                   RTSPMessageHeader *reply,
01069                                   unsigned char **content_ptr,
01070                                   const unsigned char *send_content,
01071                                   int send_content_length)
01072 {
01073     RTSPState *rt = s->priv_data;
01074     HTTPAuthType cur_auth_type;
01075     int ret;
01076 
01077 retry:
01078     cur_auth_type = rt->auth_state.auth_type;
01079     if ((ret = ff_rtsp_send_cmd_with_content_async(s, method, url, header,
01080                                                    send_content,
01081                                                    send_content_length)))
01082         return ret;
01083 
01084     if ((ret = ff_rtsp_read_reply(s, reply, content_ptr, 0, method) ) < 0)
01085         return ret;
01086 
01087     if (reply->status_code == 401 && cur_auth_type == HTTP_AUTH_NONE &&
01088         rt->auth_state.auth_type != HTTP_AUTH_NONE)
01089         goto retry;
01090 
01091     if (reply->status_code > 400){
01092         av_log(s, AV_LOG_ERROR, "method %s failed: %d%s\n",
01093                method,
01094                reply->status_code,
01095                reply->reason);
01096         av_log(s, AV_LOG_DEBUG, "%s\n", rt->last_reply);
01097     }
01098 
01099     return 0;
01100 }
01101 
01102 int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
01103                               int lower_transport, const char *real_challenge)
01104 {
01105     RTSPState *rt = s->priv_data;
01106     int rtx = 0, j, i, err, interleave = 0;
01107     RTSPStream *rtsp_st;
01108     RTSPMessageHeader reply1, *reply = &reply1;
01109     char cmd[2048];
01110     const char *trans_pref;
01111 
01112     if (rt->transport == RTSP_TRANSPORT_RDT)
01113         trans_pref = "x-pn-tng";
01114     else
01115         trans_pref = "RTP/AVP";
01116 
01117     /* default timeout: 1 minute */
01118     rt->timeout = 60;
01119 
01120     /* for each stream, make the setup request */
01121     /* XXX: we assume the same server is used for the control of each
01122      * RTSP stream */
01123 
01124     for (j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
01125         char transport[2048];
01126 
01127         /*
01128          * WMS serves all UDP data over a single connection, the RTX, which
01129          * isn't necessarily the first in the SDP but has to be the first
01130          * to be set up, else the second/third SETUP will fail with a 461.
01131          */
01132         if (lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
01133              rt->server_type == RTSP_SERVER_WMS) {
01134             if (i == 0) {
01135                 /* rtx first */
01136                 for (rtx = 0; rtx < rt->nb_rtsp_streams; rtx++) {
01137                     int len = strlen(rt->rtsp_streams[rtx]->control_url);
01138                     if (len >= 4 &&
01139                         !strcmp(rt->rtsp_streams[rtx]->control_url + len - 4,
01140                                 "/rtx"))
01141                         break;
01142                 }
01143                 if (rtx == rt->nb_rtsp_streams)
01144                     return -1; /* no RTX found */
01145                 rtsp_st = rt->rtsp_streams[rtx];
01146             } else
01147                 rtsp_st = rt->rtsp_streams[i > rtx ? i : i - 1];
01148         } else
01149             rtsp_st = rt->rtsp_streams[i];
01150 
01151         /* RTP/UDP */
01152         if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
01153             char buf[256];
01154 
01155             if (rt->server_type == RTSP_SERVER_WMS && i > 1) {
01156                 port = reply->transports[0].client_port_min;
01157                 goto have_port;
01158             }
01159 
01160             /* first try in specified port range */
01161             if (RTSP_RTP_PORT_MIN != 0) {
01162                 while (j <= RTSP_RTP_PORT_MAX) {
01163                     ff_url_join(buf, sizeof(buf), "rtp", NULL, host, -1,
01164                                 "?localport=%d", j);
01165                     /* we will use two ports per rtp stream (rtp and rtcp) */
01166                     j += 2;
01167                     if (ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE,
01168                                    &s->interrupt_callback, NULL) == 0)
01169                         goto rtp_opened;
01170                 }
01171             }
01172 
01173             av_log(s, AV_LOG_ERROR, "Unable to open an input RTP port\n");
01174             err = AVERROR(EIO);
01175             goto fail;
01176 
01177         rtp_opened:
01178             port = ff_rtp_get_local_rtp_port(rtsp_st->rtp_handle);
01179         have_port:
01180             snprintf(transport, sizeof(transport) - 1,
01181                      "%s/UDP;", trans_pref);
01182             if (rt->server_type != RTSP_SERVER_REAL)
01183                 av_strlcat(transport, "unicast;", sizeof(transport));
01184             av_strlcatf(transport, sizeof(transport),
01185                      "client_port=%d", port);
01186             if (rt->transport == RTSP_TRANSPORT_RTP &&
01187                 !(rt->server_type == RTSP_SERVER_WMS && i > 0))
01188                 av_strlcatf(transport, sizeof(transport), "-%d", port + 1);
01189         }
01190 
01191         /* RTP/TCP */
01192         else if (lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
01193             /* For WMS streams, the application streams are only used for
01194              * UDP. When trying to set it up for TCP streams, the server
01195              * will return an error. Therefore, we skip those streams. */
01196             if (rt->server_type == RTSP_SERVER_WMS &&
01197                 s->streams[rtsp_st->stream_index]->codec->codec_type ==
01198                     AVMEDIA_TYPE_DATA)
01199                 continue;
01200             snprintf(transport, sizeof(transport) - 1,
01201                      "%s/TCP;", trans_pref);
01202             if (rt->transport != RTSP_TRANSPORT_RDT)
01203                 av_strlcat(transport, "unicast;", sizeof(transport));
01204             av_strlcatf(transport, sizeof(transport),
01205                         "interleaved=%d-%d",
01206                         interleave, interleave + 1);
01207             interleave += 2;
01208         }
01209 
01210         else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) {
01211             snprintf(transport, sizeof(transport) - 1,
01212                      "%s/UDP;multicast", trans_pref);
01213         }
01214         if (s->oformat) {
01215             av_strlcat(transport, ";mode=receive", sizeof(transport));
01216         } else if (rt->server_type == RTSP_SERVER_REAL ||
01217                    rt->server_type == RTSP_SERVER_WMS)
01218             av_strlcat(transport, ";mode=play", sizeof(transport));
01219         snprintf(cmd, sizeof(cmd),
01220                  "Transport: %s\r\n",
01221                  transport);
01222         if (rt->accept_dynamic_rate)
01223             av_strlcat(cmd, "x-Dynamic-Rate: 0\r\n", sizeof(cmd));
01224         if (i == 0 && rt->server_type == RTSP_SERVER_REAL && CONFIG_RTPDEC) {
01225             char real_res[41], real_csum[9];
01226             ff_rdt_calc_response_and_checksum(real_res, real_csum,
01227                                               real_challenge);
01228             av_strlcatf(cmd, sizeof(cmd),
01229                         "If-Match: %s\r\n"
01230                         "RealChallenge2: %s, sd=%s\r\n",
01231                         rt->session_id, real_res, real_csum);
01232         }
01233         ff_rtsp_send_cmd(s, "SETUP", rtsp_st->control_url, cmd, reply, NULL);
01234         if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) {
01235             err = 1;
01236             goto fail;
01237         } else if (reply->status_code != RTSP_STATUS_OK ||
01238                    reply->nb_transports != 1) {
01239             err = AVERROR_INVALIDDATA;
01240             goto fail;
01241         }
01242 
01243         /* XXX: same protocol for all streams is required */
01244         if (i > 0) {
01245             if (reply->transports[0].lower_transport != rt->lower_transport ||
01246                 reply->transports[0].transport != rt->transport) {
01247                 err = AVERROR_INVALIDDATA;
01248                 goto fail;
01249             }
01250         } else {
01251             rt->lower_transport = reply->transports[0].lower_transport;
01252             rt->transport = reply->transports[0].transport;
01253         }
01254 
01255         /* Fail if the server responded with another lower transport mode
01256          * than what we requested. */
01257         if (reply->transports[0].lower_transport != lower_transport) {
01258             av_log(s, AV_LOG_ERROR, "Nonmatching transport in server reply\n");
01259             err = AVERROR_INVALIDDATA;
01260             goto fail;
01261         }
01262 
01263         switch(reply->transports[0].lower_transport) {
01264         case RTSP_LOWER_TRANSPORT_TCP:
01265             rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
01266             rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
01267             break;
01268 
01269         case RTSP_LOWER_TRANSPORT_UDP: {
01270             char url[1024], options[30] = "";
01271 
01272             if (rt->rtsp_flags & RTSP_FLAG_FILTER_SRC)
01273                 av_strlcpy(options, "?connect=1", sizeof(options));
01274             /* Use source address if specified */
01275             if (reply->transports[0].source[0]) {
01276                 ff_url_join(url, sizeof(url), "rtp", NULL,
01277                             reply->transports[0].source,
01278                             reply->transports[0].server_port_min, "%s", options);
01279             } else {
01280                 ff_url_join(url, sizeof(url), "rtp", NULL, host,
01281                             reply->transports[0].server_port_min, "%s", options);
01282             }
01283             if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) &&
01284                 ff_rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
01285                 err = AVERROR_INVALIDDATA;
01286                 goto fail;
01287             }
01288             /* Try to initialize the connection state in a
01289              * potential NAT router by sending dummy packets.
01290              * RTP/RTCP dummy packets are used for RDT, too.
01291              */
01292             if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat &&
01293                 CONFIG_RTPDEC)
01294                 ff_rtp_send_punch_packets(rtsp_st->rtp_handle);
01295             break;
01296         }
01297         case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: {
01298             char url[1024], namebuf[50];
01299             struct sockaddr_storage addr;
01300             int port, ttl;
01301 
01302             if (reply->transports[0].destination.ss_family) {
01303                 addr      = reply->transports[0].destination;
01304                 port      = reply->transports[0].port_min;
01305                 ttl       = reply->transports[0].ttl;
01306             } else {
01307                 addr      = rtsp_st->sdp_ip;
01308                 port      = rtsp_st->sdp_port;
01309                 ttl       = rtsp_st->sdp_ttl;
01310             }
01311             getnameinfo((struct sockaddr*) &addr, sizeof(addr),
01312                         namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST);
01313             ff_url_join(url, sizeof(url), "rtp", NULL, namebuf,
01314                         port, "?ttl=%d", ttl);
01315             if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
01316                            &s->interrupt_callback, NULL) < 0) {
01317                 err = AVERROR_INVALIDDATA;
01318                 goto fail;
01319             }
01320             break;
01321         }
01322         }
01323 
01324         if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
01325             goto fail;
01326     }
01327 
01328     if (reply->timeout > 0)
01329         rt->timeout = reply->timeout;
01330 
01331     if (rt->server_type == RTSP_SERVER_REAL)
01332         rt->need_subscription = 1;
01333 
01334     return 0;
01335 
01336 fail:
01337     ff_rtsp_undo_setup(s);
01338     return err;
01339 }
01340 
01341 void ff_rtsp_close_connections(AVFormatContext *s)
01342 {
01343     RTSPState *rt = s->priv_data;
01344     if (rt->rtsp_hd_out != rt->rtsp_hd) ffurl_close(rt->rtsp_hd_out);
01345     ffurl_close(rt->rtsp_hd);
01346     rt->rtsp_hd = rt->rtsp_hd_out = NULL;
01347 }
01348 
01349 int ff_rtsp_connect(AVFormatContext *s)
01350 {
01351     RTSPState *rt = s->priv_data;
01352     char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128];
01353     char *option_list, *option, *filename;
01354     int port, err, tcp_fd;
01355     RTSPMessageHeader reply1 = {0}, *reply = &reply1;
01356     int lower_transport_mask = 0;
01357     char real_challenge[64] = "";
01358     struct sockaddr_storage peer;
01359     socklen_t peer_len = sizeof(peer);
01360 
01361     if (!ff_network_init())
01362         return AVERROR(EIO);
01363 
01364     rt->control_transport = RTSP_MODE_PLAIN;
01365     if (rt->lower_transport_mask & (1 << RTSP_LOWER_TRANSPORT_HTTP)) {
01366         rt->lower_transport_mask = 1 << RTSP_LOWER_TRANSPORT_TCP;
01367         rt->control_transport = RTSP_MODE_TUNNEL;
01368     }
01369     /* Only pass through valid flags from here */
01370     rt->lower_transport_mask &= (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
01371 
01372 redirect:
01373     lower_transport_mask = rt->lower_transport_mask;
01374     /* extract hostname and port */
01375     av_url_split(NULL, 0, auth, sizeof(auth),
01376                  host, sizeof(host), &port, path, sizeof(path), s->filename);
01377     if (*auth) {
01378         av_strlcpy(rt->auth, auth, sizeof(rt->auth));
01379     }
01380     if (port < 0)
01381         port = RTSP_DEFAULT_PORT;
01382 
01383 #if FF_API_RTSP_URL_OPTIONS
01384     /* search for options */
01385     option_list = strrchr(path, '?');
01386     if (option_list) {
01387         /* Strip out the RTSP specific options, write out the rest of
01388          * the options back into the same string. */
01389         filename = option_list;
01390         while (option_list) {
01391             int handled = 1;
01392             /* move the option pointer */
01393             option = ++option_list;
01394             option_list = strchr(option_list, '&');
01395             if (option_list)
01396                 *option_list = 0;
01397 
01398             /* handle the options */
01399             if (!strcmp(option, "udp")) {
01400                 lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP);
01401             } else if (!strcmp(option, "multicast")) {
01402                 lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
01403             } else if (!strcmp(option, "tcp")) {
01404                 lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);
01405             } else if(!strcmp(option, "http")) {
01406                 lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);
01407                 rt->control_transport = RTSP_MODE_TUNNEL;
01408             } else if (!strcmp(option, "filter_src")) {
01409                 rt->rtsp_flags |= RTSP_FLAG_FILTER_SRC;
01410             } else {
01411                 /* Write options back into the buffer, using memmove instead
01412                  * of strcpy since the strings may overlap. */
01413                 int len = strlen(option);
01414                 memmove(++filename, option, len);
01415                 filename += len;
01416                 if (option_list) *filename = '&';
01417                 handled = 0;
01418             }
01419             if (handled)
01420                 av_log(s, AV_LOG_WARNING, "Options passed via URL are "
01421                                           "deprecated, use -rtsp_transport "
01422                                           "and -rtsp_flags instead.\n");
01423         }
01424         *filename = 0;
01425     }
01426 #endif
01427 
01428     if (!lower_transport_mask)
01429         lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
01430 
01431     if (s->oformat) {
01432         /* Only UDP or TCP - UDP multicast isn't supported. */
01433         lower_transport_mask &= (1 << RTSP_LOWER_TRANSPORT_UDP) |
01434                                 (1 << RTSP_LOWER_TRANSPORT_TCP);
01435         if (!lower_transport_mask || rt->control_transport == RTSP_MODE_TUNNEL) {
01436             av_log(s, AV_LOG_ERROR, "Unsupported lower transport method, "
01437                                     "only UDP and TCP are supported for output.\n");
01438             err = AVERROR(EINVAL);
01439             goto fail;
01440         }
01441     }
01442 
01443     /* Construct the URI used in request; this is similar to s->filename,
01444      * but with authentication credentials removed and RTSP specific options
01445      * stripped out. */
01446     ff_url_join(rt->control_uri, sizeof(rt->control_uri), "rtsp", NULL,
01447                 host, port, "%s", path);
01448 
01449     if (rt->control_transport == RTSP_MODE_TUNNEL) {
01450         /* set up initial handshake for tunneling */
01451         char httpname[1024];
01452         char sessioncookie[17];
01453         char headers[1024];
01454 
01455         ff_url_join(httpname, sizeof(httpname), "http", auth, host, port, "%s", path);
01456         snprintf(sessioncookie, sizeof(sessioncookie), "%08x%08x",
01457                  av_get_random_seed(), av_get_random_seed());
01458 
01459         /* GET requests */
01460         if (ffurl_alloc(&rt->rtsp_hd, httpname, AVIO_FLAG_READ,
01461                         &s->interrupt_callback) < 0) {
01462             err = AVERROR(EIO);
01463             goto fail;
01464         }
01465 
01466         /* generate GET headers */
01467         snprintf(headers, sizeof(headers),
01468                  "x-sessioncookie: %s\r\n"
01469                  "Accept: application/x-rtsp-tunnelled\r\n"
01470                  "Pragma: no-cache\r\n"
01471                  "Cache-Control: no-cache\r\n",
01472                  sessioncookie);
01473         av_opt_set(rt->rtsp_hd->priv_data, "headers", headers, 0);
01474 
01475         /* complete the connection */
01476         if (ffurl_connect(rt->rtsp_hd, NULL)) {
01477             err = AVERROR(EIO);
01478             goto fail;
01479         }
01480 
01481         /* POST requests */
01482         if (ffurl_alloc(&rt->rtsp_hd_out, httpname, AVIO_FLAG_WRITE,
01483                         &s->interrupt_callback) < 0 ) {
01484             err = AVERROR(EIO);
01485             goto fail;
01486         }
01487 
01488         /* generate POST headers */
01489         snprintf(headers, sizeof(headers),
01490                  "x-sessioncookie: %s\r\n"
01491                  "Content-Type: application/x-rtsp-tunnelled\r\n"
01492                  "Pragma: no-cache\r\n"
01493                  "Cache-Control: no-cache\r\n"
01494                  "Content-Length: 32767\r\n"
01495                  "Expires: Sun, 9 Jan 1972 00:00:00 GMT\r\n",
01496                  sessioncookie);
01497         av_opt_set(rt->rtsp_hd_out->priv_data, "headers", headers, 0);
01498         av_opt_set(rt->rtsp_hd_out->priv_data, "chunked_post", "0", 0);
01499 
01500         /* Initialize the authentication state for the POST session. The HTTP
01501          * protocol implementation doesn't properly handle multi-pass
01502          * authentication for POST requests, since it would require one of
01503          * the following:
01504          * - implementing Expect: 100-continue, which many HTTP servers
01505          *   don't support anyway, even less the RTSP servers that do HTTP
01506          *   tunneling
01507          * - sending the whole POST data until getting a 401 reply specifying
01508          *   what authentication method to use, then resending all that data
01509          * - waiting for potential 401 replies directly after sending the
01510          *   POST header (waiting for some unspecified time)
01511          * Therefore, we copy the full auth state, which works for both basic
01512          * and digest. (For digest, we would have to synchronize the nonce
01513          * count variable between the two sessions, if we'd do more requests
01514          * with the original session, though.)
01515          */
01516         ff_http_init_auth_state(rt->rtsp_hd_out, rt->rtsp_hd);
01517 
01518         /* complete the connection */
01519         if (ffurl_connect(rt->rtsp_hd_out, NULL)) {
01520             err = AVERROR(EIO);
01521             goto fail;
01522         }
01523     } else {
01524         /* open the tcp connection */
01525         ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL);
01526         if (ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
01527                        &s->interrupt_callback, NULL) < 0) {
01528             err = AVERROR(EIO);
01529             goto fail;
01530         }
01531         rt->rtsp_hd_out = rt->rtsp_hd;
01532     }
01533     rt->seq = 0;
01534 
01535     tcp_fd = ffurl_get_file_handle(rt->rtsp_hd);
01536     if (!getpeername(tcp_fd, (struct sockaddr*) &peer, &peer_len)) {
01537         getnameinfo((struct sockaddr*) &peer, peer_len, host, sizeof(host),
01538                     NULL, 0, NI_NUMERICHOST);
01539     }
01540 
01541     /* request options supported by the server; this also detects server
01542      * type */
01543     for (rt->server_type = RTSP_SERVER_RTP;;) {
01544         cmd[0] = 0;
01545         if (rt->server_type == RTSP_SERVER_REAL)
01546             av_strlcat(cmd,
01547                        /*
01548                         * The following entries are required for proper
01549                         * streaming from a Realmedia server. They are
01550                         * interdependent in some way although we currently
01551                         * don't quite understand how. Values were copied
01552                         * from mplayer SVN r23589.
01553                         *   ClientChallenge is a 16-byte ID in hex
01554                         *   CompanyID is a 16-byte ID in base64
01555                         */
01556                        "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7\r\n"
01557                        "PlayerStarttime: [28/03/2003:22:50:23 00:00]\r\n"
01558                        "CompanyID: KnKV4M4I/B2FjJ1TToLycw==\r\n"
01559                        "GUID: 00000000-0000-0000-0000-000000000000\r\n",
01560                        sizeof(cmd));
01561         ff_rtsp_send_cmd(s, "OPTIONS", rt->control_uri, cmd, reply, NULL);
01562         if (reply->status_code != RTSP_STATUS_OK) {
01563             err = AVERROR_INVALIDDATA;
01564             goto fail;
01565         }
01566 
01567         /* detect server type if not standard-compliant RTP */
01568         if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) {
01569             rt->server_type = RTSP_SERVER_REAL;
01570             continue;
01571         } else if (!av_strncasecmp(reply->server, "WMServer/", 9)) {
01572             rt->server_type = RTSP_SERVER_WMS;
01573         } else if (rt->server_type == RTSP_SERVER_REAL)
01574             strcpy(real_challenge, reply->real_challenge);
01575         break;
01576     }
01577 
01578     if (s->iformat && CONFIG_RTSP_DEMUXER)
01579         err = ff_rtsp_setup_input_streams(s, reply);
01580     else if (CONFIG_RTSP_MUXER)
01581         err = ff_rtsp_setup_output_streams(s, host);
01582     if (err)
01583         goto fail;
01584 
01585     do {
01586         int lower_transport = ff_log2_tab[lower_transport_mask &
01587                                   ~(lower_transport_mask - 1)];
01588 
01589         err = ff_rtsp_make_setup_request(s, host, port, lower_transport,
01590                                  rt->server_type == RTSP_SERVER_REAL ?
01591                                      real_challenge : NULL);
01592         if (err < 0)
01593             goto fail;
01594         lower_transport_mask &= ~(1 << lower_transport);
01595         if (lower_transport_mask == 0 && err == 1) {
01596             err = AVERROR(EPROTONOSUPPORT);
01597             goto fail;
01598         }
01599     } while (err);
01600 
01601     rt->lower_transport_mask = lower_transport_mask;
01602     av_strlcpy(rt->real_challenge, real_challenge, sizeof(rt->real_challenge));
01603     rt->state = RTSP_STATE_IDLE;
01604     rt->seek_timestamp = 0; /* default is to start stream at position zero */
01605     return 0;
01606  fail:
01607     ff_rtsp_close_streams(s);
01608     ff_rtsp_close_connections(s);
01609     if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) {
01610         av_strlcpy(s->filename, reply->location, sizeof(s->filename));
01611         av_log(s, AV_LOG_INFO, "Status %d: Redirecting to %s\n",
01612                reply->status_code,
01613                s->filename);
01614         goto redirect;
01615     }
01616     ff_network_close();
01617     return err;
01618 }
01619 #endif /* CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER */
01620 
01621 #if CONFIG_RTPDEC
01622 static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
01623                            uint8_t *buf, int buf_size, int64_t wait_end)
01624 {
01625     RTSPState *rt = s->priv_data;
01626     RTSPStream *rtsp_st;
01627     int n, i, ret, tcp_fd, timeout_cnt = 0;
01628     int max_p = 0;
01629     struct pollfd *p = rt->p;
01630 
01631     for (;;) {
01632         if (ff_check_interrupt(&s->interrupt_callback))
01633             return AVERROR_EXIT;
01634         if (wait_end && wait_end - av_gettime() < 0)
01635             return AVERROR(EAGAIN);
01636         max_p = 0;
01637         if (rt->rtsp_hd) {
01638             tcp_fd = ffurl_get_file_handle(rt->rtsp_hd);
01639             p[max_p].fd = tcp_fd;
01640             p[max_p++].events = POLLIN;
01641         } else {
01642             tcp_fd = -1;
01643         }
01644         for (i = 0; i < rt->nb_rtsp_streams; i++) {
01645             rtsp_st = rt->rtsp_streams[i];
01646             if (rtsp_st->rtp_handle) {
01647                 p[max_p].fd = ffurl_get_file_handle(rtsp_st->rtp_handle);
01648                 p[max_p++].events = POLLIN;
01649                 p[max_p].fd = ff_rtp_get_rtcp_file_handle(rtsp_st->rtp_handle);
01650                 p[max_p++].events = POLLIN;
01651             }
01652         }
01653         n = poll(p, max_p, POLL_TIMEOUT_MS);
01654         if (n > 0) {
01655             int j = 1 - (tcp_fd == -1);
01656             timeout_cnt = 0;
01657             for (i = 0; i < rt->nb_rtsp_streams; i++) {
01658                 rtsp_st = rt->rtsp_streams[i];
01659                 if (rtsp_st->rtp_handle) {
01660                     if (p[j].revents & POLLIN || p[j+1].revents & POLLIN) {
01661                         ret = ffurl_read(rtsp_st->rtp_handle, buf, buf_size);
01662                         if (ret > 0) {
01663                             *prtsp_st = rtsp_st;
01664                             return ret;
01665                         }
01666                     }
01667                     j+=2;
01668                 }
01669             }
01670 #if CONFIG_RTSP_DEMUXER
01671             if (tcp_fd != -1 && p[0].revents & POLLIN) {
01672                 RTSPMessageHeader reply;
01673 
01674                 ret = ff_rtsp_read_reply(s, &reply, NULL, 0, NULL);
01675                 if (ret < 0)
01676                     return ret;
01677                 /* XXX: parse message */
01678                 if (rt->state != RTSP_STATE_STREAMING)
01679                     return 0;
01680             }
01681 #endif
01682         } else if (n == 0 && ++timeout_cnt >= MAX_TIMEOUTS) {
01683             return AVERROR(ETIMEDOUT);
01684         } else if (n < 0 && errno != EINTR)
01685             return AVERROR(errno);
01686     }
01687 }
01688 
01689 int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt)
01690 {
01691     RTSPState *rt = s->priv_data;
01692     int ret, len;
01693     RTSPStream *rtsp_st, *first_queue_st = NULL;
01694     int64_t wait_end = 0;
01695 
01696     if (rt->nb_byes == rt->nb_rtsp_streams)
01697         return AVERROR_EOF;
01698 
01699     /* get next frames from the same RTP packet */
01700     if (rt->cur_transport_priv) {
01701         if (rt->transport == RTSP_TRANSPORT_RDT) {
01702             ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
01703         } else
01704             ret = ff_rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
01705         if (ret == 0) {
01706             rt->cur_transport_priv = NULL;
01707             return 0;
01708         } else if (ret == 1) {
01709             return 0;
01710         } else
01711             rt->cur_transport_priv = NULL;
01712     }
01713 
01714 redo:
01715     if (rt->transport == RTSP_TRANSPORT_RTP) {
01716         int i;
01717         int64_t first_queue_time = 0;
01718         for (i = 0; i < rt->nb_rtsp_streams; i++) {
01719             RTPDemuxContext *rtpctx = rt->rtsp_streams[i]->transport_priv;
01720             int64_t queue_time;
01721             if (!rtpctx)
01722                 continue;
01723             queue_time = ff_rtp_queued_packet_time(rtpctx);
01724             if (queue_time && (queue_time - first_queue_time < 0 ||
01725                                !first_queue_time)) {
01726                 first_queue_time = queue_time;
01727                 first_queue_st   = rt->rtsp_streams[i];
01728             }
01729         }
01730         if (first_queue_time) {
01731             wait_end = first_queue_time + s->max_delay;
01732         } else {
01733             wait_end = 0;
01734             first_queue_st = NULL;
01735         }
01736     }
01737 
01738     /* read next RTP packet */
01739     if (!rt->recvbuf) {
01740         rt->recvbuf = av_malloc(RECVBUF_SIZE);
01741         if (!rt->recvbuf)
01742             return AVERROR(ENOMEM);
01743     }
01744 
01745     switch(rt->lower_transport) {
01746     default:
01747 #if CONFIG_RTSP_DEMUXER
01748     case RTSP_LOWER_TRANSPORT_TCP:
01749         len = ff_rtsp_tcp_read_packet(s, &rtsp_st, rt->recvbuf, RECVBUF_SIZE);
01750         break;
01751 #endif
01752     case RTSP_LOWER_TRANSPORT_UDP:
01753     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
01754         len = udp_read_packet(s, &rtsp_st, rt->recvbuf, RECVBUF_SIZE, wait_end);
01755         if (len > 0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP)
01756             ff_rtp_check_and_send_back_rr(rtsp_st->transport_priv, len);
01757         break;
01758     }
01759     if (len == AVERROR(EAGAIN) && first_queue_st &&
01760         rt->transport == RTSP_TRANSPORT_RTP) {
01761         rtsp_st = first_queue_st;
01762         ret = ff_rtp_parse_packet(rtsp_st->transport_priv, pkt, NULL, 0);
01763         goto end;
01764     }
01765     if (len < 0)
01766         return len;
01767     if (len == 0)
01768         return AVERROR_EOF;
01769     if (rt->transport == RTSP_TRANSPORT_RDT) {
01770         ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);
01771     } else {
01772         ret = ff_rtp_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);
01773         if (ret < 0) {
01774             /* Either bad packet, or a RTCP packet. Check if the
01775              * first_rtcp_ntp_time field was initialized. */
01776             RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
01777             if (rtpctx->first_rtcp_ntp_time != AV_NOPTS_VALUE) {
01778                 /* first_rtcp_ntp_time has been initialized for this stream,
01779                  * copy the same value to all other uninitialized streams,
01780                  * in order to map their timestamp origin to the same ntp time
01781                  * as this one. */
01782                 int i;
01783                 AVStream *st = NULL;
01784                 if (rtsp_st->stream_index >= 0)
01785                     st = s->streams[rtsp_st->stream_index];
01786                 for (i = 0; i < rt->nb_rtsp_streams; i++) {
01787                     RTPDemuxContext *rtpctx2 = rt->rtsp_streams[i]->transport_priv;
01788                     AVStream *st2 = NULL;
01789                     if (rt->rtsp_streams[i]->stream_index >= 0)
01790                         st2 = s->streams[rt->rtsp_streams[i]->stream_index];
01791                     if (rtpctx2 && st && st2 &&
01792                         rtpctx2->first_rtcp_ntp_time == AV_NOPTS_VALUE) {
01793                         rtpctx2->first_rtcp_ntp_time = rtpctx->first_rtcp_ntp_time;
01794                         rtpctx2->rtcp_ts_offset = av_rescale_q(
01795                             rtpctx->rtcp_ts_offset, st->time_base,
01796                             st2->time_base);
01797                     }
01798                 }
01799             }
01800             if (ret == -RTCP_BYE) {
01801                 rt->nb_byes++;
01802 
01803                 av_log(s, AV_LOG_DEBUG, "Received BYE for stream %d (%d/%d)\n",
01804                        rtsp_st->stream_index, rt->nb_byes, rt->nb_rtsp_streams);
01805 
01806                 if (rt->nb_byes == rt->nb_rtsp_streams)
01807                     return AVERROR_EOF;
01808             }
01809         }
01810     }
01811 end:
01812     if (ret < 0)
01813         goto redo;
01814     if (ret == 1)
01815         /* more packets may follow, so we save the RTP context */
01816         rt->cur_transport_priv = rtsp_st->transport_priv;
01817 
01818     return ret;
01819 }
01820 #endif /* CONFIG_RTPDEC */
01821 
01822 #if CONFIG_SDP_DEMUXER
01823 static int sdp_probe(AVProbeData *p1)
01824 {
01825     const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
01826 
01827     /* we look for a line beginning "c=IN IP" */
01828     while (p < p_end && *p != '\0') {
01829         if (p + sizeof("c=IN IP") - 1 < p_end &&
01830             av_strstart(p, "c=IN IP", NULL))
01831             return AVPROBE_SCORE_MAX / 2;
01832 
01833         while (p < p_end - 1 && *p != '\n') p++;
01834         if (++p >= p_end)
01835             break;
01836         if (*p == '\r')
01837             p++;
01838     }
01839     return 0;
01840 }
01841 
01842 static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap)
01843 {
01844     RTSPState *rt = s->priv_data;
01845     RTSPStream *rtsp_st;
01846     int size, i, err;
01847     char *content;
01848     char url[1024];
01849 
01850     if (!ff_network_init())
01851         return AVERROR(EIO);
01852 
01853     /* read the whole sdp file */
01854     /* XXX: better loading */
01855     content = av_malloc(SDP_MAX_SIZE);
01856     size = avio_read(s->pb, content, SDP_MAX_SIZE - 1);
01857     if (size <= 0) {
01858         av_free(content);
01859         return AVERROR_INVALIDDATA;
01860     }
01861     content[size] ='\0';
01862 
01863     err = ff_sdp_parse(s, content);
01864     av_free(content);
01865     if (err) goto fail;
01866 
01867     /* open each RTP stream */
01868     for (i = 0; i < rt->nb_rtsp_streams; i++) {
01869         char namebuf[50];
01870         rtsp_st = rt->rtsp_streams[i];
01871 
01872         getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, sizeof(rtsp_st->sdp_ip),
01873                     namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST);
01874         ff_url_join(url, sizeof(url), "rtp", NULL,
01875                     namebuf, rtsp_st->sdp_port,
01876                     "?localport=%d&ttl=%d&connect=%d", rtsp_st->sdp_port,
01877                     rtsp_st->sdp_ttl,
01878                     rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0);
01879         if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
01880                        &s->interrupt_callback, NULL) < 0) {
01881             err = AVERROR_INVALIDDATA;
01882             goto fail;
01883         }
01884         if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
01885             goto fail;
01886     }
01887     return 0;
01888 fail:
01889     ff_rtsp_close_streams(s);
01890     ff_network_close();
01891     return err;
01892 }
01893 
01894 static int sdp_read_close(AVFormatContext *s)
01895 {
01896     ff_rtsp_close_streams(s);
01897     ff_network_close();
01898     return 0;
01899 }
01900 
01901 static const AVClass sdp_demuxer_class = {
01902     .class_name     = "SDP demuxer",
01903     .item_name      = av_default_item_name,
01904     .option         = sdp_options,
01905     .version        = LIBAVUTIL_VERSION_INT,
01906 };
01907 
01908 AVInputFormat ff_sdp_demuxer = {
01909     .name           = "sdp",
01910     .long_name      = NULL_IF_CONFIG_SMALL("SDP"),
01911     .priv_data_size = sizeof(RTSPState),
01912     .read_probe     = sdp_probe,
01913     .read_header    = sdp_read_header,
01914     .read_packet    = ff_rtsp_fetch_packet,
01915     .read_close     = sdp_read_close,
01916     .priv_class     = &sdp_demuxer_class
01917 };
01918 #endif /* CONFIG_SDP_DEMUXER */
01919 
01920 #if CONFIG_RTP_DEMUXER
01921 static int rtp_probe(AVProbeData *p)
01922 {
01923     if (av_strstart(p->filename, "rtp:", NULL))
01924         return AVPROBE_SCORE_MAX;
01925     return 0;
01926 }
01927 
01928 static int rtp_read_header(AVFormatContext *s,
01929                            AVFormatParameters *ap)
01930 {
01931     uint8_t recvbuf[1500];
01932     char host[500], sdp[500];
01933     int ret, port;
01934     URLContext* in = NULL;
01935     int payload_type;
01936     AVCodecContext codec;
01937     struct sockaddr_storage addr;
01938     AVIOContext pb;
01939     socklen_t addrlen = sizeof(addr);
01940     RTSPState *rt = s->priv_data;
01941 
01942     if (!ff_network_init())
01943         return AVERROR(EIO);
01944 
01945     ret = ffurl_open(&in, s->filename, AVIO_FLAG_READ,
01946                      &s->interrupt_callback, NULL);
01947     if (ret)
01948         goto fail;
01949 
01950     while (1) {
01951         ret = ffurl_read(in, recvbuf, sizeof(recvbuf));
01952         if (ret == AVERROR(EAGAIN))
01953             continue;
01954         if (ret < 0)
01955             goto fail;
01956         if (ret < 12) {
01957             av_log(s, AV_LOG_WARNING, "Received too short packet\n");
01958             continue;
01959         }
01960 
01961         if ((recvbuf[0] & 0xc0) != 0x80) {
01962             av_log(s, AV_LOG_WARNING, "Unsupported RTP version packet "
01963                                       "received\n");
01964             continue;
01965         }
01966 
01967         payload_type = recvbuf[1] & 0x7f;
01968         break;
01969     }
01970     getsockname(ffurl_get_file_handle(in), (struct sockaddr*) &addr, &addrlen);
01971     ffurl_close(in);
01972     in = NULL;
01973 
01974     memset(&codec, 0, sizeof(codec));
01975     if (ff_rtp_get_codec_info(&codec, payload_type)) {
01976         av_log(s, AV_LOG_ERROR, "Unable to receive RTP payload type %d "
01977                                 "without an SDP file describing it\n",
01978                                  payload_type);
01979         goto fail;
01980     }
01981     if (codec.codec_type != AVMEDIA_TYPE_DATA) {
01982         av_log(s, AV_LOG_WARNING, "Guessing on RTP content - if not received "
01983                                   "properly you need an SDP file "
01984                                   "describing it\n");
01985     }
01986 
01987     av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port,
01988                  NULL, 0, s->filename);
01989 
01990     snprintf(sdp, sizeof(sdp),
01991              "v=0\r\nc=IN IP%d %s\r\nm=%s %d RTP/AVP %d\r\n",
01992              addr.ss_family == AF_INET ? 4 : 6, host,
01993              codec.codec_type == AVMEDIA_TYPE_DATA  ? "application" :
01994              codec.codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio",
01995              port, payload_type);
01996     av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sdp);
01997 
01998     ffio_init_context(&pb, sdp, strlen(sdp), 0, NULL, NULL, NULL, NULL);
01999     s->pb = &pb;
02000 
02001     /* sdp_read_header initializes this again */
02002     ff_network_close();
02003 
02004     rt->media_type_mask = (1 << (AVMEDIA_TYPE_DATA+1)) - 1;
02005 
02006     ret = sdp_read_header(s, ap);
02007     s->pb = NULL;
02008     return ret;
02009 
02010 fail:
02011     if (in)
02012         ffurl_close(in);
02013     ff_network_close();
02014     return ret;
02015 }
02016 
02017 static const AVClass rtp_demuxer_class = {
02018     .class_name     = "RTP demuxer",
02019     .item_name      = av_default_item_name,
02020     .option         = rtp_options,
02021     .version        = LIBAVUTIL_VERSION_INT,
02022 };
02023 
02024 AVInputFormat ff_rtp_demuxer = {
02025     .name           = "rtp",
02026     .long_name      = NULL_IF_CONFIG_SMALL("RTP input format"),
02027     .priv_data_size = sizeof(RTSPState),
02028     .read_probe     = rtp_probe,
02029     .read_header    = rtp_read_header,
02030     .read_packet    = ff_rtsp_fetch_packet,
02031     .read_close     = sdp_read_close,
02032     .flags = AVFMT_NOFILE,
02033     .priv_class     = &rtp_demuxer_class
02034 };
02035 #endif /* CONFIG_RTP_DEMUXER */
02036 
Generated on Thu Jan 24 2013 17:08:56 for Libav by doxygen 1.7.1