• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • 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 FFmpeg.
00006  *
00007  * FFmpeg 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  * FFmpeg 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 FFmpeg; 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 "avformat.h"
00026 
00027 #include <sys/time.h>
00028 #if HAVE_SYS_SELECT_H
00029 #include <sys/select.h>
00030 #endif
00031 #include <strings.h>
00032 #include "internal.h"
00033 #include "network.h"
00034 #include "os_support.h"
00035 #include "rtsp.h"
00036 
00037 #include "rtpdec.h"
00038 #include "rdt.h"
00039 #include "rtpdec_asf.h"
00040 
00041 //#define DEBUG
00042 //#define DEBUG_RTP_TCP
00043 
00044 #if LIBAVFORMAT_VERSION_INT < (53 << 16)
00045 int rtsp_default_protocols = (1 << RTSP_LOWER_TRANSPORT_UDP);
00046 #endif
00047 
00048 /* Timeout values for socket select, in ms,
00049  * and read_packet(), in seconds  */
00050 #define SELECT_TIMEOUT_MS 100
00051 #define READ_PACKET_TIMEOUT_S 10
00052 #define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / SELECT_TIMEOUT_MS
00053 
00054 #define SPACE_CHARS " \t\r\n"
00055 /* we use memchr() instead of strchr() here because strchr() will return
00056  * the terminating '\0' of SPACE_CHARS instead of NULL if c is '\0'. */
00057 #define redir_isspace(c) memchr(SPACE_CHARS, c, 4)
00058 static void skip_spaces(const char **pp)
00059 {
00060     const char *p;
00061     p = *pp;
00062     while (redir_isspace(*p))
00063         p++;
00064     *pp = p;
00065 }
00066 
00067 static void get_word_until_chars(char *buf, int buf_size,
00068                                  const char *sep, const char **pp)
00069 {
00070     const char *p;
00071     char *q;
00072 
00073     p = *pp;
00074     skip_spaces(&p);
00075     q = buf;
00076     while (!strchr(sep, *p) && *p != '\0') {
00077         if ((q - buf) < buf_size - 1)
00078             *q++ = *p;
00079         p++;
00080     }
00081     if (buf_size > 0)
00082         *q = '\0';
00083     *pp = p;
00084 }
00085 
00086 static void get_word_sep(char *buf, int buf_size, const char *sep,
00087                          const char **pp)
00088 {
00089     if (**pp == '/') (*pp)++;
00090     get_word_until_chars(buf, buf_size, sep, pp);
00091 }
00092 
00093 static void get_word(char *buf, int buf_size, const char **pp)
00094 {
00095     get_word_until_chars(buf, buf_size, SPACE_CHARS, pp);
00096 }
00097 
00098 /* parse the rtpmap description: <codec_name>/<clock_rate>[/<other params>] */
00099 static int sdp_parse_rtpmap(AVFormatContext *s,
00100                             AVCodecContext *codec, RTSPStream *rtsp_st,
00101                             int payload_type, const char *p)
00102 {
00103     char buf[256];
00104     int i;
00105     AVCodec *c;
00106     const char *c_name;
00107 
00108     /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and
00109      * see if we can handle this kind of payload.
00110      * The space should normally not be there but some Real streams or
00111      * particular servers ("RealServer Version 6.1.3.970", see issue 1658)
00112      * have a trailing space. */
00113     get_word_sep(buf, sizeof(buf), "/ ", &p);
00114     if (payload_type >= RTP_PT_PRIVATE) {
00115         RTPDynamicProtocolHandler *handler;
00116         for (handler = RTPFirstDynamicPayloadHandler;
00117              handler; handler = handler->next) {
00118             if (!strcasecmp(buf, handler->enc_name) &&
00119                 codec->codec_type == handler->codec_type) {
00120                 codec->codec_id          = handler->codec_id;
00121                 rtsp_st->dynamic_handler = handler;
00122                 if (handler->open)
00123                     rtsp_st->dynamic_protocol_context = handler->open();
00124                 break;
00125             }
00126         }
00127     } else {
00128         /* We are in a standard case
00129          * (from http://www.iana.org/assignments/rtp-parameters). */
00130         /* search into AVRtpPayloadTypes[] */
00131         codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
00132     }
00133 
00134     c = avcodec_find_decoder(codec->codec_id);
00135     if (c && c->name)
00136         c_name = c->name;
00137     else
00138         c_name = "(null)";
00139 
00140     get_word_sep(buf, sizeof(buf), "/", &p);
00141     i = atoi(buf);
00142     switch (codec->codec_type) {
00143     case AVMEDIA_TYPE_AUDIO:
00144         av_log(s, AV_LOG_DEBUG, "audio codec set to: %s\n", c_name);
00145         codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE;
00146         codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS;
00147         if (i > 0) {
00148             codec->sample_rate = i;
00149             get_word_sep(buf, sizeof(buf), "/", &p);
00150             i = atoi(buf);
00151             if (i > 0)
00152                 codec->channels = i;
00153             // TODO: there is a bug here; if it is a mono stream, and
00154             // less than 22000Hz, faad upconverts to stereo and twice
00155             // the frequency.  No problem, but the sample rate is being
00156             // set here by the sdp line. Patch on its way. (rdm)
00157         }
00158         av_log(s, AV_LOG_DEBUG, "audio samplerate set to: %i\n",
00159                codec->sample_rate);
00160         av_log(s, AV_LOG_DEBUG, "audio channels set to: %i\n",
00161                codec->channels);
00162         break;
00163     case AVMEDIA_TYPE_VIDEO:
00164         av_log(s, AV_LOG_DEBUG, "video codec set to: %s\n", c_name);
00165         break;
00166     default:
00167         break;
00168     }
00169     return 0;
00170 }
00171 
00172 /* return the length and optionally the data */
00173 static int hex_to_data(uint8_t *data, const char *p)
00174 {
00175     int c, len, v;
00176 
00177     len = 0;
00178     v = 1;
00179     for (;;) {
00180         skip_spaces(&p);
00181         if (*p == '\0')
00182             break;
00183         c = toupper((unsigned char) *p++);
00184         if (c >= '0' && c <= '9')
00185             c = c - '0';
00186         else if (c >= 'A' && c <= 'F')
00187             c = c - 'A' + 10;
00188         else
00189             break;
00190         v = (v << 4) | c;
00191         if (v & 0x100) {
00192             if (data)
00193                 data[len] = v;
00194             len++;
00195             v = 1;
00196         }
00197     }
00198     return len;
00199 }
00200 
00201 static void sdp_parse_fmtp_config(AVCodecContext * codec, void *ctx,
00202                                   char *attr, char *value)
00203 {
00204     switch (codec->codec_id) {
00205     case CODEC_ID_MPEG4:
00206     case CODEC_ID_AAC:
00207         if (!strcmp(attr, "config")) {
00208             /* decode the hexa encoded parameter */
00209             int len = hex_to_data(NULL, value);
00210             if (codec->extradata)
00211                 av_free(codec->extradata);
00212             codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
00213             if (!codec->extradata)
00214                 return;
00215             codec->extradata_size = len;
00216             hex_to_data(codec->extradata, value);
00217         }
00218         break;
00219     default:
00220         break;
00221     }
00222     return;
00223 }
00224 
00225 typedef struct {
00226     const char *str;
00227     uint16_t    type;
00228     uint32_t    offset;
00229 } AttrNameMap;
00230 
00231 /* All known fmtp parameters and the corresponding RTPAttrTypeEnum */
00232 #define ATTR_NAME_TYPE_INT 0
00233 #define ATTR_NAME_TYPE_STR 1
00234 static const AttrNameMap attr_names[]=
00235 {
00236     { "SizeLength",       ATTR_NAME_TYPE_INT,
00237       offsetof(RTPPayloadData, sizelength) },
00238     { "IndexLength",      ATTR_NAME_TYPE_INT,
00239       offsetof(RTPPayloadData, indexlength) },
00240     { "IndexDeltaLength", ATTR_NAME_TYPE_INT,
00241       offsetof(RTPPayloadData, indexdeltalength) },
00242     { "profile-level-id", ATTR_NAME_TYPE_INT,
00243       offsetof(RTPPayloadData, profile_level_id) },
00244     { "StreamType",       ATTR_NAME_TYPE_INT,
00245       offsetof(RTPPayloadData, streamtype) },
00246     { "mode",             ATTR_NAME_TYPE_STR,
00247       offsetof(RTPPayloadData, mode) },
00248     { NULL, -1, -1 },
00249 };
00250 
00251 /* parse the attribute line from the fmtp a line of an sdp response. This
00252  * is broken out as a function because it is used in rtp_h264.c, which is
00253  * forthcoming. */
00254 int ff_rtsp_next_attr_and_value(const char **p, char *attr, int attr_size,
00255                                 char *value, int value_size)
00256 {
00257     skip_spaces(p);
00258     if (**p) {
00259         get_word_sep(attr, attr_size, "=", p);
00260         if (**p == '=')
00261             (*p)++;
00262         get_word_sep(value, value_size, ";", p);
00263         if (**p == ';')
00264             (*p)++;
00265         return 1;
00266     }
00267     return 0;
00268 }
00269 
00270 /* parse a SDP line and save stream attributes */
00271 static void sdp_parse_fmtp(AVStream *st, const char *p)
00272 {
00273     char attr[256];
00274     /* Vorbis setup headers can be up to 12KB and are sent base64
00275      * encoded, giving a 12KB * (4/3) = 16KB FMTP line. */
00276     char value[16384];
00277     int i;
00278     RTSPStream *rtsp_st = st->priv_data;
00279     AVCodecContext *codec = st->codec;
00280     RTPPayloadData *rtp_payload_data = &rtsp_st->rtp_payload_data;
00281 
00282     /* loop on each attribute */
00283     while (ff_rtsp_next_attr_and_value(&p, attr, sizeof(attr),
00284                                        value, sizeof(value))) {
00285         /* grab the codec extra_data from the config parameter of the fmtp
00286          * line */
00287         sdp_parse_fmtp_config(codec, rtsp_st->dynamic_protocol_context,
00288                               attr, value);
00289         /* Looking for a known attribute */
00290         for (i = 0; attr_names[i].str; ++i) {
00291             if (!strcasecmp(attr, attr_names[i].str)) {
00292                 if (attr_names[i].type == ATTR_NAME_TYPE_INT) {
00293                     *(int *)((char *)rtp_payload_data +
00294                         attr_names[i].offset) = atoi(value);
00295                 } else if (attr_names[i].type == ATTR_NAME_TYPE_STR)
00296                     *(char **)((char *)rtp_payload_data +
00297                         attr_names[i].offset) = av_strdup(value);
00298             }
00299         }
00300     }
00301 }
00302 
00307 static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end)
00308 {
00309     char buf[256];
00310 
00311     skip_spaces(&p);
00312     if (!av_stristart(p, "npt=", &p))
00313         return;
00314 
00315     *start = AV_NOPTS_VALUE;
00316     *end = AV_NOPTS_VALUE;
00317 
00318     get_word_sep(buf, sizeof(buf), "-", &p);
00319     *start = parse_date(buf, 1);
00320     if (*p == '-') {
00321         p++;
00322         get_word_sep(buf, sizeof(buf), "-", &p);
00323         *end = parse_date(buf, 1);
00324     }
00325 //    av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start);
00326 //    av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end);
00327 }
00328 
00329 typedef struct SDPParseState {
00330     /* SDP only */
00331     struct in_addr default_ip;
00332     int            default_ttl;
00333     int            skip_media;  
00334 } SDPParseState;
00335 
00336 static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
00337                            int letter, const char *buf)
00338 {
00339     RTSPState *rt = s->priv_data;
00340     char buf1[64], st_type[64];
00341     const char *p;
00342     enum AVMediaType codec_type;
00343     int payload_type, i;
00344     AVStream *st;
00345     RTSPStream *rtsp_st;
00346     struct in_addr sdp_ip;
00347     int ttl;
00348 
00349     dprintf(s, "sdp: %c='%s'\n", letter, buf);
00350 
00351     p = buf;
00352     if (s1->skip_media && letter != 'm')
00353         return;
00354     switch (letter) {
00355     case 'c':
00356         get_word(buf1, sizeof(buf1), &p);
00357         if (strcmp(buf1, "IN") != 0)
00358             return;
00359         get_word(buf1, sizeof(buf1), &p);
00360         if (strcmp(buf1, "IP4") != 0)
00361             return;
00362         get_word_sep(buf1, sizeof(buf1), "/", &p);
00363         if (ff_inet_aton(buf1, &sdp_ip) == 0)
00364             return;
00365         ttl = 16;
00366         if (*p == '/') {
00367             p++;
00368             get_word_sep(buf1, sizeof(buf1), "/", &p);
00369             ttl = atoi(buf1);
00370         }
00371         if (s->nb_streams == 0) {
00372             s1->default_ip = sdp_ip;
00373             s1->default_ttl = ttl;
00374         } else {
00375             st = s->streams[s->nb_streams - 1];
00376             rtsp_st = st->priv_data;
00377             rtsp_st->sdp_ip = sdp_ip;
00378             rtsp_st->sdp_ttl = ttl;
00379         }
00380         break;
00381     case 's':
00382         av_metadata_set2(&s->metadata, "title", p, 0);
00383         break;
00384     case 'i':
00385         if (s->nb_streams == 0) {
00386             av_metadata_set2(&s->metadata, "comment", p, 0);
00387             break;
00388         }
00389         break;
00390     case 'm':
00391         /* new stream */
00392         s1->skip_media = 0;
00393         get_word(st_type, sizeof(st_type), &p);
00394         if (!strcmp(st_type, "audio")) {
00395             codec_type = AVMEDIA_TYPE_AUDIO;
00396         } else if (!strcmp(st_type, "video")) {
00397             codec_type = AVMEDIA_TYPE_VIDEO;
00398         } else if (!strcmp(st_type, "application")) {
00399             codec_type = AVMEDIA_TYPE_DATA;
00400         } else {
00401             s1->skip_media = 1;
00402             return;
00403         }
00404         rtsp_st = av_mallocz(sizeof(RTSPStream));
00405         if (!rtsp_st)
00406             return;
00407         rtsp_st->stream_index = -1;
00408         dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st);
00409 
00410         rtsp_st->sdp_ip = s1->default_ip;
00411         rtsp_st->sdp_ttl = s1->default_ttl;
00412 
00413         get_word(buf1, sizeof(buf1), &p); /* port */
00414         rtsp_st->sdp_port = atoi(buf1);
00415 
00416         get_word(buf1, sizeof(buf1), &p); /* protocol (ignored) */
00417 
00418         /* XXX: handle list of formats */
00419         get_word(buf1, sizeof(buf1), &p); /* format list */
00420         rtsp_st->sdp_payload_type = atoi(buf1);
00421 
00422         if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
00423             /* no corresponding stream */
00424         } else {
00425             st = av_new_stream(s, 0);
00426             if (!st)
00427                 return;
00428             st->priv_data = rtsp_st;
00429             rtsp_st->stream_index = st->index;
00430             st->codec->codec_type = codec_type;
00431             if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) {
00432                 /* if standard payload type, we can find the codec right now */
00433                 ff_rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type);
00434             }
00435         }
00436         /* put a default control url */
00437         av_strlcpy(rtsp_st->control_url, rt->control_uri,
00438                    sizeof(rtsp_st->control_url));
00439         break;
00440     case 'a':
00441         if (av_strstart(p, "control:", &p)) {
00442             if (s->nb_streams == 0) {
00443                 if (!strncmp(p, "rtsp://", 7))
00444                     av_strlcpy(rt->control_uri, p,
00445                                sizeof(rt->control_uri));
00446             } else {
00447             char proto[32];
00448             /* get the control url */
00449             st = s->streams[s->nb_streams - 1];
00450             rtsp_st = st->priv_data;
00451 
00452             /* XXX: may need to add full url resolution */
00453             ff_url_split(proto, sizeof(proto), NULL, 0, NULL, 0,
00454                          NULL, NULL, 0, p);
00455             if (proto[0] == '\0') {
00456                 /* relative control URL */
00457                 if (rtsp_st->control_url[strlen(rtsp_st->control_url)-1]!='/')
00458                 av_strlcat(rtsp_st->control_url, "/",
00459                            sizeof(rtsp_st->control_url));
00460                 av_strlcat(rtsp_st->control_url, p,
00461                            sizeof(rtsp_st->control_url));
00462             } else
00463                 av_strlcpy(rtsp_st->control_url, p,
00464                            sizeof(rtsp_st->control_url));
00465             }
00466         } else if (av_strstart(p, "rtpmap:", &p) && s->nb_streams > 0) {
00467             /* NOTE: rtpmap is only supported AFTER the 'm=' tag */
00468             get_word(buf1, sizeof(buf1), &p);
00469             payload_type = atoi(buf1);
00470             st = s->streams[s->nb_streams - 1];
00471             rtsp_st = st->priv_data;
00472             sdp_parse_rtpmap(s, st->codec, rtsp_st, payload_type, p);
00473         } else if (av_strstart(p, "fmtp:", &p)) {
00474             /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */
00475             get_word(buf1, sizeof(buf1), &p);
00476             payload_type = atoi(buf1);
00477             for (i = 0; i < s->nb_streams; i++) {
00478                 st      = s->streams[i];
00479                 rtsp_st = st->priv_data;
00480                 if (rtsp_st->sdp_payload_type == payload_type) {
00481                     if (!(rtsp_st->dynamic_handler &&
00482                           rtsp_st->dynamic_handler->parse_sdp_a_line &&
00483                           rtsp_st->dynamic_handler->parse_sdp_a_line(s,
00484                               i, rtsp_st->dynamic_protocol_context, buf)))
00485                         sdp_parse_fmtp(st, p);
00486                 }
00487             }
00488         } else if (av_strstart(p, "framesize:", &p)) {
00489             // let dynamic protocol handlers have a stab at the line.
00490             get_word(buf1, sizeof(buf1), &p);
00491             payload_type = atoi(buf1);
00492             for (i = 0; i < s->nb_streams; i++) {
00493                 st      = s->streams[i];
00494                 rtsp_st = st->priv_data;
00495                 if (rtsp_st->sdp_payload_type == payload_type &&
00496                     rtsp_st->dynamic_handler &&
00497                     rtsp_st->dynamic_handler->parse_sdp_a_line)
00498                     rtsp_st->dynamic_handler->parse_sdp_a_line(s, i,
00499                         rtsp_st->dynamic_protocol_context, buf);
00500             }
00501         } else if (av_strstart(p, "range:", &p)) {
00502             int64_t start, end;
00503 
00504             // this is so that seeking on a streamed file can work.
00505             rtsp_parse_range_npt(p, &start, &end);
00506             s->start_time = start;
00507             /* AV_NOPTS_VALUE means live broadcast (and can't seek) */
00508             s->duration   = (end == AV_NOPTS_VALUE) ?
00509                             AV_NOPTS_VALUE : end - start;
00510         } else if (av_strstart(p, "IsRealDataType:integer;",&p)) {
00511             if (atoi(p) == 1)
00512                 rt->transport = RTSP_TRANSPORT_RDT;
00513         } else {
00514             if (rt->server_type == RTSP_SERVER_WMS)
00515                 ff_wms_parse_sdp_a_line(s, p);
00516             if (s->nb_streams > 0) {
00517                 if (rt->server_type == RTSP_SERVER_REAL)
00518                     ff_real_parse_sdp_a_line(s, s->nb_streams - 1, p);
00519 
00520                 rtsp_st = s->streams[s->nb_streams - 1]->priv_data;
00521                 if (rtsp_st->dynamic_handler &&
00522                     rtsp_st->dynamic_handler->parse_sdp_a_line)
00523                     rtsp_st->dynamic_handler->parse_sdp_a_line(s,
00524                         s->nb_streams - 1,
00525                         rtsp_st->dynamic_protocol_context, buf);
00526             }
00527         }
00528         break;
00529     }
00530 }
00531 
00532 static int sdp_parse(AVFormatContext *s, const char *content)
00533 {
00534     const char *p;
00535     int letter;
00536     /* Some SDP lines, particularly for Realmedia or ASF RTSP streams,
00537      * contain long SDP lines containing complete ASF Headers (several
00538      * kB) or arrays of MDPR (RM stream descriptor) headers plus
00539      * "rulebooks" describing their properties. Therefore, the SDP line
00540      * buffer is large.
00541      *
00542      * The Vorbis FMTP line can be up to 16KB - see sdp_parse_fmtp. */
00543     char buf[16384], *q;
00544     SDPParseState sdp_parse_state, *s1 = &sdp_parse_state;
00545 
00546     memset(s1, 0, sizeof(SDPParseState));
00547     p = content;
00548     for (;;) {
00549         skip_spaces(&p);
00550         letter = *p;
00551         if (letter == '\0')
00552             break;
00553         p++;
00554         if (*p != '=')
00555             goto next_line;
00556         p++;
00557         /* get the content */
00558         q = buf;
00559         while (*p != '\n' && *p != '\r' && *p != '\0') {
00560             if ((q - buf) < sizeof(buf) - 1)
00561                 *q++ = *p;
00562             p++;
00563         }
00564         *q = '\0';
00565         sdp_parse_line(s, s1, letter, buf);
00566     next_line:
00567         while (*p != '\n' && *p != '\0')
00568             p++;
00569         if (*p == '\n')
00570             p++;
00571     }
00572     return 0;
00573 }
00574 
00575 /* close and free RTSP streams */
00576 void ff_rtsp_close_streams(AVFormatContext *s)
00577 {
00578     RTSPState *rt = s->priv_data;
00579     int i;
00580     RTSPStream *rtsp_st;
00581 
00582     for (i = 0; i < rt->nb_rtsp_streams; i++) {
00583         rtsp_st = rt->rtsp_streams[i];
00584         if (rtsp_st) {
00585             if (rtsp_st->transport_priv) {
00586                 if (s->oformat) {
00587                     AVFormatContext *rtpctx = rtsp_st->transport_priv;
00588                     av_write_trailer(rtpctx);
00589                     if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
00590                         uint8_t *ptr;
00591                         url_close_dyn_buf(rtpctx->pb, &ptr);
00592                         av_free(ptr);
00593                     } else {
00594                         url_fclose(rtpctx->pb);
00595                     }
00596                     av_metadata_free(&rtpctx->streams[0]->metadata);
00597                     av_metadata_free(&rtpctx->metadata);
00598                     av_free(rtpctx->streams[0]);
00599                     av_free(rtpctx);
00600                 } else if (rt->transport == RTSP_TRANSPORT_RDT)
00601                     ff_rdt_parse_close(rtsp_st->transport_priv);
00602                 else
00603                     rtp_parse_close(rtsp_st->transport_priv);
00604             }
00605             if (rtsp_st->rtp_handle)
00606                 url_close(rtsp_st->rtp_handle);
00607             if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context)
00608                 rtsp_st->dynamic_handler->close(
00609                     rtsp_st->dynamic_protocol_context);
00610         }
00611     }
00612     av_free(rt->rtsp_streams);
00613     if (rt->asf_ctx) {
00614         av_close_input_stream (rt->asf_ctx);
00615         rt->asf_ctx = NULL;
00616     }
00617 }
00618 
00619 static void *rtsp_rtp_mux_open(AVFormatContext *s, AVStream *st,
00620                                URLContext *handle)
00621 {
00622     RTSPState *rt = s->priv_data;
00623     AVFormatContext *rtpctx;
00624     int ret;
00625     AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);
00626 
00627     if (!rtp_format)
00628         return NULL;
00629 
00630     /* Allocate an AVFormatContext for each output stream */
00631     rtpctx = avformat_alloc_context();
00632     if (!rtpctx)
00633         return NULL;
00634 
00635     rtpctx->oformat = rtp_format;
00636     if (!av_new_stream(rtpctx, 0)) {
00637         av_free(rtpctx);
00638         return NULL;
00639     }
00640     /* Copy the max delay setting; the rtp muxer reads this. */
00641     rtpctx->max_delay = s->max_delay;
00642     /* Copy other stream parameters. */
00643     rtpctx->streams[0]->sample_aspect_ratio = st->sample_aspect_ratio;
00644 
00645     /* Set the synchronized start time. */
00646     rtpctx->start_time_realtime = rt->start_time;
00647 
00648     /* Remove the local codec, link to the original codec
00649      * context instead, to give the rtp muxer access to
00650      * codec parameters. */
00651     av_free(rtpctx->streams[0]->codec);
00652     rtpctx->streams[0]->codec = st->codec;
00653 
00654     if (handle) {
00655         url_fdopen(&rtpctx->pb, handle);
00656     } else
00657         url_open_dyn_packet_buf(&rtpctx->pb, RTSP_TCP_MAX_PACKET_SIZE);
00658     ret = av_write_header(rtpctx);
00659 
00660     if (ret) {
00661         if (handle) {
00662             url_fclose(rtpctx->pb);
00663         } else {
00664             uint8_t *ptr;
00665             url_close_dyn_buf(rtpctx->pb, &ptr);
00666             av_free(ptr);
00667         }
00668         av_free(rtpctx->streams[0]);
00669         av_free(rtpctx);
00670         return NULL;
00671     }
00672 
00673     /* Copy the RTP AVStream timebase back to the original AVStream */
00674     st->time_base = rtpctx->streams[0]->time_base;
00675     return rtpctx;
00676 }
00677 
00678 static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
00679 {
00680     RTSPState *rt = s->priv_data;
00681     AVStream *st = NULL;
00682 
00683     /* open the RTP context */
00684     if (rtsp_st->stream_index >= 0)
00685         st = s->streams[rtsp_st->stream_index];
00686     if (!st)
00687         s->ctx_flags |= AVFMTCTX_NOHEADER;
00688 
00689     if (s->oformat) {
00690         rtsp_st->transport_priv = rtsp_rtp_mux_open(s, st, rtsp_st->rtp_handle);
00691         /* Ownership of rtp_handle is passed to the rtp mux context */
00692         rtsp_st->rtp_handle = NULL;
00693     } else if (rt->transport == RTSP_TRANSPORT_RDT)
00694         rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
00695                                             rtsp_st->dynamic_protocol_context,
00696                                             rtsp_st->dynamic_handler);
00697     else
00698         rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle,
00699                                          rtsp_st->sdp_payload_type,
00700                                          &rtsp_st->rtp_payload_data);
00701 
00702     if (!rtsp_st->transport_priv) {
00703          return AVERROR(ENOMEM);
00704     } else if (rt->transport != RTSP_TRANSPORT_RDT) {
00705         if (rtsp_st->dynamic_handler) {
00706             rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
00707                                            rtsp_st->dynamic_protocol_context,
00708                                            rtsp_st->dynamic_handler);
00709         }
00710     }
00711 
00712     return 0;
00713 }
00714 
00715 #if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER
00716 static int rtsp_probe(AVProbeData *p)
00717 {
00718     if (av_strstart(p->filename, "rtsp:", NULL))
00719         return AVPROBE_SCORE_MAX;
00720     return 0;
00721 }
00722 
00723 static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
00724 {
00725     const char *p;
00726     int v;
00727 
00728     p = *pp;
00729     skip_spaces(&p);
00730     v = strtol(p, (char **)&p, 10);
00731     if (*p == '-') {
00732         p++;
00733         *min_ptr = v;
00734         v = strtol(p, (char **)&p, 10);
00735         *max_ptr = v;
00736     } else {
00737         *min_ptr = v;
00738         *max_ptr = v;
00739     }
00740     *pp = p;
00741 }
00742 
00743 /* XXX: only one transport specification is parsed */
00744 static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p)
00745 {
00746     char transport_protocol[16];
00747     char profile[16];
00748     char lower_transport[16];
00749     char parameter[16];
00750     RTSPTransportField *th;
00751     char buf[256];
00752 
00753     reply->nb_transports = 0;
00754 
00755     for (;;) {
00756         skip_spaces(&p);
00757         if (*p == '\0')
00758             break;
00759 
00760         th = &reply->transports[reply->nb_transports];
00761 
00762         get_word_sep(transport_protocol, sizeof(transport_protocol),
00763                      "/", &p);
00764         if (!strcasecmp (transport_protocol, "rtp")) {
00765             get_word_sep(profile, sizeof(profile), "/;,", &p);
00766             lower_transport[0] = '\0';
00767             /* rtp/avp/<protocol> */
00768             if (*p == '/') {
00769                 get_word_sep(lower_transport, sizeof(lower_transport),
00770                              ";,", &p);
00771             }
00772             th->transport = RTSP_TRANSPORT_RTP;
00773         } else if (!strcasecmp (transport_protocol, "x-pn-tng") ||
00774                    !strcasecmp (transport_protocol, "x-real-rdt")) {
00775             /* x-pn-tng/<protocol> */
00776             get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p);
00777             profile[0] = '\0';
00778             th->transport = RTSP_TRANSPORT_RDT;
00779         }
00780         if (!strcasecmp(lower_transport, "TCP"))
00781             th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
00782         else
00783             th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
00784 
00785         if (*p == ';')
00786             p++;
00787         /* get each parameter */
00788         while (*p != '\0' && *p != ',') {
00789             get_word_sep(parameter, sizeof(parameter), "=;,", &p);
00790             if (!strcmp(parameter, "port")) {
00791                 if (*p == '=') {
00792                     p++;
00793                     rtsp_parse_range(&th->port_min, &th->port_max, &p);
00794                 }
00795             } else if (!strcmp(parameter, "client_port")) {
00796                 if (*p == '=') {
00797                     p++;
00798                     rtsp_parse_range(&th->client_port_min,
00799                                      &th->client_port_max, &p);
00800                 }
00801             } else if (!strcmp(parameter, "server_port")) {
00802                 if (*p == '=') {
00803                     p++;
00804                     rtsp_parse_range(&th->server_port_min,
00805                                      &th->server_port_max, &p);
00806                 }
00807             } else if (!strcmp(parameter, "interleaved")) {
00808                 if (*p == '=') {
00809                     p++;
00810                     rtsp_parse_range(&th->interleaved_min,
00811                                      &th->interleaved_max, &p);
00812                 }
00813             } else if (!strcmp(parameter, "multicast")) {
00814                 if (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP)
00815                     th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST;
00816             } else if (!strcmp(parameter, "ttl")) {
00817                 if (*p == '=') {
00818                     p++;
00819                     th->ttl = strtol(p, (char **)&p, 10);
00820                 }
00821             } else if (!strcmp(parameter, "destination")) {
00822                 struct in_addr ipaddr;
00823 
00824                 if (*p == '=') {
00825                     p++;
00826                     get_word_sep(buf, sizeof(buf), ";,", &p);
00827                     if (ff_inet_aton(buf, &ipaddr))
00828                         th->destination = ntohl(ipaddr.s_addr);
00829                 }
00830             }
00831             while (*p != ';' && *p != '\0' && *p != ',')
00832                 p++;
00833             if (*p == ';')
00834                 p++;
00835         }
00836         if (*p == ',')
00837             p++;
00838 
00839         reply->nb_transports++;
00840     }
00841 }
00842 
00843 void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf,
00844                         HTTPAuthState *auth_state)
00845 {
00846     const char *p;
00847 
00848     /* NOTE: we do case independent match for broken servers */
00849     p = buf;
00850     if (av_stristart(p, "Session:", &p)) {
00851         int t;
00852         get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
00853         if (av_stristart(p, ";timeout=", &p) &&
00854             (t = strtol(p, NULL, 10)) > 0) {
00855             reply->timeout = t;
00856         }
00857     } else if (av_stristart(p, "Content-Length:", &p)) {
00858         reply->content_length = strtol(p, NULL, 10);
00859     } else if (av_stristart(p, "Transport:", &p)) {
00860         rtsp_parse_transport(reply, p);
00861     } else if (av_stristart(p, "CSeq:", &p)) {
00862         reply->seq = strtol(p, NULL, 10);
00863     } else if (av_stristart(p, "Range:", &p)) {
00864         rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end);
00865     } else if (av_stristart(p, "RealChallenge1:", &p)) {
00866         skip_spaces(&p);
00867         av_strlcpy(reply->real_challenge, p, sizeof(reply->real_challenge));
00868     } else if (av_stristart(p, "Server:", &p)) {
00869         skip_spaces(&p);
00870         av_strlcpy(reply->server, p, sizeof(reply->server));
00871     } else if (av_stristart(p, "Notice:", &p) ||
00872                av_stristart(p, "X-Notice:", &p)) {
00873         reply->notice = strtol(p, NULL, 10);
00874     } else if (av_stristart(p, "Location:", &p)) {
00875         skip_spaces(&p);
00876         av_strlcpy(reply->location, p , sizeof(reply->location));
00877     } else if (av_stristart(p, "WWW-Authenticate:", &p) && auth_state) {
00878         skip_spaces(&p);
00879         ff_http_auth_handle_header(auth_state, "WWW-Authenticate", p);
00880     } else if (av_stristart(p, "Authentication-Info:", &p) && auth_state) {
00881         skip_spaces(&p);
00882         ff_http_auth_handle_header(auth_state, "Authentication-Info", p);
00883     }
00884 }
00885 
00886 /* skip a RTP/TCP interleaved packet */
00887 void ff_rtsp_skip_packet(AVFormatContext *s)
00888 {
00889     RTSPState *rt = s->priv_data;
00890     int ret, len, len1;
00891     uint8_t buf[1024];
00892 
00893     ret = url_read_complete(rt->rtsp_hd, buf, 3);
00894     if (ret != 3)
00895         return;
00896     len = AV_RB16(buf + 1);
00897 
00898     dprintf(s, "skipping RTP packet len=%d\n", len);
00899 
00900     /* skip payload */
00901     while (len > 0) {
00902         len1 = len;
00903         if (len1 > sizeof(buf))
00904             len1 = sizeof(buf);
00905         ret = url_read_complete(rt->rtsp_hd, buf, len1);
00906         if (ret != len1)
00907             return;
00908         len -= len1;
00909     }
00910 }
00911 
00912 int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
00913                        unsigned char **content_ptr,
00914                        int return_on_interleaved_data)
00915 {
00916     RTSPState *rt = s->priv_data;
00917     char buf[4096], buf1[1024], *q;
00918     unsigned char ch;
00919     const char *p;
00920     int ret, content_length, line_count = 0;
00921     unsigned char *content = NULL;
00922 
00923     memset(reply, 0, sizeof(*reply));
00924 
00925     /* parse reply (XXX: use buffers) */
00926     rt->last_reply[0] = '\0';
00927     for (;;) {
00928         q = buf;
00929         for (;;) {
00930             ret = url_read_complete(rt->rtsp_hd, &ch, 1);
00931 #ifdef DEBUG_RTP_TCP
00932             dprintf(s, "ret=%d c=%02x [%c]\n", ret, ch, ch);
00933 #endif
00934             if (ret != 1)
00935                 return -1;
00936             if (ch == '\n')
00937                 break;
00938             if (ch == '$') {
00939                 /* XXX: only parse it if first char on line ? */
00940                 if (return_on_interleaved_data) {
00941                     return 1;
00942                 } else
00943                     ff_rtsp_skip_packet(s);
00944             } else if (ch != '\r') {
00945                 if ((q - buf) < sizeof(buf) - 1)
00946                     *q++ = ch;
00947             }
00948         }
00949         *q = '\0';
00950 
00951         dprintf(s, "line='%s'\n", buf);
00952 
00953         /* test if last line */
00954         if (buf[0] == '\0')
00955             break;
00956         p = buf;
00957         if (line_count == 0) {
00958             /* get reply code */
00959             get_word(buf1, sizeof(buf1), &p);
00960             get_word(buf1, sizeof(buf1), &p);
00961             reply->status_code = atoi(buf1);
00962         } else {
00963             ff_rtsp_parse_line(reply, p, &rt->auth_state);
00964             av_strlcat(rt->last_reply, p,    sizeof(rt->last_reply));
00965             av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply));
00966         }
00967         line_count++;
00968     }
00969 
00970     if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
00971         av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id));
00972 
00973     content_length = reply->content_length;
00974     if (content_length > 0) {
00975         /* leave some room for a trailing '\0' (useful for simple parsing) */
00976         content = av_malloc(content_length + 1);
00977         (void)url_read_complete(rt->rtsp_hd, content, content_length);
00978         content[content_length] = '\0';
00979     }
00980     if (content_ptr)
00981         *content_ptr = content;
00982     else
00983         av_free(content);
00984 
00985     if (rt->seq != reply->seq) {
00986         av_log(s, AV_LOG_WARNING, "CSeq %d expected, %d received.\n",
00987             rt->seq, reply->seq);
00988     }
00989 
00990     /* EOS */
00991     if (reply->notice == 2101 /* End-of-Stream Reached */      ||
00992         reply->notice == 2104 /* Start-of-Stream Reached */    ||
00993         reply->notice == 2306 /* Continuous Feed Terminated */) {
00994         rt->state = RTSP_STATE_IDLE;
00995     } else if (reply->notice >= 4400 && reply->notice < 5500) {
00996         return AVERROR(EIO); /* data or server error */
00997     } else if (reply->notice == 2401 /* Ticket Expired */ ||
00998              (reply->notice >= 5500 && reply->notice < 5600) /* end of term */ )
00999         return AVERROR(EPERM);
01000 
01001     return 0;
01002 }
01003 
01004 void ff_rtsp_send_cmd_with_content_async(AVFormatContext *s,
01005                                          const char *method, const char *url,
01006                                          const char *headers,
01007                                          const unsigned char *send_content,
01008                                          int send_content_length)
01009 {
01010     RTSPState *rt = s->priv_data;
01011     char buf[4096];
01012 
01013     rt->seq++;
01014     snprintf(buf, sizeof(buf), "%s %s RTSP/1.0\r\n", method, url);
01015     if (headers)
01016         av_strlcat(buf, headers, sizeof(buf));
01017     av_strlcatf(buf, sizeof(buf), "CSeq: %d\r\n", rt->seq);
01018     if (rt->session_id[0] != '\0' && (!headers ||
01019         !strstr(headers, "\nIf-Match:"))) {
01020         av_strlcatf(buf, sizeof(buf), "Session: %s\r\n", rt->session_id);
01021     }
01022     if (rt->auth[0]) {
01023         char *str = ff_http_auth_create_response(&rt->auth_state,
01024                                                  rt->auth, url, method);
01025         if (str)
01026             av_strlcat(buf, str, sizeof(buf));
01027         av_free(str);
01028     }
01029     if (send_content_length > 0 && send_content)
01030         av_strlcatf(buf, sizeof(buf), "Content-Length: %d\r\n", send_content_length);
01031     av_strlcat(buf, "\r\n", sizeof(buf));
01032 
01033     dprintf(s, "Sending:\n%s--\n", buf);
01034 
01035     url_write(rt->rtsp_hd, buf, strlen(buf));
01036     if (send_content_length > 0 && send_content)
01037         url_write(rt->rtsp_hd, send_content, send_content_length);
01038     rt->last_cmd_time = av_gettime();
01039 }
01040 
01041 void ff_rtsp_send_cmd_async(AVFormatContext *s, const char *method,
01042                             const char *url, const char *headers)
01043 {
01044     ff_rtsp_send_cmd_with_content_async(s, method, url, headers, NULL, 0);
01045 }
01046 
01047 void ff_rtsp_send_cmd(AVFormatContext *s, const char *method, const char *url,
01048                       const char *headers, RTSPMessageHeader *reply,
01049                       unsigned char **content_ptr)
01050 {
01051     ff_rtsp_send_cmd_with_content(s, method, url, headers, reply,
01052                                   content_ptr, NULL, 0);
01053 }
01054 
01055 void ff_rtsp_send_cmd_with_content(AVFormatContext *s,
01056                                    const char *method, const char *url,
01057                                    const char *header,
01058                                    RTSPMessageHeader *reply,
01059                                    unsigned char **content_ptr,
01060                                    const unsigned char *send_content,
01061                                    int send_content_length)
01062 {
01063     RTSPState *rt = s->priv_data;
01064     HTTPAuthType cur_auth_type;
01065 
01066 retry:
01067     cur_auth_type = rt->auth_state.auth_type;
01068     ff_rtsp_send_cmd_with_content_async(s, method, url, header,
01069                                         send_content, send_content_length);
01070 
01071     ff_rtsp_read_reply(s, reply, content_ptr, 0);
01072 
01073     if (reply->status_code == 401 && cur_auth_type == HTTP_AUTH_NONE &&
01074         rt->auth_state.auth_type != HTTP_AUTH_NONE)
01075         goto retry;
01076 }
01077 
01081 static int make_setup_request(AVFormatContext *s, const char *host, int port,
01082                               int lower_transport, const char *real_challenge)
01083 {
01084     RTSPState *rt = s->priv_data;
01085     int rtx, j, i, err, interleave = 0;
01086     RTSPStream *rtsp_st;
01087     RTSPMessageHeader reply1, *reply = &reply1;
01088     char cmd[2048];
01089     const char *trans_pref;
01090 
01091     if (rt->transport == RTSP_TRANSPORT_RDT)
01092         trans_pref = "x-pn-tng";
01093     else
01094         trans_pref = "RTP/AVP";
01095 
01096     /* default timeout: 1 minute */
01097     rt->timeout = 60;
01098 
01099     /* for each stream, make the setup request */
01100     /* XXX: we assume the same server is used for the control of each
01101      * RTSP stream */
01102 
01103     for (j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
01104         char transport[2048];
01105 
01111         if (lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
01112              rt->server_type == RTSP_SERVER_WMS) {
01113             if (i == 0) {
01114                 /* rtx first */
01115                 for (rtx = 0; rtx < rt->nb_rtsp_streams; rtx++) {
01116                     int len = strlen(rt->rtsp_streams[rtx]->control_url);
01117                     if (len >= 4 &&
01118                         !strcmp(rt->rtsp_streams[rtx]->control_url + len - 4,
01119                                 "/rtx"))
01120                         break;
01121                 }
01122                 if (rtx == rt->nb_rtsp_streams)
01123                     return -1; /* no RTX found */
01124                 rtsp_st = rt->rtsp_streams[rtx];
01125             } else
01126                 rtsp_st = rt->rtsp_streams[i > rtx ? i : i - 1];
01127         } else
01128             rtsp_st = rt->rtsp_streams[i];
01129 
01130         /* RTP/UDP */
01131         if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
01132             char buf[256];
01133 
01134             if (rt->server_type == RTSP_SERVER_WMS && i > 1) {
01135                 port = reply->transports[0].client_port_min;
01136                 goto have_port;
01137             }
01138 
01139             /* first try in specified port range */
01140             if (RTSP_RTP_PORT_MIN != 0) {
01141                 while (j <= RTSP_RTP_PORT_MAX) {
01142                     ff_url_join(buf, sizeof(buf), "rtp", NULL, host, -1,
01143                                 "?localport=%d", j);
01144                     /* we will use two ports per rtp stream (rtp and rtcp) */
01145                     j += 2;
01146                     if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0)
01147                         goto rtp_opened;
01148                 }
01149             }
01150 
01151 #if 0
01152             /* then try on any port */
01153             if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) {
01154                 err = AVERROR_INVALIDDATA;
01155                 goto fail;
01156             }
01157 #endif
01158 
01159         rtp_opened:
01160             port = rtp_get_local_port(rtsp_st->rtp_handle);
01161         have_port:
01162             snprintf(transport, sizeof(transport) - 1,
01163                      "%s/UDP;", trans_pref);
01164             if (rt->server_type != RTSP_SERVER_REAL)
01165                 av_strlcat(transport, "unicast;", sizeof(transport));
01166             av_strlcatf(transport, sizeof(transport),
01167                      "client_port=%d", port);
01168             if (rt->transport == RTSP_TRANSPORT_RTP &&
01169                 !(rt->server_type == RTSP_SERVER_WMS && i > 0))
01170                 av_strlcatf(transport, sizeof(transport), "-%d", port + 1);
01171         }
01172 
01173         /* RTP/TCP */
01174         else if (lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
01178             if (rt->server_type == RTSP_SERVER_WMS &&
01179                 s->streams[rtsp_st->stream_index]->codec->codec_type ==
01180                     AVMEDIA_TYPE_DATA)
01181                 continue;
01182             snprintf(transport, sizeof(transport) - 1,
01183                      "%s/TCP;", trans_pref);
01184             if (rt->server_type == RTSP_SERVER_WMS)
01185                 av_strlcat(transport, "unicast;", sizeof(transport));
01186             av_strlcatf(transport, sizeof(transport),
01187                         "interleaved=%d-%d",
01188                         interleave, interleave + 1);
01189             interleave += 2;
01190         }
01191 
01192         else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) {
01193             snprintf(transport, sizeof(transport) - 1,
01194                      "%s/UDP;multicast", trans_pref);
01195         }
01196         if (s->oformat) {
01197             av_strlcat(transport, ";mode=receive", sizeof(transport));
01198         } else if (rt->server_type == RTSP_SERVER_REAL ||
01199                    rt->server_type == RTSP_SERVER_WMS)
01200             av_strlcat(transport, ";mode=play", sizeof(transport));
01201         snprintf(cmd, sizeof(cmd),
01202                  "Transport: %s\r\n",
01203                  transport);
01204         if (i == 0 && rt->server_type == RTSP_SERVER_REAL) {
01205             char real_res[41], real_csum[9];
01206             ff_rdt_calc_response_and_checksum(real_res, real_csum,
01207                                               real_challenge);
01208             av_strlcatf(cmd, sizeof(cmd),
01209                         "If-Match: %s\r\n"
01210                         "RealChallenge2: %s, sd=%s\r\n",
01211                         rt->session_id, real_res, real_csum);
01212         }
01213         ff_rtsp_send_cmd(s, "SETUP", rtsp_st->control_url, cmd, reply, NULL);
01214         if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) {
01215             err = 1;
01216             goto fail;
01217         } else if (reply->status_code != RTSP_STATUS_OK ||
01218                    reply->nb_transports != 1) {
01219             err = AVERROR_INVALIDDATA;
01220             goto fail;
01221         }
01222 
01223         /* XXX: same protocol for all streams is required */
01224         if (i > 0) {
01225             if (reply->transports[0].lower_transport != rt->lower_transport ||
01226                 reply->transports[0].transport != rt->transport) {
01227                 err = AVERROR_INVALIDDATA;
01228                 goto fail;
01229             }
01230         } else {
01231             rt->lower_transport = reply->transports[0].lower_transport;
01232             rt->transport = reply->transports[0].transport;
01233         }
01234 
01235         /* close RTP connection if not choosen */
01236         if (reply->transports[0].lower_transport != RTSP_LOWER_TRANSPORT_UDP &&
01237             (lower_transport == RTSP_LOWER_TRANSPORT_UDP)) {
01238             url_close(rtsp_st->rtp_handle);
01239             rtsp_st->rtp_handle = NULL;
01240         }
01241 
01242         switch(reply->transports[0].lower_transport) {
01243         case RTSP_LOWER_TRANSPORT_TCP:
01244             rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
01245             rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
01246             break;
01247 
01248         case RTSP_LOWER_TRANSPORT_UDP: {
01249             char url[1024];
01250 
01251             /* XXX: also use address if specified */
01252             ff_url_join(url, sizeof(url), "rtp", NULL, host,
01253                         reply->transports[0].server_port_min, NULL);
01254             if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) &&
01255                 rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
01256                 err = AVERROR_INVALIDDATA;
01257                 goto fail;
01258             }
01259             /* Try to initialize the connection state in a
01260              * potential NAT router by sending dummy packets.
01261              * RTP/RTCP dummy packets are used for RDT, too.
01262              */
01263             if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat)
01264                 rtp_send_punch_packets(rtsp_st->rtp_handle);
01265             break;
01266         }
01267         case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: {
01268             char url[1024];
01269             struct in_addr in;
01270             int port, ttl;
01271 
01272             if (reply->transports[0].destination) {
01273                 in.s_addr = htonl(reply->transports[0].destination);
01274                 port      = reply->transports[0].port_min;
01275                 ttl       = reply->transports[0].ttl;
01276             } else {
01277                 in        = rtsp_st->sdp_ip;
01278                 port      = rtsp_st->sdp_port;
01279                 ttl       = rtsp_st->sdp_ttl;
01280             }
01281             ff_url_join(url, sizeof(url), "rtp", NULL, inet_ntoa(in),
01282                         port, "?ttl=%d", ttl);
01283             if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
01284                 err = AVERROR_INVALIDDATA;
01285                 goto fail;
01286             }
01287             break;
01288         }
01289         }
01290 
01291         if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
01292             goto fail;
01293     }
01294 
01295     if (reply->timeout > 0)
01296         rt->timeout = reply->timeout;
01297 
01298     if (rt->server_type == RTSP_SERVER_REAL)
01299         rt->need_subscription = 1;
01300 
01301     return 0;
01302 
01303 fail:
01304     for (i = 0; i < rt->nb_rtsp_streams; i++) {
01305         if (rt->rtsp_streams[i]->rtp_handle) {
01306             url_close(rt->rtsp_streams[i]->rtp_handle);
01307             rt->rtsp_streams[i]->rtp_handle = NULL;
01308         }
01309     }
01310     return err;
01311 }
01312 
01313 static int rtsp_read_play(AVFormatContext *s)
01314 {
01315     RTSPState *rt = s->priv_data;
01316     RTSPMessageHeader reply1, *reply = &reply1;
01317     int i;
01318     char cmd[1024];
01319 
01320     av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state);
01321 
01322     if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
01323         if (rt->state == RTSP_STATE_PAUSED) {
01324             cmd[0] = 0;
01325         } else {
01326             snprintf(cmd, sizeof(cmd),
01327                      "Range: npt=%0.3f-\r\n",
01328                      (double)rt->seek_timestamp / AV_TIME_BASE);
01329         }
01330         ff_rtsp_send_cmd(s, "PLAY", rt->control_uri, cmd, reply, NULL);
01331         if (reply->status_code != RTSP_STATUS_OK) {
01332             return -1;
01333         }
01334         if (reply->range_start != AV_NOPTS_VALUE &&
01335             rt->transport == RTSP_TRANSPORT_RTP) {
01336             for (i = 0; i < rt->nb_rtsp_streams; i++) {
01337                 RTSPStream *rtsp_st = rt->rtsp_streams[i];
01338                 RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
01339                 AVStream *st = NULL;
01340                 if (!rtpctx)
01341                     continue;
01342                 if (rtsp_st->stream_index >= 0)
01343                     st = s->streams[rtsp_st->stream_index];
01344                 rtpctx->last_rtcp_ntp_time  = AV_NOPTS_VALUE;
01345                 rtpctx->first_rtcp_ntp_time = AV_NOPTS_VALUE;
01346                 if (st)
01347                     rtpctx->range_start_offset = av_rescale_q(reply->range_start,
01348                                                               AV_TIME_BASE_Q,
01349                                                               st->time_base);
01350             }
01351         }
01352     }
01353     rt->state = RTSP_STATE_STREAMING;
01354     return 0;
01355 }
01356 
01357 static int rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply)
01358 {
01359     RTSPState *rt = s->priv_data;
01360     char cmd[1024];
01361     unsigned char *content = NULL;
01362     int ret;
01363 
01364     /* describe the stream */
01365     snprintf(cmd, sizeof(cmd),
01366              "Accept: application/sdp\r\n");
01367     if (rt->server_type == RTSP_SERVER_REAL) {
01372         av_strlcat(cmd,
01373                    "Require: com.real.retain-entity-for-setup\r\n",
01374                    sizeof(cmd));
01375     }
01376     ff_rtsp_send_cmd(s, "DESCRIBE", rt->control_uri, cmd, reply, &content);
01377     if (!content)
01378         return AVERROR_INVALIDDATA;
01379     if (reply->status_code != RTSP_STATUS_OK) {
01380         av_freep(&content);
01381         return AVERROR_INVALIDDATA;
01382     }
01383 
01384     /* now we got the SDP description, we parse it */
01385     ret = sdp_parse(s, (const char *)content);
01386     av_freep(&content);
01387     if (ret < 0)
01388         return AVERROR_INVALIDDATA;
01389 
01390     return 0;
01391 }
01392 
01393 static int rtsp_setup_output_streams(AVFormatContext *s, const char *addr)
01394 {
01395     RTSPState *rt = s->priv_data;
01396     RTSPMessageHeader reply1, *reply = &reply1;
01397     int i;
01398     char *sdp;
01399     AVFormatContext sdp_ctx, *ctx_array[1];
01400 
01401     rt->start_time = av_gettime();
01402 
01403     /* Announce the stream */
01404     sdp = av_mallocz(8192);
01405     if (sdp == NULL)
01406         return AVERROR(ENOMEM);
01407     /* We create the SDP based on the RTSP AVFormatContext where we
01408      * aren't allowed to change the filename field. (We create the SDP
01409      * based on the RTSP context since the contexts for the RTP streams
01410      * don't exist yet.) In order to specify a custom URL with the actual
01411      * peer IP instead of the originally specified hostname, we create
01412      * a temporary copy of the AVFormatContext, where the custom URL is set.
01413      *
01414      * FIXME: Create the SDP without copying the AVFormatContext.
01415      * This either requires setting up the RTP stream AVFormatContexts
01416      * already here (complicating things immensely) or getting a more
01417      * flexible SDP creation interface.
01418      */
01419     sdp_ctx = *s;
01420     ff_url_join(sdp_ctx.filename, sizeof(sdp_ctx.filename),
01421                 "rtsp", NULL, addr, -1, NULL);
01422     ctx_array[0] = &sdp_ctx;
01423     if (avf_sdp_create(ctx_array, 1, sdp, 8192)) {
01424         av_free(sdp);
01425         return AVERROR_INVALIDDATA;
01426     }
01427     av_log(s, AV_LOG_INFO, "SDP:\n%s\n", sdp);
01428     ff_rtsp_send_cmd_with_content(s, "ANNOUNCE", rt->control_uri,
01429                                   "Content-Type: application/sdp\r\n",
01430                                   reply, NULL, sdp, strlen(sdp));
01431     av_free(sdp);
01432     if (reply->status_code != RTSP_STATUS_OK)
01433         return AVERROR_INVALIDDATA;
01434 
01435     /* Set up the RTSPStreams for each AVStream */
01436     for (i = 0; i < s->nb_streams; i++) {
01437         RTSPStream *rtsp_st;
01438         AVStream *st = s->streams[i];
01439 
01440         rtsp_st = av_mallocz(sizeof(RTSPStream));
01441         if (!rtsp_st)
01442             return AVERROR(ENOMEM);
01443         dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st);
01444 
01445         st->priv_data = rtsp_st;
01446         rtsp_st->stream_index = i;
01447 
01448         av_strlcpy(rtsp_st->control_url, rt->control_uri, sizeof(rtsp_st->control_url));
01449         /* Note, this must match the relative uri set in the sdp content */
01450         av_strlcatf(rtsp_st->control_url, sizeof(rtsp_st->control_url),
01451                     "/streamid=%d", i);
01452     }
01453 
01454     return 0;
01455 }
01456 
01457 int ff_rtsp_connect(AVFormatContext *s)
01458 {
01459     RTSPState *rt = s->priv_data;
01460     char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128];
01461     char *option_list, *option, *filename;
01462     URLContext *rtsp_hd;
01463     int port, err, tcp_fd;
01464     RTSPMessageHeader reply1 = {}, *reply = &reply1;
01465     int lower_transport_mask = 0;
01466     char real_challenge[64];
01467     struct sockaddr_storage peer;
01468     socklen_t peer_len = sizeof(peer);
01469 
01470     if (!ff_network_init())
01471         return AVERROR(EIO);
01472 redirect:
01473     /* extract hostname and port */
01474     ff_url_split(NULL, 0, auth, sizeof(auth),
01475                  host, sizeof(host), &port, path, sizeof(path), s->filename);
01476     if (*auth) {
01477         av_strlcpy(rt->auth, auth, sizeof(rt->auth));
01478     }
01479     if (port < 0)
01480         port = RTSP_DEFAULT_PORT;
01481 
01482     /* search for options */
01483     option_list = strrchr(path, '?');
01484     if (option_list) {
01485         /* Strip out the RTSP specific options, write out the rest of
01486          * the options back into the same string. */
01487         filename = option_list;
01488         while (option_list) {
01489             /* move the option pointer */
01490             option = ++option_list;
01491             option_list = strchr(option_list, '&');
01492             if (option_list)
01493                 *option_list = 0;
01494 
01495             /* handle the options */
01496             if (!strcmp(option, "udp")) {
01497                 lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP);
01498             } else if (!strcmp(option, "multicast")) {
01499                 lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
01500             } else if (!strcmp(option, "tcp")) {
01501                 lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);
01502             } else {
01503                 /* Write options back into the buffer, using memmove instead
01504                  * of strcpy since the strings may overlap. */
01505                 int len = strlen(option);
01506                 memmove(++filename, option, len);
01507                 filename += len;
01508                 if (option_list) *filename = '&';
01509             }
01510         }
01511         *filename = 0;
01512     }
01513 
01514     if (!lower_transport_mask)
01515         lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
01516 
01517     if (s->oformat) {
01518         /* Only UDP or TCP - UDP multicast isn't supported. */
01519         lower_transport_mask &= (1 << RTSP_LOWER_TRANSPORT_UDP) |
01520                                 (1 << RTSP_LOWER_TRANSPORT_TCP);
01521         if (!lower_transport_mask) {
01522             av_log(s, AV_LOG_ERROR, "Unsupported lower transport method, "
01523                                     "only UDP and TCP are supported for output.\n");
01524             err = AVERROR(EINVAL);
01525             goto fail;
01526         }
01527     }
01528 
01529     /* Construct the URI used in request; this is similar to s->filename,
01530      * but with authentication credentials removed and RTSP specific options
01531      * stripped out. */
01532     ff_url_join(rt->control_uri, sizeof(rt->control_uri), "rtsp", NULL,
01533                 host, port, "%s", path);
01534 
01535     /* open the tcp connexion */
01536     ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL);
01537     if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0) {
01538         err = AVERROR(EIO);
01539         goto fail;
01540     }
01541     rt->rtsp_hd = rtsp_hd;
01542     rt->seq = 0;
01543 
01544     tcp_fd = url_get_file_handle(rtsp_hd);
01545     if (!getpeername(tcp_fd, (struct sockaddr*) &peer, &peer_len)) {
01546         getnameinfo((struct sockaddr*) &peer, peer_len, host, sizeof(host),
01547                     NULL, 0, NI_NUMERICHOST);
01548     }
01549 
01550     /* request options supported by the server; this also detects server
01551      * type */
01552     for (rt->server_type = RTSP_SERVER_RTP;;) {
01553         cmd[0] = 0;
01554         if (rt->server_type == RTSP_SERVER_REAL)
01555             av_strlcat(cmd,
01565                        "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7\r\n"
01566                        "PlayerStarttime: [28/03/2003:22:50:23 00:00]\r\n"
01567                        "CompanyID: KnKV4M4I/B2FjJ1TToLycw==\r\n"
01568                        "GUID: 00000000-0000-0000-0000-000000000000\r\n",
01569                        sizeof(cmd));
01570         ff_rtsp_send_cmd(s, "OPTIONS", rt->control_uri, cmd, reply, NULL);
01571         if (reply->status_code != RTSP_STATUS_OK) {
01572             err = AVERROR_INVALIDDATA;
01573             goto fail;
01574         }
01575 
01576         /* detect server type if not standard-compliant RTP */
01577         if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) {
01578             rt->server_type = RTSP_SERVER_REAL;
01579             continue;
01580         } else if (!strncasecmp(reply->server, "WMServer/", 9)) {
01581             rt->server_type = RTSP_SERVER_WMS;
01582         } else if (rt->server_type == RTSP_SERVER_REAL)
01583             strcpy(real_challenge, reply->real_challenge);
01584         break;
01585     }
01586 
01587     if (s->iformat)
01588         err = rtsp_setup_input_streams(s, reply);
01589     else
01590         err = rtsp_setup_output_streams(s, host);
01591     if (err)
01592         goto fail;
01593 
01594     do {
01595         int lower_transport = ff_log2_tab[lower_transport_mask &
01596                                   ~(lower_transport_mask - 1)];
01597 
01598         err = make_setup_request(s, host, port, lower_transport,
01599                                  rt->server_type == RTSP_SERVER_REAL ?
01600                                      real_challenge : NULL);
01601         if (err < 0)
01602             goto fail;
01603         lower_transport_mask &= ~(1 << lower_transport);
01604         if (lower_transport_mask == 0 && err == 1) {
01605             err = FF_NETERROR(EPROTONOSUPPORT);
01606             goto fail;
01607         }
01608     } while (err);
01609 
01610     rt->state = RTSP_STATE_IDLE;
01611     rt->seek_timestamp = 0; /* default is to start stream at position zero */
01612     return 0;
01613  fail:
01614     ff_rtsp_close_streams(s);
01615     url_close(rt->rtsp_hd);
01616     if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) {
01617         av_strlcpy(s->filename, reply->location, sizeof(s->filename));
01618         av_log(s, AV_LOG_INFO, "Status %d: Redirecting to %s\n",
01619                reply->status_code,
01620                s->filename);
01621         goto redirect;
01622     }
01623     ff_network_close();
01624     return err;
01625 }
01626 #endif
01627 
01628 #if CONFIG_RTSP_DEMUXER
01629 static int rtsp_read_header(AVFormatContext *s,
01630                             AVFormatParameters *ap)
01631 {
01632     RTSPState *rt = s->priv_data;
01633     int ret;
01634 
01635     ret = ff_rtsp_connect(s);
01636     if (ret)
01637         return ret;
01638 
01639     if (ap->initial_pause) {
01640          /* do not start immediately */
01641     } else {
01642          if (rtsp_read_play(s) < 0) {
01643             ff_rtsp_close_streams(s);
01644             url_close(rt->rtsp_hd);
01645             return AVERROR_INVALIDDATA;
01646         }
01647     }
01648 
01649     return 0;
01650 }
01651 
01652 static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
01653                            uint8_t *buf, int buf_size)
01654 {
01655     RTSPState *rt = s->priv_data;
01656     RTSPStream *rtsp_st;
01657     fd_set rfds;
01658     int fd, fd_max, n, i, ret, tcp_fd, timeout_cnt = 0;
01659     struct timeval tv;
01660 
01661     for (;;) {
01662         if (url_interrupt_cb())
01663             return AVERROR(EINTR);
01664         FD_ZERO(&rfds);
01665         if (rt->rtsp_hd) {
01666             tcp_fd = fd_max = url_get_file_handle(rt->rtsp_hd);
01667             FD_SET(tcp_fd, &rfds);
01668         } else {
01669             fd_max = 0;
01670             tcp_fd = -1;
01671         }
01672         for (i = 0; i < rt->nb_rtsp_streams; i++) {
01673             rtsp_st = rt->rtsp_streams[i];
01674             if (rtsp_st->rtp_handle) {
01675                 /* currently, we cannot probe RTCP handle because of
01676                  * blocking restrictions */
01677                 fd = url_get_file_handle(rtsp_st->rtp_handle);
01678                 if (fd > fd_max)
01679                     fd_max = fd;
01680                 FD_SET(fd, &rfds);
01681             }
01682         }
01683         tv.tv_sec = 0;
01684         tv.tv_usec = SELECT_TIMEOUT_MS * 1000;
01685         n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
01686         if (n > 0) {
01687             timeout_cnt = 0;
01688             for (i = 0; i < rt->nb_rtsp_streams; i++) {
01689                 rtsp_st = rt->rtsp_streams[i];
01690                 if (rtsp_st->rtp_handle) {
01691                     fd = url_get_file_handle(rtsp_st->rtp_handle);
01692                     if (FD_ISSET(fd, &rfds)) {
01693                         ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
01694                         if (ret > 0) {
01695                             *prtsp_st = rtsp_st;
01696                             return ret;
01697                         }
01698                     }
01699                 }
01700             }
01701 #if CONFIG_RTSP_DEMUXER
01702             if (tcp_fd != -1 && FD_ISSET(tcp_fd, &rfds)) {
01703                 RTSPMessageHeader reply;
01704 
01705                 ret = ff_rtsp_read_reply(s, &reply, NULL, 0);
01706                 if (ret < 0)
01707                     return ret;
01708                 /* XXX: parse message */
01709                 if (rt->state != RTSP_STATE_STREAMING)
01710                     return 0;
01711             }
01712 #endif
01713         } else if (n == 0 && ++timeout_cnt >= MAX_TIMEOUTS) {
01714             return FF_NETERROR(ETIMEDOUT);
01715         } else if (n < 0 && errno != EINTR)
01716             return AVERROR(errno);
01717     }
01718 }
01719 
01720 static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
01721                            uint8_t *buf, int buf_size)
01722 {
01723     RTSPState *rt = s->priv_data;
01724     int id, len, i, ret;
01725     RTSPStream *rtsp_st;
01726 
01727 #ifdef DEBUG_RTP_TCP
01728     dprintf(s, "tcp_read_packet:\n");
01729 #endif
01730 redo:
01731     for (;;) {
01732         RTSPMessageHeader reply;
01733 
01734         ret = ff_rtsp_read_reply(s, &reply, NULL, 1);
01735         if (ret == -1)
01736             return -1;
01737         if (ret == 1) /* received '$' */
01738             break;
01739         /* XXX: parse message */
01740         if (rt->state != RTSP_STATE_STREAMING)
01741             return 0;
01742     }
01743     ret = url_read_complete(rt->rtsp_hd, buf, 3);
01744     if (ret != 3)
01745         return -1;
01746     id  = buf[0];
01747     len = AV_RB16(buf + 1);
01748 #ifdef DEBUG_RTP_TCP
01749     dprintf(s, "id=%d len=%d\n", id, len);
01750 #endif
01751     if (len > buf_size || len < 12)
01752         goto redo;
01753     /* get the data */
01754     ret = url_read_complete(rt->rtsp_hd, buf, len);
01755     if (ret != len)
01756         return -1;
01757     if (rt->transport == RTSP_TRANSPORT_RDT &&
01758         ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL) < 0)
01759         return -1;
01760 
01761     /* find the matching stream */
01762     for (i = 0; i < rt->nb_rtsp_streams; i++) {
01763         rtsp_st = rt->rtsp_streams[i];
01764         if (id >= rtsp_st->interleaved_min &&
01765             id <= rtsp_st->interleaved_max)
01766             goto found;
01767     }
01768     goto redo;
01769 found:
01770     *prtsp_st = rtsp_st;
01771     return len;
01772 }
01773 
01774 static int rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt)
01775 {
01776     RTSPState *rt = s->priv_data;
01777     int ret, len;
01778     uint8_t buf[10 * RTP_MAX_PACKET_LENGTH];
01779     RTSPStream *rtsp_st;
01780 
01781     /* get next frames from the same RTP packet */
01782     if (rt->cur_transport_priv) {
01783         if (rt->transport == RTSP_TRANSPORT_RDT) {
01784             ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
01785         } else
01786             ret = rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
01787         if (ret == 0) {
01788             rt->cur_transport_priv = NULL;
01789             return 0;
01790         } else if (ret == 1) {
01791             return 0;
01792         } else
01793             rt->cur_transport_priv = NULL;
01794     }
01795 
01796     /* read next RTP packet */
01797  redo:
01798     switch(rt->lower_transport) {
01799     default:
01800 #if CONFIG_RTSP_DEMUXER
01801     case RTSP_LOWER_TRANSPORT_TCP:
01802         len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf));
01803         break;
01804 #endif
01805     case RTSP_LOWER_TRANSPORT_UDP:
01806     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
01807         len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf));
01808         if (len >=0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP)
01809             rtp_check_and_send_back_rr(rtsp_st->transport_priv, len);
01810         break;
01811     }
01812     if (len < 0)
01813         return len;
01814     if (len == 0)
01815         return AVERROR_EOF;
01816     if (rt->transport == RTSP_TRANSPORT_RDT) {
01817         ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
01818     } else {
01819         ret = rtp_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
01820         if (ret < 0) {
01821             /* Either bad packet, or a RTCP packet. Check if the
01822              * first_rtcp_ntp_time field was initialized. */
01823             RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
01824             if (rtpctx->first_rtcp_ntp_time != AV_NOPTS_VALUE) {
01825                 /* first_rtcp_ntp_time has been initialized for this stream,
01826                  * copy the same value to all other uninitialized streams,
01827                  * in order to map their timestamp origin to the same ntp time
01828                  * as this one. */
01829                 int i;
01830                 for (i = 0; i < rt->nb_rtsp_streams; i++) {
01831                     RTPDemuxContext *rtpctx2 = rtsp_st->transport_priv;
01832                     if (rtpctx2 &&
01833                         rtpctx2->first_rtcp_ntp_time == AV_NOPTS_VALUE)
01834                         rtpctx2->first_rtcp_ntp_time = rtpctx->first_rtcp_ntp_time;
01835                 }
01836             }
01837         }
01838     }
01839     if (ret < 0)
01840         goto redo;
01841     if (ret == 1)
01842         /* more packets may follow, so we save the RTP context */
01843         rt->cur_transport_priv = rtsp_st->transport_priv;
01844 
01845     return ret;
01846 }
01847 
01848 static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt)
01849 {
01850     RTSPState *rt = s->priv_data;
01851     int ret;
01852     RTSPMessageHeader reply1, *reply = &reply1;
01853     char cmd[1024];
01854 
01855     if (rt->server_type == RTSP_SERVER_REAL) {
01856         int i;
01857         enum AVDiscard cache[MAX_STREAMS];
01858 
01859         for (i = 0; i < s->nb_streams; i++)
01860             cache[i] = s->streams[i]->discard;
01861 
01862         if (!rt->need_subscription) {
01863             if (memcmp (cache, rt->real_setup_cache,
01864                         sizeof(enum AVDiscard) * s->nb_streams)) {
01865                 snprintf(cmd, sizeof(cmd),
01866                          "Unsubscribe: %s\r\n",
01867                          rt->last_subscription);
01868                 ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
01869                                  cmd, reply, NULL);
01870                 if (reply->status_code != RTSP_STATUS_OK)
01871                     return AVERROR_INVALIDDATA;
01872                 rt->need_subscription = 1;
01873             }
01874         }
01875 
01876         if (rt->need_subscription) {
01877             int r, rule_nr, first = 1;
01878 
01879             memcpy(rt->real_setup_cache, cache,
01880                    sizeof(enum AVDiscard) * s->nb_streams);
01881             rt->last_subscription[0] = 0;
01882 
01883             snprintf(cmd, sizeof(cmd),
01884                      "Subscribe: ");
01885             for (i = 0; i < rt->nb_rtsp_streams; i++) {
01886                 rule_nr = 0;
01887                 for (r = 0; r < s->nb_streams; r++) {
01888                     if (s->streams[r]->priv_data == rt->rtsp_streams[i]) {
01889                         if (s->streams[r]->discard != AVDISCARD_ALL) {
01890                             if (!first)
01891                                 av_strlcat(rt->last_subscription, ",",
01892                                            sizeof(rt->last_subscription));
01893                             ff_rdt_subscribe_rule(
01894                                 rt->last_subscription,
01895                                 sizeof(rt->last_subscription), i, rule_nr);
01896                             first = 0;
01897                         }
01898                         rule_nr++;
01899                     }
01900                 }
01901             }
01902             av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription);
01903             ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
01904                              cmd, reply, NULL);
01905             if (reply->status_code != RTSP_STATUS_OK)
01906                 return AVERROR_INVALIDDATA;
01907             rt->need_subscription = 0;
01908 
01909             if (rt->state == RTSP_STATE_STREAMING)
01910                 rtsp_read_play (s);
01911         }
01912     }
01913 
01914     ret = rtsp_fetch_packet(s, pkt);
01915     if (ret < 0)
01916         return ret;
01917 
01918     /* send dummy request to keep TCP connection alive */
01919     if ((rt->server_type == RTSP_SERVER_WMS ||
01920          rt->server_type == RTSP_SERVER_REAL) &&
01921         (av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) {
01922         if (rt->server_type == RTSP_SERVER_WMS) {
01923             ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL);
01924         } else {
01925             ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL);
01926         }
01927     }
01928 
01929     return 0;
01930 }
01931 
01932 /* pause the stream */
01933 static int rtsp_read_pause(AVFormatContext *s)
01934 {
01935     RTSPState *rt = s->priv_data;
01936     RTSPMessageHeader reply1, *reply = &reply1;
01937 
01938     if (rt->state != RTSP_STATE_STREAMING)
01939         return 0;
01940     else if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
01941         ff_rtsp_send_cmd(s, "PAUSE", rt->control_uri, NULL, reply, NULL);
01942         if (reply->status_code != RTSP_STATUS_OK) {
01943             return -1;
01944         }
01945     }
01946     rt->state = RTSP_STATE_PAUSED;
01947     return 0;
01948 }
01949 
01950 static int rtsp_read_seek(AVFormatContext *s, int stream_index,
01951                           int64_t timestamp, int flags)
01952 {
01953     RTSPState *rt = s->priv_data;
01954 
01955     rt->seek_timestamp = av_rescale_q(timestamp,
01956                                       s->streams[stream_index]->time_base,
01957                                       AV_TIME_BASE_Q);
01958     switch(rt->state) {
01959     default:
01960     case RTSP_STATE_IDLE:
01961         break;
01962     case RTSP_STATE_STREAMING:
01963         if (rtsp_read_pause(s) != 0)
01964             return -1;
01965         rt->state = RTSP_STATE_SEEKING;
01966         if (rtsp_read_play(s) != 0)
01967             return -1;
01968         break;
01969     case RTSP_STATE_PAUSED:
01970         rt->state = RTSP_STATE_IDLE;
01971         break;
01972     }
01973     return 0;
01974 }
01975 
01976 static int rtsp_read_close(AVFormatContext *s)
01977 {
01978     RTSPState *rt = s->priv_data;
01979 
01980 #if 0
01981     /* NOTE: it is valid to flush the buffer here */
01982     if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
01983         url_fclose(&rt->rtsp_gb);
01984     }
01985 #endif
01986     ff_rtsp_send_cmd_async(s, "TEARDOWN", rt->control_uri, NULL);
01987 
01988     ff_rtsp_close_streams(s);
01989     url_close(rt->rtsp_hd);
01990     ff_network_close();
01991     return 0;
01992 }
01993 
01994 AVInputFormat rtsp_demuxer = {
01995     "rtsp",
01996     NULL_IF_CONFIG_SMALL("RTSP input format"),
01997     sizeof(RTSPState),
01998     rtsp_probe,
01999     rtsp_read_header,
02000     rtsp_read_packet,
02001     rtsp_read_close,
02002     rtsp_read_seek,
02003     .flags = AVFMT_NOFILE,
02004     .read_play = rtsp_read_play,
02005     .read_pause = rtsp_read_pause,
02006 };
02007 #endif
02008 
02009 static int sdp_probe(AVProbeData *p1)
02010 {
02011     const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
02012 
02013     /* we look for a line beginning "c=IN IP4" */
02014     while (p < p_end && *p != '\0') {
02015         if (p + sizeof("c=IN IP4") - 1 < p_end &&
02016             av_strstart(p, "c=IN IP4", NULL))
02017             return AVPROBE_SCORE_MAX / 2;
02018 
02019         while (p < p_end - 1 && *p != '\n') p++;
02020         if (++p >= p_end)
02021             break;
02022         if (*p == '\r')
02023             p++;
02024     }
02025     return 0;
02026 }
02027 
02028 #define SDP_MAX_SIZE 8192
02029 
02030 static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap)
02031 {
02032     RTSPState *rt = s->priv_data;
02033     RTSPStream *rtsp_st;
02034     int size, i, err;
02035     char *content;
02036     char url[1024];
02037 
02038     if (!ff_network_init())
02039         return AVERROR(EIO);
02040 
02041     /* read the whole sdp file */
02042     /* XXX: better loading */
02043     content = av_malloc(SDP_MAX_SIZE);
02044     size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1);
02045     if (size <= 0) {
02046         av_free(content);
02047         return AVERROR_INVALIDDATA;
02048     }
02049     content[size] ='\0';
02050 
02051     sdp_parse(s, content);
02052     av_free(content);
02053 
02054     /* open each RTP stream */
02055     for (i = 0; i < rt->nb_rtsp_streams; i++) {
02056         rtsp_st = rt->rtsp_streams[i];
02057 
02058         ff_url_join(url, sizeof(url), "rtp", NULL,
02059                     inet_ntoa(rtsp_st->sdp_ip), rtsp_st->sdp_port,
02060                     "?localport=%d&ttl=%d", rtsp_st->sdp_port,
02061                     rtsp_st->sdp_ttl);
02062         if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
02063             err = AVERROR_INVALIDDATA;
02064             goto fail;
02065         }
02066         if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
02067             goto fail;
02068     }
02069     return 0;
02070 fail:
02071     ff_rtsp_close_streams(s);
02072     ff_network_close();
02073     return err;
02074 }
02075 
02076 static int sdp_read_close(AVFormatContext *s)
02077 {
02078     ff_rtsp_close_streams(s);
02079     ff_network_close();
02080     return 0;
02081 }
02082 
02083 AVInputFormat sdp_demuxer = {
02084     "sdp",
02085     NULL_IF_CONFIG_SMALL("SDP"),
02086     sizeof(RTSPState),
02087     sdp_probe,
02088     sdp_read_header,
02089     rtsp_fetch_packet,
02090     sdp_read_close,
02091 };

Generated on Fri Sep 16 2011 17:17:51 for FFmpeg by  doxygen 1.7.1