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