00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00051
00052
00053
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
00152
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
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
00194
00195
00196
00197
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
00204
00205
00206
00207 if (!rtsp_st->dynamic_handler)
00208 codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
00209 } else {
00210
00211
00212
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
00237
00238
00239
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
00261
00262
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
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
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);
00365 rtsp_st->sdp_port = atoi(buf1);
00366
00367 get_word(buf1, sizeof(buf1), &p);
00368
00369
00370 get_word(buf1, sizeof(buf1), &p);
00371 rtsp_st->sdp_payload_type = atoi(buf1);
00372
00373 if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
00374
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
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
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
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
00411 rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
00412
00413
00414 av_url_split(proto, sizeof(proto), NULL, 0, NULL, 0,
00415 NULL, NULL, 0, p);
00416 if (proto[0] == '\0') {
00417
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
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
00437
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
00452 rtsp_parse_range_npt(p, &start, &end);
00453 s->start_time = start;
00454
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
00489
00490
00491
00492
00493
00494
00495
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
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
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
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 av_close_input_stream (rt->asf_ctx);
00584 rt->asf_ctx = NULL;
00585 }
00586 av_free(rt->p);
00587 av_free(rt->recvbuf);
00588 }
00589
00590 static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
00591 {
00592 RTSPState *rt = s->priv_data;
00593 AVStream *st = NULL;
00594
00595
00596 if (rtsp_st->stream_index >= 0)
00597 st = s->streams[rtsp_st->stream_index];
00598 if (!st)
00599 s->ctx_flags |= AVFMTCTX_NOHEADER;
00600
00601 if (s->oformat && CONFIG_RTSP_MUXER) {
00602 rtsp_st->transport_priv = ff_rtp_chain_mux_open(s, st,
00603 rtsp_st->rtp_handle,
00604 RTSP_TCP_MAX_PACKET_SIZE);
00605
00606 rtsp_st->rtp_handle = NULL;
00607 } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC)
00608 rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
00609 rtsp_st->dynamic_protocol_context,
00610 rtsp_st->dynamic_handler);
00611 else if (CONFIG_RTPDEC)
00612 rtsp_st->transport_priv = ff_rtp_parse_open(s, st, rtsp_st->rtp_handle,
00613 rtsp_st->sdp_payload_type,
00614 (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP || !s->max_delay)
00615 ? 0 : RTP_REORDER_QUEUE_DEFAULT_SIZE);
00616
00617 if (!rtsp_st->transport_priv) {
00618 return AVERROR(ENOMEM);
00619 } else if (rt->transport != RTSP_TRANSPORT_RDT && CONFIG_RTPDEC) {
00620 if (rtsp_st->dynamic_handler) {
00621 ff_rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
00622 rtsp_st->dynamic_protocol_context,
00623 rtsp_st->dynamic_handler);
00624 }
00625 }
00626
00627 return 0;
00628 }
00629
00630 #if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER
00631 static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
00632 {
00633 const char *p;
00634 int v;
00635
00636 p = *pp;
00637 p += strspn(p, SPACE_CHARS);
00638 v = strtol(p, (char **)&p, 10);
00639 if (*p == '-') {
00640 p++;
00641 *min_ptr = v;
00642 v = strtol(p, (char **)&p, 10);
00643 *max_ptr = v;
00644 } else {
00645 *min_ptr = v;
00646 *max_ptr = v;
00647 }
00648 *pp = p;
00649 }
00650
00651
00652 static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p)
00653 {
00654 char transport_protocol[16];
00655 char profile[16];
00656 char lower_transport[16];
00657 char parameter[16];
00658 RTSPTransportField *th;
00659 char buf[256];
00660
00661 reply->nb_transports = 0;
00662
00663 for (;;) {
00664 p += strspn(p, SPACE_CHARS);
00665 if (*p == '\0')
00666 break;
00667
00668 th = &reply->transports[reply->nb_transports];
00669
00670 get_word_sep(transport_protocol, sizeof(transport_protocol),
00671 "/", &p);
00672 if (!av_strcasecmp (transport_protocol, "rtp")) {
00673 get_word_sep(profile, sizeof(profile), "/;,", &p);
00674 lower_transport[0] = '\0';
00675
00676 if (*p == '/') {
00677 get_word_sep(lower_transport, sizeof(lower_transport),
00678 ";,", &p);
00679 }
00680 th->transport = RTSP_TRANSPORT_RTP;
00681 } else if (!av_strcasecmp (transport_protocol, "x-pn-tng") ||
00682 !av_strcasecmp (transport_protocol, "x-real-rdt")) {
00683
00684 get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p);
00685 profile[0] = '\0';
00686 th->transport = RTSP_TRANSPORT_RDT;
00687 }
00688 if (!av_strcasecmp(lower_transport, "TCP"))
00689 th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
00690 else
00691 th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
00692
00693 if (*p == ';')
00694 p++;
00695
00696 while (*p != '\0' && *p != ',') {
00697 get_word_sep(parameter, sizeof(parameter), "=;,", &p);
00698 if (!strcmp(parameter, "port")) {
00699 if (*p == '=') {
00700 p++;
00701 rtsp_parse_range(&th->port_min, &th->port_max, &p);
00702 }
00703 } else if (!strcmp(parameter, "client_port")) {
00704 if (*p == '=') {
00705 p++;
00706 rtsp_parse_range(&th->client_port_min,
00707 &th->client_port_max, &p);
00708 }
00709 } else if (!strcmp(parameter, "server_port")) {
00710 if (*p == '=') {
00711 p++;
00712 rtsp_parse_range(&th->server_port_min,
00713 &th->server_port_max, &p);
00714 }
00715 } else if (!strcmp(parameter, "interleaved")) {
00716 if (*p == '=') {
00717 p++;
00718 rtsp_parse_range(&th->interleaved_min,
00719 &th->interleaved_max, &p);
00720 }
00721 } else if (!strcmp(parameter, "multicast")) {
00722 if (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP)
00723 th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST;
00724 } else if (!strcmp(parameter, "ttl")) {
00725 if (*p == '=') {
00726 p++;
00727 th->ttl = strtol(p, (char **)&p, 10);
00728 }
00729 } else if (!strcmp(parameter, "destination")) {
00730 if (*p == '=') {
00731 p++;
00732 get_word_sep(buf, sizeof(buf), ";,", &p);
00733 get_sockaddr(buf, &th->destination);
00734 }
00735 } else if (!strcmp(parameter, "source")) {
00736 if (*p == '=') {
00737 p++;
00738 get_word_sep(buf, sizeof(buf), ";,", &p);
00739 av_strlcpy(th->source, buf, sizeof(th->source));
00740 }
00741 }
00742
00743 while (*p != ';' && *p != '\0' && *p != ',')
00744 p++;
00745 if (*p == ';')
00746 p++;
00747 }
00748 if (*p == ',')
00749 p++;
00750
00751 reply->nb_transports++;
00752 }
00753 }
00754
00755 static void handle_rtp_info(RTSPState *rt, const char *url,
00756 uint32_t seq, uint32_t rtptime)
00757 {
00758 int i;
00759 if (!rtptime || !url[0])
00760 return;
00761 if (rt->transport != RTSP_TRANSPORT_RTP)
00762 return;
00763 for (i = 0; i < rt->nb_rtsp_streams; i++) {
00764 RTSPStream *rtsp_st = rt->rtsp_streams[i];
00765 RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
00766 if (!rtpctx)
00767 continue;
00768 if (!strcmp(rtsp_st->control_url, url)) {
00769 rtpctx->base_timestamp = rtptime;
00770 break;
00771 }
00772 }
00773 }
00774
00775 static void rtsp_parse_rtp_info(RTSPState *rt, const char *p)
00776 {
00777 int read = 0;
00778 char key[20], value[1024], url[1024] = "";
00779 uint32_t seq = 0, rtptime = 0;
00780
00781 for (;;) {
00782 p += strspn(p, SPACE_CHARS);
00783 if (!*p)
00784 break;
00785 get_word_sep(key, sizeof(key), "=", &p);
00786 if (*p != '=')
00787 break;
00788 p++;
00789 get_word_sep(value, sizeof(value), ";, ", &p);
00790 read++;
00791 if (!strcmp(key, "url"))
00792 av_strlcpy(url, value, sizeof(url));
00793 else if (!strcmp(key, "seq"))
00794 seq = strtoul(value, NULL, 10);
00795 else if (!strcmp(key, "rtptime"))
00796 rtptime = strtoul(value, NULL, 10);
00797 if (*p == ',') {
00798 handle_rtp_info(rt, url, seq, rtptime);
00799 url[0] = '\0';
00800 seq = rtptime = 0;
00801 read = 0;
00802 }
00803 if (*p)
00804 p++;
00805 }
00806 if (read > 0)
00807 handle_rtp_info(rt, url, seq, rtptime);
00808 }
00809
00810 void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf,
00811 RTSPState *rt, const char *method)
00812 {
00813 const char *p;
00814
00815
00816 p = buf;
00817 if (av_stristart(p, "Session:", &p)) {
00818 int t;
00819 get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
00820 if (av_stristart(p, ";timeout=", &p) &&
00821 (t = strtol(p, NULL, 10)) > 0) {
00822 reply->timeout = t;
00823 }
00824 } else if (av_stristart(p, "Content-Length:", &p)) {
00825 reply->content_length = strtol(p, NULL, 10);
00826 } else if (av_stristart(p, "Transport:", &p)) {
00827 rtsp_parse_transport(reply, p);
00828 } else if (av_stristart(p, "CSeq:", &p)) {
00829 reply->seq = strtol(p, NULL, 10);
00830 } else if (av_stristart(p, "Range:", &p)) {
00831 rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end);
00832 } else if (av_stristart(p, "RealChallenge1:", &p)) {
00833 p += strspn(p, SPACE_CHARS);
00834 av_strlcpy(reply->real_challenge, p, sizeof(reply->real_challenge));
00835 } else if (av_stristart(p, "Server:", &p)) {
00836 p += strspn(p, SPACE_CHARS);
00837 av_strlcpy(reply->server, p, sizeof(reply->server));
00838 } else if (av_stristart(p, "Notice:", &p) ||
00839 av_stristart(p, "X-Notice:", &p)) {
00840 reply->notice = strtol(p, NULL, 10);
00841 } else if (av_stristart(p, "Location:", &p)) {
00842 p += strspn(p, SPACE_CHARS);
00843 av_strlcpy(reply->location, p , sizeof(reply->location));
00844 } else if (av_stristart(p, "WWW-Authenticate:", &p) && rt) {
00845 p += strspn(p, SPACE_CHARS);
00846 ff_http_auth_handle_header(&rt->auth_state, "WWW-Authenticate", p);
00847 } else if (av_stristart(p, "Authentication-Info:", &p) && rt) {
00848 p += strspn(p, SPACE_CHARS);
00849 ff_http_auth_handle_header(&rt->auth_state, "Authentication-Info", p);
00850 } else if (av_stristart(p, "Content-Base:", &p) && rt) {
00851 p += strspn(p, SPACE_CHARS);
00852 if (method && !strcmp(method, "DESCRIBE"))
00853 av_strlcpy(rt->control_uri, p , sizeof(rt->control_uri));
00854 } else if (av_stristart(p, "RTP-Info:", &p) && rt) {
00855 p += strspn(p, SPACE_CHARS);
00856 if (method && !strcmp(method, "PLAY"))
00857 rtsp_parse_rtp_info(rt, p);
00858 } else if (av_stristart(p, "Public:", &p) && rt) {
00859 if (strstr(p, "GET_PARAMETER") &&
00860 method && !strcmp(method, "OPTIONS"))
00861 rt->get_parameter_supported = 1;
00862 } else if (av_stristart(p, "x-Accept-Dynamic-Rate:", &p) && rt) {
00863 p += strspn(p, SPACE_CHARS);
00864 rt->accept_dynamic_rate = atoi(p);
00865 }
00866 }
00867
00868
00869 void ff_rtsp_skip_packet(AVFormatContext *s)
00870 {
00871 RTSPState *rt = s->priv_data;
00872 int ret, len, len1;
00873 uint8_t buf[1024];
00874
00875 ret = ffurl_read_complete(rt->rtsp_hd, buf, 3);
00876 if (ret != 3)
00877 return;
00878 len = AV_RB16(buf + 1);
00879
00880 av_dlog(s, "skipping RTP packet len=%d\n", len);
00881
00882
00883 while (len > 0) {
00884 len1 = len;
00885 if (len1 > sizeof(buf))
00886 len1 = sizeof(buf);
00887 ret = ffurl_read_complete(rt->rtsp_hd, buf, len1);
00888 if (ret != len1)
00889 return;
00890 len -= len1;
00891 }
00892 }
00893
00894 int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
00895 unsigned char **content_ptr,
00896 int return_on_interleaved_data, const char *method)
00897 {
00898 RTSPState *rt = s->priv_data;
00899 char buf[4096], buf1[1024], *q;
00900 unsigned char ch;
00901 const char *p;
00902 int ret, content_length, line_count = 0;
00903 unsigned char *content = NULL;
00904
00905 memset(reply, 0, sizeof(*reply));
00906
00907
00908 rt->last_reply[0] = '\0';
00909 for (;;) {
00910 q = buf;
00911 for (;;) {
00912 ret = ffurl_read_complete(rt->rtsp_hd, &ch, 1);
00913 av_dlog(s, "ret=%d c=%02x [%c]\n", ret, ch, ch);
00914 if (ret != 1)
00915 return AVERROR_EOF;
00916 if (ch == '\n')
00917 break;
00918 if (ch == '$') {
00919
00920 if (return_on_interleaved_data) {
00921 return 1;
00922 } else
00923 ff_rtsp_skip_packet(s);
00924 } else if (ch != '\r') {
00925 if ((q - buf) < sizeof(buf) - 1)
00926 *q++ = ch;
00927 }
00928 }
00929 *q = '\0';
00930
00931 av_dlog(s, "line='%s'\n", buf);
00932
00933
00934 if (buf[0] == '\0')
00935 break;
00936 p = buf;
00937 if (line_count == 0) {
00938
00939 get_word(buf1, sizeof(buf1), &p);
00940 get_word(buf1, sizeof(buf1), &p);
00941 reply->status_code = atoi(buf1);
00942 av_strlcpy(reply->reason, p, sizeof(reply->reason));
00943 } else {
00944 ff_rtsp_parse_line(reply, p, rt, method);
00945 av_strlcat(rt->last_reply, p, sizeof(rt->last_reply));
00946 av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply));
00947 }
00948 line_count++;
00949 }
00950
00951 if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
00952 av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id));
00953
00954 content_length = reply->content_length;
00955 if (content_length > 0) {
00956
00957 content = av_malloc(content_length + 1);
00958 ffurl_read_complete(rt->rtsp_hd, content, content_length);
00959 content[content_length] = '\0';
00960 }
00961 if (content_ptr)
00962 *content_ptr = content;
00963 else
00964 av_free(content);
00965
00966 if (rt->seq != reply->seq) {
00967 av_log(s, AV_LOG_WARNING, "CSeq %d expected, %d received.\n",
00968 rt->seq, reply->seq);
00969 }
00970
00971
00972 if (reply->notice == 2101 ||
00973 reply->notice == 2104 ||
00974 reply->notice == 2306 ) {
00975 rt->state = RTSP_STATE_IDLE;
00976 } else if (reply->notice >= 4400 && reply->notice < 5500) {
00977 return AVERROR(EIO);
00978 } else if (reply->notice == 2401 ||
00979 (reply->notice >= 5500 && reply->notice < 5600) )
00980 return AVERROR(EPERM);
00981
00982 return 0;
00983 }
00984
00998 static int ff_rtsp_send_cmd_with_content_async(AVFormatContext *s,
00999 const char *method, const char *url,
01000 const char *headers,
01001 const unsigned char *send_content,
01002 int send_content_length)
01003 {
01004 RTSPState *rt = s->priv_data;
01005 char buf[4096], *out_buf;
01006 char base64buf[AV_BASE64_SIZE(sizeof(buf))];
01007
01008
01009 out_buf = buf;
01010 rt->seq++;
01011 snprintf(buf, sizeof(buf), "%s %s RTSP/1.0\r\n", method, url);
01012 if (headers)
01013 av_strlcat(buf, headers, sizeof(buf));
01014 av_strlcatf(buf, sizeof(buf), "CSeq: %d\r\n", rt->seq);
01015 if (rt->session_id[0] != '\0' && (!headers ||
01016 !strstr(headers, "\nIf-Match:"))) {
01017 av_strlcatf(buf, sizeof(buf), "Session: %s\r\n", rt->session_id);
01018 }
01019 if (rt->auth[0]) {
01020 char *str = ff_http_auth_create_response(&rt->auth_state,
01021 rt->auth, url, method);
01022 if (str)
01023 av_strlcat(buf, str, sizeof(buf));
01024 av_free(str);
01025 }
01026 if (send_content_length > 0 && send_content)
01027 av_strlcatf(buf, sizeof(buf), "Content-Length: %d\r\n", send_content_length);
01028 av_strlcat(buf, "\r\n", sizeof(buf));
01029
01030
01031 if (rt->control_transport == RTSP_MODE_TUNNEL) {
01032 av_base64_encode(base64buf, sizeof(base64buf), buf, strlen(buf));
01033 out_buf = base64buf;
01034 }
01035
01036 av_dlog(s, "Sending:\n%s--\n", buf);
01037
01038 ffurl_write(rt->rtsp_hd_out, out_buf, strlen(out_buf));
01039 if (send_content_length > 0 && send_content) {
01040 if (rt->control_transport == RTSP_MODE_TUNNEL) {
01041 av_log(s, AV_LOG_ERROR, "tunneling of RTSP requests "
01042 "with content data not supported\n");
01043 return AVERROR_PATCHWELCOME;
01044 }
01045 ffurl_write(rt->rtsp_hd_out, send_content, send_content_length);
01046 }
01047 rt->last_cmd_time = av_gettime();
01048
01049 return 0;
01050 }
01051
01052 int ff_rtsp_send_cmd_async(AVFormatContext *s, const char *method,
01053 const char *url, const char *headers)
01054 {
01055 return ff_rtsp_send_cmd_with_content_async(s, method, url, headers, NULL, 0);
01056 }
01057
01058 int ff_rtsp_send_cmd(AVFormatContext *s, const char *method, const char *url,
01059 const char *headers, RTSPMessageHeader *reply,
01060 unsigned char **content_ptr)
01061 {
01062 return ff_rtsp_send_cmd_with_content(s, method, url, headers, reply,
01063 content_ptr, NULL, 0);
01064 }
01065
01066 int ff_rtsp_send_cmd_with_content(AVFormatContext *s,
01067 const char *method, const char *url,
01068 const char *header,
01069 RTSPMessageHeader *reply,
01070 unsigned char **content_ptr,
01071 const unsigned char *send_content,
01072 int send_content_length)
01073 {
01074 RTSPState *rt = s->priv_data;
01075 HTTPAuthType cur_auth_type;
01076 int ret;
01077
01078 retry:
01079 cur_auth_type = rt->auth_state.auth_type;
01080 if ((ret = ff_rtsp_send_cmd_with_content_async(s, method, url, header,
01081 send_content,
01082 send_content_length)))
01083 return ret;
01084
01085 if ((ret = ff_rtsp_read_reply(s, reply, content_ptr, 0, method) ) < 0)
01086 return ret;
01087
01088 if (reply->status_code == 401 && cur_auth_type == HTTP_AUTH_NONE &&
01089 rt->auth_state.auth_type != HTTP_AUTH_NONE)
01090 goto retry;
01091
01092 if (reply->status_code > 400){
01093 av_log(s, AV_LOG_ERROR, "method %s failed: %d%s\n",
01094 method,
01095 reply->status_code,
01096 reply->reason);
01097 av_log(s, AV_LOG_DEBUG, "%s\n", rt->last_reply);
01098 }
01099
01100 return 0;
01101 }
01102
01103 int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
01104 int lower_transport, const char *real_challenge)
01105 {
01106 RTSPState *rt = s->priv_data;
01107 int rtx, j, i, err, interleave = 0;
01108 RTSPStream *rtsp_st;
01109 RTSPMessageHeader reply1, *reply = &reply1;
01110 char cmd[2048];
01111 const char *trans_pref;
01112
01113 if (rt->transport == RTSP_TRANSPORT_RDT)
01114 trans_pref = "x-pn-tng";
01115 else
01116 trans_pref = "RTP/AVP";
01117
01118
01119 rt->timeout = 60;
01120
01121
01122
01123
01124
01125 for (j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
01126 char transport[2048];
01127
01128
01129
01130
01131
01132
01133 if (lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
01134 rt->server_type == RTSP_SERVER_WMS) {
01135 if (i == 0) {
01136
01137 for (rtx = 0; rtx < rt->nb_rtsp_streams; rtx++) {
01138 int len = strlen(rt->rtsp_streams[rtx]->control_url);
01139 if (len >= 4 &&
01140 !strcmp(rt->rtsp_streams[rtx]->control_url + len - 4,
01141 "/rtx"))
01142 break;
01143 }
01144 if (rtx == rt->nb_rtsp_streams)
01145 return -1;
01146 rtsp_st = rt->rtsp_streams[rtx];
01147 } else
01148 rtsp_st = rt->rtsp_streams[i > rtx ? i : i - 1];
01149 } else
01150 rtsp_st = rt->rtsp_streams[i];
01151
01152
01153 if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
01154 char buf[256];
01155
01156 if (rt->server_type == RTSP_SERVER_WMS && i > 1) {
01157 port = reply->transports[0].client_port_min;
01158 goto have_port;
01159 }
01160
01161
01162 if (RTSP_RTP_PORT_MIN != 0) {
01163 while (j <= RTSP_RTP_PORT_MAX) {
01164 ff_url_join(buf, sizeof(buf), "rtp", NULL, host, -1,
01165 "?localport=%d", j);
01166
01167 j += 2;
01168 if (ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE,
01169 &s->interrupt_callback, NULL) == 0)
01170 goto rtp_opened;
01171 }
01172 }
01173
01174 av_log(s, AV_LOG_ERROR, "Unable to open an input RTP port\n");
01175 err = AVERROR(EIO);
01176 goto fail;
01177
01178 rtp_opened:
01179 port = ff_rtp_get_local_rtp_port(rtsp_st->rtp_handle);
01180 have_port:
01181 snprintf(transport, sizeof(transport) - 1,
01182 "%s/UDP;", trans_pref);
01183 if (rt->server_type != RTSP_SERVER_REAL)
01184 av_strlcat(transport, "unicast;", sizeof(transport));
01185 av_strlcatf(transport, sizeof(transport),
01186 "client_port=%d", port);
01187 if (rt->transport == RTSP_TRANSPORT_RTP &&
01188 !(rt->server_type == RTSP_SERVER_WMS && i > 0))
01189 av_strlcatf(transport, sizeof(transport), "-%d", port + 1);
01190 }
01191
01192
01193 else if (lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
01194
01195
01196
01197 if (rt->server_type == RTSP_SERVER_WMS &&
01198 s->streams[rtsp_st->stream_index]->codec->codec_type ==
01199 AVMEDIA_TYPE_DATA)
01200 continue;
01201 snprintf(transport, sizeof(transport) - 1,
01202 "%s/TCP;", trans_pref);
01203 if (rt->transport != RTSP_TRANSPORT_RDT)
01204 av_strlcat(transport, "unicast;", sizeof(transport));
01205 av_strlcatf(transport, sizeof(transport),
01206 "interleaved=%d-%d",
01207 interleave, interleave + 1);
01208 interleave += 2;
01209 }
01210
01211 else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) {
01212 snprintf(transport, sizeof(transport) - 1,
01213 "%s/UDP;multicast", trans_pref);
01214 }
01215 if (s->oformat) {
01216 av_strlcat(transport, ";mode=receive", sizeof(transport));
01217 } else if (rt->server_type == RTSP_SERVER_REAL ||
01218 rt->server_type == RTSP_SERVER_WMS)
01219 av_strlcat(transport, ";mode=play", sizeof(transport));
01220 snprintf(cmd, sizeof(cmd),
01221 "Transport: %s\r\n",
01222 transport);
01223 if (rt->accept_dynamic_rate)
01224 av_strlcat(cmd, "x-Dynamic-Rate: 0\r\n", sizeof(cmd));
01225 if (i == 0 && rt->server_type == RTSP_SERVER_REAL && CONFIG_RTPDEC) {
01226 char real_res[41], real_csum[9];
01227 ff_rdt_calc_response_and_checksum(real_res, real_csum,
01228 real_challenge);
01229 av_strlcatf(cmd, sizeof(cmd),
01230 "If-Match: %s\r\n"
01231 "RealChallenge2: %s, sd=%s\r\n",
01232 rt->session_id, real_res, real_csum);
01233 }
01234 ff_rtsp_send_cmd(s, "SETUP", rtsp_st->control_url, cmd, reply, NULL);
01235 if (reply->status_code == 461 && i == 0) {
01236 err = 1;
01237 goto fail;
01238 } else if (reply->status_code != RTSP_STATUS_OK ||
01239 reply->nb_transports != 1) {
01240 err = AVERROR_INVALIDDATA;
01241 goto fail;
01242 }
01243
01244
01245 if (i > 0) {
01246 if (reply->transports[0].lower_transport != rt->lower_transport ||
01247 reply->transports[0].transport != rt->transport) {
01248 err = AVERROR_INVALIDDATA;
01249 goto fail;
01250 }
01251 } else {
01252 rt->lower_transport = reply->transports[0].lower_transport;
01253 rt->transport = reply->transports[0].transport;
01254 }
01255
01256
01257
01258 if (reply->transports[0].lower_transport != lower_transport) {
01259 av_log(s, AV_LOG_ERROR, "Nonmatching transport in server reply\n");
01260 err = AVERROR_INVALIDDATA;
01261 goto fail;
01262 }
01263
01264 switch(reply->transports[0].lower_transport) {
01265 case RTSP_LOWER_TRANSPORT_TCP:
01266 rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
01267 rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
01268 break;
01269
01270 case RTSP_LOWER_TRANSPORT_UDP: {
01271 char url[1024], options[30] = "";
01272
01273 if (rt->rtsp_flags & RTSP_FLAG_FILTER_SRC)
01274 av_strlcpy(options, "?connect=1", sizeof(options));
01275
01276 if (reply->transports[0].source[0]) {
01277 ff_url_join(url, sizeof(url), "rtp", NULL,
01278 reply->transports[0].source,
01279 reply->transports[0].server_port_min, "%s", options);
01280 } else {
01281 ff_url_join(url, sizeof(url), "rtp", NULL, host,
01282 reply->transports[0].server_port_min, "%s", options);
01283 }
01284 if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) &&
01285 ff_rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
01286 err = AVERROR_INVALIDDATA;
01287 goto fail;
01288 }
01289
01290
01291
01292
01293 if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat &&
01294 CONFIG_RTPDEC)
01295 ff_rtp_send_punch_packets(rtsp_st->rtp_handle);
01296 break;
01297 }
01298 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: {
01299 char url[1024], namebuf[50];
01300 struct sockaddr_storage addr;
01301 int port, ttl;
01302
01303 if (reply->transports[0].destination.ss_family) {
01304 addr = reply->transports[0].destination;
01305 port = reply->transports[0].port_min;
01306 ttl = reply->transports[0].ttl;
01307 } else {
01308 addr = rtsp_st->sdp_ip;
01309 port = rtsp_st->sdp_port;
01310 ttl = rtsp_st->sdp_ttl;
01311 }
01312 getnameinfo((struct sockaddr*) &addr, sizeof(addr),
01313 namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST);
01314 ff_url_join(url, sizeof(url), "rtp", NULL, namebuf,
01315 port, "?ttl=%d", ttl);
01316 if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
01317 &s->interrupt_callback, NULL) < 0) {
01318 err = AVERROR_INVALIDDATA;
01319 goto fail;
01320 }
01321 break;
01322 }
01323 }
01324
01325 if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
01326 goto fail;
01327 }
01328
01329 if (reply->timeout > 0)
01330 rt->timeout = reply->timeout;
01331
01332 if (rt->server_type == RTSP_SERVER_REAL)
01333 rt->need_subscription = 1;
01334
01335 return 0;
01336
01337 fail:
01338 ff_rtsp_undo_setup(s);
01339 return err;
01340 }
01341
01342 void ff_rtsp_close_connections(AVFormatContext *s)
01343 {
01344 RTSPState *rt = s->priv_data;
01345 if (rt->rtsp_hd_out != rt->rtsp_hd) ffurl_close(rt->rtsp_hd_out);
01346 ffurl_close(rt->rtsp_hd);
01347 rt->rtsp_hd = rt->rtsp_hd_out = NULL;
01348 }
01349
01350 int ff_rtsp_connect(AVFormatContext *s)
01351 {
01352 RTSPState *rt = s->priv_data;
01353 char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128];
01354 char *option_list, *option, *filename;
01355 int port, err, tcp_fd;
01356 RTSPMessageHeader reply1 = {0}, *reply = &reply1;
01357 int lower_transport_mask = 0;
01358 char real_challenge[64] = "";
01359 struct sockaddr_storage peer;
01360 socklen_t peer_len = sizeof(peer);
01361
01362 if (!ff_network_init())
01363 return AVERROR(EIO);
01364
01365 rt->control_transport = RTSP_MODE_PLAIN;
01366 if (rt->lower_transport_mask & (1 << RTSP_LOWER_TRANSPORT_HTTP)) {
01367 rt->lower_transport_mask = 1 << RTSP_LOWER_TRANSPORT_TCP;
01368 rt->control_transport = RTSP_MODE_TUNNEL;
01369 }
01370
01371 rt->lower_transport_mask &= (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
01372
01373 redirect:
01374 lower_transport_mask = rt->lower_transport_mask;
01375
01376 av_url_split(NULL, 0, auth, sizeof(auth),
01377 host, sizeof(host), &port, path, sizeof(path), s->filename);
01378 if (*auth) {
01379 av_strlcpy(rt->auth, auth, sizeof(rt->auth));
01380 }
01381 if (port < 0)
01382 port = RTSP_DEFAULT_PORT;
01383
01384 #if FF_API_RTSP_URL_OPTIONS
01385
01386 option_list = strrchr(path, '?');
01387 if (option_list) {
01388
01389
01390 filename = option_list;
01391 while (option_list) {
01392 int handled = 1;
01393
01394 option = ++option_list;
01395 option_list = strchr(option_list, '&');
01396 if (option_list)
01397 *option_list = 0;
01398
01399
01400 if (!strcmp(option, "udp")) {
01401 lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP);
01402 } else if (!strcmp(option, "multicast")) {
01403 lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
01404 } else if (!strcmp(option, "tcp")) {
01405 lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);
01406 } else if(!strcmp(option, "http")) {
01407 lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);
01408 rt->control_transport = RTSP_MODE_TUNNEL;
01409 } else if (!strcmp(option, "filter_src")) {
01410 rt->rtsp_flags |= RTSP_FLAG_FILTER_SRC;
01411 } else {
01412
01413
01414 int len = strlen(option);
01415 memmove(++filename, option, len);
01416 filename += len;
01417 if (option_list) *filename = '&';
01418 handled = 0;
01419 }
01420 if (handled)
01421 av_log(s, AV_LOG_WARNING, "Options passed via URL are "
01422 "deprecated, use -rtsp_transport "
01423 "and -rtsp_flags instead.\n");
01424 }
01425 *filename = 0;
01426 }
01427 #endif
01428
01429 if (!lower_transport_mask)
01430 lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
01431
01432 if (s->oformat) {
01433
01434 lower_transport_mask &= (1 << RTSP_LOWER_TRANSPORT_UDP) |
01435 (1 << RTSP_LOWER_TRANSPORT_TCP);
01436 if (!lower_transport_mask || rt->control_transport == RTSP_MODE_TUNNEL) {
01437 av_log(s, AV_LOG_ERROR, "Unsupported lower transport method, "
01438 "only UDP and TCP are supported for output.\n");
01439 err = AVERROR(EINVAL);
01440 goto fail;
01441 }
01442 }
01443
01444
01445
01446
01447 ff_url_join(rt->control_uri, sizeof(rt->control_uri), "rtsp", NULL,
01448 host, port, "%s", path);
01449
01450 if (rt->control_transport == RTSP_MODE_TUNNEL) {
01451
01452 char httpname[1024];
01453 char sessioncookie[17];
01454 char headers[1024];
01455
01456 ff_url_join(httpname, sizeof(httpname), "http", auth, host, port, "%s", path);
01457 snprintf(sessioncookie, sizeof(sessioncookie), "%08x%08x",
01458 av_get_random_seed(), av_get_random_seed());
01459
01460
01461 if (ffurl_alloc(&rt->rtsp_hd, httpname, AVIO_FLAG_READ,
01462 &s->interrupt_callback) < 0) {
01463 err = AVERROR(EIO);
01464 goto fail;
01465 }
01466
01467
01468 snprintf(headers, sizeof(headers),
01469 "x-sessioncookie: %s\r\n"
01470 "Accept: application/x-rtsp-tunnelled\r\n"
01471 "Pragma: no-cache\r\n"
01472 "Cache-Control: no-cache\r\n",
01473 sessioncookie);
01474 av_opt_set(rt->rtsp_hd->priv_data, "headers", headers, 0);
01475
01476
01477 if (ffurl_connect(rt->rtsp_hd, NULL)) {
01478 err = AVERROR(EIO);
01479 goto fail;
01480 }
01481
01482
01483 if (ffurl_alloc(&rt->rtsp_hd_out, httpname, AVIO_FLAG_WRITE,
01484 &s->interrupt_callback) < 0 ) {
01485 err = AVERROR(EIO);
01486 goto fail;
01487 }
01488
01489
01490 snprintf(headers, sizeof(headers),
01491 "x-sessioncookie: %s\r\n"
01492 "Content-Type: application/x-rtsp-tunnelled\r\n"
01493 "Pragma: no-cache\r\n"
01494 "Cache-Control: no-cache\r\n"
01495 "Content-Length: 32767\r\n"
01496 "Expires: Sun, 9 Jan 1972 00:00:00 GMT\r\n",
01497 sessioncookie);
01498 av_opt_set(rt->rtsp_hd_out->priv_data, "headers", headers, 0);
01499 av_opt_set(rt->rtsp_hd_out->priv_data, "chunked_post", "0", 0);
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517 ff_http_init_auth_state(rt->rtsp_hd_out, rt->rtsp_hd);
01518
01519
01520 if (ffurl_connect(rt->rtsp_hd_out, NULL)) {
01521 err = AVERROR(EIO);
01522 goto fail;
01523 }
01524 } else {
01525
01526 ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL);
01527 if (ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
01528 &s->interrupt_callback, NULL) < 0) {
01529 err = AVERROR(EIO);
01530 goto fail;
01531 }
01532 rt->rtsp_hd_out = rt->rtsp_hd;
01533 }
01534 rt->seq = 0;
01535
01536 tcp_fd = ffurl_get_file_handle(rt->rtsp_hd);
01537 if (!getpeername(tcp_fd, (struct sockaddr*) &peer, &peer_len)) {
01538 getnameinfo((struct sockaddr*) &peer, peer_len, host, sizeof(host),
01539 NULL, 0, NI_NUMERICHOST);
01540 }
01541
01542
01543
01544 for (rt->server_type = RTSP_SERVER_RTP;;) {
01545 cmd[0] = 0;
01546 if (rt->server_type == RTSP_SERVER_REAL)
01547 av_strlcat(cmd,
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557 "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7\r\n"
01558 "PlayerStarttime: [28/03/2003:22:50:23 00:00]\r\n"
01559 "CompanyID: KnKV4M4I/B2FjJ1TToLycw==\r\n"
01560 "GUID: 00000000-0000-0000-0000-000000000000\r\n",
01561 sizeof(cmd));
01562 ff_rtsp_send_cmd(s, "OPTIONS", rt->control_uri, cmd, reply, NULL);
01563 if (reply->status_code != RTSP_STATUS_OK) {
01564 err = AVERROR_INVALIDDATA;
01565 goto fail;
01566 }
01567
01568
01569 if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) {
01570 rt->server_type = RTSP_SERVER_REAL;
01571 continue;
01572 } else if (!av_strncasecmp(reply->server, "WMServer/", 9)) {
01573 rt->server_type = RTSP_SERVER_WMS;
01574 } else if (rt->server_type == RTSP_SERVER_REAL)
01575 strcpy(real_challenge, reply->real_challenge);
01576 break;
01577 }
01578
01579 if (s->iformat && CONFIG_RTSP_DEMUXER)
01580 err = ff_rtsp_setup_input_streams(s, reply);
01581 else if (CONFIG_RTSP_MUXER)
01582 err = ff_rtsp_setup_output_streams(s, host);
01583 if (err)
01584 goto fail;
01585
01586 do {
01587 int lower_transport = ff_log2_tab[lower_transport_mask &
01588 ~(lower_transport_mask - 1)];
01589
01590 err = ff_rtsp_make_setup_request(s, host, port, lower_transport,
01591 rt->server_type == RTSP_SERVER_REAL ?
01592 real_challenge : NULL);
01593 if (err < 0)
01594 goto fail;
01595 lower_transport_mask &= ~(1 << lower_transport);
01596 if (lower_transport_mask == 0 && err == 1) {
01597 err = AVERROR(EPROTONOSUPPORT);
01598 goto fail;
01599 }
01600 } while (err);
01601
01602 rt->lower_transport_mask = lower_transport_mask;
01603 av_strlcpy(rt->real_challenge, real_challenge, sizeof(rt->real_challenge));
01604 rt->state = RTSP_STATE_IDLE;
01605 rt->seek_timestamp = 0;
01606 return 0;
01607 fail:
01608 ff_rtsp_close_streams(s);
01609 ff_rtsp_close_connections(s);
01610 if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) {
01611 av_strlcpy(s->filename, reply->location, sizeof(s->filename));
01612 av_log(s, AV_LOG_INFO, "Status %d: Redirecting to %s\n",
01613 reply->status_code,
01614 s->filename);
01615 goto redirect;
01616 }
01617 ff_network_close();
01618 return err;
01619 }
01620 #endif
01621
01622 #if CONFIG_RTPDEC
01623 static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
01624 uint8_t *buf, int buf_size, int64_t wait_end)
01625 {
01626 RTSPState *rt = s->priv_data;
01627 RTSPStream *rtsp_st;
01628 int n, i, ret, tcp_fd, timeout_cnt = 0;
01629 int max_p = 0;
01630 struct pollfd *p = rt->p;
01631
01632 for (;;) {
01633 if (ff_check_interrupt(&s->interrupt_callback))
01634 return AVERROR_EXIT;
01635 if (wait_end && wait_end - av_gettime() < 0)
01636 return AVERROR(EAGAIN);
01637 max_p = 0;
01638 if (rt->rtsp_hd) {
01639 tcp_fd = ffurl_get_file_handle(rt->rtsp_hd);
01640 p[max_p].fd = tcp_fd;
01641 p[max_p++].events = POLLIN;
01642 } else {
01643 tcp_fd = -1;
01644 }
01645 for (i = 0; i < rt->nb_rtsp_streams; i++) {
01646 rtsp_st = rt->rtsp_streams[i];
01647 if (rtsp_st->rtp_handle) {
01648 p[max_p].fd = ffurl_get_file_handle(rtsp_st->rtp_handle);
01649 p[max_p++].events = POLLIN;
01650 p[max_p].fd = ff_rtp_get_rtcp_file_handle(rtsp_st->rtp_handle);
01651 p[max_p++].events = POLLIN;
01652 }
01653 }
01654 n = poll(p, max_p, POLL_TIMEOUT_MS);
01655 if (n > 0) {
01656 int j = 1 - (tcp_fd == -1);
01657 timeout_cnt = 0;
01658 for (i = 0; i < rt->nb_rtsp_streams; i++) {
01659 rtsp_st = rt->rtsp_streams[i];
01660 if (rtsp_st->rtp_handle) {
01661 if (p[j].revents & POLLIN || p[j+1].revents & POLLIN) {
01662 ret = ffurl_read(rtsp_st->rtp_handle, buf, buf_size);
01663 if (ret > 0) {
01664 *prtsp_st = rtsp_st;
01665 return ret;
01666 }
01667 }
01668 j+=2;
01669 }
01670 }
01671 #if CONFIG_RTSP_DEMUXER
01672 if (tcp_fd != -1 && p[0].revents & POLLIN) {
01673 RTSPMessageHeader reply;
01674
01675 ret = ff_rtsp_read_reply(s, &reply, NULL, 0, NULL);
01676 if (ret < 0)
01677 return ret;
01678
01679 if (rt->state != RTSP_STATE_STREAMING)
01680 return 0;
01681 }
01682 #endif
01683 } else if (n == 0 && ++timeout_cnt >= MAX_TIMEOUTS) {
01684 return AVERROR(ETIMEDOUT);
01685 } else if (n < 0 && errno != EINTR)
01686 return AVERROR(errno);
01687 }
01688 }
01689
01690 int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt)
01691 {
01692 RTSPState *rt = s->priv_data;
01693 int ret, len;
01694 RTSPStream *rtsp_st, *first_queue_st = NULL;
01695 int64_t wait_end = 0;
01696
01697 if (rt->nb_byes == rt->nb_rtsp_streams)
01698 return AVERROR_EOF;
01699
01700
01701 if (rt->cur_transport_priv) {
01702 if (rt->transport == RTSP_TRANSPORT_RDT) {
01703 ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
01704 } else
01705 ret = ff_rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
01706 if (ret == 0) {
01707 rt->cur_transport_priv = NULL;
01708 return 0;
01709 } else if (ret == 1) {
01710 return 0;
01711 } else
01712 rt->cur_transport_priv = NULL;
01713 }
01714
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 }
01733
01734
01735 redo:
01736 if (!rt->recvbuf) {
01737 rt->recvbuf = av_malloc(RECVBUF_SIZE);
01738 if (!rt->recvbuf)
01739 return AVERROR(ENOMEM);
01740 }
01741
01742 switch(rt->lower_transport) {
01743 default:
01744 #if CONFIG_RTSP_DEMUXER
01745 case RTSP_LOWER_TRANSPORT_TCP:
01746 len = ff_rtsp_tcp_read_packet(s, &rtsp_st, rt->recvbuf, RECVBUF_SIZE);
01747 break;
01748 #endif
01749 case RTSP_LOWER_TRANSPORT_UDP:
01750 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
01751 len = udp_read_packet(s, &rtsp_st, rt->recvbuf, RECVBUF_SIZE, wait_end);
01752 if (len > 0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP)
01753 ff_rtp_check_and_send_back_rr(rtsp_st->transport_priv, len);
01754 break;
01755 }
01756 if (len == AVERROR(EAGAIN) && first_queue_st &&
01757 rt->transport == RTSP_TRANSPORT_RTP) {
01758 rtsp_st = first_queue_st;
01759 ret = ff_rtp_parse_packet(rtsp_st->transport_priv, pkt, NULL, 0);
01760 goto end;
01761 }
01762 if (len < 0)
01763 return len;
01764 if (len == 0)
01765 return AVERROR_EOF;
01766 if (rt->transport == RTSP_TRANSPORT_RDT) {
01767 ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);
01768 } else {
01769 ret = ff_rtp_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);
01770 if (ret < 0) {
01771
01772
01773 RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
01774 if (rtpctx->first_rtcp_ntp_time != AV_NOPTS_VALUE) {
01775
01776
01777
01778
01779 int i;
01780 AVStream *st = NULL;
01781 if (rtsp_st->stream_index >= 0)
01782 st = s->streams[rtsp_st->stream_index];
01783 for (i = 0; i < rt->nb_rtsp_streams; i++) {
01784 RTPDemuxContext *rtpctx2 = rt->rtsp_streams[i]->transport_priv;
01785 AVStream *st2 = NULL;
01786 if (rt->rtsp_streams[i]->stream_index >= 0)
01787 st2 = s->streams[rt->rtsp_streams[i]->stream_index];
01788 if (rtpctx2 && st && st2 &&
01789 rtpctx2->first_rtcp_ntp_time == AV_NOPTS_VALUE) {
01790 rtpctx2->first_rtcp_ntp_time = rtpctx->first_rtcp_ntp_time;
01791 rtpctx2->rtcp_ts_offset = av_rescale_q(
01792 rtpctx->rtcp_ts_offset, st->time_base,
01793 st2->time_base);
01794 }
01795 }
01796 }
01797 if (ret == -RTCP_BYE) {
01798 rt->nb_byes++;
01799
01800 av_log(s, AV_LOG_DEBUG, "Received BYE for stream %d (%d/%d)\n",
01801 rtsp_st->stream_index, rt->nb_byes, rt->nb_rtsp_streams);
01802
01803 if (rt->nb_byes == rt->nb_rtsp_streams)
01804 return AVERROR_EOF;
01805 }
01806 }
01807 }
01808 end:
01809 if (ret < 0)
01810 goto redo;
01811 if (ret == 1)
01812
01813 rt->cur_transport_priv = rtsp_st->transport_priv;
01814
01815 return ret;
01816 }
01817 #endif
01818
01819 #if CONFIG_SDP_DEMUXER
01820 static int sdp_probe(AVProbeData *p1)
01821 {
01822 const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
01823
01824
01825 while (p < p_end && *p != '\0') {
01826 if (p + sizeof("c=IN IP") - 1 < p_end &&
01827 av_strstart(p, "c=IN IP", NULL))
01828 return AVPROBE_SCORE_MAX / 2;
01829
01830 while (p < p_end - 1 && *p != '\n') p++;
01831 if (++p >= p_end)
01832 break;
01833 if (*p == '\r')
01834 p++;
01835 }
01836 return 0;
01837 }
01838
01839 static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap)
01840 {
01841 RTSPState *rt = s->priv_data;
01842 RTSPStream *rtsp_st;
01843 int size, i, err;
01844 char *content;
01845 char url[1024];
01846
01847 if (!ff_network_init())
01848 return AVERROR(EIO);
01849
01850
01851
01852 content = av_malloc(SDP_MAX_SIZE);
01853 size = avio_read(s->pb, content, SDP_MAX_SIZE - 1);
01854 if (size <= 0) {
01855 av_free(content);
01856 return AVERROR_INVALIDDATA;
01857 }
01858 content[size] ='\0';
01859
01860 err = ff_sdp_parse(s, content);
01861 av_free(content);
01862 if (err) goto fail;
01863
01864
01865 for (i = 0; i < rt->nb_rtsp_streams; i++) {
01866 char namebuf[50];
01867 rtsp_st = rt->rtsp_streams[i];
01868
01869 getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, sizeof(rtsp_st->sdp_ip),
01870 namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST);
01871 ff_url_join(url, sizeof(url), "rtp", NULL,
01872 namebuf, rtsp_st->sdp_port,
01873 "?localport=%d&ttl=%d&connect=%d", rtsp_st->sdp_port,
01874 rtsp_st->sdp_ttl,
01875 rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0);
01876 if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
01877 &s->interrupt_callback, NULL) < 0) {
01878 err = AVERROR_INVALIDDATA;
01879 goto fail;
01880 }
01881 if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
01882 goto fail;
01883 }
01884 return 0;
01885 fail:
01886 ff_rtsp_close_streams(s);
01887 ff_network_close();
01888 return err;
01889 }
01890
01891 static int sdp_read_close(AVFormatContext *s)
01892 {
01893 ff_rtsp_close_streams(s);
01894 ff_network_close();
01895 return 0;
01896 }
01897
01898 static const AVClass sdp_demuxer_class = {
01899 .class_name = "SDP demuxer",
01900 .item_name = av_default_item_name,
01901 .option = sdp_options,
01902 .version = LIBAVUTIL_VERSION_INT,
01903 };
01904
01905 AVInputFormat ff_sdp_demuxer = {
01906 .name = "sdp",
01907 .long_name = NULL_IF_CONFIG_SMALL("SDP"),
01908 .priv_data_size = sizeof(RTSPState),
01909 .read_probe = sdp_probe,
01910 .read_header = sdp_read_header,
01911 .read_packet = ff_rtsp_fetch_packet,
01912 .read_close = sdp_read_close,
01913 .priv_class = &sdp_demuxer_class
01914 };
01915 #endif
01916
01917 #if CONFIG_RTP_DEMUXER
01918 static int rtp_probe(AVProbeData *p)
01919 {
01920 if (av_strstart(p->filename, "rtp:", NULL))
01921 return AVPROBE_SCORE_MAX;
01922 return 0;
01923 }
01924
01925 static int rtp_read_header(AVFormatContext *s,
01926 AVFormatParameters *ap)
01927 {
01928 uint8_t recvbuf[1500];
01929 char host[500], sdp[500];
01930 int ret, port;
01931 URLContext* in = NULL;
01932 int payload_type;
01933 AVCodecContext codec;
01934 struct sockaddr_storage addr;
01935 AVIOContext pb;
01936 socklen_t addrlen = sizeof(addr);
01937 RTSPState *rt = s->priv_data;
01938
01939 if (!ff_network_init())
01940 return AVERROR(EIO);
01941
01942 ret = ffurl_open(&in, s->filename, AVIO_FLAG_READ,
01943 &s->interrupt_callback, NULL);
01944 if (ret)
01945 goto fail;
01946
01947 while (1) {
01948 ret = ffurl_read(in, recvbuf, sizeof(recvbuf));
01949 if (ret == AVERROR(EAGAIN))
01950 continue;
01951 if (ret < 0)
01952 goto fail;
01953 if (ret < 12) {
01954 av_log(s, AV_LOG_WARNING, "Received too short packet\n");
01955 continue;
01956 }
01957
01958 if ((recvbuf[0] & 0xc0) != 0x80) {
01959 av_log(s, AV_LOG_WARNING, "Unsupported RTP version packet "
01960 "received\n");
01961 continue;
01962 }
01963
01964 payload_type = recvbuf[1] & 0x7f;
01965 break;
01966 }
01967 getsockname(ffurl_get_file_handle(in), (struct sockaddr*) &addr, &addrlen);
01968 ffurl_close(in);
01969 in = NULL;
01970
01971 memset(&codec, 0, sizeof(codec));
01972 if (ff_rtp_get_codec_info(&codec, payload_type)) {
01973 av_log(s, AV_LOG_ERROR, "Unable to receive RTP payload type %d "
01974 "without an SDP file describing it\n",
01975 payload_type);
01976 goto fail;
01977 }
01978 if (codec.codec_type != AVMEDIA_TYPE_DATA) {
01979 av_log(s, AV_LOG_WARNING, "Guessing on RTP content - if not received "
01980 "properly you need an SDP file "
01981 "describing it\n");
01982 }
01983
01984 av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port,
01985 NULL, 0, s->filename);
01986
01987 snprintf(sdp, sizeof(sdp),
01988 "v=0\r\nc=IN IP%d %s\r\nm=%s %d RTP/AVP %d\r\n",
01989 addr.ss_family == AF_INET ? 4 : 6, host,
01990 codec.codec_type == AVMEDIA_TYPE_DATA ? "application" :
01991 codec.codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio",
01992 port, payload_type);
01993 av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sdp);
01994
01995 ffio_init_context(&pb, sdp, strlen(sdp), 0, NULL, NULL, NULL, NULL);
01996 s->pb = &pb;
01997
01998
01999 ff_network_close();
02000
02001 rt->media_type_mask = (1 << (AVMEDIA_TYPE_DATA+1)) - 1;
02002
02003 ret = sdp_read_header(s, ap);
02004 s->pb = NULL;
02005 return ret;
02006
02007 fail:
02008 if (in)
02009 ffurl_close(in);
02010 ff_network_close();
02011 return ret;
02012 }
02013
02014 static const AVClass rtp_demuxer_class = {
02015 .class_name = "RTP demuxer",
02016 .item_name = av_default_item_name,
02017 .option = rtp_options,
02018 .version = LIBAVUTIL_VERSION_INT,
02019 };
02020
02021 AVInputFormat ff_rtp_demuxer = {
02022 .name = "rtp",
02023 .long_name = NULL_IF_CONFIG_SMALL("RTP input format"),
02024 .priv_data_size = sizeof(RTSPState),
02025 .read_probe = rtp_probe,
02026 .read_header = rtp_read_header,
02027 .read_packet = ff_rtsp_fetch_packet,
02028 .read_close = sdp_read_close,
02029 .flags = AVFMT_NOFILE,
02030 .priv_class = &rtp_demuxer_class
02031 };
02032 #endif
02033