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