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