Libav
|
00001 /* 00002 * RTSP/SDP client 00003 * Copyright (c) 2002 Fabrice Bellard 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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 //#define DEBUG 00042 //#define DEBUG_RTP_TCP 00043 00044 #if LIBAVFORMAT_VERSION_INT < (53 << 16) 00045 int rtsp_default_protocols = (1 << RTSP_LOWER_TRANSPORT_UDP); 00046 #endif 00047 00048 /* Timeout values for socket select, in ms, 00049 * and read_packet(), in seconds */ 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 /* we use memchr() instead of strchr() here because strchr() will return 00056 * the terminating '\0' of SPACE_CHARS instead of NULL if c is '\0'. */ 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 /* parse the rtpmap description: <codec_name>/<clock_rate>[/<other params>] */ 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 /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and 00109 * see if we can handle this kind of payload. 00110 * The space should normally not be there but some Real streams or 00111 * particular servers ("RealServer Version 6.1.3.970", see issue 1658) 00112 * have a trailing space. */ 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 /* We are in a standard case 00129 * (from http://www.iana.org/assignments/rtp-parameters). */ 00130 /* search into AVRtpPayloadTypes[] */ 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 // TODO: there is a bug here; if it is a mono stream, and 00154 // less than 22000Hz, faad upconverts to stereo and twice 00155 // the frequency. No problem, but the sample rate is being 00156 // set here by the sdp line. Patch on its way. (rdm) 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 /* return the length and optionally the data */ 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 /* decode the hexa encoded parameter */ 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 /* All known fmtp parameters and the corresponding RTPAttrTypeEnum */ 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 /* parse the attribute line from the fmtp a line of an sdp response. This 00252 * is broken out as a function because it is used in rtp_h264.c, which is 00253 * forthcoming. */ 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 /* parse a SDP line and save stream attributes */ 00271 static void sdp_parse_fmtp(AVStream *st, const char *p) 00272 { 00273 char attr[256]; 00274 /* Vorbis setup headers can be up to 12KB and are sent base64 00275 * encoded, giving a 12KB * (4/3) = 16KB FMTP line. */ 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 /* loop on each attribute */ 00283 while (ff_rtsp_next_attr_and_value(&p, attr, sizeof(attr), 00284 value, sizeof(value))) { 00285 /* grab the codec extra_data from the config parameter of the fmtp 00286 * line */ 00287 sdp_parse_fmtp_config(codec, rtsp_st->dynamic_protocol_context, 00288 attr, value); 00289 /* Looking for a known attribute */ 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 // av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start); 00326 // av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end); 00327 } 00328 00329 typedef struct SDPParseState { 00330 /* SDP only */ 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 /* new stream */ 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); /* port */ 00414 rtsp_st->sdp_port = atoi(buf1); 00415 00416 get_word(buf1, sizeof(buf1), &p); /* protocol (ignored) */ 00417 00418 /* XXX: handle list of formats */ 00419 get_word(buf1, sizeof(buf1), &p); /* format list */ 00420 rtsp_st->sdp_payload_type = atoi(buf1); 00421 00422 if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) { 00423 /* no corresponding stream */ 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 /* if standard payload type, we can find the codec right now */ 00433 ff_rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type); 00434 } 00435 } 00436 /* put a default control url */ 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 /* get the control url */ 00449 st = s->streams[s->nb_streams - 1]; 00450 rtsp_st = st->priv_data; 00451 00452 /* XXX: may need to add full url resolution */ 00453 ff_url_split(proto, sizeof(proto), NULL, 0, NULL, 0, 00454 NULL, NULL, 0, p); 00455 if (proto[0] == '\0') { 00456 /* relative control URL */ 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 /* NOTE: rtpmap is only supported AFTER the 'm=' tag */ 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 /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */ 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 // let dynamic protocol handlers have a stab at the line. 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 // this is so that seeking on a streamed file can work. 00505 rtsp_parse_range_npt(p, &start, &end); 00506 s->start_time = start; 00507 /* AV_NOPTS_VALUE means live broadcast (and can't seek) */ 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 /* Some SDP lines, particularly for Realmedia or ASF RTSP streams, 00537 * contain long SDP lines containing complete ASF Headers (several 00538 * kB) or arrays of MDPR (RM stream descriptor) headers plus 00539 * "rulebooks" describing their properties. Therefore, the SDP line 00540 * buffer is large. 00541 * 00542 * The Vorbis FMTP line can be up to 16KB - see sdp_parse_fmtp. */ 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 /* get the content */ 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 /* close and free RTSP streams */ 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 /* Allocate an AVFormatContext for each output stream */ 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 /* Copy the max delay setting; the rtp muxer reads this. */ 00641 rtpctx->max_delay = s->max_delay; 00642 /* Copy other stream parameters. */ 00643 rtpctx->streams[0]->sample_aspect_ratio = st->sample_aspect_ratio; 00644 00645 /* Set the synchronized start time. */ 00646 rtpctx->start_time_realtime = rt->start_time; 00647 00648 /* Remove the local codec, link to the original codec 00649 * context instead, to give the rtp muxer access to 00650 * codec parameters. */ 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 /* Copy the RTP AVStream timebase back to the original AVStream */ 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 /* open the RTP context */ 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 /* Ownership of rtp_handle is passed to the rtp mux context */ 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 /* XXX: only one transport specification is parsed */ 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 /* rtp/avp/<protocol> */ 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 /* x-pn-tng/<protocol> */ 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 /* get each parameter */ 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 /* NOTE: we do case independent match for broken servers */ 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 /* skip a RTP/TCP interleaved packet */ 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 /* skip payload */ 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 /* parse reply (XXX: use buffers) */ 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 /* XXX: only parse it if first char on line ? */ 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 /* test if last line */ 00954 if (buf[0] == '\0') 00955 break; 00956 p = buf; 00957 if (line_count == 0) { 00958 /* get reply code */ 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 /* leave some room for a trailing '\0' (useful for simple parsing) */ 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 /* EOS */ 00991 if (reply->notice == 2101 /* End-of-Stream Reached */ || 00992 reply->notice == 2104 /* Start-of-Stream Reached */ || 00993 reply->notice == 2306 /* Continuous Feed Terminated */) { 00994 rt->state = RTSP_STATE_IDLE; 00995 } else if (reply->notice >= 4400 && reply->notice < 5500) { 00996 return AVERROR(EIO); /* data or server error */ 00997 } else if (reply->notice == 2401 /* Ticket Expired */ || 00998 (reply->notice >= 5500 && reply->notice < 5600) /* end of term */ ) 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 /* default timeout: 1 minute */ 01097 rt->timeout = 60; 01098 01099 /* for each stream, make the setup request */ 01100 /* XXX: we assume the same server is used for the control of each 01101 * RTSP stream */ 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 /* rtx first */ 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; /* no RTX found */ 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 /* RTP/UDP */ 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 /* first try in specified port range */ 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 /* we will use two ports per rtp stream (rtp and rtcp) */ 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 /* then try on any port */ 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 /* RTP/TCP */ 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 /* Unsupported protocol */ && 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 /* XXX: same protocol for all streams is required */ 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 /* close RTP connection if not choosen */ 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 /* XXX: also use address if specified */ 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 /* Try to initialize the connection state in a 01260 * potential NAT router by sending dummy packets. 01261 * RTP/RTCP dummy packets are used for RDT, too. 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 /* describe the stream */ 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 /* now we got the SDP description, we parse it */ 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 /* Announce the stream */ 01404 sdp = av_mallocz(8192); 01405 if (sdp == NULL) 01406 return AVERROR(ENOMEM); 01407 /* We create the SDP based on the RTSP AVFormatContext where we 01408 * aren't allowed to change the filename field. (We create the SDP 01409 * based on the RTSP context since the contexts for the RTP streams 01410 * don't exist yet.) In order to specify a custom URL with the actual 01411 * peer IP instead of the originally specified hostname, we create 01412 * a temporary copy of the AVFormatContext, where the custom URL is set. 01413 * 01414 * FIXME: Create the SDP without copying the AVFormatContext. 01415 * This either requires setting up the RTP stream AVFormatContexts 01416 * already here (complicating things immensely) or getting a more 01417 * flexible SDP creation interface. 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 /* Set up the RTSPStreams for each AVStream */ 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 /* Note, this must match the relative uri set in the sdp content */ 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 /* extract hostname and port */ 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 /* search for options */ 01483 option_list = strrchr(path, '?'); 01484 if (option_list) { 01485 /* Strip out the RTSP specific options, write out the rest of 01486 * the options back into the same string. */ 01487 filename = option_list; 01488 while (option_list) { 01489 /* move the option pointer */ 01490 option = ++option_list; 01491 option_list = strchr(option_list, '&'); 01492 if (option_list) 01493 *option_list = 0; 01494 01495 /* handle the options */ 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 /* Write options back into the buffer, using memmove instead 01504 * of strcpy since the strings may overlap. */ 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 /* Only UDP or TCP - UDP multicast isn't supported. */ 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 /* Construct the URI used in request; this is similar to s->filename, 01530 * but with authentication credentials removed and RTSP specific options 01531 * stripped out. */ 01532 ff_url_join(rt->control_uri, sizeof(rt->control_uri), "rtsp", NULL, 01533 host, port, "%s", path); 01534 01535 /* open the tcp connexion */ 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 /* request options supported by the server; this also detects server 01551 * type */ 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 /* detect server type if not standard-compliant RTP */ 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; /* default is to start stream at position zero */ 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 /* do not start immediately */ 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 /* currently, we cannot probe RTCP handle because of 01676 * blocking restrictions */ 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 /* XXX: parse message */ 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) /* received '$' */ 01738 break; 01739 /* XXX: parse message */ 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 /* get the data */ 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 /* find the matching stream */ 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 /* get next frames from the same RTP packet */ 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 /* read next RTP packet */ 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 /* Either bad packet, or a RTCP packet. Check if the 01822 * first_rtcp_ntp_time field was initialized. */ 01823 RTPDemuxContext *rtpctx = rtsp_st->transport_priv; 01824 if (rtpctx->first_rtcp_ntp_time != AV_NOPTS_VALUE) { 01825 /* first_rtcp_ntp_time has been initialized for this stream, 01826 * copy the same value to all other uninitialized streams, 01827 * in order to map their timestamp origin to the same ntp time 01828 * as this one. */ 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 /* more packets may follow, so we save the RTP context */ 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 /* send dummy request to keep TCP connection alive */ 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 /* pause the stream */ 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 /* NOTE: it is valid to flush the buffer here */ 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 /* we look for a line beginning "c=IN IP4" */ 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 /* read the whole sdp file */ 02042 /* XXX: better loading */ 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 /* open each RTP stream */ 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 };