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