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 "avformat.h"
00026
00027 #include <sys/time.h>
00028 #if HAVE_SYS_SELECT_H
00029 #include <sys/select.h>
00030 #endif
00031 #include <strings.h>
00032 #include "internal.h"
00033 #include "network.h"
00034 #include "os_support.h"
00035 #include "rtsp.h"
00036
00037 #include "rtpdec.h"
00038 #include "rdt.h"
00039 #include "rtpdec_asf.h"
00040
00041
00042
00043
00044 #if LIBAVFORMAT_VERSION_INT < (53 << 16)
00045 int rtsp_default_protocols = (1 << RTSP_LOWER_TRANSPORT_UDP);
00046 #endif
00047
00048
00049
00050 #define SELECT_TIMEOUT_MS 100
00051 #define READ_PACKET_TIMEOUT_S 10
00052 #define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / SELECT_TIMEOUT_MS
00053
00054 #define SPACE_CHARS " \t\r\n"
00055
00056
00057 #define redir_isspace(c) memchr(SPACE_CHARS, c, 4)
00058 static void skip_spaces(const char **pp)
00059 {
00060 const char *p;
00061 p = *pp;
00062 while (redir_isspace(*p))
00063 p++;
00064 *pp = p;
00065 }
00066
00067 static void get_word_until_chars(char *buf, int buf_size,
00068 const char *sep, const char **pp)
00069 {
00070 const char *p;
00071 char *q;
00072
00073 p = *pp;
00074 skip_spaces(&p);
00075 q = buf;
00076 while (!strchr(sep, *p) && *p != '\0') {
00077 if ((q - buf) < buf_size - 1)
00078 *q++ = *p;
00079 p++;
00080 }
00081 if (buf_size > 0)
00082 *q = '\0';
00083 *pp = p;
00084 }
00085
00086 static void get_word_sep(char *buf, int buf_size, const char *sep,
00087 const char **pp)
00088 {
00089 if (**pp == '/') (*pp)++;
00090 get_word_until_chars(buf, buf_size, sep, pp);
00091 }
00092
00093 static void get_word(char *buf, int buf_size, const char **pp)
00094 {
00095 get_word_until_chars(buf, buf_size, SPACE_CHARS, pp);
00096 }
00097
00098
00099 static int sdp_parse_rtpmap(AVFormatContext *s,
00100 AVCodecContext *codec, RTSPStream *rtsp_st,
00101 int payload_type, const char *p)
00102 {
00103 char buf[256];
00104 int i;
00105 AVCodec *c;
00106 const char *c_name;
00107
00108
00109
00110
00111
00112
00113 get_word_sep(buf, sizeof(buf), "/ ", &p);
00114 if (payload_type >= RTP_PT_PRIVATE) {
00115 RTPDynamicProtocolHandler *handler;
00116 for (handler = RTPFirstDynamicPayloadHandler;
00117 handler; handler = handler->next) {
00118 if (!strcasecmp(buf, handler->enc_name) &&
00119 codec->codec_type == handler->codec_type) {
00120 codec->codec_id = handler->codec_id;
00121 rtsp_st->dynamic_handler = handler;
00122 if (handler->open)
00123 rtsp_st->dynamic_protocol_context = handler->open();
00124 break;
00125 }
00126 }
00127 } else {
00128
00129
00130
00131 codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
00132 }
00133
00134 c = avcodec_find_decoder(codec->codec_id);
00135 if (c && c->name)
00136 c_name = c->name;
00137 else
00138 c_name = "(null)";
00139
00140 get_word_sep(buf, sizeof(buf), "/", &p);
00141 i = atoi(buf);
00142 switch (codec->codec_type) {
00143 case AVMEDIA_TYPE_AUDIO:
00144 av_log(s, AV_LOG_DEBUG, "audio codec set to: %s\n", c_name);
00145 codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE;
00146 codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS;
00147 if (i > 0) {
00148 codec->sample_rate = i;
00149 get_word_sep(buf, sizeof(buf), "/", &p);
00150 i = atoi(buf);
00151 if (i > 0)
00152 codec->channels = i;
00153
00154
00155
00156
00157 }
00158 av_log(s, AV_LOG_DEBUG, "audio samplerate set to: %i\n",
00159 codec->sample_rate);
00160 av_log(s, AV_LOG_DEBUG, "audio channels set to: %i\n",
00161 codec->channels);
00162 break;
00163 case AVMEDIA_TYPE_VIDEO:
00164 av_log(s, AV_LOG_DEBUG, "video codec set to: %s\n", c_name);
00165 break;
00166 default:
00167 break;
00168 }
00169 return 0;
00170 }
00171
00172
00173 static int hex_to_data(uint8_t *data, const char *p)
00174 {
00175 int c, len, v;
00176
00177 len = 0;
00178 v = 1;
00179 for (;;) {
00180 skip_spaces(&p);
00181 if (*p == '\0')
00182 break;
00183 c = toupper((unsigned char) *p++);
00184 if (c >= '0' && c <= '9')
00185 c = c - '0';
00186 else if (c >= 'A' && c <= 'F')
00187 c = c - 'A' + 10;
00188 else
00189 break;
00190 v = (v << 4) | c;
00191 if (v & 0x100) {
00192 if (data)
00193 data[len] = v;
00194 len++;
00195 v = 1;
00196 }
00197 }
00198 return len;
00199 }
00200
00201 static void sdp_parse_fmtp_config(AVCodecContext * codec, void *ctx,
00202 char *attr, char *value)
00203 {
00204 switch (codec->codec_id) {
00205 case CODEC_ID_MPEG4:
00206 case CODEC_ID_AAC:
00207 if (!strcmp(attr, "config")) {
00208
00209 int len = hex_to_data(NULL, value);
00210 if (codec->extradata)
00211 av_free(codec->extradata);
00212 codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
00213 if (!codec->extradata)
00214 return;
00215 codec->extradata_size = len;
00216 hex_to_data(codec->extradata, value);
00217 }
00218 break;
00219 default:
00220 break;
00221 }
00222 return;
00223 }
00224
00225 typedef struct {
00226 const char *str;
00227 uint16_t type;
00228 uint32_t offset;
00229 } AttrNameMap;
00230
00231
00232 #define ATTR_NAME_TYPE_INT 0
00233 #define ATTR_NAME_TYPE_STR 1
00234 static const AttrNameMap attr_names[]=
00235 {
00236 { "SizeLength", ATTR_NAME_TYPE_INT,
00237 offsetof(RTPPayloadData, sizelength) },
00238 { "IndexLength", ATTR_NAME_TYPE_INT,
00239 offsetof(RTPPayloadData, indexlength) },
00240 { "IndexDeltaLength", ATTR_NAME_TYPE_INT,
00241 offsetof(RTPPayloadData, indexdeltalength) },
00242 { "profile-level-id", ATTR_NAME_TYPE_INT,
00243 offsetof(RTPPayloadData, profile_level_id) },
00244 { "StreamType", ATTR_NAME_TYPE_INT,
00245 offsetof(RTPPayloadData, streamtype) },
00246 { "mode", ATTR_NAME_TYPE_STR,
00247 offsetof(RTPPayloadData, mode) },
00248 { NULL, -1, -1 },
00249 };
00250
00251
00252
00253
00254 int ff_rtsp_next_attr_and_value(const char **p, char *attr, int attr_size,
00255 char *value, int value_size)
00256 {
00257 skip_spaces(p);
00258 if (**p) {
00259 get_word_sep(attr, attr_size, "=", p);
00260 if (**p == '=')
00261 (*p)++;
00262 get_word_sep(value, value_size, ";", p);
00263 if (**p == ';')
00264 (*p)++;
00265 return 1;
00266 }
00267 return 0;
00268 }
00269
00270
00271 static void sdp_parse_fmtp(AVStream *st, const char *p)
00272 {
00273 char attr[256];
00274
00275
00276 char value[16384];
00277 int i;
00278 RTSPStream *rtsp_st = st->priv_data;
00279 AVCodecContext *codec = st->codec;
00280 RTPPayloadData *rtp_payload_data = &rtsp_st->rtp_payload_data;
00281
00282
00283 while (ff_rtsp_next_attr_and_value(&p, attr, sizeof(attr),
00284 value, sizeof(value))) {
00285
00286
00287 sdp_parse_fmtp_config(codec, rtsp_st->dynamic_protocol_context,
00288 attr, value);
00289
00290 for (i = 0; attr_names[i].str; ++i) {
00291 if (!strcasecmp(attr, attr_names[i].str)) {
00292 if (attr_names[i].type == ATTR_NAME_TYPE_INT) {
00293 *(int *)((char *)rtp_payload_data +
00294 attr_names[i].offset) = atoi(value);
00295 } else if (attr_names[i].type == ATTR_NAME_TYPE_STR)
00296 *(char **)((char *)rtp_payload_data +
00297 attr_names[i].offset) = av_strdup(value);
00298 }
00299 }
00300 }
00301 }
00302
00307 static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end)
00308 {
00309 char buf[256];
00310
00311 skip_spaces(&p);
00312 if (!av_stristart(p, "npt=", &p))
00313 return;
00314
00315 *start = AV_NOPTS_VALUE;
00316 *end = AV_NOPTS_VALUE;
00317
00318 get_word_sep(buf, sizeof(buf), "-", &p);
00319 *start = parse_date(buf, 1);
00320 if (*p == '-') {
00321 p++;
00322 get_word_sep(buf, sizeof(buf), "-", &p);
00323 *end = parse_date(buf, 1);
00324 }
00325
00326
00327 }
00328
00329 typedef struct SDPParseState {
00330
00331 struct in_addr default_ip;
00332 int default_ttl;
00333 int skip_media;
00334 } SDPParseState;
00335
00336 static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
00337 int letter, const char *buf)
00338 {
00339 RTSPState *rt = s->priv_data;
00340 char buf1[64], st_type[64];
00341 const char *p;
00342 enum AVMediaType codec_type;
00343 int payload_type, i;
00344 AVStream *st;
00345 RTSPStream *rtsp_st;
00346 struct in_addr sdp_ip;
00347 int ttl;
00348
00349 dprintf(s, "sdp: %c='%s'\n", letter, buf);
00350
00351 p = buf;
00352 if (s1->skip_media && letter != 'm')
00353 return;
00354 switch (letter) {
00355 case 'c':
00356 get_word(buf1, sizeof(buf1), &p);
00357 if (strcmp(buf1, "IN") != 0)
00358 return;
00359 get_word(buf1, sizeof(buf1), &p);
00360 if (strcmp(buf1, "IP4") != 0)
00361 return;
00362 get_word_sep(buf1, sizeof(buf1), "/", &p);
00363 if (ff_inet_aton(buf1, &sdp_ip) == 0)
00364 return;
00365 ttl = 16;
00366 if (*p == '/') {
00367 p++;
00368 get_word_sep(buf1, sizeof(buf1), "/", &p);
00369 ttl = atoi(buf1);
00370 }
00371 if (s->nb_streams == 0) {
00372 s1->default_ip = sdp_ip;
00373 s1->default_ttl = ttl;
00374 } else {
00375 st = s->streams[s->nb_streams - 1];
00376 rtsp_st = st->priv_data;
00377 rtsp_st->sdp_ip = sdp_ip;
00378 rtsp_st->sdp_ttl = ttl;
00379 }
00380 break;
00381 case 's':
00382 av_metadata_set2(&s->metadata, "title", p, 0);
00383 break;
00384 case 'i':
00385 if (s->nb_streams == 0) {
00386 av_metadata_set2(&s->metadata, "comment", p, 0);
00387 break;
00388 }
00389 break;
00390 case 'm':
00391
00392 s1->skip_media = 0;
00393 get_word(st_type, sizeof(st_type), &p);
00394 if (!strcmp(st_type, "audio")) {
00395 codec_type = AVMEDIA_TYPE_AUDIO;
00396 } else if (!strcmp(st_type, "video")) {
00397 codec_type = AVMEDIA_TYPE_VIDEO;
00398 } else if (!strcmp(st_type, "application")) {
00399 codec_type = AVMEDIA_TYPE_DATA;
00400 } else {
00401 s1->skip_media = 1;
00402 return;
00403 }
00404 rtsp_st = av_mallocz(sizeof(RTSPStream));
00405 if (!rtsp_st)
00406 return;
00407 rtsp_st->stream_index = -1;
00408 dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st);
00409
00410 rtsp_st->sdp_ip = s1->default_ip;
00411 rtsp_st->sdp_ttl = s1->default_ttl;
00412
00413 get_word(buf1, sizeof(buf1), &p);
00414 rtsp_st->sdp_port = atoi(buf1);
00415
00416 get_word(buf1, sizeof(buf1), &p);
00417
00418
00419 get_word(buf1, sizeof(buf1), &p);
00420 rtsp_st->sdp_payload_type = atoi(buf1);
00421
00422 if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
00423
00424 } else {
00425 st = av_new_stream(s, 0);
00426 if (!st)
00427 return;
00428 st->priv_data = rtsp_st;
00429 rtsp_st->stream_index = st->index;
00430 st->codec->codec_type = codec_type;
00431 if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) {
00432
00433 ff_rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type);
00434 }
00435 }
00436
00437 av_strlcpy(rtsp_st->control_url, rt->control_uri,
00438 sizeof(rtsp_st->control_url));
00439 break;
00440 case 'a':
00441 if (av_strstart(p, "control:", &p)) {
00442 if (s->nb_streams == 0) {
00443 if (!strncmp(p, "rtsp://", 7))
00444 av_strlcpy(rt->control_uri, p,
00445 sizeof(rt->control_uri));
00446 } else {
00447 char proto[32];
00448
00449 st = s->streams[s->nb_streams - 1];
00450 rtsp_st = st->priv_data;
00451
00452
00453 ff_url_split(proto, sizeof(proto), NULL, 0, NULL, 0,
00454 NULL, NULL, 0, p);
00455 if (proto[0] == '\0') {
00456
00457 if (rtsp_st->control_url[strlen(rtsp_st->control_url)-1]!='/')
00458 av_strlcat(rtsp_st->control_url, "/",
00459 sizeof(rtsp_st->control_url));
00460 av_strlcat(rtsp_st->control_url, p,
00461 sizeof(rtsp_st->control_url));
00462 } else
00463 av_strlcpy(rtsp_st->control_url, p,
00464 sizeof(rtsp_st->control_url));
00465 }
00466 } else if (av_strstart(p, "rtpmap:", &p) && s->nb_streams > 0) {
00467
00468 get_word(buf1, sizeof(buf1), &p);
00469 payload_type = atoi(buf1);
00470 st = s->streams[s->nb_streams - 1];
00471 rtsp_st = st->priv_data;
00472 sdp_parse_rtpmap(s, st->codec, rtsp_st, payload_type, p);
00473 } else if (av_strstart(p, "fmtp:", &p)) {
00474
00475 get_word(buf1, sizeof(buf1), &p);
00476 payload_type = atoi(buf1);
00477 for (i = 0; i < s->nb_streams; i++) {
00478 st = s->streams[i];
00479 rtsp_st = st->priv_data;
00480 if (rtsp_st->sdp_payload_type == payload_type) {
00481 if (!(rtsp_st->dynamic_handler &&
00482 rtsp_st->dynamic_handler->parse_sdp_a_line &&
00483 rtsp_st->dynamic_handler->parse_sdp_a_line(s,
00484 i, rtsp_st->dynamic_protocol_context, buf)))
00485 sdp_parse_fmtp(st, p);
00486 }
00487 }
00488 } else if (av_strstart(p, "framesize:", &p)) {
00489
00490 get_word(buf1, sizeof(buf1), &p);
00491 payload_type = atoi(buf1);
00492 for (i = 0; i < s->nb_streams; i++) {
00493 st = s->streams[i];
00494 rtsp_st = st->priv_data;
00495 if (rtsp_st->sdp_payload_type == payload_type &&
00496 rtsp_st->dynamic_handler &&
00497 rtsp_st->dynamic_handler->parse_sdp_a_line)
00498 rtsp_st->dynamic_handler->parse_sdp_a_line(s, i,
00499 rtsp_st->dynamic_protocol_context, buf);
00500 }
00501 } else if (av_strstart(p, "range:", &p)) {
00502 int64_t start, end;
00503
00504
00505 rtsp_parse_range_npt(p, &start, &end);
00506 s->start_time = start;
00507
00508 s->duration = (end == AV_NOPTS_VALUE) ?
00509 AV_NOPTS_VALUE : end - start;
00510 } else if (av_strstart(p, "IsRealDataType:integer;",&p)) {
00511 if (atoi(p) == 1)
00512 rt->transport = RTSP_TRANSPORT_RDT;
00513 } else {
00514 if (rt->server_type == RTSP_SERVER_WMS)
00515 ff_wms_parse_sdp_a_line(s, p);
00516 if (s->nb_streams > 0) {
00517 if (rt->server_type == RTSP_SERVER_REAL)
00518 ff_real_parse_sdp_a_line(s, s->nb_streams - 1, p);
00519
00520 rtsp_st = s->streams[s->nb_streams - 1]->priv_data;
00521 if (rtsp_st->dynamic_handler &&
00522 rtsp_st->dynamic_handler->parse_sdp_a_line)
00523 rtsp_st->dynamic_handler->parse_sdp_a_line(s,
00524 s->nb_streams - 1,
00525 rtsp_st->dynamic_protocol_context, buf);
00526 }
00527 }
00528 break;
00529 }
00530 }
00531
00532 static int sdp_parse(AVFormatContext *s, const char *content)
00533 {
00534 const char *p;
00535 int letter;
00536
00537
00538
00539
00540
00541
00542
00543 char buf[16384], *q;
00544 SDPParseState sdp_parse_state, *s1 = &sdp_parse_state;
00545
00546 memset(s1, 0, sizeof(SDPParseState));
00547 p = content;
00548 for (;;) {
00549 skip_spaces(&p);
00550 letter = *p;
00551 if (letter == '\0')
00552 break;
00553 p++;
00554 if (*p != '=')
00555 goto next_line;
00556 p++;
00557
00558 q = buf;
00559 while (*p != '\n' && *p != '\r' && *p != '\0') {
00560 if ((q - buf) < sizeof(buf) - 1)
00561 *q++ = *p;
00562 p++;
00563 }
00564 *q = '\0';
00565 sdp_parse_line(s, s1, letter, buf);
00566 next_line:
00567 while (*p != '\n' && *p != '\0')
00568 p++;
00569 if (*p == '\n')
00570 p++;
00571 }
00572 return 0;
00573 }
00574
00575
00576 void ff_rtsp_close_streams(AVFormatContext *s)
00577 {
00578 RTSPState *rt = s->priv_data;
00579 int i;
00580 RTSPStream *rtsp_st;
00581
00582 for (i = 0; i < rt->nb_rtsp_streams; i++) {
00583 rtsp_st = rt->rtsp_streams[i];
00584 if (rtsp_st) {
00585 if (rtsp_st->transport_priv) {
00586 if (s->oformat) {
00587 AVFormatContext *rtpctx = rtsp_st->transport_priv;
00588 av_write_trailer(rtpctx);
00589 if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
00590 uint8_t *ptr;
00591 url_close_dyn_buf(rtpctx->pb, &ptr);
00592 av_free(ptr);
00593 } else {
00594 url_fclose(rtpctx->pb);
00595 }
00596 av_metadata_free(&rtpctx->streams[0]->metadata);
00597 av_metadata_free(&rtpctx->metadata);
00598 av_free(rtpctx->streams[0]);
00599 av_free(rtpctx);
00600 } else if (rt->transport == RTSP_TRANSPORT_RDT)
00601 ff_rdt_parse_close(rtsp_st->transport_priv);
00602 else
00603 rtp_parse_close(rtsp_st->transport_priv);
00604 }
00605 if (rtsp_st->rtp_handle)
00606 url_close(rtsp_st->rtp_handle);
00607 if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context)
00608 rtsp_st->dynamic_handler->close(
00609 rtsp_st->dynamic_protocol_context);
00610 }
00611 }
00612 av_free(rt->rtsp_streams);
00613 if (rt->asf_ctx) {
00614 av_close_input_stream (rt->asf_ctx);
00615 rt->asf_ctx = NULL;
00616 }
00617 }
00618
00619 static void *rtsp_rtp_mux_open(AVFormatContext *s, AVStream *st,
00620 URLContext *handle)
00621 {
00622 RTSPState *rt = s->priv_data;
00623 AVFormatContext *rtpctx;
00624 int ret;
00625 AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);
00626
00627 if (!rtp_format)
00628 return NULL;
00629
00630
00631 rtpctx = avformat_alloc_context();
00632 if (!rtpctx)
00633 return NULL;
00634
00635 rtpctx->oformat = rtp_format;
00636 if (!av_new_stream(rtpctx, 0)) {
00637 av_free(rtpctx);
00638 return NULL;
00639 }
00640
00641 rtpctx->max_delay = s->max_delay;
00642
00643 rtpctx->streams[0]->sample_aspect_ratio = st->sample_aspect_ratio;
00644
00645
00646 rtpctx->start_time_realtime = rt->start_time;
00647
00648
00649
00650
00651 av_free(rtpctx->streams[0]->codec);
00652 rtpctx->streams[0]->codec = st->codec;
00653
00654 if (handle) {
00655 url_fdopen(&rtpctx->pb, handle);
00656 } else
00657 url_open_dyn_packet_buf(&rtpctx->pb, RTSP_TCP_MAX_PACKET_SIZE);
00658 ret = av_write_header(rtpctx);
00659
00660 if (ret) {
00661 if (handle) {
00662 url_fclose(rtpctx->pb);
00663 } else {
00664 uint8_t *ptr;
00665 url_close_dyn_buf(rtpctx->pb, &ptr);
00666 av_free(ptr);
00667 }
00668 av_free(rtpctx->streams[0]);
00669 av_free(rtpctx);
00670 return NULL;
00671 }
00672
00673
00674 st->time_base = rtpctx->streams[0]->time_base;
00675 return rtpctx;
00676 }
00677
00678 static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
00679 {
00680 RTSPState *rt = s->priv_data;
00681 AVStream *st = NULL;
00682
00683
00684 if (rtsp_st->stream_index >= 0)
00685 st = s->streams[rtsp_st->stream_index];
00686 if (!st)
00687 s->ctx_flags |= AVFMTCTX_NOHEADER;
00688
00689 if (s->oformat) {
00690 rtsp_st->transport_priv = rtsp_rtp_mux_open(s, st, rtsp_st->rtp_handle);
00691
00692 rtsp_st->rtp_handle = NULL;
00693 } else if (rt->transport == RTSP_TRANSPORT_RDT)
00694 rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
00695 rtsp_st->dynamic_protocol_context,
00696 rtsp_st->dynamic_handler);
00697 else
00698 rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle,
00699 rtsp_st->sdp_payload_type,
00700 &rtsp_st->rtp_payload_data);
00701
00702 if (!rtsp_st->transport_priv) {
00703 return AVERROR(ENOMEM);
00704 } else if (rt->transport != RTSP_TRANSPORT_RDT) {
00705 if (rtsp_st->dynamic_handler) {
00706 rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
00707 rtsp_st->dynamic_protocol_context,
00708 rtsp_st->dynamic_handler);
00709 }
00710 }
00711
00712 return 0;
00713 }
00714
00715 #if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER
00716 static int rtsp_probe(AVProbeData *p)
00717 {
00718 if (av_strstart(p->filename, "rtsp:", NULL))
00719 return AVPROBE_SCORE_MAX;
00720 return 0;
00721 }
00722
00723 static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
00724 {
00725 const char *p;
00726 int v;
00727
00728 p = *pp;
00729 skip_spaces(&p);
00730 v = strtol(p, (char **)&p, 10);
00731 if (*p == '-') {
00732 p++;
00733 *min_ptr = v;
00734 v = strtol(p, (char **)&p, 10);
00735 *max_ptr = v;
00736 } else {
00737 *min_ptr = v;
00738 *max_ptr = v;
00739 }
00740 *pp = p;
00741 }
00742
00743
00744 static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p)
00745 {
00746 char transport_protocol[16];
00747 char profile[16];
00748 char lower_transport[16];
00749 char parameter[16];
00750 RTSPTransportField *th;
00751 char buf[256];
00752
00753 reply->nb_transports = 0;
00754
00755 for (;;) {
00756 skip_spaces(&p);
00757 if (*p == '\0')
00758 break;
00759
00760 th = &reply->transports[reply->nb_transports];
00761
00762 get_word_sep(transport_protocol, sizeof(transport_protocol),
00763 "/", &p);
00764 if (!strcasecmp (transport_protocol, "rtp")) {
00765 get_word_sep(profile, sizeof(profile), "/;,", &p);
00766 lower_transport[0] = '\0';
00767
00768 if (*p == '/') {
00769 get_word_sep(lower_transport, sizeof(lower_transport),
00770 ";,", &p);
00771 }
00772 th->transport = RTSP_TRANSPORT_RTP;
00773 } else if (!strcasecmp (transport_protocol, "x-pn-tng") ||
00774 !strcasecmp (transport_protocol, "x-real-rdt")) {
00775
00776 get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p);
00777 profile[0] = '\0';
00778 th->transport = RTSP_TRANSPORT_RDT;
00779 }
00780 if (!strcasecmp(lower_transport, "TCP"))
00781 th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
00782 else
00783 th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
00784
00785 if (*p == ';')
00786 p++;
00787
00788 while (*p != '\0' && *p != ',') {
00789 get_word_sep(parameter, sizeof(parameter), "=;,", &p);
00790 if (!strcmp(parameter, "port")) {
00791 if (*p == '=') {
00792 p++;
00793 rtsp_parse_range(&th->port_min, &th->port_max, &p);
00794 }
00795 } else if (!strcmp(parameter, "client_port")) {
00796 if (*p == '=') {
00797 p++;
00798 rtsp_parse_range(&th->client_port_min,
00799 &th->client_port_max, &p);
00800 }
00801 } else if (!strcmp(parameter, "server_port")) {
00802 if (*p == '=') {
00803 p++;
00804 rtsp_parse_range(&th->server_port_min,
00805 &th->server_port_max, &p);
00806 }
00807 } else if (!strcmp(parameter, "interleaved")) {
00808 if (*p == '=') {
00809 p++;
00810 rtsp_parse_range(&th->interleaved_min,
00811 &th->interleaved_max, &p);
00812 }
00813 } else if (!strcmp(parameter, "multicast")) {
00814 if (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP)
00815 th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST;
00816 } else if (!strcmp(parameter, "ttl")) {
00817 if (*p == '=') {
00818 p++;
00819 th->ttl = strtol(p, (char **)&p, 10);
00820 }
00821 } else if (!strcmp(parameter, "destination")) {
00822 struct in_addr ipaddr;
00823
00824 if (*p == '=') {
00825 p++;
00826 get_word_sep(buf, sizeof(buf), ";,", &p);
00827 if (ff_inet_aton(buf, &ipaddr))
00828 th->destination = ntohl(ipaddr.s_addr);
00829 }
00830 }
00831 while (*p != ';' && *p != '\0' && *p != ',')
00832 p++;
00833 if (*p == ';')
00834 p++;
00835 }
00836 if (*p == ',')
00837 p++;
00838
00839 reply->nb_transports++;
00840 }
00841 }
00842
00843 void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf,
00844 HTTPAuthState *auth_state)
00845 {
00846 const char *p;
00847
00848
00849 p = buf;
00850 if (av_stristart(p, "Session:", &p)) {
00851 int t;
00852 get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
00853 if (av_stristart(p, ";timeout=", &p) &&
00854 (t = strtol(p, NULL, 10)) > 0) {
00855 reply->timeout = t;
00856 }
00857 } else if (av_stristart(p, "Content-Length:", &p)) {
00858 reply->content_length = strtol(p, NULL, 10);
00859 } else if (av_stristart(p, "Transport:", &p)) {
00860 rtsp_parse_transport(reply, p);
00861 } else if (av_stristart(p, "CSeq:", &p)) {
00862 reply->seq = strtol(p, NULL, 10);
00863 } else if (av_stristart(p, "Range:", &p)) {
00864 rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end);
00865 } else if (av_stristart(p, "RealChallenge1:", &p)) {
00866 skip_spaces(&p);
00867 av_strlcpy(reply->real_challenge, p, sizeof(reply->real_challenge));
00868 } else if (av_stristart(p, "Server:", &p)) {
00869 skip_spaces(&p);
00870 av_strlcpy(reply->server, p, sizeof(reply->server));
00871 } else if (av_stristart(p, "Notice:", &p) ||
00872 av_stristart(p, "X-Notice:", &p)) {
00873 reply->notice = strtol(p, NULL, 10);
00874 } else if (av_stristart(p, "Location:", &p)) {
00875 skip_spaces(&p);
00876 av_strlcpy(reply->location, p , sizeof(reply->location));
00877 } else if (av_stristart(p, "WWW-Authenticate:", &p) && auth_state) {
00878 skip_spaces(&p);
00879 ff_http_auth_handle_header(auth_state, "WWW-Authenticate", p);
00880 } else if (av_stristart(p, "Authentication-Info:", &p) && auth_state) {
00881 skip_spaces(&p);
00882 ff_http_auth_handle_header(auth_state, "Authentication-Info", p);
00883 }
00884 }
00885
00886
00887 void ff_rtsp_skip_packet(AVFormatContext *s)
00888 {
00889 RTSPState *rt = s->priv_data;
00890 int ret, len, len1;
00891 uint8_t buf[1024];
00892
00893 ret = url_read_complete(rt->rtsp_hd, buf, 3);
00894 if (ret != 3)
00895 return;
00896 len = AV_RB16(buf + 1);
00897
00898 dprintf(s, "skipping RTP packet len=%d\n", len);
00899
00900
00901 while (len > 0) {
00902 len1 = len;
00903 if (len1 > sizeof(buf))
00904 len1 = sizeof(buf);
00905 ret = url_read_complete(rt->rtsp_hd, buf, len1);
00906 if (ret != len1)
00907 return;
00908 len -= len1;
00909 }
00910 }
00911
00912 int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
00913 unsigned char **content_ptr,
00914 int return_on_interleaved_data)
00915 {
00916 RTSPState *rt = s->priv_data;
00917 char buf[4096], buf1[1024], *q;
00918 unsigned char ch;
00919 const char *p;
00920 int ret, content_length, line_count = 0;
00921 unsigned char *content = NULL;
00922
00923 memset(reply, 0, sizeof(*reply));
00924
00925
00926 rt->last_reply[0] = '\0';
00927 for (;;) {
00928 q = buf;
00929 for (;;) {
00930 ret = url_read_complete(rt->rtsp_hd, &ch, 1);
00931 #ifdef DEBUG_RTP_TCP
00932 dprintf(s, "ret=%d c=%02x [%c]\n", ret, ch, ch);
00933 #endif
00934 if (ret != 1)
00935 return -1;
00936 if (ch == '\n')
00937 break;
00938 if (ch == '$') {
00939
00940 if (return_on_interleaved_data) {
00941 return 1;
00942 } else
00943 ff_rtsp_skip_packet(s);
00944 } else if (ch != '\r') {
00945 if ((q - buf) < sizeof(buf) - 1)
00946 *q++ = ch;
00947 }
00948 }
00949 *q = '\0';
00950
00951 dprintf(s, "line='%s'\n", buf);
00952
00953
00954 if (buf[0] == '\0')
00955 break;
00956 p = buf;
00957 if (line_count == 0) {
00958
00959 get_word(buf1, sizeof(buf1), &p);
00960 get_word(buf1, sizeof(buf1), &p);
00961 reply->status_code = atoi(buf1);
00962 } else {
00963 ff_rtsp_parse_line(reply, p, &rt->auth_state);
00964 av_strlcat(rt->last_reply, p, sizeof(rt->last_reply));
00965 av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply));
00966 }
00967 line_count++;
00968 }
00969
00970 if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
00971 av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id));
00972
00973 content_length = reply->content_length;
00974 if (content_length > 0) {
00975
00976 content = av_malloc(content_length + 1);
00977 (void)url_read_complete(rt->rtsp_hd, content, content_length);
00978 content[content_length] = '\0';
00979 }
00980 if (content_ptr)
00981 *content_ptr = content;
00982 else
00983 av_free(content);
00984
00985 if (rt->seq != reply->seq) {
00986 av_log(s, AV_LOG_WARNING, "CSeq %d expected, %d received.\n",
00987 rt->seq, reply->seq);
00988 }
00989
00990
00991 if (reply->notice == 2101 ||
00992 reply->notice == 2104 ||
00993 reply->notice == 2306 ) {
00994 rt->state = RTSP_STATE_IDLE;
00995 } else if (reply->notice >= 4400 && reply->notice < 5500) {
00996 return AVERROR(EIO);
00997 } else if (reply->notice == 2401 ||
00998 (reply->notice >= 5500 && reply->notice < 5600) )
00999 return AVERROR(EPERM);
01000
01001 return 0;
01002 }
01003
01004 void ff_rtsp_send_cmd_with_content_async(AVFormatContext *s,
01005 const char *method, const char *url,
01006 const char *headers,
01007 const unsigned char *send_content,
01008 int send_content_length)
01009 {
01010 RTSPState *rt = s->priv_data;
01011 char buf[4096];
01012
01013 rt->seq++;
01014 snprintf(buf, sizeof(buf), "%s %s RTSP/1.0\r\n", method, url);
01015 if (headers)
01016 av_strlcat(buf, headers, sizeof(buf));
01017 av_strlcatf(buf, sizeof(buf), "CSeq: %d\r\n", rt->seq);
01018 if (rt->session_id[0] != '\0' && (!headers ||
01019 !strstr(headers, "\nIf-Match:"))) {
01020 av_strlcatf(buf, sizeof(buf), "Session: %s\r\n", rt->session_id);
01021 }
01022 if (rt->auth[0]) {
01023 char *str = ff_http_auth_create_response(&rt->auth_state,
01024 rt->auth, url, method);
01025 if (str)
01026 av_strlcat(buf, str, sizeof(buf));
01027 av_free(str);
01028 }
01029 if (send_content_length > 0 && send_content)
01030 av_strlcatf(buf, sizeof(buf), "Content-Length: %d\r\n", send_content_length);
01031 av_strlcat(buf, "\r\n", sizeof(buf));
01032
01033 dprintf(s, "Sending:\n%s--\n", buf);
01034
01035 url_write(rt->rtsp_hd, buf, strlen(buf));
01036 if (send_content_length > 0 && send_content)
01037 url_write(rt->rtsp_hd, send_content, send_content_length);
01038 rt->last_cmd_time = av_gettime();
01039 }
01040
01041 void ff_rtsp_send_cmd_async(AVFormatContext *s, const char *method,
01042 const char *url, const char *headers)
01043 {
01044 ff_rtsp_send_cmd_with_content_async(s, method, url, headers, NULL, 0);
01045 }
01046
01047 void ff_rtsp_send_cmd(AVFormatContext *s, const char *method, const char *url,
01048 const char *headers, RTSPMessageHeader *reply,
01049 unsigned char **content_ptr)
01050 {
01051 ff_rtsp_send_cmd_with_content(s, method, url, headers, reply,
01052 content_ptr, NULL, 0);
01053 }
01054
01055 void ff_rtsp_send_cmd_with_content(AVFormatContext *s,
01056 const char *method, const char *url,
01057 const char *header,
01058 RTSPMessageHeader *reply,
01059 unsigned char **content_ptr,
01060 const unsigned char *send_content,
01061 int send_content_length)
01062 {
01063 RTSPState *rt = s->priv_data;
01064 HTTPAuthType cur_auth_type;
01065
01066 retry:
01067 cur_auth_type = rt->auth_state.auth_type;
01068 ff_rtsp_send_cmd_with_content_async(s, method, url, header,
01069 send_content, send_content_length);
01070
01071 ff_rtsp_read_reply(s, reply, content_ptr, 0);
01072
01073 if (reply->status_code == 401 && cur_auth_type == HTTP_AUTH_NONE &&
01074 rt->auth_state.auth_type != HTTP_AUTH_NONE)
01075 goto retry;
01076 }
01077
01081 static int make_setup_request(AVFormatContext *s, const char *host, int port,
01082 int lower_transport, const char *real_challenge)
01083 {
01084 RTSPState *rt = s->priv_data;
01085 int rtx, j, i, err, interleave = 0;
01086 RTSPStream *rtsp_st;
01087 RTSPMessageHeader reply1, *reply = &reply1;
01088 char cmd[2048];
01089 const char *trans_pref;
01090
01091 if (rt->transport == RTSP_TRANSPORT_RDT)
01092 trans_pref = "x-pn-tng";
01093 else
01094 trans_pref = "RTP/AVP";
01095
01096
01097 rt->timeout = 60;
01098
01099
01100
01101
01102
01103 for (j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
01104 char transport[2048];
01105
01111 if (lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
01112 rt->server_type == RTSP_SERVER_WMS) {
01113 if (i == 0) {
01114
01115 for (rtx = 0; rtx < rt->nb_rtsp_streams; rtx++) {
01116 int len = strlen(rt->rtsp_streams[rtx]->control_url);
01117 if (len >= 4 &&
01118 !strcmp(rt->rtsp_streams[rtx]->control_url + len - 4,
01119 "/rtx"))
01120 break;
01121 }
01122 if (rtx == rt->nb_rtsp_streams)
01123 return -1;
01124 rtsp_st = rt->rtsp_streams[rtx];
01125 } else
01126 rtsp_st = rt->rtsp_streams[i > rtx ? i : i - 1];
01127 } else
01128 rtsp_st = rt->rtsp_streams[i];
01129
01130
01131 if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
01132 char buf[256];
01133
01134 if (rt->server_type == RTSP_SERVER_WMS && i > 1) {
01135 port = reply->transports[0].client_port_min;
01136 goto have_port;
01137 }
01138
01139
01140 if (RTSP_RTP_PORT_MIN != 0) {
01141 while (j <= RTSP_RTP_PORT_MAX) {
01142 ff_url_join(buf, sizeof(buf), "rtp", NULL, host, -1,
01143 "?localport=%d", j);
01144
01145 j += 2;
01146 if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0)
01147 goto rtp_opened;
01148 }
01149 }
01150
01151 #if 0
01152
01153 if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) {
01154 err = AVERROR_INVALIDDATA;
01155 goto fail;
01156 }
01157 #endif
01158
01159 rtp_opened:
01160 port = rtp_get_local_port(rtsp_st->rtp_handle);
01161 have_port:
01162 snprintf(transport, sizeof(transport) - 1,
01163 "%s/UDP;", trans_pref);
01164 if (rt->server_type != RTSP_SERVER_REAL)
01165 av_strlcat(transport, "unicast;", sizeof(transport));
01166 av_strlcatf(transport, sizeof(transport),
01167 "client_port=%d", port);
01168 if (rt->transport == RTSP_TRANSPORT_RTP &&
01169 !(rt->server_type == RTSP_SERVER_WMS && i > 0))
01170 av_strlcatf(transport, sizeof(transport), "-%d", port + 1);
01171 }
01172
01173
01174 else if (lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
01178 if (rt->server_type == RTSP_SERVER_WMS &&
01179 s->streams[rtsp_st->stream_index]->codec->codec_type ==
01180 AVMEDIA_TYPE_DATA)
01181 continue;
01182 snprintf(transport, sizeof(transport) - 1,
01183 "%s/TCP;", trans_pref);
01184 if (rt->server_type == RTSP_SERVER_WMS)
01185 av_strlcat(transport, "unicast;", sizeof(transport));
01186 av_strlcatf(transport, sizeof(transport),
01187 "interleaved=%d-%d",
01188 interleave, interleave + 1);
01189 interleave += 2;
01190 }
01191
01192 else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) {
01193 snprintf(transport, sizeof(transport) - 1,
01194 "%s/UDP;multicast", trans_pref);
01195 }
01196 if (s->oformat) {
01197 av_strlcat(transport, ";mode=receive", sizeof(transport));
01198 } else if (rt->server_type == RTSP_SERVER_REAL ||
01199 rt->server_type == RTSP_SERVER_WMS)
01200 av_strlcat(transport, ";mode=play", sizeof(transport));
01201 snprintf(cmd, sizeof(cmd),
01202 "Transport: %s\r\n",
01203 transport);
01204 if (i == 0 && rt->server_type == RTSP_SERVER_REAL) {
01205 char real_res[41], real_csum[9];
01206 ff_rdt_calc_response_and_checksum(real_res, real_csum,
01207 real_challenge);
01208 av_strlcatf(cmd, sizeof(cmd),
01209 "If-Match: %s\r\n"
01210 "RealChallenge2: %s, sd=%s\r\n",
01211 rt->session_id, real_res, real_csum);
01212 }
01213 ff_rtsp_send_cmd(s, "SETUP", rtsp_st->control_url, cmd, reply, NULL);
01214 if (reply->status_code == 461 && i == 0) {
01215 err = 1;
01216 goto fail;
01217 } else if (reply->status_code != RTSP_STATUS_OK ||
01218 reply->nb_transports != 1) {
01219 err = AVERROR_INVALIDDATA;
01220 goto fail;
01221 }
01222
01223
01224 if (i > 0) {
01225 if (reply->transports[0].lower_transport != rt->lower_transport ||
01226 reply->transports[0].transport != rt->transport) {
01227 err = AVERROR_INVALIDDATA;
01228 goto fail;
01229 }
01230 } else {
01231 rt->lower_transport = reply->transports[0].lower_transport;
01232 rt->transport = reply->transports[0].transport;
01233 }
01234
01235
01236 if (reply->transports[0].lower_transport != RTSP_LOWER_TRANSPORT_UDP &&
01237 (lower_transport == RTSP_LOWER_TRANSPORT_UDP)) {
01238 url_close(rtsp_st->rtp_handle);
01239 rtsp_st->rtp_handle = NULL;
01240 }
01241
01242 switch(reply->transports[0].lower_transport) {
01243 case RTSP_LOWER_TRANSPORT_TCP:
01244 rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
01245 rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
01246 break;
01247
01248 case RTSP_LOWER_TRANSPORT_UDP: {
01249 char url[1024];
01250
01251
01252 ff_url_join(url, sizeof(url), "rtp", NULL, host,
01253 reply->transports[0].server_port_min, NULL);
01254 if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) &&
01255 rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
01256 err = AVERROR_INVALIDDATA;
01257 goto fail;
01258 }
01259
01260
01261
01262
01263 if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat)
01264 rtp_send_punch_packets(rtsp_st->rtp_handle);
01265 break;
01266 }
01267 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: {
01268 char url[1024];
01269 struct in_addr in;
01270 int port, ttl;
01271
01272 if (reply->transports[0].destination) {
01273 in.s_addr = htonl(reply->transports[0].destination);
01274 port = reply->transports[0].port_min;
01275 ttl = reply->transports[0].ttl;
01276 } else {
01277 in = rtsp_st->sdp_ip;
01278 port = rtsp_st->sdp_port;
01279 ttl = rtsp_st->sdp_ttl;
01280 }
01281 ff_url_join(url, sizeof(url), "rtp", NULL, inet_ntoa(in),
01282 port, "?ttl=%d", ttl);
01283 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
01284 err = AVERROR_INVALIDDATA;
01285 goto fail;
01286 }
01287 break;
01288 }
01289 }
01290
01291 if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
01292 goto fail;
01293 }
01294
01295 if (reply->timeout > 0)
01296 rt->timeout = reply->timeout;
01297
01298 if (rt->server_type == RTSP_SERVER_REAL)
01299 rt->need_subscription = 1;
01300
01301 return 0;
01302
01303 fail:
01304 for (i = 0; i < rt->nb_rtsp_streams; i++) {
01305 if (rt->rtsp_streams[i]->rtp_handle) {
01306 url_close(rt->rtsp_streams[i]->rtp_handle);
01307 rt->rtsp_streams[i]->rtp_handle = NULL;
01308 }
01309 }
01310 return err;
01311 }
01312
01313 static int rtsp_read_play(AVFormatContext *s)
01314 {
01315 RTSPState *rt = s->priv_data;
01316 RTSPMessageHeader reply1, *reply = &reply1;
01317 int i;
01318 char cmd[1024];
01319
01320 av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state);
01321
01322 if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
01323 if (rt->state == RTSP_STATE_PAUSED) {
01324 cmd[0] = 0;
01325 } else {
01326 snprintf(cmd, sizeof(cmd),
01327 "Range: npt=%0.3f-\r\n",
01328 (double)rt->seek_timestamp / AV_TIME_BASE);
01329 }
01330 ff_rtsp_send_cmd(s, "PLAY", rt->control_uri, cmd, reply, NULL);
01331 if (reply->status_code != RTSP_STATUS_OK) {
01332 return -1;
01333 }
01334 if (reply->range_start != AV_NOPTS_VALUE &&
01335 rt->transport == RTSP_TRANSPORT_RTP) {
01336 for (i = 0; i < rt->nb_rtsp_streams; i++) {
01337 RTSPStream *rtsp_st = rt->rtsp_streams[i];
01338 RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
01339 AVStream *st = NULL;
01340 if (!rtpctx)
01341 continue;
01342 if (rtsp_st->stream_index >= 0)
01343 st = s->streams[rtsp_st->stream_index];
01344 rtpctx->last_rtcp_ntp_time = AV_NOPTS_VALUE;
01345 rtpctx->first_rtcp_ntp_time = AV_NOPTS_VALUE;
01346 if (st)
01347 rtpctx->range_start_offset = av_rescale_q(reply->range_start,
01348 AV_TIME_BASE_Q,
01349 st->time_base);
01350 }
01351 }
01352 }
01353 rt->state = RTSP_STATE_STREAMING;
01354 return 0;
01355 }
01356
01357 static int rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply)
01358 {
01359 RTSPState *rt = s->priv_data;
01360 char cmd[1024];
01361 unsigned char *content = NULL;
01362 int ret;
01363
01364
01365 snprintf(cmd, sizeof(cmd),
01366 "Accept: application/sdp\r\n");
01367 if (rt->server_type == RTSP_SERVER_REAL) {
01372 av_strlcat(cmd,
01373 "Require: com.real.retain-entity-for-setup\r\n",
01374 sizeof(cmd));
01375 }
01376 ff_rtsp_send_cmd(s, "DESCRIBE", rt->control_uri, cmd, reply, &content);
01377 if (!content)
01378 return AVERROR_INVALIDDATA;
01379 if (reply->status_code != RTSP_STATUS_OK) {
01380 av_freep(&content);
01381 return AVERROR_INVALIDDATA;
01382 }
01383
01384
01385 ret = sdp_parse(s, (const char *)content);
01386 av_freep(&content);
01387 if (ret < 0)
01388 return AVERROR_INVALIDDATA;
01389
01390 return 0;
01391 }
01392
01393 static int rtsp_setup_output_streams(AVFormatContext *s, const char *addr)
01394 {
01395 RTSPState *rt = s->priv_data;
01396 RTSPMessageHeader reply1, *reply = &reply1;
01397 int i;
01398 char *sdp;
01399 AVFormatContext sdp_ctx, *ctx_array[1];
01400
01401 rt->start_time = av_gettime();
01402
01403
01404 sdp = av_mallocz(8192);
01405 if (sdp == NULL)
01406 return AVERROR(ENOMEM);
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419 sdp_ctx = *s;
01420 ff_url_join(sdp_ctx.filename, sizeof(sdp_ctx.filename),
01421 "rtsp", NULL, addr, -1, NULL);
01422 ctx_array[0] = &sdp_ctx;
01423 if (avf_sdp_create(ctx_array, 1, sdp, 8192)) {
01424 av_free(sdp);
01425 return AVERROR_INVALIDDATA;
01426 }
01427 av_log(s, AV_LOG_INFO, "SDP:\n%s\n", sdp);
01428 ff_rtsp_send_cmd_with_content(s, "ANNOUNCE", rt->control_uri,
01429 "Content-Type: application/sdp\r\n",
01430 reply, NULL, sdp, strlen(sdp));
01431 av_free(sdp);
01432 if (reply->status_code != RTSP_STATUS_OK)
01433 return AVERROR_INVALIDDATA;
01434
01435
01436 for (i = 0; i < s->nb_streams; i++) {
01437 RTSPStream *rtsp_st;
01438 AVStream *st = s->streams[i];
01439
01440 rtsp_st = av_mallocz(sizeof(RTSPStream));
01441 if (!rtsp_st)
01442 return AVERROR(ENOMEM);
01443 dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st);
01444
01445 st->priv_data = rtsp_st;
01446 rtsp_st->stream_index = i;
01447
01448 av_strlcpy(rtsp_st->control_url, rt->control_uri, sizeof(rtsp_st->control_url));
01449
01450 av_strlcatf(rtsp_st->control_url, sizeof(rtsp_st->control_url),
01451 "/streamid=%d", i);
01452 }
01453
01454 return 0;
01455 }
01456
01457 int ff_rtsp_connect(AVFormatContext *s)
01458 {
01459 RTSPState *rt = s->priv_data;
01460 char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128];
01461 char *option_list, *option, *filename;
01462 URLContext *rtsp_hd;
01463 int port, err, tcp_fd;
01464 RTSPMessageHeader reply1 = {}, *reply = &reply1;
01465 int lower_transport_mask = 0;
01466 char real_challenge[64];
01467 struct sockaddr_storage peer;
01468 socklen_t peer_len = sizeof(peer);
01469
01470 if (!ff_network_init())
01471 return AVERROR(EIO);
01472 redirect:
01473
01474 ff_url_split(NULL, 0, auth, sizeof(auth),
01475 host, sizeof(host), &port, path, sizeof(path), s->filename);
01476 if (*auth) {
01477 av_strlcpy(rt->auth, auth, sizeof(rt->auth));
01478 }
01479 if (port < 0)
01480 port = RTSP_DEFAULT_PORT;
01481
01482
01483 option_list = strrchr(path, '?');
01484 if (option_list) {
01485
01486
01487 filename = option_list;
01488 while (option_list) {
01489
01490 option = ++option_list;
01491 option_list = strchr(option_list, '&');
01492 if (option_list)
01493 *option_list = 0;
01494
01495
01496 if (!strcmp(option, "udp")) {
01497 lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP);
01498 } else if (!strcmp(option, "multicast")) {
01499 lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
01500 } else if (!strcmp(option, "tcp")) {
01501 lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);
01502 } else {
01503
01504
01505 int len = strlen(option);
01506 memmove(++filename, option, len);
01507 filename += len;
01508 if (option_list) *filename = '&';
01509 }
01510 }
01511 *filename = 0;
01512 }
01513
01514 if (!lower_transport_mask)
01515 lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
01516
01517 if (s->oformat) {
01518
01519 lower_transport_mask &= (1 << RTSP_LOWER_TRANSPORT_UDP) |
01520 (1 << RTSP_LOWER_TRANSPORT_TCP);
01521 if (!lower_transport_mask) {
01522 av_log(s, AV_LOG_ERROR, "Unsupported lower transport method, "
01523 "only UDP and TCP are supported for output.\n");
01524 err = AVERROR(EINVAL);
01525 goto fail;
01526 }
01527 }
01528
01529
01530
01531
01532 ff_url_join(rt->control_uri, sizeof(rt->control_uri), "rtsp", NULL,
01533 host, port, "%s", path);
01534
01535
01536 ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL);
01537 if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0) {
01538 err = AVERROR(EIO);
01539 goto fail;
01540 }
01541 rt->rtsp_hd = rtsp_hd;
01542 rt->seq = 0;
01543
01544 tcp_fd = url_get_file_handle(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,
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 (!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)
01588 err = rtsp_setup_input_streams(s, reply);
01589 else
01590 err = 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 = 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 = FF_NETERROR(EPROTONOSUPPORT);
01606 goto fail;
01607 }
01608 } while (err);
01609
01610 rt->state = RTSP_STATE_IDLE;
01611 rt->seek_timestamp = 0;
01612 return 0;
01613 fail:
01614 ff_rtsp_close_streams(s);
01615 url_close(rt->rtsp_hd);
01616 if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) {
01617 av_strlcpy(s->filename, reply->location, sizeof(s->filename));
01618 av_log(s, AV_LOG_INFO, "Status %d: Redirecting to %s\n",
01619 reply->status_code,
01620 s->filename);
01621 goto redirect;
01622 }
01623 ff_network_close();
01624 return err;
01625 }
01626 #endif
01627
01628 #if CONFIG_RTSP_DEMUXER
01629 static int rtsp_read_header(AVFormatContext *s,
01630 AVFormatParameters *ap)
01631 {
01632 RTSPState *rt = s->priv_data;
01633 int ret;
01634
01635 ret = ff_rtsp_connect(s);
01636 if (ret)
01637 return ret;
01638
01639 if (ap->initial_pause) {
01640
01641 } else {
01642 if (rtsp_read_play(s) < 0) {
01643 ff_rtsp_close_streams(s);
01644 url_close(rt->rtsp_hd);
01645 return AVERROR_INVALIDDATA;
01646 }
01647 }
01648
01649 return 0;
01650 }
01651
01652 static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
01653 uint8_t *buf, int buf_size)
01654 {
01655 RTSPState *rt = s->priv_data;
01656 RTSPStream *rtsp_st;
01657 fd_set rfds;
01658 int fd, fd_max, n, i, ret, tcp_fd, timeout_cnt = 0;
01659 struct timeval tv;
01660
01661 for (;;) {
01662 if (url_interrupt_cb())
01663 return AVERROR(EINTR);
01664 FD_ZERO(&rfds);
01665 if (rt->rtsp_hd) {
01666 tcp_fd = fd_max = url_get_file_handle(rt->rtsp_hd);
01667 FD_SET(tcp_fd, &rfds);
01668 } else {
01669 fd_max = 0;
01670 tcp_fd = -1;
01671 }
01672 for (i = 0; i < rt->nb_rtsp_streams; i++) {
01673 rtsp_st = rt->rtsp_streams[i];
01674 if (rtsp_st->rtp_handle) {
01675
01676
01677 fd = url_get_file_handle(rtsp_st->rtp_handle);
01678 if (fd > fd_max)
01679 fd_max = fd;
01680 FD_SET(fd, &rfds);
01681 }
01682 }
01683 tv.tv_sec = 0;
01684 tv.tv_usec = SELECT_TIMEOUT_MS * 1000;
01685 n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
01686 if (n > 0) {
01687 timeout_cnt = 0;
01688 for (i = 0; i < rt->nb_rtsp_streams; i++) {
01689 rtsp_st = rt->rtsp_streams[i];
01690 if (rtsp_st->rtp_handle) {
01691 fd = url_get_file_handle(rtsp_st->rtp_handle);
01692 if (FD_ISSET(fd, &rfds)) {
01693 ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
01694 if (ret > 0) {
01695 *prtsp_st = rtsp_st;
01696 return ret;
01697 }
01698 }
01699 }
01700 }
01701 #if CONFIG_RTSP_DEMUXER
01702 if (tcp_fd != -1 && FD_ISSET(tcp_fd, &rfds)) {
01703 RTSPMessageHeader reply;
01704
01705 ret = ff_rtsp_read_reply(s, &reply, NULL, 0);
01706 if (ret < 0)
01707 return ret;
01708
01709 if (rt->state != RTSP_STATE_STREAMING)
01710 return 0;
01711 }
01712 #endif
01713 } else if (n == 0 && ++timeout_cnt >= MAX_TIMEOUTS) {
01714 return FF_NETERROR(ETIMEDOUT);
01715 } else if (n < 0 && errno != EINTR)
01716 return AVERROR(errno);
01717 }
01718 }
01719
01720 static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
01721 uint8_t *buf, int buf_size)
01722 {
01723 RTSPState *rt = s->priv_data;
01724 int id, len, i, ret;
01725 RTSPStream *rtsp_st;
01726
01727 #ifdef DEBUG_RTP_TCP
01728 dprintf(s, "tcp_read_packet:\n");
01729 #endif
01730 redo:
01731 for (;;) {
01732 RTSPMessageHeader reply;
01733
01734 ret = ff_rtsp_read_reply(s, &reply, NULL, 1);
01735 if (ret == -1)
01736 return -1;
01737 if (ret == 1)
01738 break;
01739
01740 if (rt->state != RTSP_STATE_STREAMING)
01741 return 0;
01742 }
01743 ret = url_read_complete(rt->rtsp_hd, buf, 3);
01744 if (ret != 3)
01745 return -1;
01746 id = buf[0];
01747 len = AV_RB16(buf + 1);
01748 #ifdef DEBUG_RTP_TCP
01749 dprintf(s, "id=%d len=%d\n", id, len);
01750 #endif
01751 if (len > buf_size || len < 12)
01752 goto redo;
01753
01754 ret = url_read_complete(rt->rtsp_hd, buf, len);
01755 if (ret != len)
01756 return -1;
01757 if (rt->transport == RTSP_TRANSPORT_RDT &&
01758 ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL) < 0)
01759 return -1;
01760
01761
01762 for (i = 0; i < rt->nb_rtsp_streams; i++) {
01763 rtsp_st = rt->rtsp_streams[i];
01764 if (id >= rtsp_st->interleaved_min &&
01765 id <= rtsp_st->interleaved_max)
01766 goto found;
01767 }
01768 goto redo;
01769 found:
01770 *prtsp_st = rtsp_st;
01771 return len;
01772 }
01773
01774 static int rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt)
01775 {
01776 RTSPState *rt = s->priv_data;
01777 int ret, len;
01778 uint8_t buf[10 * RTP_MAX_PACKET_LENGTH];
01779 RTSPStream *rtsp_st;
01780
01781
01782 if (rt->cur_transport_priv) {
01783 if (rt->transport == RTSP_TRANSPORT_RDT) {
01784 ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
01785 } else
01786 ret = rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
01787 if (ret == 0) {
01788 rt->cur_transport_priv = NULL;
01789 return 0;
01790 } else if (ret == 1) {
01791 return 0;
01792 } else
01793 rt->cur_transport_priv = NULL;
01794 }
01795
01796
01797 redo:
01798 switch(rt->lower_transport) {
01799 default:
01800 #if CONFIG_RTSP_DEMUXER
01801 case RTSP_LOWER_TRANSPORT_TCP:
01802 len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf));
01803 break;
01804 #endif
01805 case RTSP_LOWER_TRANSPORT_UDP:
01806 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
01807 len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf));
01808 if (len >=0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP)
01809 rtp_check_and_send_back_rr(rtsp_st->transport_priv, len);
01810 break;
01811 }
01812 if (len < 0)
01813 return len;
01814 if (len == 0)
01815 return AVERROR_EOF;
01816 if (rt->transport == RTSP_TRANSPORT_RDT) {
01817 ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
01818 } else {
01819 ret = rtp_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
01820 if (ret < 0) {
01821
01822
01823 RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
01824 if (rtpctx->first_rtcp_ntp_time != AV_NOPTS_VALUE) {
01825
01826
01827
01828
01829 int i;
01830 for (i = 0; i < rt->nb_rtsp_streams; i++) {
01831 RTPDemuxContext *rtpctx2 = rtsp_st->transport_priv;
01832 if (rtpctx2 &&
01833 rtpctx2->first_rtcp_ntp_time == AV_NOPTS_VALUE)
01834 rtpctx2->first_rtcp_ntp_time = rtpctx->first_rtcp_ntp_time;
01835 }
01836 }
01837 }
01838 }
01839 if (ret < 0)
01840 goto redo;
01841 if (ret == 1)
01842
01843 rt->cur_transport_priv = rtsp_st->transport_priv;
01844
01845 return ret;
01846 }
01847
01848 static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt)
01849 {
01850 RTSPState *rt = s->priv_data;
01851 int ret;
01852 RTSPMessageHeader reply1, *reply = &reply1;
01853 char cmd[1024];
01854
01855 if (rt->server_type == RTSP_SERVER_REAL) {
01856 int i;
01857 enum AVDiscard cache[MAX_STREAMS];
01858
01859 for (i = 0; i < s->nb_streams; i++)
01860 cache[i] = s->streams[i]->discard;
01861
01862 if (!rt->need_subscription) {
01863 if (memcmp (cache, rt->real_setup_cache,
01864 sizeof(enum AVDiscard) * s->nb_streams)) {
01865 snprintf(cmd, sizeof(cmd),
01866 "Unsubscribe: %s\r\n",
01867 rt->last_subscription);
01868 ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
01869 cmd, reply, NULL);
01870 if (reply->status_code != RTSP_STATUS_OK)
01871 return AVERROR_INVALIDDATA;
01872 rt->need_subscription = 1;
01873 }
01874 }
01875
01876 if (rt->need_subscription) {
01877 int r, rule_nr, first = 1;
01878
01879 memcpy(rt->real_setup_cache, cache,
01880 sizeof(enum AVDiscard) * s->nb_streams);
01881 rt->last_subscription[0] = 0;
01882
01883 snprintf(cmd, sizeof(cmd),
01884 "Subscribe: ");
01885 for (i = 0; i < rt->nb_rtsp_streams; i++) {
01886 rule_nr = 0;
01887 for (r = 0; r < s->nb_streams; r++) {
01888 if (s->streams[r]->priv_data == rt->rtsp_streams[i]) {
01889 if (s->streams[r]->discard != AVDISCARD_ALL) {
01890 if (!first)
01891 av_strlcat(rt->last_subscription, ",",
01892 sizeof(rt->last_subscription));
01893 ff_rdt_subscribe_rule(
01894 rt->last_subscription,
01895 sizeof(rt->last_subscription), i, rule_nr);
01896 first = 0;
01897 }
01898 rule_nr++;
01899 }
01900 }
01901 }
01902 av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription);
01903 ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
01904 cmd, reply, NULL);
01905 if (reply->status_code != RTSP_STATUS_OK)
01906 return AVERROR_INVALIDDATA;
01907 rt->need_subscription = 0;
01908
01909 if (rt->state == RTSP_STATE_STREAMING)
01910 rtsp_read_play (s);
01911 }
01912 }
01913
01914 ret = rtsp_fetch_packet(s, pkt);
01915 if (ret < 0)
01916 return ret;
01917
01918
01919 if ((rt->server_type == RTSP_SERVER_WMS ||
01920 rt->server_type == RTSP_SERVER_REAL) &&
01921 (av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) {
01922 if (rt->server_type == RTSP_SERVER_WMS) {
01923 ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL);
01924 } else {
01925 ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL);
01926 }
01927 }
01928
01929 return 0;
01930 }
01931
01932
01933 static int rtsp_read_pause(AVFormatContext *s)
01934 {
01935 RTSPState *rt = s->priv_data;
01936 RTSPMessageHeader reply1, *reply = &reply1;
01937
01938 if (rt->state != RTSP_STATE_STREAMING)
01939 return 0;
01940 else if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
01941 ff_rtsp_send_cmd(s, "PAUSE", rt->control_uri, NULL, reply, NULL);
01942 if (reply->status_code != RTSP_STATUS_OK) {
01943 return -1;
01944 }
01945 }
01946 rt->state = RTSP_STATE_PAUSED;
01947 return 0;
01948 }
01949
01950 static int rtsp_read_seek(AVFormatContext *s, int stream_index,
01951 int64_t timestamp, int flags)
01952 {
01953 RTSPState *rt = s->priv_data;
01954
01955 rt->seek_timestamp = av_rescale_q(timestamp,
01956 s->streams[stream_index]->time_base,
01957 AV_TIME_BASE_Q);
01958 switch(rt->state) {
01959 default:
01960 case RTSP_STATE_IDLE:
01961 break;
01962 case RTSP_STATE_STREAMING:
01963 if (rtsp_read_pause(s) != 0)
01964 return -1;
01965 rt->state = RTSP_STATE_SEEKING;
01966 if (rtsp_read_play(s) != 0)
01967 return -1;
01968 break;
01969 case RTSP_STATE_PAUSED:
01970 rt->state = RTSP_STATE_IDLE;
01971 break;
01972 }
01973 return 0;
01974 }
01975
01976 static int rtsp_read_close(AVFormatContext *s)
01977 {
01978 RTSPState *rt = s->priv_data;
01979
01980 #if 0
01981
01982 if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
01983 url_fclose(&rt->rtsp_gb);
01984 }
01985 #endif
01986 ff_rtsp_send_cmd_async(s, "TEARDOWN", rt->control_uri, NULL);
01987
01988 ff_rtsp_close_streams(s);
01989 url_close(rt->rtsp_hd);
01990 ff_network_close();
01991 return 0;
01992 }
01993
01994 AVInputFormat rtsp_demuxer = {
01995 "rtsp",
01996 NULL_IF_CONFIG_SMALL("RTSP input format"),
01997 sizeof(RTSPState),
01998 rtsp_probe,
01999 rtsp_read_header,
02000 rtsp_read_packet,
02001 rtsp_read_close,
02002 rtsp_read_seek,
02003 .flags = AVFMT_NOFILE,
02004 .read_play = rtsp_read_play,
02005 .read_pause = rtsp_read_pause,
02006 };
02007 #endif
02008
02009 static int sdp_probe(AVProbeData *p1)
02010 {
02011 const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
02012
02013
02014 while (p < p_end && *p != '\0') {
02015 if (p + sizeof("c=IN IP4") - 1 < p_end &&
02016 av_strstart(p, "c=IN IP4", NULL))
02017 return AVPROBE_SCORE_MAX / 2;
02018
02019 while (p < p_end - 1 && *p != '\n') p++;
02020 if (++p >= p_end)
02021 break;
02022 if (*p == '\r')
02023 p++;
02024 }
02025 return 0;
02026 }
02027
02028 #define SDP_MAX_SIZE 8192
02029
02030 static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap)
02031 {
02032 RTSPState *rt = s->priv_data;
02033 RTSPStream *rtsp_st;
02034 int size, i, err;
02035 char *content;
02036 char url[1024];
02037
02038 if (!ff_network_init())
02039 return AVERROR(EIO);
02040
02041
02042
02043 content = av_malloc(SDP_MAX_SIZE);
02044 size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1);
02045 if (size <= 0) {
02046 av_free(content);
02047 return AVERROR_INVALIDDATA;
02048 }
02049 content[size] ='\0';
02050
02051 sdp_parse(s, content);
02052 av_free(content);
02053
02054
02055 for (i = 0; i < rt->nb_rtsp_streams; i++) {
02056 rtsp_st = rt->rtsp_streams[i];
02057
02058 ff_url_join(url, sizeof(url), "rtp", NULL,
02059 inet_ntoa(rtsp_st->sdp_ip), rtsp_st->sdp_port,
02060 "?localport=%d&ttl=%d", rtsp_st->sdp_port,
02061 rtsp_st->sdp_ttl);
02062 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
02063 err = AVERROR_INVALIDDATA;
02064 goto fail;
02065 }
02066 if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
02067 goto fail;
02068 }
02069 return 0;
02070 fail:
02071 ff_rtsp_close_streams(s);
02072 ff_network_close();
02073 return err;
02074 }
02075
02076 static int sdp_read_close(AVFormatContext *s)
02077 {
02078 ff_rtsp_close_streams(s);
02079 ff_network_close();
02080 return 0;
02081 }
02082
02083 AVInputFormat sdp_demuxer = {
02084 "sdp",
02085 NULL_IF_CONFIG_SMALL("SDP"),
02086 sizeof(RTSPState),
02087 sdp_probe,
02088 sdp_read_header,
02089 rtsp_fetch_packet,
02090 sdp_read_close,
02091 };