Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: patched-ffmpeg-mt/libavformat/rtsp.c

Issue 789004: ffmpeg roll of source to mar 9 version... (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/third_party/ffmpeg/
Patch Set: '' Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * RTSP/SDP client 2 * RTSP/SDP client
3 * Copyright (c) 2002 Fabrice Bellard 3 * Copyright (c) 2002 Fabrice Bellard
4 * 4 *
5 * This file is part of FFmpeg. 5 * This file is part of FFmpeg.
6 * 6 *
7 * FFmpeg is free software; you can redistribute it and/or 7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public 8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version. 10 * version 2.1 of the License, or (at your option) any later version.
11 * 11 *
12 * FFmpeg is distributed in the hope that it will be useful, 12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details. 15 * Lesser General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU Lesser General Public 17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software 18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */ 20 */
21 21
22 /* needed by inet_aton() */
23 #define _SVID_SOURCE
24
25 #include "libavutil/base64.h" 22 #include "libavutil/base64.h"
26 #include "libavutil/avstring.h" 23 #include "libavutil/avstring.h"
27 #include "libavutil/intreadwrite.h" 24 #include "libavutil/intreadwrite.h"
28 #include "avformat.h" 25 #include "avformat.h"
29 26
30 #include <sys/time.h> 27 #include <sys/time.h>
31 #if HAVE_SYS_SELECT_H 28 #if HAVE_SYS_SELECT_H
32 #include <sys/select.h> 29 #include <sys/select.h>
33 #endif 30 #endif
34 #include <strings.h> 31 #include <strings.h>
35 #include "network.h" 32 #include "network.h"
36 #include "rtsp.h" 33 #include "rtsp.h"
37 34
38 #include "rtpdec.h" 35 #include "rtpdec.h"
39 #include "rdt.h" 36 #include "rdt.h"
40 #include "rtp_asf.h" 37 #include "rtpdec_asf.h"
41 #include "rtp_vorbis.h" 38 #include "rtpdec_vorbis.h"
42 39
43 //#define DEBUG 40 //#define DEBUG
44 //#define DEBUG_RTP_TCP 41 //#define DEBUG_RTP_TCP
45 42
46 #if LIBAVFORMAT_VERSION_INT < (53 << 16) 43 #if LIBAVFORMAT_VERSION_INT < (53 << 16)
47 int rtsp_default_protocols = (1 << RTSP_LOWER_TRANSPORT_UDP); 44 int rtsp_default_protocols = (1 << RTSP_LOWER_TRANSPORT_UDP);
48 #endif 45 #endif
49 46
50 #define SPACE_CHARS " \t\r\n" 47 #define SPACE_CHARS " \t\r\n"
51 /* we use memchr() instead of strchr() here because strchr() will return 48 /* we use memchr() instead of strchr() here because strchr() will return
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 /* We are in a standard case 121 /* We are in a standard case
125 * (from http://www.iana.org/assignments/rtp-parameters). */ 122 * (from http://www.iana.org/assignments/rtp-parameters). */
126 /* search into AVRtpPayloadTypes[] */ 123 /* search into AVRtpPayloadTypes[] */
127 codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type); 124 codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
128 } 125 }
129 126
130 c = avcodec_find_decoder(codec->codec_id); 127 c = avcodec_find_decoder(codec->codec_id);
131 if (c && c->name) 128 if (c && c->name)
132 c_name = c->name; 129 c_name = c->name;
133 else 130 else
134 c_name = (char *) NULL; 131 c_name = "(null)";
135 132
136 if (c_name) { 133 get_word_sep(buf, sizeof(buf), "/", &p);
137 get_word_sep(buf, sizeof(buf), "/", &p); 134 i = atoi(buf);
138 i = atoi(buf); 135 switch (codec->codec_type) {
139 switch (codec->codec_type) { 136 case CODEC_TYPE_AUDIO:
140 case CODEC_TYPE_AUDIO: 137 av_log(s, AV_LOG_DEBUG, "audio codec set to: %s\n", c_name);
141 av_log(s, AV_LOG_DEBUG, "audio codec set to: %s\n", c_name); 138 codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE;
142 codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE; 139 codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS;
143 codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS; 140 if (i > 0) {
144 if (i > 0) { 141 codec->sample_rate = i;
145 codec->sample_rate = i; 142 get_word_sep(buf, sizeof(buf), "/", &p);
146 get_word_sep(buf, sizeof(buf), "/", &p); 143 i = atoi(buf);
147 i = atoi(buf); 144 if (i > 0)
148 if (i > 0) 145 codec->channels = i;
149 codec->channels = i; 146 // TODO: there is a bug here; if it is a mono stream, and
150 // TODO: there is a bug here; if it is a mono stream, and 147 // less than 22000Hz, faad upconverts to stereo and twice
151 // less than 22000Hz, faad upconverts to stereo and twice 148 // the frequency. No problem, but the sample rate is being
152 // the frequency. No problem, but the sample rate is being 149 // set here by the sdp line. Patch on its way. (rdm)
153 // set here by the sdp line. Patch on its way. (rdm)
154 }
155 av_log(s, AV_LOG_DEBUG, "audio samplerate set to: %i\n",
156 codec->sample_rate);
157 av_log(s, AV_LOG_DEBUG, "audio channels set to: %i\n",
158 codec->channels);
159 break;
160 case CODEC_TYPE_VIDEO:
161 av_log(s, AV_LOG_DEBUG, "video codec set to: %s\n", c_name);
162 break;
163 default:
164 break;
165 } 150 }
166 return 0; 151 av_log(s, AV_LOG_DEBUG, "audio samplerate set to: %i\n",
152 codec->sample_rate);
153 av_log(s, AV_LOG_DEBUG, "audio channels set to: %i\n",
154 codec->channels);
155 break;
156 case CODEC_TYPE_VIDEO:
157 av_log(s, AV_LOG_DEBUG, "video codec set to: %s\n", c_name);
158 break;
159 default:
160 break;
167 } 161 }
168 162 return 0;
169 return -1;
170 } 163 }
171 164
172 /* return the length and optionally the data */ 165 /* return the length and optionally the data */
173 static int hex_to_data(uint8_t *data, const char *p) 166 static int hex_to_data(uint8_t *data, const char *p)
174 { 167 {
175 int c, len, v; 168 int c, len, v;
176 169
177 len = 0; 170 len = 0;
178 v = 1; 171 v = 1;
179 for (;;) { 172 for (;;) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 { "StreamType", ATTR_NAME_TYPE_INT, 240 { "StreamType", ATTR_NAME_TYPE_INT,
248 offsetof(RTPPayloadData, streamtype) }, 241 offsetof(RTPPayloadData, streamtype) },
249 { "mode", ATTR_NAME_TYPE_STR, 242 { "mode", ATTR_NAME_TYPE_STR,
250 offsetof(RTPPayloadData, mode) }, 243 offsetof(RTPPayloadData, mode) },
251 { NULL, -1, -1 }, 244 { NULL, -1, -1 },
252 }; 245 };
253 246
254 /* parse the attribute line from the fmtp a line of an sdp resonse. This 247 /* parse the attribute line from the fmtp a line of an sdp resonse. This
255 * is broken out as a function because it is used in rtp_h264.c, which is 248 * is broken out as a function because it is used in rtp_h264.c, which is
256 * forthcoming. */ 249 * forthcoming. */
257 int rtsp_next_attr_and_value(const char **p, char *attr, int attr_size, 250 int ff_rtsp_next_attr_and_value(const char **p, char *attr, int attr_size,
258 char *value, int value_size) 251 char *value, int value_size)
259 { 252 {
260 skip_spaces(p); 253 skip_spaces(p);
261 if (**p) { 254 if (**p) {
262 get_word_sep(attr, attr_size, "=", p); 255 get_word_sep(attr, attr_size, "=", p);
263 if (**p == '=') 256 if (**p == '=')
264 (*p)++; 257 (*p)++;
265 get_word_sep(value, value_size, ";", p); 258 get_word_sep(value, value_size, ";", p);
266 if (**p == ';') 259 if (**p == ';')
267 (*p)++; 260 (*p)++;
268 return 1; 261 return 1;
269 } 262 }
270 return 0; 263 return 0;
271 } 264 }
272 265
273 /* parse a SDP line and save stream attributes */ 266 /* parse a SDP line and save stream attributes */
274 static void sdp_parse_fmtp(AVStream *st, const char *p) 267 static void sdp_parse_fmtp(AVStream *st, const char *p)
275 { 268 {
276 char attr[256]; 269 char attr[256];
277 /* Vorbis setup headers can be up to 12KB and are sent base64 270 /* Vorbis setup headers can be up to 12KB and are sent base64
278 * encoded, giving a 12KB * (4/3) = 16KB FMTP line. */ 271 * encoded, giving a 12KB * (4/3) = 16KB FMTP line. */
279 char value[16384]; 272 char value[16384];
280 int i; 273 int i;
281 RTSPStream *rtsp_st = st->priv_data; 274 RTSPStream *rtsp_st = st->priv_data;
282 AVCodecContext *codec = st->codec; 275 AVCodecContext *codec = st->codec;
283 RTPPayloadData *rtp_payload_data = &rtsp_st->rtp_payload_data; 276 RTPPayloadData *rtp_payload_data = &rtsp_st->rtp_payload_data;
284 277
285 /* loop on each attribute */ 278 /* loop on each attribute */
286 while (rtsp_next_attr_and_value(&p, attr, sizeof(attr), 279 while (ff_rtsp_next_attr_and_value(&p, attr, sizeof(attr),
287 value, sizeof(value))) { 280 value, sizeof(value))) {
288 /* grab the codec extra_data from the config parameter of the fmtp 281 /* grab the codec extra_data from the config parameter of the fmtp
289 * line */ 282 * line */
290 sdp_parse_fmtp_config(codec, rtsp_st->dynamic_protocol_context, 283 sdp_parse_fmtp_config(codec, rtsp_st->dynamic_protocol_context,
291 attr, value); 284 attr, value);
292 /* Looking for a known attribute */ 285 /* Looking for a known attribute */
293 for (i = 0; attr_names[i].str; ++i) { 286 for (i = 0; attr_names[i].str; ++i) {
294 if (!strcasecmp(attr, attr_names[i].str)) { 287 if (!strcasecmp(attr, attr_names[i].str)) {
295 if (attr_names[i].type == ATTR_NAME_TYPE_INT) { 288 if (attr_names[i].type == ATTR_NAME_TYPE_INT) {
296 *(int *)((char *)rtp_payload_data + 289 *(int *)((char *)rtp_payload_data +
297 attr_names[i].offset) = atoi(value); 290 attr_names[i].offset) = atoi(value);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 return; 349 return;
357 switch (letter) { 350 switch (letter) {
358 case 'c': 351 case 'c':
359 get_word(buf1, sizeof(buf1), &p); 352 get_word(buf1, sizeof(buf1), &p);
360 if (strcmp(buf1, "IN") != 0) 353 if (strcmp(buf1, "IN") != 0)
361 return; 354 return;
362 get_word(buf1, sizeof(buf1), &p); 355 get_word(buf1, sizeof(buf1), &p);
363 if (strcmp(buf1, "IP4") != 0) 356 if (strcmp(buf1, "IP4") != 0)
364 return; 357 return;
365 get_word_sep(buf1, sizeof(buf1), "/", &p); 358 get_word_sep(buf1, sizeof(buf1), "/", &p);
366 if (inet_aton(buf1, &sdp_ip) == 0) 359 if (ff_inet_aton(buf1, &sdp_ip) == 0)
367 return; 360 return;
368 ttl = 16; 361 ttl = 16;
369 if (*p == '/') { 362 if (*p == '/') {
370 p++; 363 p++;
371 get_word_sep(buf1, sizeof(buf1), "/", &p); 364 get_word_sep(buf1, sizeof(buf1), "/", &p);
372 ttl = atoi(buf1); 365 ttl = atoi(buf1);
373 } 366 }
374 if (s->nb_streams == 0) { 367 if (s->nb_streams == 0) {
375 s1->default_ip = sdp_ip; 368 s1->default_ip = sdp_ip;
376 s1->default_ttl = ttl; 369 s1->default_ttl = ttl;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 if (!strncmp(p, "rtsp://", 7)) 439 if (!strncmp(p, "rtsp://", 7))
447 av_strlcpy(rt->control_uri, p, 440 av_strlcpy(rt->control_uri, p,
448 sizeof(rt->control_uri)); 441 sizeof(rt->control_uri));
449 } else { 442 } else {
450 char proto[32]; 443 char proto[32];
451 /* get the control url */ 444 /* get the control url */
452 st = s->streams[s->nb_streams - 1]; 445 st = s->streams[s->nb_streams - 1];
453 rtsp_st = st->priv_data; 446 rtsp_st = st->priv_data;
454 447
455 /* XXX: may need to add full url resolution */ 448 /* XXX: may need to add full url resolution */
456 url_split(proto, sizeof(proto), NULL, 0, NULL, 0, 449 ff_url_split(proto, sizeof(proto), NULL, 0, NULL, 0,
457 NULL, NULL, 0, p); 450 NULL, NULL, 0, p);
458 if (proto[0] == '\0') { 451 if (proto[0] == '\0') {
459 /* relative control URL */ 452 /* relative control URL */
460 if (rtsp_st->control_url[strlen(rtsp_st->control_url)-1]!='/') 453 if (rtsp_st->control_url[strlen(rtsp_st->control_url)-1]!='/')
461 av_strlcat(rtsp_st->control_url, "/", 454 av_strlcat(rtsp_st->control_url, "/",
462 sizeof(rtsp_st->control_url)); 455 sizeof(rtsp_st->control_url));
463 av_strlcat(rtsp_st->control_url, p, 456 av_strlcat(rtsp_st->control_url, p,
464 sizeof(rtsp_st->control_url)); 457 sizeof(rtsp_st->control_url));
465 } else 458 } else
466 av_strlcpy(rtsp_st->control_url, p, 459 av_strlcpy(rtsp_st->control_url, p,
467 sizeof(rtsp_st->control_url)); 460 sizeof(rtsp_st->control_url));
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 next_line: 562 next_line:
570 while (*p != '\n' && *p != '\0') 563 while (*p != '\n' && *p != '\0')
571 p++; 564 p++;
572 if (*p == '\n') 565 if (*p == '\n')
573 p++; 566 p++;
574 } 567 }
575 return 0; 568 return 0;
576 } 569 }
577 570
578 /* close and free RTSP streams */ 571 /* close and free RTSP streams */
579 static void rtsp_close_streams(RTSPState *rt) 572 void ff_rtsp_close_streams(AVFormatContext *s)
580 { 573 {
574 RTSPState *rt = s->priv_data;
581 int i; 575 int i;
582 RTSPStream *rtsp_st; 576 RTSPStream *rtsp_st;
583 577
584 for (i = 0; i < rt->nb_rtsp_streams; i++) { 578 for (i = 0; i < rt->nb_rtsp_streams; i++) {
585 rtsp_st = rt->rtsp_streams[i]; 579 rtsp_st = rt->rtsp_streams[i];
586 if (rtsp_st) { 580 if (rtsp_st) {
587 if (rtsp_st->transport_priv) { 581 if (rtsp_st->transport_priv) {
588 if (rt->transport == RTSP_TRANSPORT_RDT) 582 if (s->oformat) {
583 AVFormatContext *rtpctx = rtsp_st->transport_priv;
584 av_write_trailer(rtpctx);
585 url_fclose(rtpctx->pb);
586 av_metadata_free(&rtpctx->streams[0]->metadata);
587 av_metadata_free(&rtpctx->metadata);
588 av_free(rtpctx->streams[0]);
589 av_free(rtpctx);
590 } else if (rt->transport == RTSP_TRANSPORT_RDT)
589 ff_rdt_parse_close(rtsp_st->transport_priv); 591 ff_rdt_parse_close(rtsp_st->transport_priv);
590 else 592 else
591 rtp_parse_close(rtsp_st->transport_priv); 593 rtp_parse_close(rtsp_st->transport_priv);
592 } 594 }
593 if (rtsp_st->rtp_handle) 595 if (rtsp_st->rtp_handle)
594 url_close(rtsp_st->rtp_handle); 596 url_close(rtsp_st->rtp_handle);
595 if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context) 597 if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context)
596 rtsp_st->dynamic_handler->close( 598 rtsp_st->dynamic_handler->close(
597 rtsp_st->dynamic_protocol_context); 599 rtsp_st->dynamic_protocol_context);
598 } 600 }
599 } 601 }
600 av_free(rt->rtsp_streams); 602 av_free(rt->rtsp_streams);
601 if (rt->asf_ctx) { 603 if (rt->asf_ctx) {
602 av_close_input_stream (rt->asf_ctx); 604 av_close_input_stream (rt->asf_ctx);
603 rt->asf_ctx = NULL; 605 rt->asf_ctx = NULL;
604 } 606 }
605 av_freep(&rt->auth_b64); 607 av_freep(&rt->auth_b64);
606 } 608 }
607 609
610 static void *rtsp_rtp_mux_open(AVFormatContext *s, AVStream *st, URLContext *han dle) {
611 AVFormatContext *rtpctx;
612 int ret;
613 AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);
614
615 if (!rtp_format)
616 return NULL;
617
618 /* Allocate an AVFormatContext for each output stream */
619 rtpctx = avformat_alloc_context();
620 if (!rtpctx)
621 return NULL;
622
623 rtpctx->oformat = rtp_format;
624 if (!av_new_stream(rtpctx, 0)) {
625 av_free(rtpctx);
626 return NULL;
627 }
628 /* Copy the max delay setting; the rtp muxer reads this. */
629 rtpctx->max_delay = s->max_delay;
630 /* Copy other stream parameters. */
631 rtpctx->streams[0]->sample_aspect_ratio = st->sample_aspect_ratio;
632
633 /* Remove the local codec, link to the original codec
634 * context instead, to give the rtp muxer access to
635 * codec parameters. */
636 av_free(rtpctx->streams[0]->codec);
637 rtpctx->streams[0]->codec = st->codec;
638
639 url_fdopen(&rtpctx->pb, handle);
640 ret = av_write_header(rtpctx);
641
642 if (ret) {
643 url_fclose(rtpctx->pb);
644 av_free(rtpctx->streams[0]);
645 av_free(rtpctx);
646 return NULL;
647 }
648
649 /* Copy the RTP AVStream timebase back to the original AVStream */
650 st->time_base = rtpctx->streams[0]->time_base;
651 return rtpctx;
652 }
653
608 static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st) 654 static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
609 { 655 {
610 RTSPState *rt = s->priv_data; 656 RTSPState *rt = s->priv_data;
611 AVStream *st = NULL; 657 AVStream *st = NULL;
612 658
613 /* open the RTP context */ 659 /* open the RTP context */
614 if (rtsp_st->stream_index >= 0) 660 if (rtsp_st->stream_index >= 0)
615 st = s->streams[rtsp_st->stream_index]; 661 st = s->streams[rtsp_st->stream_index];
616 if (!st) 662 if (!st)
617 s->ctx_flags |= AVFMTCTX_NOHEADER; 663 s->ctx_flags |= AVFMTCTX_NOHEADER;
618 664
619 if (rt->transport == RTSP_TRANSPORT_RDT) 665 if (s->oformat) {
666 rtsp_st->transport_priv = rtsp_rtp_mux_open(s, st, rtsp_st->rtp_handle);
667 /* Ownage of rtp_handle is passed to the rtp mux context */
668 rtsp_st->rtp_handle = NULL;
669 } else if (rt->transport == RTSP_TRANSPORT_RDT)
620 rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index, 670 rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index,
621 rtsp_st->dynamic_protocol_context, 671 rtsp_st->dynamic_protocol_context,
622 rtsp_st->dynamic_handler); 672 rtsp_st->dynamic_handler);
623 else 673 else
624 rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle, 674 rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle,
625 rtsp_st->sdp_payload_type, 675 rtsp_st->sdp_payload_type,
626 &rtsp_st->rtp_payload_data); 676 &rtsp_st->rtp_payload_data);
627 677
628 if (!rtsp_st->transport_priv) { 678 if (!rtsp_st->transport_priv) {
629 return AVERROR(ENOMEM); 679 return AVERROR(ENOMEM);
630 } else if (rt->transport != RTSP_TRANSPORT_RDT) { 680 } else if (rt->transport != RTSP_TRANSPORT_RDT) {
631 if (rtsp_st->dynamic_handler) { 681 if (rtsp_st->dynamic_handler) {
632 rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv, 682 rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
633 rtsp_st->dynamic_protocol_context, 683 rtsp_st->dynamic_protocol_context,
634 rtsp_st->dynamic_handler); 684 rtsp_st->dynamic_handler);
635 } 685 }
636 } 686 }
637 687
638 return 0; 688 return 0;
639 } 689 }
640 690
641 #if CONFIG_RTSP_DEMUXER 691 #if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER
642 static int rtsp_probe(AVProbeData *p) 692 static int rtsp_probe(AVProbeData *p)
643 { 693 {
644 if (av_strstart(p->filename, "rtsp:", NULL)) 694 if (av_strstart(p->filename, "rtsp:", NULL))
645 return AVPROBE_SCORE_MAX; 695 return AVPROBE_SCORE_MAX;
646 return 0; 696 return 0;
647 } 697 }
648 698
649 static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp) 699 static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
650 { 700 {
651 const char *p; 701 const char *p;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 if (*p == '=') { 793 if (*p == '=') {
744 p++; 794 p++;
745 th->ttl = strtol(p, (char **)&p, 10); 795 th->ttl = strtol(p, (char **)&p, 10);
746 } 796 }
747 } else if (!strcmp(parameter, "destination")) { 797 } else if (!strcmp(parameter, "destination")) {
748 struct in_addr ipaddr; 798 struct in_addr ipaddr;
749 799
750 if (*p == '=') { 800 if (*p == '=') {
751 p++; 801 p++;
752 get_word_sep(buf, sizeof(buf), ";,", &p); 802 get_word_sep(buf, sizeof(buf), ";,", &p);
753 if (inet_aton(buf, &ipaddr)) 803 if (ff_inet_aton(buf, &ipaddr))
754 th->destination = ntohl(ipaddr.s_addr); 804 th->destination = ntohl(ipaddr.s_addr);
755 } 805 }
756 } 806 }
757 while (*p != ';' && *p != '\0' && *p != ',') 807 while (*p != ';' && *p != '\0' && *p != ',')
758 p++; 808 p++;
759 if (*p == ';') 809 if (*p == ';')
760 p++; 810 p++;
761 } 811 }
762 if (*p == ',') 812 if (*p == ',')
763 p++; 813 p++;
764 814
765 reply->nb_transports++; 815 reply->nb_transports++;
766 } 816 }
767 } 817 }
768 818
769 void rtsp_parse_line(RTSPMessageHeader *reply, const char *buf) 819 void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf)
770 { 820 {
771 const char *p; 821 const char *p;
772 822
773 /* NOTE: we do case independent match for broken servers */ 823 /* NOTE: we do case independent match for broken servers */
774 p = buf; 824 p = buf;
775 if (av_stristart(p, "Session:", &p)) { 825 if (av_stristart(p, "Session:", &p)) {
776 int t; 826 int t;
777 get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p); 827 get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
778 if (av_stristart(p, ";timeout=", &p) && 828 if (av_stristart(p, ";timeout=", &p) &&
779 (t = strtol(p, NULL, 10)) > 0) { 829 (t = strtol(p, NULL, 10)) > 0) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 len1 = len; 871 len1 = len;
822 if (len1 > sizeof(buf)) 872 if (len1 > sizeof(buf))
823 len1 = sizeof(buf); 873 len1 = sizeof(buf);
824 ret = url_read_complete(rt->rtsp_hd, buf, len1); 874 ret = url_read_complete(rt->rtsp_hd, buf, len1);
825 if (ret != len1) 875 if (ret != len1)
826 return; 876 return;
827 len -= len1; 877 len -= len1;
828 } 878 }
829 } 879 }
830 880
831 /** 881 int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
832 * Read a RTSP message from the server, or prepare to read data 882 unsigned char **content_ptr,
833 * packets if we're reading data interleaved over the TCP/RTSP 883 int return_on_interleaved_data)
834 * connection as well.
835 *
836 * @param s RTSP demuxer context
837 * @param reply pointer where the RTSP message header will be stored
838 * @param content_ptr pointer where the RTSP message body, if any, will
839 * be stored (length is in reply)
840 * @param return_on_interleaved_data whether the function may return if we
841 * encounter a data marker ('$'), which precedes data
842 * packets over interleaved TCP/RTSP connections. If this
843 * is set, this function will return 1 after encountering
844 * a '$'. If it is not set, the function will skip any
845 * data packets (if they are encountered), until a reply
846 * has been fully parsed. If no more data is available
847 * without parsing a reply, it will return an error.
848 *
849 * @returns 1 if a data packets is ready to be received, -1 on error,
850 * and 0 on success.
851 */
852 static int rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
853 unsigned char **content_ptr,
854 int return_on_interleaved_data)
855 { 884 {
856 RTSPState *rt = s->priv_data; 885 RTSPState *rt = s->priv_data;
857 char buf[4096], buf1[1024], *q; 886 char buf[4096], buf1[1024], *q;
858 unsigned char ch; 887 unsigned char ch;
859 const char *p; 888 const char *p;
860 int ret, content_length, line_count = 0; 889 int ret, content_length, line_count = 0;
861 unsigned char *content = NULL; 890 unsigned char *content = NULL;
862 891
863 memset(reply, 0, sizeof(*reply)); 892 memset(reply, 0, sizeof(*reply));
864 893
(...skipping 28 matching lines...) Expand all
893 /* test if last line */ 922 /* test if last line */
894 if (buf[0] == '\0') 923 if (buf[0] == '\0')
895 break; 924 break;
896 p = buf; 925 p = buf;
897 if (line_count == 0) { 926 if (line_count == 0) {
898 /* get reply code */ 927 /* get reply code */
899 get_word(buf1, sizeof(buf1), &p); 928 get_word(buf1, sizeof(buf1), &p);
900 get_word(buf1, sizeof(buf1), &p); 929 get_word(buf1, sizeof(buf1), &p);
901 reply->status_code = atoi(buf1); 930 reply->status_code = atoi(buf1);
902 } else { 931 } else {
903 rtsp_parse_line(reply, p); 932 ff_rtsp_parse_line(reply, p);
904 av_strlcat(rt->last_reply, p, sizeof(rt->last_reply)); 933 av_strlcat(rt->last_reply, p, sizeof(rt->last_reply));
905 av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply)); 934 av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply));
906 } 935 }
907 line_count++; 936 line_count++;
908 } 937 }
909 938
910 if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0') 939 if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
911 av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id)); 940 av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id));
912 941
913 content_length = reply->content_length; 942 content_length = reply->content_length;
(...skipping 15 matching lines...) Expand all
929 rt->state = RTSP_STATE_IDLE; 958 rt->state = RTSP_STATE_IDLE;
930 } else if (reply->notice >= 4400 && reply->notice < 5500) { 959 } else if (reply->notice >= 4400 && reply->notice < 5500) {
931 return AVERROR(EIO); /* data or server error */ 960 return AVERROR(EIO); /* data or server error */
932 } else if (reply->notice == 2401 /* Ticket Expired */ || 961 } else if (reply->notice == 2401 /* Ticket Expired */ ||
933 (reply->notice >= 5500 && reply->notice < 5600) /* end of term */ ) 962 (reply->notice >= 5500 && reply->notice < 5600) /* end of term */ )
934 return AVERROR(EPERM); 963 return AVERROR(EPERM);
935 964
936 return 0; 965 return 0;
937 } 966 }
938 967
939 static void rtsp_send_cmd_async(AVFormatContext *s, const char *cmd) 968 void ff_rtsp_send_cmd_with_content_async(AVFormatContext *s,
969 const char *cmd,
970 const unsigned char *send_content,
971 int send_content_length)
940 { 972 {
941 RTSPState *rt = s->priv_data; 973 RTSPState *rt = s->priv_data;
942 char buf[4096], buf1[1024]; 974 char buf[4096], buf1[1024];
943 975
944 rt->seq++; 976 rt->seq++;
945 av_strlcpy(buf, cmd, sizeof(buf)); 977 av_strlcpy(buf, cmd, sizeof(buf));
946 snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq); 978 snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq);
947 av_strlcat(buf, buf1, sizeof(buf)); 979 av_strlcat(buf, buf1, sizeof(buf));
948 if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) { 980 if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
949 snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id); 981 snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id);
950 av_strlcat(buf, buf1, sizeof(buf)); 982 av_strlcat(buf, buf1, sizeof(buf));
951 } 983 }
952 if (rt->auth_b64) 984 if (rt->auth_b64)
953 av_strlcatf(buf, sizeof(buf), 985 av_strlcatf(buf, sizeof(buf),
954 "Authorization: Basic %s\r\n", 986 "Authorization: Basic %s\r\n",
955 rt->auth_b64); 987 rt->auth_b64);
988 if (send_content_length > 0 && send_content)
989 av_strlcatf(buf, sizeof(buf), "Content-Length: %d\r\n", send_content_len gth);
956 av_strlcat(buf, "\r\n", sizeof(buf)); 990 av_strlcat(buf, "\r\n", sizeof(buf));
957 991
958 dprintf(s, "Sending:\n%s--\n", buf); 992 dprintf(s, "Sending:\n%s--\n", buf);
959 993
960 url_write(rt->rtsp_hd, buf, strlen(buf)); 994 url_write(rt->rtsp_hd, buf, strlen(buf));
995 if (send_content_length > 0 && send_content)
996 url_write(rt->rtsp_hd, send_content, send_content_length);
961 rt->last_cmd_time = av_gettime(); 997 rt->last_cmd_time = av_gettime();
962 } 998 }
963 999
964 static void rtsp_send_cmd(AVFormatContext *s, 1000 void ff_rtsp_send_cmd_async(AVFormatContext *s, const char *cmd)
965 const char *cmd, RTSPMessageHeader *reply,
966 unsigned char **content_ptr)
967 { 1001 {
968 rtsp_send_cmd_async(s, cmd); 1002 ff_rtsp_send_cmd_with_content_async(s, cmd, NULL, 0);
1003 }
969 1004
970 rtsp_read_reply(s, reply, content_ptr, 0); 1005 void ff_rtsp_send_cmd(AVFormatContext *s,
1006 const char *cmd, RTSPMessageHeader *reply,
1007 unsigned char **content_ptr)
1008 {
1009 ff_rtsp_send_cmd_async(s, cmd);
1010
1011 ff_rtsp_read_reply(s, reply, content_ptr, 0);
1012 }
1013
1014 void ff_rtsp_send_cmd_with_content(AVFormatContext *s,
1015 const char *cmd,
1016 RTSPMessageHeader *reply,
1017 unsigned char **content_ptr,
1018 const unsigned char *send_content,
1019 int send_content_length)
1020 {
1021 ff_rtsp_send_cmd_with_content_async(s, cmd, send_content, send_content_lengt h);
1022
1023 ff_rtsp_read_reply(s, reply, content_ptr, 0);
971 } 1024 }
972 1025
973 /** 1026 /**
974 * @returns 0 on success, <0 on error, 1 if protocol is unavailable. 1027 * @returns 0 on success, <0 on error, 1 if protocol is unavailable.
975 */ 1028 */
976 static int make_setup_request(AVFormatContext *s, const char *host, int port, 1029 static int make_setup_request(AVFormatContext *s, const char *host, int port,
977 int lower_transport, const char *real_challenge) 1030 int lower_transport, const char *real_challenge)
978 { 1031 {
979 RTSPState *rt = s->priv_data; 1032 RTSPState *rt = s->priv_data;
980 int rtx, j, i, err, interleave = 0; 1033 int rtx, j, i, err, interleave = 0;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1027 char buf[256]; 1080 char buf[256];
1028 1081
1029 if (rt->server_type == RTSP_SERVER_WMS && i > 1) { 1082 if (rt->server_type == RTSP_SERVER_WMS && i > 1) {
1030 port = reply->transports[0].client_port_min; 1083 port = reply->transports[0].client_port_min;
1031 goto have_port; 1084 goto have_port;
1032 } 1085 }
1033 1086
1034 /* first try in specified port range */ 1087 /* first try in specified port range */
1035 if (RTSP_RTP_PORT_MIN != 0) { 1088 if (RTSP_RTP_PORT_MIN != 0) {
1036 while (j <= RTSP_RTP_PORT_MAX) { 1089 while (j <= RTSP_RTP_PORT_MAX) {
1037 snprintf(buf, sizeof(buf), "rtp://%s?localport=%d", 1090 ff_url_join(buf, sizeof(buf), "rtp", NULL, host, -1,
1038 host, j); 1091 "?localport=%d", j);
1039 /* we will use two ports per rtp stream (rtp and rtcp) */ 1092 /* we will use two ports per rtp stream (rtp and rtcp) */
1040 j += 2; 1093 j += 2;
1041 if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0) 1094 if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0)
1042 goto rtp_opened; 1095 goto rtp_opened;
1043 } 1096 }
1044 } 1097 }
1045 1098
1046 #if 0 1099 #if 0
1047 /* then try on any port */ 1100 /* then try on any port */
1048 if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) { 1101 if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1081 av_strlcatf(transport, sizeof(transport), 1134 av_strlcatf(transport, sizeof(transport),
1082 "interleaved=%d-%d", 1135 "interleaved=%d-%d",
1083 interleave, interleave + 1); 1136 interleave, interleave + 1);
1084 interleave += 2; 1137 interleave += 2;
1085 } 1138 }
1086 1139
1087 else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) { 1140 else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) {
1088 snprintf(transport, sizeof(transport) - 1, 1141 snprintf(transport, sizeof(transport) - 1,
1089 "%s/UDP;multicast", trans_pref); 1142 "%s/UDP;multicast", trans_pref);
1090 } 1143 }
1091 if (rt->server_type == RTSP_SERVER_REAL || 1144 if (s->oformat) {
1092 rt->server_type == RTSP_SERVER_WMS) 1145 av_strlcat(transport, ";mode=receive", sizeof(transport));
1146 } else if (rt->server_type == RTSP_SERVER_REAL ||
1147 rt->server_type == RTSP_SERVER_WMS)
1093 av_strlcat(transport, ";mode=play", sizeof(transport)); 1148 av_strlcat(transport, ";mode=play", sizeof(transport));
1094 snprintf(cmd, sizeof(cmd), 1149 snprintf(cmd, sizeof(cmd),
1095 "SETUP %s RTSP/1.0\r\n" 1150 "SETUP %s RTSP/1.0\r\n"
1096 "Transport: %s\r\n", 1151 "Transport: %s\r\n",
1097 rtsp_st->control_url, transport); 1152 rtsp_st->control_url, transport);
1098 if (i == 0 && rt->server_type == RTSP_SERVER_REAL) { 1153 if (i == 0 && rt->server_type == RTSP_SERVER_REAL) {
1099 char real_res[41], real_csum[9]; 1154 char real_res[41], real_csum[9];
1100 ff_rdt_calc_response_and_checksum(real_res, real_csum, 1155 ff_rdt_calc_response_and_checksum(real_res, real_csum,
1101 real_challenge); 1156 real_challenge);
1102 av_strlcatf(cmd, sizeof(cmd), 1157 av_strlcatf(cmd, sizeof(cmd),
1103 "If-Match: %s\r\n" 1158 "If-Match: %s\r\n"
1104 "RealChallenge2: %s, sd=%s\r\n", 1159 "RealChallenge2: %s, sd=%s\r\n",
1105 rt->session_id, real_res, real_csum); 1160 rt->session_id, real_res, real_csum);
1106 } 1161 }
1107 rtsp_send_cmd(s, cmd, reply, NULL); 1162 ff_rtsp_send_cmd(s, cmd, reply, NULL);
1108 if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) { 1163 if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) {
1109 err = 1; 1164 err = 1;
1110 goto fail; 1165 goto fail;
1111 } else if (reply->status_code != RTSP_STATUS_OK || 1166 } else if (reply->status_code != RTSP_STATUS_OK ||
1112 reply->nb_transports != 1) { 1167 reply->nb_transports != 1) {
1113 err = AVERROR_INVALIDDATA; 1168 err = AVERROR_INVALIDDATA;
1114 goto fail; 1169 goto fail;
1115 } 1170 }
1116 1171
1117 /* XXX: same protocol for all streams is required */ 1172 /* XXX: same protocol for all streams is required */
(...skipping 18 matching lines...) Expand all
1136 switch(reply->transports[0].lower_transport) { 1191 switch(reply->transports[0].lower_transport) {
1137 case RTSP_LOWER_TRANSPORT_TCP: 1192 case RTSP_LOWER_TRANSPORT_TCP:
1138 rtsp_st->interleaved_min = reply->transports[0].interleaved_min; 1193 rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
1139 rtsp_st->interleaved_max = reply->transports[0].interleaved_max; 1194 rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
1140 break; 1195 break;
1141 1196
1142 case RTSP_LOWER_TRANSPORT_UDP: { 1197 case RTSP_LOWER_TRANSPORT_UDP: {
1143 char url[1024]; 1198 char url[1024];
1144 1199
1145 /* XXX: also use address if specified */ 1200 /* XXX: also use address if specified */
1146 snprintf(url, sizeof(url), "rtp://%s:%d", 1201 ff_url_join(url, sizeof(url), "rtp", NULL, host,
1147 host, reply->transports[0].server_port_min); 1202 reply->transports[0].server_port_min, NULL);
1148 if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && 1203 if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) &&
1149 rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) { 1204 rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
1150 err = AVERROR_INVALIDDATA; 1205 err = AVERROR_INVALIDDATA;
1151 goto fail; 1206 goto fail;
1152 } 1207 }
1208 /* Try to initialize the connection state in a
1209 * potential NAT router by sending dummy packets.
1210 * RTP/RTCP dummy packets are used for RDT, too.
1211 */
1212 if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat)
1213 rtp_send_punch_packets(rtsp_st->rtp_handle);
1153 break; 1214 break;
1154 } 1215 }
1155 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: { 1216 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: {
1156 char url[1024]; 1217 char url[1024];
1157 struct in_addr in; 1218 struct in_addr in;
1158 int port, ttl; 1219 int port, ttl;
1159 1220
1160 if (reply->transports[0].destination) { 1221 if (reply->transports[0].destination) {
1161 in.s_addr = htonl(reply->transports[0].destination); 1222 in.s_addr = htonl(reply->transports[0].destination);
1162 port = reply->transports[0].port_min; 1223 port = reply->transports[0].port_min;
1163 ttl = reply->transports[0].ttl; 1224 ttl = reply->transports[0].ttl;
1164 } else { 1225 } else {
1165 in = rtsp_st->sdp_ip; 1226 in = rtsp_st->sdp_ip;
1166 port = rtsp_st->sdp_port; 1227 port = rtsp_st->sdp_port;
1167 ttl = rtsp_st->sdp_ttl; 1228 ttl = rtsp_st->sdp_ttl;
1168 } 1229 }
1169 snprintf(url, sizeof(url), "rtp://%s:%d?ttl=%d", 1230 ff_url_join(url, sizeof(url), "rtp", NULL, inet_ntoa(in),
1170 inet_ntoa(in), port, ttl); 1231 port, "?ttl=%d", ttl);
1171 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { 1232 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
1172 err = AVERROR_INVALIDDATA; 1233 err = AVERROR_INVALIDDATA;
1173 goto fail; 1234 goto fail;
1174 } 1235 }
1175 break; 1236 break;
1176 } 1237 }
1177 } 1238 }
1178 1239
1179 if ((err = rtsp_open_transport_ctx(s, rtsp_st))) 1240 if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
1180 goto fail; 1241 goto fail;
(...skipping 30 matching lines...) Expand all
1211 snprintf(cmd, sizeof(cmd), 1272 snprintf(cmd, sizeof(cmd),
1212 "PLAY %s RTSP/1.0\r\n", 1273 "PLAY %s RTSP/1.0\r\n",
1213 rt->control_uri); 1274 rt->control_uri);
1214 } else { 1275 } else {
1215 snprintf(cmd, sizeof(cmd), 1276 snprintf(cmd, sizeof(cmd),
1216 "PLAY %s RTSP/1.0\r\n" 1277 "PLAY %s RTSP/1.0\r\n"
1217 "Range: npt=%0.3f-\r\n", 1278 "Range: npt=%0.3f-\r\n",
1218 rt->control_uri, 1279 rt->control_uri,
1219 (double)rt->seek_timestamp / AV_TIME_BASE); 1280 (double)rt->seek_timestamp / AV_TIME_BASE);
1220 } 1281 }
1221 rtsp_send_cmd(s, cmd, reply, NULL); 1282 ff_rtsp_send_cmd(s, cmd, reply, NULL);
1222 if (reply->status_code != RTSP_STATUS_OK) { 1283 if (reply->status_code != RTSP_STATUS_OK) {
1223 return -1; 1284 return -1;
1224 } 1285 }
1225 } 1286 }
1226 rt->state = RTSP_STATE_PLAYING; 1287 rt->state = RTSP_STATE_STREAMING;
1227 return 0; 1288 return 0;
1228 } 1289 }
1229 1290
1230 static int rtsp_read_header(AVFormatContext *s, 1291 static int rtsp_setup_input_streams(AVFormatContext *s)
1231 AVFormatParameters *ap) 1292 {
1293 RTSPState *rt = s->priv_data;
1294 RTSPMessageHeader reply1, *reply = &reply1;
1295 char cmd[1024];
1296 unsigned char *content = NULL;
1297 int ret;
1298
1299 /* describe the stream */
1300 snprintf(cmd, sizeof(cmd),
1301 "DESCRIBE %s RTSP/1.0\r\n"
1302 "Accept: application/sdp\r\n",
1303 s->filename);
1304 if (rt->server_type == RTSP_SERVER_REAL) {
1305 /**
1306 * The Require: attribute is needed for proper streaming from
1307 * Realmedia servers.
1308 */
1309 av_strlcat(cmd,
1310 "Require: com.real.retain-entity-for-setup\r\n",
1311 sizeof(cmd));
1312 }
1313 ff_rtsp_send_cmd(s, cmd, reply, &content);
1314 if (!content)
1315 return AVERROR_INVALIDDATA;
1316 if (reply->status_code != RTSP_STATUS_OK) {
1317 av_freep(&content);
1318 return AVERROR_INVALIDDATA;
1319 }
1320
1321 /* now we got the SDP description, we parse it */
1322 ret = sdp_parse(s, (const char *)content);
1323 av_freep(&content);
1324 if (ret < 0)
1325 return AVERROR_INVALIDDATA;
1326
1327 return 0;
1328 }
1329
1330 static int rtsp_setup_output_streams(AVFormatContext *s)
1331 {
1332 RTSPState *rt = s->priv_data;
1333 RTSPMessageHeader reply1, *reply = &reply1;
1334 char cmd[1024];
1335 int i;
1336 char *sdp;
1337
1338 /* Announce the stream */
1339 snprintf(cmd, sizeof(cmd),
1340 "ANNOUNCE %s RTSP/1.0\r\n"
1341 "Content-Type: application/sdp\r\n",
1342 s->filename);
1343 sdp = av_mallocz(8192);
1344 if (sdp == NULL)
1345 return AVERROR(ENOMEM);
1346 if (avf_sdp_create(&s, 1, sdp, 8192)) {
1347 av_free(sdp);
1348 return AVERROR_INVALIDDATA;
1349 }
1350 av_log(s, AV_LOG_INFO, "SDP:\n%s\n", sdp);
1351 ff_rtsp_send_cmd_with_content(s, cmd, reply, NULL, sdp, strlen(sdp));
1352 av_free(sdp);
1353 if (reply->status_code != RTSP_STATUS_OK)
1354 return AVERROR_INVALIDDATA;
1355
1356 /* Set up the RTSPStreams for each AVStream */
1357 for (i = 0; i < s->nb_streams; i++) {
1358 RTSPStream *rtsp_st;
1359 AVStream *st = s->streams[i];
1360
1361 rtsp_st = av_mallocz(sizeof(RTSPStream));
1362 if (!rtsp_st)
1363 return AVERROR(ENOMEM);
1364 dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st);
1365
1366 st->priv_data = rtsp_st;
1367 rtsp_st->stream_index = i;
1368
1369 av_strlcpy(rtsp_st->control_url, s->filename, sizeof(rtsp_st->control_ur l));
1370 /* Note, this must match the relative uri set in the sdp content */
1371 av_strlcatf(rtsp_st->control_url, sizeof(rtsp_st->control_url),
1372 "/streamid=%d", i);
1373 }
1374
1375 return 0;
1376 }
1377
1378 int ff_rtsp_connect(AVFormatContext *s)
1232 { 1379 {
1233 RTSPState *rt = s->priv_data; 1380 RTSPState *rt = s->priv_data;
1234 char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128]; 1381 char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128];
1235 char *option_list, *option, *filename; 1382 char *option_list, *option, *filename;
1236 URLContext *rtsp_hd; 1383 URLContext *rtsp_hd;
1237 int port, ret, err; 1384 int port, err;
1238 RTSPMessageHeader reply1, *reply = &reply1; 1385 RTSPMessageHeader reply1, *reply = &reply1;
1239 unsigned char *content = NULL;
1240 int lower_transport_mask = 0; 1386 int lower_transport_mask = 0;
1241 char real_challenge[64]; 1387 char real_challenge[64];
1388
1389 if (!ff_network_init())
1390 return AVERROR(EIO);
1242 redirect: 1391 redirect:
1243 /* extract hostname and port */ 1392 /* extract hostname and port */
1244 url_split(NULL, 0, auth, sizeof(auth), 1393 ff_url_split(NULL, 0, auth, sizeof(auth),
1245 host, sizeof(host), &port, path, sizeof(path), s->filename); 1394 host, sizeof(host), &port, path, sizeof(path), s->filename);
1246 if (*auth) { 1395 if (*auth) {
1247 int auth_len = strlen(auth), b64_len = ((auth_len + 2) / 3) * 4 + 1; 1396 int auth_len = strlen(auth), b64_len = ((auth_len + 2) / 3) * 4 + 1;
1248 1397
1249 if (!(rt->auth_b64 = av_malloc(b64_len))) 1398 if (!(rt->auth_b64 = av_malloc(b64_len)))
1250 return AVERROR(ENOMEM); 1399 return AVERROR(ENOMEM);
1251 if (!av_base64_encode(rt->auth_b64, b64_len, auth, auth_len)) { 1400 if (!av_base64_encode(rt->auth_b64, b64_len, auth, auth_len)) {
1252 err = AVERROR(EINVAL); 1401 err = AVERROR(EINVAL);
1253 goto fail; 1402 goto fail;
1254 } 1403 }
1255 } 1404 }
(...skipping 23 matching lines...) Expand all
1279 filename += strlen(option); 1428 filename += strlen(option);
1280 if (option_list) *filename = '&'; 1429 if (option_list) *filename = '&';
1281 } 1430 }
1282 } 1431 }
1283 *filename = 0; 1432 *filename = 0;
1284 } 1433 }
1285 1434
1286 if (!lower_transport_mask) 1435 if (!lower_transport_mask)
1287 lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1; 1436 lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;
1288 1437
1438 if (s->oformat) {
1439 /* Only UDP output is supported at the moment. */
1440 lower_transport_mask &= 1 << RTSP_LOWER_TRANSPORT_UDP;
1441 if (!lower_transport_mask) {
1442 av_log(s, AV_LOG_ERROR, "Unsupported lower transport method, "
1443 "only UDP is supported for output.\n");
1444 err = AVERROR(EINVAL);
1445 goto fail;
1446 }
1447 }
1448
1289 /* open the tcp connexion */ 1449 /* open the tcp connexion */
1290 snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port); 1450 ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL);
1291 if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0) { 1451 if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0) {
1292 err = AVERROR(EIO); 1452 err = AVERROR(EIO);
1293 goto fail; 1453 goto fail;
1294 } 1454 }
1295 rt->rtsp_hd = rtsp_hd; 1455 rt->rtsp_hd = rtsp_hd;
1296 rt->seq = 0; 1456 rt->seq = 0;
1297 1457
1298 /* request options supported by the server; this also detects server 1458 /* request options supported by the server; this also detects server
1299 * type */ 1459 * type */
1300 av_strlcpy(rt->control_uri, s->filename, 1460 av_strlcpy(rt->control_uri, s->filename,
(...skipping 10 matching lines...) Expand all
1311 * don't quite understand how. Values were copied 1471 * don't quite understand how. Values were copied
1312 * from mplayer SVN r23589. 1472 * from mplayer SVN r23589.
1313 * @param CompanyID is a 16-byte ID in base64 1473 * @param CompanyID is a 16-byte ID in base64
1314 * @param ClientChallenge is a 16-byte ID in hex 1474 * @param ClientChallenge is a 16-byte ID in hex
1315 */ 1475 */
1316 "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7\r\n" 1476 "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7\r\n"
1317 "PlayerStarttime: [28/03/2003:22:50:23 00:00]\r\n" 1477 "PlayerStarttime: [28/03/2003:22:50:23 00:00]\r\n"
1318 "CompanyID: KnKV4M4I/B2FjJ1TToLycw==\r\n" 1478 "CompanyID: KnKV4M4I/B2FjJ1TToLycw==\r\n"
1319 "GUID: 00000000-0000-0000-0000-000000000000\r\n", 1479 "GUID: 00000000-0000-0000-0000-000000000000\r\n",
1320 sizeof(cmd)); 1480 sizeof(cmd));
1321 rtsp_send_cmd(s, cmd, reply, NULL); 1481 ff_rtsp_send_cmd(s, cmd, reply, NULL);
1322 if (reply->status_code != RTSP_STATUS_OK) { 1482 if (reply->status_code != RTSP_STATUS_OK) {
1323 err = AVERROR_INVALIDDATA; 1483 err = AVERROR_INVALIDDATA;
1324 goto fail; 1484 goto fail;
1325 } 1485 }
1326 1486
1327 /* detect server type if not standard-compliant RTP */ 1487 /* detect server type if not standard-compliant RTP */
1328 if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) { 1488 if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) {
1329 rt->server_type = RTSP_SERVER_REAL; 1489 rt->server_type = RTSP_SERVER_REAL;
1330 continue; 1490 continue;
1331 } else if (!strncasecmp(reply->server, "WMServer/", 9)) { 1491 } else if (!strncasecmp(reply->server, "WMServer/", 9)) {
1332 rt->server_type = RTSP_SERVER_WMS; 1492 rt->server_type = RTSP_SERVER_WMS;
1333 } else if (rt->server_type == RTSP_SERVER_REAL) 1493 } else if (rt->server_type == RTSP_SERVER_REAL)
1334 strcpy(real_challenge, reply->real_challenge); 1494 strcpy(real_challenge, reply->real_challenge);
1335 break; 1495 break;
1336 } 1496 }
1337 1497
1338 /* describe the stream */ 1498 if (s->iformat)
1339 snprintf(cmd, sizeof(cmd), 1499 err = rtsp_setup_input_streams(s);
1340 "DESCRIBE %s RTSP/1.0\r\n" 1500 else
1341 "Accept: application/sdp\r\n", 1501 err = rtsp_setup_output_streams(s);
1342 s->filename); 1502 if (err)
1343 if (rt->server_type == RTSP_SERVER_REAL) {
1344 /**
1345 * The Require: attribute is needed for proper streaming from
1346 * Realmedia servers.
1347 */
1348 av_strlcat(cmd,
1349 "Require: com.real.retain-entity-for-setup\r\n",
1350 sizeof(cmd));
1351 }
1352 rtsp_send_cmd(s, cmd, reply, &content);
1353 if (!content) {
1354 err = AVERROR_INVALIDDATA;
1355 goto fail; 1503 goto fail;
1356 }
1357 if (reply->status_code != RTSP_STATUS_OK) {
1358 err = AVERROR_INVALIDDATA;
1359 goto fail;
1360 }
1361
1362 /* now we got the SDP description, we parse it */
1363 ret = sdp_parse(s, (const char *)content);
1364 av_freep(&content);
1365 if (ret < 0) {
1366 err = AVERROR_INVALIDDATA;
1367 goto fail;
1368 }
1369 1504
1370 do { 1505 do {
1371 int lower_transport = ff_log2_tab[lower_transport_mask & 1506 int lower_transport = ff_log2_tab[lower_transport_mask &
1372 ~(lower_transport_mask - 1)]; 1507 ~(lower_transport_mask - 1)];
1373 1508
1374 err = make_setup_request(s, host, port, lower_transport, 1509 err = make_setup_request(s, host, port, lower_transport,
1375 rt->server_type == RTSP_SERVER_REAL ? 1510 rt->server_type == RTSP_SERVER_REAL ?
1376 real_challenge : NULL); 1511 real_challenge : NULL);
1377 if (err < 0) 1512 if (err < 0)
1378 goto fail; 1513 goto fail;
1379 lower_transport_mask &= ~(1 << lower_transport); 1514 lower_transport_mask &= ~(1 << lower_transport);
1380 if (lower_transport_mask == 0 && err == 1) { 1515 if (lower_transport_mask == 0 && err == 1) {
1381 err = AVERROR(FF_NETERROR(EPROTONOSUPPORT)); 1516 err = AVERROR(FF_NETERROR(EPROTONOSUPPORT));
1382 goto fail; 1517 goto fail;
1383 } 1518 }
1384 } while (err); 1519 } while (err);
1385 1520
1386 rt->state = RTSP_STATE_IDLE; 1521 rt->state = RTSP_STATE_IDLE;
1387 rt->seek_timestamp = 0; /* default is to start stream at position zero */ 1522 rt->seek_timestamp = 0; /* default is to start stream at position zero */
1388 if (ap->initial_pause) {
1389 /* do not start immediately */
1390 } else {
1391 if (rtsp_read_play(s) < 0) {
1392 err = AVERROR_INVALIDDATA;
1393 goto fail;
1394 }
1395 }
1396 return 0; 1523 return 0;
1397 fail: 1524 fail:
1398 rtsp_close_streams(rt); 1525 ff_rtsp_close_streams(s);
1399 av_freep(&content);
1400 url_close(rt->rtsp_hd); 1526 url_close(rt->rtsp_hd);
1401 if (reply->status_code >=300 && reply->status_code < 400) { 1527 if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) {
1402 av_strlcpy(s->filename, reply->location, sizeof(s->filename)); 1528 av_strlcpy(s->filename, reply->location, sizeof(s->filename));
1403 av_log(s, AV_LOG_INFO, "Status %d: Redirecting to %s\n", 1529 av_log(s, AV_LOG_INFO, "Status %d: Redirecting to %s\n",
1404 reply->status_code, 1530 reply->status_code,
1405 s->filename); 1531 s->filename);
1406 goto redirect; 1532 goto redirect;
1407 } 1533 }
1534 ff_network_close();
1408 return err; 1535 return err;
1409 } 1536 }
1537 #endif
1538
1539 #if CONFIG_RTSP_DEMUXER
1540 static int rtsp_read_header(AVFormatContext *s,
1541 AVFormatParameters *ap)
1542 {
1543 RTSPState *rt = s->priv_data;
1544 int ret;
1545
1546 ret = ff_rtsp_connect(s);
1547 if (ret)
1548 return ret;
1549
1550 if (ap->initial_pause) {
1551 /* do not start immediately */
1552 } else {
1553 if (rtsp_read_play(s) < 0) {
1554 ff_rtsp_close_streams(s);
1555 url_close(rt->rtsp_hd);
1556 return AVERROR_INVALIDDATA;
1557 }
1558 }
1559
1560 return 0;
1561 }
1410 1562
1411 static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, 1563 static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
1412 uint8_t *buf, int buf_size) 1564 uint8_t *buf, int buf_size)
1413 { 1565 {
1414 RTSPState *rt = s->priv_data; 1566 RTSPState *rt = s->priv_data;
1415 RTSPStream *rtsp_st; 1567 RTSPStream *rtsp_st;
1416 fd_set rfds; 1568 fd_set rfds;
1417 int fd, fd_max, n, i, ret, tcp_fd; 1569 int fd, fd_max, n, i, ret, tcp_fd;
1418 struct timeval tv; 1570 struct timeval tv;
1419 1571
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1453 *prtsp_st = rtsp_st; 1605 *prtsp_st = rtsp_st;
1454 return ret; 1606 return ret;
1455 } 1607 }
1456 } 1608 }
1457 } 1609 }
1458 } 1610 }
1459 #if CONFIG_RTSP_DEMUXER 1611 #if CONFIG_RTSP_DEMUXER
1460 if (tcp_fd != -1 && FD_ISSET(tcp_fd, &rfds)) { 1612 if (tcp_fd != -1 && FD_ISSET(tcp_fd, &rfds)) {
1461 RTSPMessageHeader reply; 1613 RTSPMessageHeader reply;
1462 1614
1463 rtsp_read_reply(s, &reply, NULL, 0); 1615 ff_rtsp_read_reply(s, &reply, NULL, 0);
1464 /* XXX: parse message */ 1616 /* XXX: parse message */
1465 if (rt->state != RTSP_STATE_PLAYING) 1617 if (rt->state != RTSP_STATE_STREAMING)
1466 return 0; 1618 return 0;
1467 } 1619 }
1468 #endif 1620 #endif
1469 } 1621 }
1470 } 1622 }
1471 } 1623 }
1472 1624
1473 static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, 1625 static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
1474 uint8_t *buf, int buf_size) 1626 uint8_t *buf, int buf_size)
1475 { 1627 {
1476 RTSPState *rt = s->priv_data; 1628 RTSPState *rt = s->priv_data;
1477 int id, len, i, ret; 1629 int id, len, i, ret;
1478 RTSPStream *rtsp_st; 1630 RTSPStream *rtsp_st;
1479 1631
1480 #ifdef DEBUG_RTP_TCP 1632 #ifdef DEBUG_RTP_TCP
1481 dprintf(s, "tcp_read_packet:\n"); 1633 dprintf(s, "tcp_read_packet:\n");
1482 #endif 1634 #endif
1483 redo: 1635 redo:
1484 for (;;) { 1636 for (;;) {
1485 RTSPMessageHeader reply; 1637 RTSPMessageHeader reply;
1486 1638
1487 ret = rtsp_read_reply(s, &reply, NULL, 1); 1639 ret = ff_rtsp_read_reply(s, &reply, NULL, 1);
1488 if (ret == -1) 1640 if (ret == -1)
1489 return -1; 1641 return -1;
1490 if (ret == 1) /* received '$' */ 1642 if (ret == 1) /* received '$' */
1491 break; 1643 break;
1492 /* XXX: parse message */ 1644 /* XXX: parse message */
1493 if (rt->state != RTSP_STATE_PLAYING) 1645 if (rt->state != RTSP_STATE_STREAMING)
1494 return 0; 1646 return 0;
1495 } 1647 }
1496 ret = url_read_complete(rt->rtsp_hd, buf, 3); 1648 ret = url_read_complete(rt->rtsp_hd, buf, 3);
1497 if (ret != 3) 1649 if (ret != 3)
1498 return -1; 1650 return -1;
1499 id = buf[0]; 1651 id = buf[0];
1500 len = AV_RB16(buf + 1); 1652 len = AV_RB16(buf + 1);
1501 #ifdef DEBUG_RTP_TCP 1653 #ifdef DEBUG_RTP_TCP
1502 dprintf(s, "id=%d len=%d\n", id, len); 1654 dprintf(s, "id=%d len=%d\n", id, len);
1503 #endif 1655 #endif
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1593 for (i = 0; i < s->nb_streams; i++) 1745 for (i = 0; i < s->nb_streams; i++)
1594 cache[i] = s->streams[i]->discard; 1746 cache[i] = s->streams[i]->discard;
1595 1747
1596 if (!rt->need_subscription) { 1748 if (!rt->need_subscription) {
1597 if (memcmp (cache, rt->real_setup_cache, 1749 if (memcmp (cache, rt->real_setup_cache,
1598 sizeof(enum AVDiscard) * s->nb_streams)) { 1750 sizeof(enum AVDiscard) * s->nb_streams)) {
1599 snprintf(cmd, sizeof(cmd), 1751 snprintf(cmd, sizeof(cmd),
1600 "SET_PARAMETER %s RTSP/1.0\r\n" 1752 "SET_PARAMETER %s RTSP/1.0\r\n"
1601 "Unsubscribe: %s\r\n", 1753 "Unsubscribe: %s\r\n",
1602 rt->control_uri, rt->last_subscription); 1754 rt->control_uri, rt->last_subscription);
1603 rtsp_send_cmd(s, cmd, reply, NULL); 1755 ff_rtsp_send_cmd(s, cmd, reply, NULL);
1604 if (reply->status_code != RTSP_STATUS_OK) 1756 if (reply->status_code != RTSP_STATUS_OK)
1605 return AVERROR_INVALIDDATA; 1757 return AVERROR_INVALIDDATA;
1606 rt->need_subscription = 1; 1758 rt->need_subscription = 1;
1607 } 1759 }
1608 } 1760 }
1609 1761
1610 if (rt->need_subscription) { 1762 if (rt->need_subscription) {
1611 int r, rule_nr, first = 1; 1763 int r, rule_nr, first = 1;
1612 1764
1613 memcpy(rt->real_setup_cache, cache, 1765 memcpy(rt->real_setup_cache, cache,
(...skipping 15 matching lines...) Expand all
1629 ff_rdt_subscribe_rule( 1781 ff_rdt_subscribe_rule(
1630 rt->last_subscription, 1782 rt->last_subscription,
1631 sizeof(rt->last_subscription), i, rule_nr); 1783 sizeof(rt->last_subscription), i, rule_nr);
1632 first = 0; 1784 first = 0;
1633 } 1785 }
1634 rule_nr++; 1786 rule_nr++;
1635 } 1787 }
1636 } 1788 }
1637 } 1789 }
1638 av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription); 1790 av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription);
1639 rtsp_send_cmd(s, cmd, reply, NULL); 1791 ff_rtsp_send_cmd(s, cmd, reply, NULL);
1640 if (reply->status_code != RTSP_STATUS_OK) 1792 if (reply->status_code != RTSP_STATUS_OK)
1641 return AVERROR_INVALIDDATA; 1793 return AVERROR_INVALIDDATA;
1642 rt->need_subscription = 0; 1794 rt->need_subscription = 0;
1643 1795
1644 if (rt->state == RTSP_STATE_PLAYING) 1796 if (rt->state == RTSP_STATE_STREAMING)
1645 rtsp_read_play (s); 1797 rtsp_read_play (s);
1646 } 1798 }
1647 } 1799 }
1648 1800
1649 ret = rtsp_fetch_packet(s, pkt); 1801 ret = rtsp_fetch_packet(s, pkt);
1650 if (ret < 0) 1802 if (ret < 0)
1651 return ret; 1803 return ret;
1652 1804
1653 /* send dummy request to keep TCP connection alive */ 1805 /* send dummy request to keep TCP connection alive */
1654 if ((rt->server_type == RTSP_SERVER_WMS || 1806 if ((rt->server_type == RTSP_SERVER_WMS ||
1655 rt->server_type == RTSP_SERVER_REAL) && 1807 rt->server_type == RTSP_SERVER_REAL) &&
1656 (av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) { 1808 (av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) {
1657 if (rt->server_type == RTSP_SERVER_WMS) { 1809 if (rt->server_type == RTSP_SERVER_WMS) {
1658 snprintf(cmd, sizeof(cmd) - 1, 1810 snprintf(cmd, sizeof(cmd) - 1,
1659 "GET_PARAMETER %s RTSP/1.0\r\n", 1811 "GET_PARAMETER %s RTSP/1.0\r\n",
1660 rt->control_uri); 1812 rt->control_uri);
1661 rtsp_send_cmd_async(s, cmd); 1813 ff_rtsp_send_cmd_async(s, cmd);
1662 } else { 1814 } else {
1663 rtsp_send_cmd_async(s, "OPTIONS * RTSP/1.0\r\n"); 1815 ff_rtsp_send_cmd_async(s, "OPTIONS * RTSP/1.0\r\n");
1664 } 1816 }
1665 } 1817 }
1666 1818
1667 return 0; 1819 return 0;
1668 } 1820 }
1669 1821
1670 /* pause the stream */ 1822 /* pause the stream */
1671 static int rtsp_read_pause(AVFormatContext *s) 1823 static int rtsp_read_pause(AVFormatContext *s)
1672 { 1824 {
1673 RTSPState *rt = s->priv_data; 1825 RTSPState *rt = s->priv_data;
1674 RTSPMessageHeader reply1, *reply = &reply1; 1826 RTSPMessageHeader reply1, *reply = &reply1;
1675 char cmd[1024]; 1827 char cmd[1024];
1676 1828
1677 rt = s->priv_data; 1829 rt = s->priv_data;
1678 1830
1679 if (rt->state != RTSP_STATE_PLAYING) 1831 if (rt->state != RTSP_STATE_STREAMING)
1680 return 0; 1832 return 0;
1681 else if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) { 1833 else if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
1682 snprintf(cmd, sizeof(cmd), 1834 snprintf(cmd, sizeof(cmd),
1683 "PAUSE %s RTSP/1.0\r\n", 1835 "PAUSE %s RTSP/1.0\r\n",
1684 rt->control_uri); 1836 rt->control_uri);
1685 rtsp_send_cmd(s, cmd, reply, NULL); 1837 ff_rtsp_send_cmd(s, cmd, reply, NULL);
1686 if (reply->status_code != RTSP_STATUS_OK) { 1838 if (reply->status_code != RTSP_STATUS_OK) {
1687 return -1; 1839 return -1;
1688 } 1840 }
1689 } 1841 }
1690 rt->state = RTSP_STATE_PAUSED; 1842 rt->state = RTSP_STATE_PAUSED;
1691 return 0; 1843 return 0;
1692 } 1844 }
1693 1845
1694 static int rtsp_read_seek(AVFormatContext *s, int stream_index, 1846 static int rtsp_read_seek(AVFormatContext *s, int stream_index,
1695 int64_t timestamp, int flags) 1847 int64_t timestamp, int flags)
1696 { 1848 {
1697 RTSPState *rt = s->priv_data; 1849 RTSPState *rt = s->priv_data;
1698 1850
1699 rt->seek_timestamp = av_rescale_q(timestamp, 1851 rt->seek_timestamp = av_rescale_q(timestamp,
1700 s->streams[stream_index]->time_base, 1852 s->streams[stream_index]->time_base,
1701 AV_TIME_BASE_Q); 1853 AV_TIME_BASE_Q);
1702 switch(rt->state) { 1854 switch(rt->state) {
1703 default: 1855 default:
1704 case RTSP_STATE_IDLE: 1856 case RTSP_STATE_IDLE:
1705 break; 1857 break;
1706 case RTSP_STATE_PLAYING: 1858 case RTSP_STATE_STREAMING:
1707 if (rtsp_read_pause(s) != 0) 1859 if (rtsp_read_pause(s) != 0)
1708 return -1; 1860 return -1;
1709 rt->state = RTSP_STATE_SEEKING; 1861 rt->state = RTSP_STATE_SEEKING;
1710 if (rtsp_read_play(s) != 0) 1862 if (rtsp_read_play(s) != 0)
1711 return -1; 1863 return -1;
1712 break; 1864 break;
1713 case RTSP_STATE_PAUSED: 1865 case RTSP_STATE_PAUSED:
1714 rt->state = RTSP_STATE_IDLE; 1866 rt->state = RTSP_STATE_IDLE;
1715 break; 1867 break;
1716 } 1868 }
1717 return 0; 1869 return 0;
1718 } 1870 }
1719 1871
1720 static int rtsp_read_close(AVFormatContext *s) 1872 static int rtsp_read_close(AVFormatContext *s)
1721 { 1873 {
1722 RTSPState *rt = s->priv_data; 1874 RTSPState *rt = s->priv_data;
1723 char cmd[1024]; 1875 char cmd[1024];
1724 1876
1725 #if 0 1877 #if 0
1726 /* NOTE: it is valid to flush the buffer here */ 1878 /* NOTE: it is valid to flush the buffer here */
1727 if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) { 1879 if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
1728 url_fclose(&rt->rtsp_gb); 1880 url_fclose(&rt->rtsp_gb);
1729 } 1881 }
1730 #endif 1882 #endif
1731 snprintf(cmd, sizeof(cmd), 1883 snprintf(cmd, sizeof(cmd),
1732 "TEARDOWN %s RTSP/1.0\r\n", 1884 "TEARDOWN %s RTSP/1.0\r\n",
1733 s->filename); 1885 s->filename);
1734 rtsp_send_cmd_async(s, cmd); 1886 ff_rtsp_send_cmd_async(s, cmd);
1735 1887
1736 rtsp_close_streams(rt); 1888 ff_rtsp_close_streams(s);
1737 url_close(rt->rtsp_hd); 1889 url_close(rt->rtsp_hd);
1890 ff_network_close();
1738 return 0; 1891 return 0;
1739 } 1892 }
1740 1893
1741 AVInputFormat rtsp_demuxer = { 1894 AVInputFormat rtsp_demuxer = {
1742 "rtsp", 1895 "rtsp",
1743 NULL_IF_CONFIG_SMALL("RTSP input format"), 1896 NULL_IF_CONFIG_SMALL("RTSP input format"),
1744 sizeof(RTSPState), 1897 sizeof(RTSPState),
1745 rtsp_probe, 1898 rtsp_probe,
1746 rtsp_read_header, 1899 rtsp_read_header,
1747 rtsp_read_packet, 1900 rtsp_read_packet,
(...skipping 27 matching lines...) Expand all
1775 #define SDP_MAX_SIZE 8192 1928 #define SDP_MAX_SIZE 8192
1776 1929
1777 static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap) 1930 static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap)
1778 { 1931 {
1779 RTSPState *rt = s->priv_data; 1932 RTSPState *rt = s->priv_data;
1780 RTSPStream *rtsp_st; 1933 RTSPStream *rtsp_st;
1781 int size, i, err; 1934 int size, i, err;
1782 char *content; 1935 char *content;
1783 char url[1024]; 1936 char url[1024];
1784 1937
1938 if (!ff_network_init())
1939 return AVERROR(EIO);
1940
1785 /* read the whole sdp file */ 1941 /* read the whole sdp file */
1786 /* XXX: better loading */ 1942 /* XXX: better loading */
1787 content = av_malloc(SDP_MAX_SIZE); 1943 content = av_malloc(SDP_MAX_SIZE);
1788 size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1); 1944 size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1);
1789 if (size <= 0) { 1945 if (size <= 0) {
1790 av_free(content); 1946 av_free(content);
1791 return AVERROR_INVALIDDATA; 1947 return AVERROR_INVALIDDATA;
1792 } 1948 }
1793 content[size] ='\0'; 1949 content[size] ='\0';
1794 1950
1795 sdp_parse(s, content); 1951 sdp_parse(s, content);
1796 av_free(content); 1952 av_free(content);
1797 1953
1798 /* open each RTP stream */ 1954 /* open each RTP stream */
1799 for (i = 0; i < rt->nb_rtsp_streams; i++) { 1955 for (i = 0; i < rt->nb_rtsp_streams; i++) {
1800 rtsp_st = rt->rtsp_streams[i]; 1956 rtsp_st = rt->rtsp_streams[i];
1801 1957
1802 snprintf(url, sizeof(url), "rtp://%s:%d?localport=%d&ttl=%d", 1958 ff_url_join(url, sizeof(url), "rtp", NULL,
1803 inet_ntoa(rtsp_st->sdp_ip), 1959 inet_ntoa(rtsp_st->sdp_ip), rtsp_st->sdp_port,
1804 rtsp_st->sdp_port, 1960 "?localport=%d&ttl=%d", rtsp_st->sdp_port,
1805 rtsp_st->sdp_port, 1961 rtsp_st->sdp_ttl);
1806 rtsp_st->sdp_ttl);
1807 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { 1962 if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
1808 err = AVERROR_INVALIDDATA; 1963 err = AVERROR_INVALIDDATA;
1809 goto fail; 1964 goto fail;
1810 } 1965 }
1811 if ((err = rtsp_open_transport_ctx(s, rtsp_st))) 1966 if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
1812 goto fail; 1967 goto fail;
1813 } 1968 }
1814 return 0; 1969 return 0;
1815 fail: 1970 fail:
1816 rtsp_close_streams(rt); 1971 ff_rtsp_close_streams(s);
1972 ff_network_close();
1817 return err; 1973 return err;
1818 } 1974 }
1819 1975
1820 static int sdp_read_close(AVFormatContext *s) 1976 static int sdp_read_close(AVFormatContext *s)
1821 { 1977 {
1822 RTSPState *rt = s->priv_data; 1978 ff_rtsp_close_streams(s);
1823 rtsp_close_streams(rt); 1979 ff_network_close();
1824 return 0; 1980 return 0;
1825 } 1981 }
1826 1982
1827 AVInputFormat sdp_demuxer = { 1983 AVInputFormat sdp_demuxer = {
1828 "sdp", 1984 "sdp",
1829 NULL_IF_CONFIG_SMALL("SDP"), 1985 NULL_IF_CONFIG_SMALL("SDP"),
1830 sizeof(RTSPState), 1986 sizeof(RTSPState),
1831 sdp_probe, 1987 sdp_probe,
1832 sdp_read_header, 1988 sdp_read_header,
1833 rtsp_fetch_packet, 1989 rtsp_fetch_packet,
1834 sdp_read_close, 1990 sdp_read_close,
1835 }; 1991 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698