00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #define _SVID_SOURCE
00024
00025 #include "libavutil/avstring.h"
00026 #include "libavutil/intreadwrite.h"
00027 #include "avformat.h"
00028
00029 #include <sys/time.h>
00030 #if HAVE_SYS_SELECT_H
00031 #include <sys/select.h>
00032 #endif
00033 #include <strings.h>
00034 #include "network.h"
00035 #include "rtsp.h"
00036
00037 #include "rtpdec.h"
00038 #include "rdt.h"
00039
00040
00041
00042
00043 static int rtsp_read_play(AVFormatContext *s);
00044
00045
00046
00047
00048 #if LIBAVFORMAT_VERSION_INT < (53 << 16)
00049 int rtsp_default_protocols = (1 << RTSP_LOWER_TRANSPORT_UDP);
00050 #endif
00051
00052 static int rtsp_probe(AVProbeData *p)
00053 {
00054 if (av_strstart(p->filename, "rtsp:", NULL))
00055 return AVPROBE_SCORE_MAX;
00056 return 0;
00057 }
00058
00059 static int redir_isspace(int c)
00060 {
00061 return c == ' ' || c == '\t' || c == '\n' || c == '\r';
00062 }
00063
00064 static void skip_spaces(const char **pp)
00065 {
00066 const char *p;
00067 p = *pp;
00068 while (redir_isspace(*p))
00069 p++;
00070 *pp = p;
00071 }
00072
00073 static void get_word_sep(char *buf, int buf_size, const char *sep,
00074 const char **pp)
00075 {
00076 const char *p;
00077 char *q;
00078
00079 p = *pp;
00080 if (*p == '/')
00081 p++;
00082 skip_spaces(&p);
00083 q = buf;
00084 while (!strchr(sep, *p) && *p != '\0') {
00085 if ((q - buf) < buf_size - 1)
00086 *q++ = *p;
00087 p++;
00088 }
00089 if (buf_size > 0)
00090 *q = '\0';
00091 *pp = p;
00092 }
00093
00094 static void get_word(char *buf, int buf_size, const char **pp)
00095 {
00096 const char *p;
00097 char *q;
00098
00099 p = *pp;
00100 skip_spaces(&p);
00101 q = buf;
00102 while (!redir_isspace(*p) && *p != '\0') {
00103 if ((q - buf) < buf_size - 1)
00104 *q++ = *p;
00105 p++;
00106 }
00107 if (buf_size > 0)
00108 *q = '\0';
00109 *pp = p;
00110 }
00111
00112
00113
00114 static int sdp_parse_rtpmap(AVCodecContext *codec, RTSPStream *rtsp_st, int payload_type, const char *p)
00115 {
00116 char buf[256];
00117 int i;
00118 AVCodec *c;
00119 const char *c_name;
00120
00121
00122
00123 get_word_sep(buf, sizeof(buf), "/", &p);
00124 if (payload_type >= RTP_PT_PRIVATE) {
00125 RTPDynamicProtocolHandler *handler= RTPFirstDynamicPayloadHandler;
00126 while(handler) {
00127 if (!strcmp(buf, handler->enc_name) && (codec->codec_type == handler->codec_type)) {
00128 codec->codec_id = handler->codec_id;
00129 rtsp_st->dynamic_handler= handler;
00130 if(handler->open) {
00131 rtsp_st->dynamic_protocol_context= handler->open();
00132 }
00133 break;
00134 }
00135 handler= handler->next;
00136 }
00137 } else {
00138
00139
00140 codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
00141 }
00142
00143 c = avcodec_find_decoder(codec->codec_id);
00144 if (c && c->name)
00145 c_name = c->name;
00146 else
00147 c_name = (char *)NULL;
00148
00149 if (c_name) {
00150 get_word_sep(buf, sizeof(buf), "/", &p);
00151 i = atoi(buf);
00152 switch (codec->codec_type) {
00153 case CODEC_TYPE_AUDIO:
00154 av_log(codec, AV_LOG_DEBUG, " audio codec set to : %s\n", c_name);
00155 codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE;
00156 codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS;
00157 if (i > 0) {
00158 codec->sample_rate = i;
00159 get_word_sep(buf, sizeof(buf), "/", &p);
00160 i = atoi(buf);
00161 if (i > 0)
00162 codec->channels = i;
00163
00164
00165 }
00166 av_log(codec, AV_LOG_DEBUG, " audio samplerate set to : %i\n", codec->sample_rate);
00167 av_log(codec, AV_LOG_DEBUG, " audio channels set to : %i\n", codec->channels);
00168 break;
00169 case CODEC_TYPE_VIDEO:
00170 av_log(codec, AV_LOG_DEBUG, " video codec set to : %s\n", c_name);
00171 break;
00172 default:
00173 break;
00174 }
00175 return 0;
00176 }
00177
00178 return -1;
00179 }
00180
00181
00182 static int hex_to_data(uint8_t *data, const char *p)
00183 {
00184 int c, len, v;
00185
00186 len = 0;
00187 v = 1;
00188 for(;;) {
00189 skip_spaces(&p);
00190 if (p == '\0')
00191 break;
00192 c = toupper((unsigned char)*p++);
00193 if (c >= '0' && c <= '9')
00194 c = c - '0';
00195 else if (c >= 'A' && c <= 'F')
00196 c = c - 'A' + 10;
00197 else
00198 break;
00199 v = (v << 4) | c;
00200 if (v & 0x100) {
00201 if (data)
00202 data[len] = v;
00203 len++;
00204 v = 1;
00205 }
00206 }
00207 return len;
00208 }
00209
00210 static void sdp_parse_fmtp_config(AVCodecContext *codec, char *attr, char *value)
00211 {
00212 switch (codec->codec_id) {
00213 case CODEC_ID_MPEG4:
00214 case CODEC_ID_AAC:
00215 if (!strcmp(attr, "config")) {
00216
00217 int len = hex_to_data(NULL, value);
00218 codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
00219 if (!codec->extradata)
00220 return;
00221 codec->extradata_size = len;
00222 hex_to_data(codec->extradata, value);
00223 }
00224 break;
00225 default:
00226 break;
00227 }
00228 return;
00229 }
00230
00231 typedef struct {
00232 const char *str;
00233 uint16_t type;
00234 uint32_t offset;
00235 } AttrNameMap;
00236
00237
00238 #define ATTR_NAME_TYPE_INT 0
00239 #define ATTR_NAME_TYPE_STR 1
00240 static const AttrNameMap attr_names[]=
00241 {
00242 {"SizeLength", ATTR_NAME_TYPE_INT, offsetof(RTPPayloadData, sizelength)},
00243 {"IndexLength", ATTR_NAME_TYPE_INT, offsetof(RTPPayloadData, indexlength)},
00244 {"IndexDeltaLength", ATTR_NAME_TYPE_INT, offsetof(RTPPayloadData, indexdeltalength)},
00245 {"profile-level-id", ATTR_NAME_TYPE_INT, offsetof(RTPPayloadData, profile_level_id)},
00246 {"StreamType", ATTR_NAME_TYPE_INT, offsetof(RTPPayloadData, streamtype)},
00247 {"mode", ATTR_NAME_TYPE_STR, offsetof(RTPPayloadData, mode)},
00248 {NULL, -1, -1},
00249 };
00250
00254 int rtsp_next_attr_and_value(const char **p, char *attr, int attr_size, char *value, int value_size)
00255 {
00256 skip_spaces(p);
00257 if(**p)
00258 {
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 char value[4096];
00275 int i;
00276
00277 RTSPStream *rtsp_st = st->priv_data;
00278 AVCodecContext *codec = st->codec;
00279 RTPPayloadData *rtp_payload_data = &rtsp_st->rtp_payload_data;
00280
00281
00282 while(rtsp_next_attr_and_value(&p, attr, sizeof(attr), value, sizeof(value)))
00283 {
00284
00285 sdp_parse_fmtp_config(codec, attr, value);
00286
00287 for (i = 0; attr_names[i].str; ++i) {
00288 if (!strcasecmp(attr, attr_names[i].str)) {
00289 if (attr_names[i].type == ATTR_NAME_TYPE_INT)
00290 *(int *)((char *)rtp_payload_data + attr_names[i].offset) = atoi(value);
00291 else if (attr_names[i].type == ATTR_NAME_TYPE_STR)
00292 *(char **)((char *)rtp_payload_data + attr_names[i].offset) = av_strdup(value);
00293 }
00294 }
00295 }
00296 }
00297
00302 static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end)
00303 {
00304 char buf[256];
00305
00306 skip_spaces(&p);
00307 if (!av_stristart(p, "npt=", &p))
00308 return;
00309
00310 *start = AV_NOPTS_VALUE;
00311 *end = AV_NOPTS_VALUE;
00312
00313 get_word_sep(buf, sizeof(buf), "-", &p);
00314 *start = parse_date(buf, 1);
00315 if (*p == '-') {
00316 p++;
00317 get_word_sep(buf, sizeof(buf), "-", &p);
00318 *end = parse_date(buf, 1);
00319 }
00320
00321
00322 }
00323
00324 typedef struct SDPParseState {
00325
00326 struct in_addr default_ip;
00327 int default_ttl;
00328 int skip_media;
00329 } SDPParseState;
00330
00331 static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
00332 int letter, const char *buf)
00333 {
00334 RTSPState *rt = s->priv_data;
00335 char buf1[64], st_type[64];
00336 const char *p;
00337 enum CodecType codec_type;
00338 int payload_type, i;
00339 AVStream *st;
00340 RTSPStream *rtsp_st;
00341 struct in_addr sdp_ip;
00342 int ttl;
00343
00344 #ifdef DEBUG
00345 printf("sdp: %c='%s'\n", letter, buf);
00346 #endif
00347
00348 p = buf;
00349 if (s1->skip_media && letter != 'm')
00350 return;
00351 switch(letter) {
00352 case 'c':
00353 get_word(buf1, sizeof(buf1), &p);
00354 if (strcmp(buf1, "IN") != 0)
00355 return;
00356 get_word(buf1, sizeof(buf1), &p);
00357 if (strcmp(buf1, "IP4") != 0)
00358 return;
00359 get_word_sep(buf1, sizeof(buf1), "/", &p);
00360 if (inet_aton(buf1, &sdp_ip) == 0)
00361 return;
00362 ttl = 16;
00363 if (*p == '/') {
00364 p++;
00365 get_word_sep(buf1, sizeof(buf1), "/", &p);
00366 ttl = atoi(buf1);
00367 }
00368 if (s->nb_streams == 0) {
00369 s1->default_ip = sdp_ip;
00370 s1->default_ttl = ttl;
00371 } else {
00372 st = s->streams[s->nb_streams - 1];
00373 rtsp_st = st->priv_data;
00374 rtsp_st->sdp_ip = sdp_ip;
00375 rtsp_st->sdp_ttl = ttl;
00376 }
00377 break;
00378 case 's':
00379 av_metadata_set(&s->metadata, "title", p);
00380 break;
00381 case 'i':
00382 if (s->nb_streams == 0) {
00383 av_metadata_set(&s->metadata, "comment", p);
00384 break;
00385 }
00386 break;
00387 case 'm':
00388
00389 s1->skip_media = 0;
00390 get_word(st_type, sizeof(st_type), &p);
00391 if (!strcmp(st_type, "audio")) {
00392 codec_type = CODEC_TYPE_AUDIO;
00393 } else if (!strcmp(st_type, "video")) {
00394 codec_type = CODEC_TYPE_VIDEO;
00395 } else {
00396 s1->skip_media = 1;
00397 return;
00398 }
00399 rtsp_st = av_mallocz(sizeof(RTSPStream));
00400 if (!rtsp_st)
00401 return;
00402 rtsp_st->stream_index = -1;
00403 dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st);
00404
00405 rtsp_st->sdp_ip = s1->default_ip;
00406 rtsp_st->sdp_ttl = s1->default_ttl;
00407
00408 get_word(buf1, sizeof(buf1), &p);
00409 rtsp_st->sdp_port = atoi(buf1);
00410
00411 get_word(buf1, sizeof(buf1), &p);
00412
00413
00414 get_word(buf1, sizeof(buf1), &p);
00415 rtsp_st->sdp_payload_type = atoi(buf1);
00416
00417 if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
00418
00419 } else {
00420 st = av_new_stream(s, 0);
00421 if (!st)
00422 return;
00423 st->priv_data = rtsp_st;
00424 rtsp_st->stream_index = st->index;
00425 st->codec->codec_type = codec_type;
00426 if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) {
00427
00428 ff_rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type);
00429 }
00430 }
00431
00432 av_strlcpy(rtsp_st->control_url, s->filename, sizeof(rtsp_st->control_url));
00433 break;
00434 case 'a':
00435 if (av_strstart(p, "control:", &p) && s->nb_streams > 0) {
00436 char proto[32];
00437
00438 st = s->streams[s->nb_streams - 1];
00439 rtsp_st = st->priv_data;
00440
00441
00442 url_split(proto, sizeof(proto), NULL, 0, NULL, 0, NULL, NULL, 0, p);
00443 if (proto[0] == '\0') {
00444
00445 av_strlcat(rtsp_st->control_url, "/", sizeof(rtsp_st->control_url));
00446 av_strlcat(rtsp_st->control_url, p, sizeof(rtsp_st->control_url));
00447 } else {
00448 av_strlcpy(rtsp_st->control_url, p, sizeof(rtsp_st->control_url));
00449 }
00450 } else if (av_strstart(p, "rtpmap:", &p) && s->nb_streams > 0) {
00451
00452 get_word(buf1, sizeof(buf1), &p);
00453 payload_type = atoi(buf1);
00454 st = s->streams[s->nb_streams - 1];
00455 rtsp_st = st->priv_data;
00456 sdp_parse_rtpmap(st->codec, rtsp_st, payload_type, p);
00457 } else if (av_strstart(p, "fmtp:", &p)) {
00458
00459 get_word(buf1, sizeof(buf1), &p);
00460 payload_type = atoi(buf1);
00461 for(i = 0; i < s->nb_streams;i++) {
00462 st = s->streams[i];
00463 rtsp_st = st->priv_data;
00464 if (rtsp_st->sdp_payload_type == payload_type) {
00465 if(rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) {
00466 if(!rtsp_st->dynamic_handler->parse_sdp_a_line(s, i, rtsp_st->dynamic_protocol_context, buf)) {
00467 sdp_parse_fmtp(st, p);
00468 }
00469 } else {
00470 sdp_parse_fmtp(st, p);
00471 }
00472 }
00473 }
00474 } else if(av_strstart(p, "framesize:", &p)) {
00475
00476 get_word(buf1, sizeof(buf1), &p);
00477 payload_type = atoi(buf1);
00478 for(i = 0; i < s->nb_streams;i++) {
00479 st = s->streams[i];
00480 rtsp_st = st->priv_data;
00481 if (rtsp_st->sdp_payload_type == payload_type) {
00482 if(rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) {
00483 rtsp_st->dynamic_handler->parse_sdp_a_line(s, i, rtsp_st->dynamic_protocol_context, buf);
00484 }
00485 }
00486 }
00487 } else if(av_strstart(p, "range:", &p)) {
00488 int64_t start, end;
00489
00490
00491 rtsp_parse_range_npt(p, &start, &end);
00492 s->start_time= start;
00493 s->duration= (end==AV_NOPTS_VALUE)?AV_NOPTS_VALUE:end-start;
00494 } else if (av_strstart(p, "IsRealDataType:integer;",&p)) {
00495 if (atoi(p) == 1)
00496 rt->transport = RTSP_TRANSPORT_RDT;
00497 } else if (s->nb_streams > 0) {
00498 if (rt->server_type == RTSP_SERVER_REAL)
00499 ff_real_parse_sdp_a_line(s, s->nb_streams - 1, p);
00500
00501 rtsp_st = s->streams[s->nb_streams - 1]->priv_data;
00502 if (rtsp_st->dynamic_handler &&
00503 rtsp_st->dynamic_handler->parse_sdp_a_line)
00504 rtsp_st->dynamic_handler->parse_sdp_a_line(s, s->nb_streams - 1,
00505 rtsp_st->dynamic_protocol_context, buf);
00506 }
00507 break;
00508 }
00509 }
00510
00511 static int sdp_parse(AVFormatContext *s, const char *content)
00512 {
00513 const char *p;
00514 int letter;
00515
00516
00517
00518
00519
00520 char buf[8192], *q;
00521 SDPParseState sdp_parse_state, *s1 = &sdp_parse_state;
00522
00523 memset(s1, 0, sizeof(SDPParseState));
00524 p = content;
00525 for(;;) {
00526 skip_spaces(&p);
00527 letter = *p;
00528 if (letter == '\0')
00529 break;
00530 p++;
00531 if (*p != '=')
00532 goto next_line;
00533 p++;
00534
00535 q = buf;
00536 while (*p != '\n' && *p != '\r' && *p != '\0') {
00537 if ((q - buf) < sizeof(buf) - 1)
00538 *q++ = *p;
00539 p++;
00540 }
00541 *q = '\0';
00542 sdp_parse_line(s, s1, letter, buf);
00543 next_line:
00544 while (*p != '\n' && *p != '\0')
00545 p++;
00546 if (*p == '\n')
00547 p++;
00548 }
00549 return 0;
00550 }
00551
00552 static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
00553 {
00554 const char *p;
00555 int v;
00556
00557 p = *pp;
00558 skip_spaces(&p);
00559 v = strtol(p, (char **)&p, 10);
00560 if (*p == '-') {
00561 p++;
00562 *min_ptr = v;
00563 v = strtol(p, (char **)&p, 10);
00564 *max_ptr = v;
00565 } else {
00566 *min_ptr = v;
00567 *max_ptr = v;
00568 }
00569 *pp = p;
00570 }
00571
00572
00573 static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p)
00574 {
00575 char transport_protocol[16];
00576 char profile[16];
00577 char lower_transport[16];
00578 char parameter[16];
00579 RTSPTransportField *th;
00580 char buf[256];
00581
00582 reply->nb_transports = 0;
00583
00584 for(;;) {
00585 skip_spaces(&p);
00586 if (*p == '\0')
00587 break;
00588
00589 th = &reply->transports[reply->nb_transports];
00590
00591 get_word_sep(transport_protocol, sizeof(transport_protocol),
00592 "/", &p);
00593 if (*p == '/')
00594 p++;
00595 if (!strcasecmp (transport_protocol, "rtp")) {
00596 get_word_sep(profile, sizeof(profile), "/;,", &p);
00597 lower_transport[0] = '\0';
00598
00599 if (*p == '/') {
00600 p++;
00601 get_word_sep(lower_transport, sizeof(lower_transport),
00602 ";,", &p);
00603 }
00604 th->transport = RTSP_TRANSPORT_RTP;
00605 } else if (!strcasecmp (transport_protocol, "x-pn-tng") ||
00606 !strcasecmp (transport_protocol, "x-real-rdt")) {
00607
00608 get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p);
00609 profile[0] = '\0';
00610 th->transport = RTSP_TRANSPORT_RDT;
00611 }
00612 if (!strcasecmp(lower_transport, "TCP"))
00613 th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
00614 else
00615 th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
00616
00617 if (*p == ';')
00618 p++;
00619
00620 while (*p != '\0' && *p != ',') {
00621 get_word_sep(parameter, sizeof(parameter), "=;,", &p);
00622 if (!strcmp(parameter, "port")) {
00623 if (*p == '=') {
00624 p++;
00625 rtsp_parse_range(&th->port_min, &th->port_max, &p);
00626 }
00627 } else if (!strcmp(parameter, "client_port")) {
00628 if (*p == '=') {
00629 p++;
00630 rtsp_parse_range(&th->client_port_min,
00631 &th->client_port_max, &p);
00632 }
00633 } else if (!strcmp(parameter, "server_port")) {
00634 if (*p == '=') {
00635 p++;
00636 rtsp_parse_range(&th->server_port_min,
00637 &th->server_port_max, &p);
00638 }
00639 } else if (!strcmp(parameter, "interleaved")) {
00640 if (*p == '=') {
00641 p++;
00642 rtsp_parse_range(&th->interleaved_min,
00643 &th->interleaved_max, &p);
00644 }
00645 } else if (!strcmp(parameter, "multicast")) {
00646 if (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP)
00647 th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST;
00648 } else if (!strcmp(parameter, "ttl")) {
00649 if (*p == '=') {
00650 p++;
00651 th->ttl = strtol(p, (char **)&p, 10);
00652 }
00653 } else if (!strcmp(parameter, "destination")) {
00654 struct in_addr ipaddr;
00655
00656 if (*p == '=') {
00657 p++;
00658 get_word_sep(buf, sizeof(buf), ";,", &p);
00659 if (inet_aton(buf, &ipaddr))
00660 th->destination = ntohl(ipaddr.s_addr);
00661 }
00662 }
00663 while (*p != ';' && *p != '\0' && *p != ',')
00664 p++;
00665 if (*p == ';')
00666 p++;
00667 }
00668 if (*p == ',')
00669 p++;
00670
00671 reply->nb_transports++;
00672 }
00673 }
00674
00675 void rtsp_parse_line(RTSPMessageHeader *reply, const char *buf)
00676 {
00677 const char *p;
00678
00679
00680 p = buf;
00681 if (av_stristart(p, "Session:", &p)) {
00682 get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
00683 } else if (av_stristart(p, "Content-Length:", &p)) {
00684 reply->content_length = strtol(p, NULL, 10);
00685 } else if (av_stristart(p, "Transport:", &p)) {
00686 rtsp_parse_transport(reply, p);
00687 } else if (av_stristart(p, "CSeq:", &p)) {
00688 reply->seq = strtol(p, NULL, 10);
00689 } else if (av_stristart(p, "Range:", &p)) {
00690 rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end);
00691 } else if (av_stristart(p, "RealChallenge1:", &p)) {
00692 skip_spaces(&p);
00693 av_strlcpy(reply->real_challenge, p, sizeof(reply->real_challenge));
00694 } else if (av_stristart(p, "Server:", &p)) {
00695 skip_spaces(&p);
00696 av_strlcpy(reply->server, p, sizeof(reply->server));
00697 }
00698 }
00699
00700 static int url_readbuf(URLContext *h, unsigned char *buf, int size)
00701 {
00702 int ret, len;
00703
00704 len = 0;
00705 while (len < size) {
00706 ret = url_read(h, buf+len, size-len);
00707 if (ret < 1)
00708 return ret;
00709 len += ret;
00710 }
00711 return len;
00712 }
00713
00714
00715 static void rtsp_skip_packet(AVFormatContext *s)
00716 {
00717 RTSPState *rt = s->priv_data;
00718 int ret, len, len1;
00719 uint8_t buf[1024];
00720
00721 ret = url_readbuf(rt->rtsp_hd, buf, 3);
00722 if (ret != 3)
00723 return;
00724 len = AV_RB16(buf + 1);
00725 #ifdef DEBUG
00726 printf("skipping RTP packet len=%d\n", len);
00727 #endif
00728
00729 while (len > 0) {
00730 len1 = len;
00731 if (len1 > sizeof(buf))
00732 len1 = sizeof(buf);
00733 ret = url_readbuf(rt->rtsp_hd, buf, len1);
00734 if (ret != len1)
00735 return;
00736 len -= len1;
00737 }
00738 }
00739
00740 static void rtsp_send_cmd(AVFormatContext *s,
00741 const char *cmd, RTSPMessageHeader *reply,
00742 unsigned char **content_ptr)
00743 {
00744 RTSPState *rt = s->priv_data;
00745 char buf[4096], buf1[1024], *q;
00746 unsigned char ch;
00747 const char *p;
00748 int content_length, line_count;
00749 unsigned char *content = NULL;
00750
00751 memset(reply, 0, sizeof(*reply));
00752
00753 rt->seq++;
00754 av_strlcpy(buf, cmd, sizeof(buf));
00755 snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq);
00756 av_strlcat(buf, buf1, sizeof(buf));
00757 if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
00758 snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id);
00759 av_strlcat(buf, buf1, sizeof(buf));
00760 }
00761 av_strlcat(buf, "\r\n", sizeof(buf));
00762 #ifdef DEBUG
00763 printf("Sending:\n%s--\n", buf);
00764 #endif
00765 url_write(rt->rtsp_hd, buf, strlen(buf));
00766
00767
00768 line_count = 0;
00769 rt->last_reply[0] = '\0';
00770 for(;;) {
00771 q = buf;
00772 for(;;) {
00773 if (url_readbuf(rt->rtsp_hd, &ch, 1) != 1)
00774 break;
00775 if (ch == '\n')
00776 break;
00777 if (ch == '$') {
00778
00779 rtsp_skip_packet(s);
00780 } else if (ch != '\r') {
00781 if ((q - buf) < sizeof(buf) - 1)
00782 *q++ = ch;
00783 }
00784 }
00785 *q = '\0';
00786 #ifdef DEBUG
00787 printf("line='%s'\n", buf);
00788 #endif
00789
00790 if (buf[0] == '\0')
00791 break;
00792 p = buf;
00793 if (line_count == 0) {
00794
00795 get_word(buf1, sizeof(buf1), &p);
00796 get_word(buf1, sizeof(buf1), &p);
00797 reply->status_code = atoi(buf1);
00798 } else {
00799 rtsp_parse_line(reply, p);
00800 av_strlcat(rt->last_reply, p, sizeof(rt->last_reply));
00801 av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply));
00802 }
00803 line_count++;
00804 }
00805
00806 if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
00807 av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id));
00808
00809 content_length = reply->content_length;
00810 if (content_length > 0) {
00811
00812 content = av_malloc(content_length + 1);
00813 (void)url_readbuf(rt->rtsp_hd, content, content_length);
00814 content[content_length] = '\0';
00815 }
00816 if (content_ptr)
00817 *content_ptr = content;
00818 else
00819 av_free(content);
00820 }
00821
00822
00823
00824 static void rtsp_close_streams(RTSPState *rt)
00825 {
00826 int i;
00827 RTSPStream *rtsp_st;
00828
00829 for(i=0;i<rt->nb_rtsp_streams;i++) {
00830 rtsp_st = rt->rtsp_streams[i];
00831 if (rtsp_st) {
00832 if (rtsp_st->transport_priv) {
00833 if (rt->transport == RTSP_TRANSPORT_RDT)
00834 ff_rdt_parse_close(rtsp_st->transport_priv);
00835 else
00836 rtp_parse_close(rtsp_st->transport_priv);
00837 }
00838 if (rtsp_st->rtp_handle)
00839 url_close(rtsp_st->rtp_handle);
00840 if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context)
00841 rtsp_st->dynamic_handler->close(rtsp_st->dynamic_protocol_context);
00842 }
00843 }
00844 av_free(rt->rtsp_streams);
00845 }
00846
00847 static int
00848 rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
00849 {
00850 RTSPState *rt = s->priv_data;
00851 AVStream *st = NULL;
00852
00853
00854 if (rtsp_st->stream_index >= 0)
00855 st = s->streams[rtsp_st->stream_index];
00856 if (!st)
00857 s->ctx_flags |= AVFMTCTX_NOHEADER;
00858
00859 if (rt->transport == RTSP_TRANSPORT_RDT)
00860 rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
00861 rtsp_st->dynamic_protocol_context,
00862 rtsp_st->dynamic_handler);
00863 else
00864 rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle,
00865 rtsp_st->sdp_payload_type,
00866 &rtsp_st->rtp_payload_data);
00867
00868 if (!rtsp_st->transport_priv) {
00869 return AVERROR(ENOMEM);
00870 } else if (rt->transport != RTSP_TRANSPORT_RDT) {
00871 if(rtsp_st->dynamic_handler) {
00872 rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
00873 rtsp_st->dynamic_protocol_context,
00874 rtsp_st->dynamic_handler);
00875 }
00876 }
00877
00878 return 0;
00879 }
00880
00884 static int
00885 make_setup_request (AVFormatContext *s, const char *host, int port,
00886 int lower_transport, const char *real_challenge)
00887 {
00888 RTSPState *rt = s->priv_data;
00889 int j, i, err, interleave = 0;
00890 RTSPStream *rtsp_st;
00891 RTSPMessageHeader reply1, *reply = &reply1;
00892 char cmd[2048];
00893 const char *trans_pref;
00894
00895 if (rt->transport == RTSP_TRANSPORT_RDT)
00896 trans_pref = "x-pn-tng";
00897 else
00898 trans_pref = "RTP/AVP";
00899
00900
00901
00902
00903
00904 for(j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
00905 char transport[2048];
00906
00907 rtsp_st = rt->rtsp_streams[i];
00908
00909
00910 if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
00911 char buf[256];
00912
00913
00914 if (RTSP_RTP_PORT_MIN != 0) {
00915 while(j <= RTSP_RTP_PORT_MAX) {
00916 snprintf(buf, sizeof(buf), "rtp://%s?localport=%d", host, j);
00917 j += 2;
00918 if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0) {
00919 goto rtp_opened;
00920 }
00921 }
00922 }
00923
00924
00925
00926
00927
00928
00929
00930
00931 rtp_opened:
00932 port = rtp_get_local_port(rtsp_st->rtp_handle);
00933 snprintf(transport, sizeof(transport) - 1,
00934 "%s/UDP;", trans_pref);
00935 if (rt->server_type != RTSP_SERVER_REAL)
00936 av_strlcat(transport, "unicast;", sizeof(transport));
00937 av_strlcatf(transport, sizeof(transport),
00938 "client_port=%d", port);
00939 if (rt->transport == RTSP_TRANSPORT_RTP)
00940 av_strlcatf(transport, sizeof(transport), "-%d", port + 1);
00941 }
00942
00943
00944 else if (lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
00945 snprintf(transport, sizeof(transport) - 1,
00946 "%s/TCP;", trans_pref);
00947 if (rt->server_type == RTSP_SERVER_WMS)
00948 av_strlcat(transport, "unicast;", sizeof(transport));
00949 av_strlcatf(transport, sizeof(transport),
00950 "interleaved=%d-%d",
00951 interleave, interleave + 1);
00952 interleave += 2;
00953 }
00954
00955 else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) {
00956 snprintf(transport, sizeof(transport) - 1,
00957 "%s/UDP;multicast", trans_pref);
00958 }
00959 if (rt->server_type == RTSP_SERVER_REAL ||
00960 rt->server_type == RTSP_SERVER_WMS)
00961 av_strlcat(transport, ";mode=play", sizeof(transport));
00962 snprintf(cmd, sizeof(cmd),
00963 "SETUP %s RTSP/1.0\r\n"
00964 "Transport: %s\r\n",
00965 rtsp_st->control_url, transport);
00966 if (i == 0 && rt->server_type == RTSP_SERVER_REAL) {
00967 char real_res[41], real_csum[9];
00968 ff_rdt_calc_response_and_checksum(real_res, real_csum,
00969 real_challenge);
00970 av_strlcatf(cmd, sizeof(cmd),
00971 "If-Match: %s\r\n"
00972 "RealChallenge2: %s, sd=%s\r\n",
00973 rt->session_id, real_res, real_csum);
00974 }
00975 rtsp_send_cmd(s, cmd, reply, NULL);
00976 if (reply->status_code == 461 && i == 0) {
00977 err = 1;
00978 goto fail;
00979 } else if (reply->status_code != RTSP_STATUS_OK ||
00980 reply->nb_transports != 1) {
00981 err = AVERROR_INVALIDDATA;
00982 goto fail;
00983 }
00984
00985
00986 if (i > 0) {
00987 if (reply->transports[0].lower_transport != rt->lower_transport ||
00988 reply->transports[0].transport != rt->transport) {
00989 err = AVERROR_INVALIDDATA;
00990 goto fail;
00991 }
00992 } else {
00993 rt->lower_transport = reply->transports[0].lower_transport;
00994 rt->transport = reply->transports[0].transport;
00995 }
00996
00997
00998 if (reply->transports[0].lower_transport != RTSP_LOWER_TRANSPORT_UDP &&
00999 (lower_transport == RTSP_LOWER_TRANSPORT_UDP)) {
01000 url_close(rtsp_st->rtp_handle);
01001 rtsp_st->rtp_handle = NULL;
01002 }
01003
01004 switch(reply->transports[0].lower_transport) {
01005 case RTSP_LOWER_TRANSPORT_TCP:
01006 rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
01007 rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
01008 break;
01009
01010 case RTSP_LOWER_TRANSPORT_UDP:
01011 {
01012 char url[1024];
01013
01014
01015 snprintf(url, sizeof(url), "rtp://%s:%d",
01016 host, reply->transports[0].server_port_min);
01017 if (rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
01018 err = AVERROR_INVALIDDATA;
01019 goto fail;
01020 }
01021 }
01022 break;
01023 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
01024 {
01025 char url[1024];
01026 struct in_addr in;
01027
01028 in.s_addr = htonl(reply->transports[0].destination);
01029 snprintf(url, sizeof(url), "rtp://%s:%d?ttl=%d",
01030 inet_ntoa(in),
01031 reply->transports[0].port_min,
01032 reply->transports[0].ttl);
01033 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
01034 err = AVERROR_INVALIDDATA;
01035 goto fail;
01036 }
01037 }
01038 break;
01039 }
01040
01041 if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
01042 goto fail;
01043 }
01044
01045 if (rt->server_type == RTSP_SERVER_REAL)
01046 rt->need_subscription = 1;
01047
01048 return 0;
01049
01050 fail:
01051 for (i=0; i<rt->nb_rtsp_streams; i++) {
01052 if (rt->rtsp_streams[i]->rtp_handle) {
01053 url_close(rt->rtsp_streams[i]->rtp_handle);
01054 rt->rtsp_streams[i]->rtp_handle = NULL;
01055 }
01056 }
01057 return err;
01058 }
01059
01060 static int rtsp_read_header(AVFormatContext *s,
01061 AVFormatParameters *ap)
01062 {
01063 RTSPState *rt = s->priv_data;
01064 char host[1024], path[1024], tcpname[1024], cmd[2048], *option_list, *option;
01065 URLContext *rtsp_hd;
01066 int port, ret, err;
01067 RTSPMessageHeader reply1, *reply = &reply1;
01068 unsigned char *content = NULL;
01069 int lower_transport_mask = 0;
01070 char real_challenge[64];
01071
01072
01073 url_split(NULL, 0, NULL, 0,
01074 host, sizeof(host), &port, path, sizeof(path), s->filename);
01075 if (port < 0)
01076 port = RTSP_DEFAULT_PORT;
01077
01078
01079 option_list = strchr(path, '?');
01080 if (option_list) {
01081
01082 *option_list++ = 0;
01083 while(option_list) {
01084
01085 option = option_list;
01086 option_list = strchr(option_list, '&');
01087 if (option_list)
01088 *(option_list++) = 0;
01089
01090 if (strcmp(option, "udp") == 0)
01091 lower_transport_mask = (1<< RTSP_LOWER_TRANSPORT_UDP);
01092 else if (strcmp(option, "multicast") == 0)
01093 lower_transport_mask = (1<< RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
01094 else if (strcmp(option, "tcp") == 0)
01095 lower_transport_mask = (1<< RTSP_LOWER_TRANSPORT_TCP);
01096 }
01097 }
01098
01099 if (!lower_transport_mask)
01100 lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
01101
01102
01103 snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
01104 if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0)
01105 return AVERROR(EIO);
01106 rt->rtsp_hd = rtsp_hd;
01107 rt->seq = 0;
01108
01109
01110 for (rt->server_type = RTSP_SERVER_RTP;;) {
01111 snprintf(cmd, sizeof(cmd),
01112 "OPTIONS %s RTSP/1.0\r\n", s->filename);
01113 if (rt->server_type == RTSP_SERVER_REAL)
01114 av_strlcat(cmd,
01124 "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7\r\n"
01125 "PlayerStarttime: [28/03/2003:22:50:23 00:00]\r\n"
01126 "CompanyID: KnKV4M4I/B2FjJ1TToLycw==\r\n"
01127 "GUID: 00000000-0000-0000-0000-000000000000\r\n",
01128 sizeof(cmd));
01129 rtsp_send_cmd(s, cmd, reply, NULL);
01130 if (reply->status_code != RTSP_STATUS_OK) {
01131 err = AVERROR_INVALIDDATA;
01132 goto fail;
01133 }
01134
01135
01136 if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) {
01137 rt->server_type = RTSP_SERVER_REAL;
01138 continue;
01139 } else if (!strncasecmp(reply->server, "WMServer/", 9)) {
01140 rt->server_type = RTSP_SERVER_WMS;
01141 } else if (rt->server_type == RTSP_SERVER_REAL) {
01142 strcpy(real_challenge, reply->real_challenge);
01143 }
01144 break;
01145 }
01146
01147
01148 snprintf(cmd, sizeof(cmd),
01149 "DESCRIBE %s RTSP/1.0\r\n"
01150 "Accept: application/sdp\r\n",
01151 s->filename);
01152 if (rt->server_type == RTSP_SERVER_REAL) {
01157 av_strlcat(cmd,
01158 "Require: com.real.retain-entity-for-setup\r\n",
01159 sizeof(cmd));
01160 }
01161 rtsp_send_cmd(s, cmd, reply, &content);
01162 if (!content) {
01163 err = AVERROR_INVALIDDATA;
01164 goto fail;
01165 }
01166 if (reply->status_code != RTSP_STATUS_OK) {
01167 err = AVERROR_INVALIDDATA;
01168 goto fail;
01169 }
01170
01171
01172 ret = sdp_parse(s, (const char *)content);
01173 av_freep(&content);
01174 if (ret < 0) {
01175 err = AVERROR_INVALIDDATA;
01176 goto fail;
01177 }
01178
01179 do {
01180 int lower_transport = ff_log2_tab[lower_transport_mask & ~(lower_transport_mask - 1)];
01181
01182 err = make_setup_request(s, host, port, lower_transport,
01183 rt->server_type == RTSP_SERVER_REAL ?
01184 real_challenge : NULL);
01185 if (err < 0)
01186 goto fail;
01187 lower_transport_mask &= ~(1 << lower_transport);
01188 if (lower_transport_mask == 0 && err == 1) {
01189 err = AVERROR(FF_NETERROR(EPROTONOSUPPORT));
01190 goto fail;
01191 }
01192 } while (err);
01193
01194 rt->state = RTSP_STATE_IDLE;
01195 rt->seek_timestamp = 0;
01196
01197 if (ap->initial_pause) {
01198
01199 } else {
01200 if (rtsp_read_play(s) < 0) {
01201 err = AVERROR_INVALIDDATA;
01202 goto fail;
01203 }
01204 }
01205 return 0;
01206 fail:
01207 rtsp_close_streams(rt);
01208 av_freep(&content);
01209 url_close(rt->rtsp_hd);
01210 return err;
01211 }
01212
01213 static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
01214 uint8_t *buf, int buf_size)
01215 {
01216 RTSPState *rt = s->priv_data;
01217 int id, len, i, ret;
01218 RTSPStream *rtsp_st;
01219
01220 #ifdef DEBUG_RTP_TCP
01221 printf("tcp_read_packet:\n");
01222 #endif
01223 redo:
01224 for(;;) {
01225 ret = url_readbuf(rt->rtsp_hd, buf, 1);
01226 #ifdef DEBUG_RTP_TCP
01227 printf("ret=%d c=%02x [%c]\n", ret, buf[0], buf[0]);
01228 #endif
01229 if (ret != 1)
01230 return -1;
01231 if (buf[0] == '$')
01232 break;
01233 }
01234 ret = url_readbuf(rt->rtsp_hd, buf, 3);
01235 if (ret != 3)
01236 return -1;
01237 id = buf[0];
01238 len = AV_RB16(buf + 1);
01239 #ifdef DEBUG_RTP_TCP
01240 printf("id=%d len=%d\n", id, len);
01241 #endif
01242 if (len > buf_size || len < 12)
01243 goto redo;
01244
01245 ret = url_readbuf(rt->rtsp_hd, buf, len);
01246 if (ret != len)
01247 return -1;
01248 if (rt->transport == RTSP_TRANSPORT_RDT &&
01249 ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL) < 0)
01250 return -1;
01251
01252
01253 for(i = 0; i < rt->nb_rtsp_streams; i++) {
01254 rtsp_st = rt->rtsp_streams[i];
01255 if (id >= rtsp_st->interleaved_min &&
01256 id <= rtsp_st->interleaved_max)
01257 goto found;
01258 }
01259 goto redo;
01260 found:
01261 *prtsp_st = rtsp_st;
01262 return len;
01263 }
01264
01265 static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
01266 uint8_t *buf, int buf_size)
01267 {
01268 RTSPState *rt = s->priv_data;
01269 RTSPStream *rtsp_st;
01270 fd_set rfds;
01271 int fd1, fd2, fd_max, n, i, ret;
01272 struct timeval tv;
01273
01274 for(;;) {
01275 if (url_interrupt_cb())
01276 return AVERROR(EINTR);
01277 FD_ZERO(&rfds);
01278 fd_max = -1;
01279 for(i = 0; i < rt->nb_rtsp_streams; i++) {
01280 rtsp_st = rt->rtsp_streams[i];
01281
01282 rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2);
01283 if (fd1 > fd_max)
01284 fd_max = fd1;
01285 FD_SET(fd1, &rfds);
01286 }
01287 tv.tv_sec = 0;
01288 tv.tv_usec = 100 * 1000;
01289 n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
01290 if (n > 0) {
01291 for(i = 0; i < rt->nb_rtsp_streams; i++) {
01292 rtsp_st = rt->rtsp_streams[i];
01293 rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2);
01294 if (FD_ISSET(fd1, &rfds)) {
01295 ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
01296 if (ret > 0) {
01297 *prtsp_st = rtsp_st;
01298 return ret;
01299 }
01300 }
01301 }
01302 }
01303 }
01304 }
01305
01306 static int rtsp_read_packet(AVFormatContext *s,
01307 AVPacket *pkt)
01308 {
01309 RTSPState *rt = s->priv_data;
01310 RTSPStream *rtsp_st;
01311 int ret, len;
01312 uint8_t buf[10 * RTP_MAX_PACKET_LENGTH];
01313
01314 if (rt->server_type == RTSP_SERVER_REAL) {
01315 int i;
01316 RTSPMessageHeader reply1, *reply = &reply1;
01317 enum AVDiscard cache[MAX_STREAMS];
01318 char cmd[1024];
01319
01320 for (i = 0; i < s->nb_streams; i++)
01321 cache[i] = s->streams[i]->discard;
01322
01323 if (!rt->need_subscription) {
01324 if (memcmp (cache, rt->real_setup_cache,
01325 sizeof(enum AVDiscard) * s->nb_streams)) {
01326 av_strlcatf(cmd, sizeof(cmd),
01327 "SET_PARAMETER %s RTSP/1.0\r\n"
01328 "Unsubscribe: %s\r\n",
01329 s->filename, rt->last_subscription);
01330 rtsp_send_cmd(s, cmd, reply, NULL);
01331 if (reply->status_code != RTSP_STATUS_OK)
01332 return AVERROR_INVALIDDATA;
01333 rt->need_subscription = 1;
01334 }
01335 }
01336
01337 if (rt->need_subscription) {
01338 int r, rule_nr, first = 1;
01339
01340 memcpy(rt->real_setup_cache, cache,
01341 sizeof(enum AVDiscard) * s->nb_streams);
01342 rt->last_subscription[0] = 0;
01343
01344 snprintf(cmd, sizeof(cmd),
01345 "SET_PARAMETER %s RTSP/1.0\r\n"
01346 "Subscribe: ",
01347 s->filename);
01348 for (i = 0; i < rt->nb_rtsp_streams; i++) {
01349 rule_nr = 0;
01350 for (r = 0; r < s->nb_streams; r++) {
01351 if (s->streams[r]->priv_data == rt->rtsp_streams[i]) {
01352 if (s->streams[r]->discard != AVDISCARD_ALL) {
01353 if (!first)
01354 av_strlcat(rt->last_subscription, ",",
01355 sizeof(rt->last_subscription));
01356 ff_rdt_subscribe_rule(
01357 rt->last_subscription,
01358 sizeof(rt->last_subscription), i, rule_nr);
01359 first = 0;
01360 }
01361 rule_nr++;
01362 }
01363 }
01364 }
01365 av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription);
01366 rtsp_send_cmd(s, cmd, reply, NULL);
01367 if (reply->status_code != RTSP_STATUS_OK)
01368 return AVERROR_INVALIDDATA;
01369 rt->need_subscription = 0;
01370
01371 if (rt->state == RTSP_STATE_PLAYING)
01372 rtsp_read_play (s);
01373 }
01374 }
01375
01376
01377 if (rt->cur_transport_priv) {
01378 if (rt->transport == RTSP_TRANSPORT_RDT)
01379 ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
01380 else
01381 ret = rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
01382 if (ret == 0) {
01383 rt->cur_transport_priv = NULL;
01384 return 0;
01385 } else if (ret == 1) {
01386 return 0;
01387 } else {
01388 rt->cur_transport_priv = NULL;
01389 }
01390 }
01391
01392
01393 redo:
01394 switch(rt->lower_transport) {
01395 default:
01396 case RTSP_LOWER_TRANSPORT_TCP:
01397 len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf));
01398 break;
01399 case RTSP_LOWER_TRANSPORT_UDP:
01400 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
01401 len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf));
01402 if (len >=0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP)
01403 rtp_check_and_send_back_rr(rtsp_st->transport_priv, len);
01404 break;
01405 }
01406 if (len < 0)
01407 return len;
01408 if (rt->transport == RTSP_TRANSPORT_RDT)
01409 ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
01410 else
01411 ret = rtp_parse_packet(rtsp_st->transport_priv, pkt, buf, len);
01412 if (ret < 0)
01413 goto redo;
01414 if (ret == 1) {
01415
01416 rt->cur_transport_priv = rtsp_st->transport_priv;
01417 }
01418 return 0;
01419 }
01420
01421 static int rtsp_read_play(AVFormatContext *s)
01422 {
01423 RTSPState *rt = s->priv_data;
01424 RTSPMessageHeader reply1, *reply = &reply1;
01425 char cmd[1024];
01426
01427 av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state);
01428
01429 if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
01430 if (rt->state == RTSP_STATE_PAUSED) {
01431 snprintf(cmd, sizeof(cmd),
01432 "PLAY %s RTSP/1.0\r\n",
01433 s->filename);
01434 } else {
01435 snprintf(cmd, sizeof(cmd),
01436 "PLAY %s RTSP/1.0\r\n"
01437 "Range: npt=%0.3f-\r\n",
01438 s->filename,
01439 (double)rt->seek_timestamp / AV_TIME_BASE);
01440 }
01441 rtsp_send_cmd(s, cmd, reply, NULL);
01442 if (reply->status_code != RTSP_STATUS_OK) {
01443 return -1;
01444 }
01445 }
01446 rt->state = RTSP_STATE_PLAYING;
01447 return 0;
01448 }
01449
01450
01451 static int rtsp_read_pause(AVFormatContext *s)
01452 {
01453 RTSPState *rt = s->priv_data;
01454 RTSPMessageHeader reply1, *reply = &reply1;
01455 char cmd[1024];
01456
01457 rt = s->priv_data;
01458
01459 if (rt->state != RTSP_STATE_PLAYING)
01460 return 0;
01461 else if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
01462 snprintf(cmd, sizeof(cmd),
01463 "PAUSE %s RTSP/1.0\r\n",
01464 s->filename);
01465 rtsp_send_cmd(s, cmd, reply, NULL);
01466 if (reply->status_code != RTSP_STATUS_OK) {
01467 return -1;
01468 }
01469 }
01470 rt->state = RTSP_STATE_PAUSED;
01471 return 0;
01472 }
01473
01474 static int rtsp_read_seek(AVFormatContext *s, int stream_index,
01475 int64_t timestamp, int flags)
01476 {
01477 RTSPState *rt = s->priv_data;
01478
01479 rt->seek_timestamp = av_rescale_q(timestamp, s->streams[stream_index]->time_base, AV_TIME_BASE_Q);
01480 switch(rt->state) {
01481 default:
01482 case RTSP_STATE_IDLE:
01483 break;
01484 case RTSP_STATE_PLAYING:
01485 if (rtsp_read_play(s) != 0)
01486 return -1;
01487 break;
01488 case RTSP_STATE_PAUSED:
01489 rt->state = RTSP_STATE_IDLE;
01490 break;
01491 }
01492 return 0;
01493 }
01494
01495 static int rtsp_read_close(AVFormatContext *s)
01496 {
01497 RTSPState *rt = s->priv_data;
01498 RTSPMessageHeader reply1, *reply = &reply1;
01499 char cmd[1024];
01500
01501 #if 0
01502
01503 if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
01504 url_fclose(&rt->rtsp_gb);
01505 }
01506 #endif
01507 snprintf(cmd, sizeof(cmd),
01508 "TEARDOWN %s RTSP/1.0\r\n",
01509 s->filename);
01510 rtsp_send_cmd(s, cmd, reply, NULL);
01511
01512 rtsp_close_streams(rt);
01513 url_close(rt->rtsp_hd);
01514 return 0;
01515 }
01516
01517 #if CONFIG_RTSP_DEMUXER
01518 AVInputFormat rtsp_demuxer = {
01519 "rtsp",
01520 NULL_IF_CONFIG_SMALL("RTSP input format"),
01521 sizeof(RTSPState),
01522 rtsp_probe,
01523 rtsp_read_header,
01524 rtsp_read_packet,
01525 rtsp_read_close,
01526 rtsp_read_seek,
01527 .flags = AVFMT_NOFILE,
01528 .read_play = rtsp_read_play,
01529 .read_pause = rtsp_read_pause,
01530 };
01531 #endif
01532
01533 static int sdp_probe(AVProbeData *p1)
01534 {
01535 const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
01536
01537
01538 while (p < p_end && *p != '\0') {
01539 if (p + sizeof("c=IN IP4") - 1 < p_end && av_strstart(p, "c=IN IP4", NULL))
01540 return AVPROBE_SCORE_MAX / 2;
01541
01542 while(p < p_end - 1 && *p != '\n') p++;
01543 if (++p >= p_end)
01544 break;
01545 if (*p == '\r')
01546 p++;
01547 }
01548 return 0;
01549 }
01550
01551 #define SDP_MAX_SIZE 8192
01552
01553 static int sdp_read_header(AVFormatContext *s,
01554 AVFormatParameters *ap)
01555 {
01556 RTSPState *rt = s->priv_data;
01557 RTSPStream *rtsp_st;
01558 int size, i, err;
01559 char *content;
01560 char url[1024];
01561
01562
01563
01564 content = av_malloc(SDP_MAX_SIZE);
01565 size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1);
01566 if (size <= 0) {
01567 av_free(content);
01568 return AVERROR_INVALIDDATA;
01569 }
01570 content[size] ='\0';
01571
01572 sdp_parse(s, content);
01573 av_free(content);
01574
01575
01576 for(i=0;i<rt->nb_rtsp_streams;i++) {
01577 rtsp_st = rt->rtsp_streams[i];
01578
01579 snprintf(url, sizeof(url), "rtp://%s:%d?localport=%d&ttl=%d",
01580 inet_ntoa(rtsp_st->sdp_ip),
01581 rtsp_st->sdp_port,
01582 rtsp_st->sdp_port,
01583 rtsp_st->sdp_ttl);
01584 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
01585 err = AVERROR_INVALIDDATA;
01586 goto fail;
01587 }
01588 if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
01589 goto fail;
01590 }
01591 return 0;
01592 fail:
01593 rtsp_close_streams(rt);
01594 return err;
01595 }
01596
01597 static int sdp_read_packet(AVFormatContext *s,
01598 AVPacket *pkt)
01599 {
01600 return rtsp_read_packet(s, pkt);
01601 }
01602
01603 static int sdp_read_close(AVFormatContext *s)
01604 {
01605 RTSPState *rt = s->priv_data;
01606 rtsp_close_streams(rt);
01607 return 0;
01608 }
01609
01610 #if CONFIG_SDP_DEMUXER
01611 AVInputFormat sdp_demuxer = {
01612 "sdp",
01613 NULL_IF_CONFIG_SMALL("SDP"),
01614 sizeof(RTSPState),
01615 sdp_probe,
01616 sdp_read_header,
01617 sdp_read_packet,
01618 sdp_read_close,
01619 };
01620 #endif
01621
01622 #if CONFIG_REDIR_DEMUXER
01623
01624 static int redir_probe(AVProbeData *pd)
01625 {
01626 const char *p;
01627 p = pd->buf;
01628 while (redir_isspace(*p))
01629 p++;
01630 if (av_strstart(p, "http://", NULL) ||
01631 av_strstart(p, "rtsp://", NULL))
01632 return AVPROBE_SCORE_MAX;
01633 return 0;
01634 }
01635
01636 static int redir_read_header(AVFormatContext *s, AVFormatParameters *ap)
01637 {
01638 char buf[4096], *q;
01639 int c;
01640 AVFormatContext *ic = NULL;
01641 ByteIOContext *f = s->pb;
01642
01643
01644 c = url_fgetc(f);
01645 while (c != URL_EOF) {
01646
01647 for(;;) {
01648 if (!redir_isspace(c))
01649 break;
01650 c = url_fgetc(f);
01651 }
01652 if (c == URL_EOF)
01653 break;
01654
01655 q = buf;
01656 for(;;) {
01657 if (c == URL_EOF || redir_isspace(c))
01658 break;
01659 if ((q - buf) < sizeof(buf) - 1)
01660 *q++ = c;
01661 c = url_fgetc(f);
01662 }
01663 *q = '\0';
01664
01665
01666 if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0)
01667 break;
01668 }
01669 if (!ic)
01670 return AVERROR(EIO);
01671
01672 *s = *ic;
01673 url_fclose(f);
01674
01675 return 0;
01676 }
01677
01678 AVInputFormat redir_demuxer = {
01679 "redir",
01680 NULL_IF_CONFIG_SMALL("Redirector format"),
01681 0,
01682 redir_probe,
01683 redir_read_header,
01684 NULL,
01685 NULL,
01686 };
01687 #endif