diff options
author | Diego 'Flameeyes' Pettenò <flameeyes@gmail.com> | 2008-03-01 03:05:13 +0100 |
---|---|---|
committer | Diego 'Flameeyes' Pettenò <flameeyes@gmail.com> | 2008-03-01 03:05:13 +0100 |
commit | 1d0b3b20c34517b9d1ddf3ea347776304b0c4b44 (patch) | |
tree | 89f4fc640c2becc6f00ae08996754952ecf149c1 /contrib/ffmpeg/libavformat/rtsp.c | |
parent | 09496ad3469a0ade8dbd9a351e639b78f20b7942 (diff) | |
download | xine-lib-1d0b3b20c34517b9d1ddf3ea347776304b0c4b44.tar.gz xine-lib-1d0b3b20c34517b9d1ddf3ea347776304b0c4b44.tar.bz2 |
Update internal FFmpeg copy.
Diffstat (limited to 'contrib/ffmpeg/libavformat/rtsp.c')
-rw-r--r-- | contrib/ffmpeg/libavformat/rtsp.c | 204 |
1 files changed, 108 insertions, 96 deletions
diff --git a/contrib/ffmpeg/libavformat/rtsp.c b/contrib/ffmpeg/libavformat/rtsp.c index 7d4c6bf78..14f0a5ce4 100644 --- a/contrib/ffmpeg/libavformat/rtsp.c +++ b/contrib/ffmpeg/libavformat/rtsp.c @@ -23,6 +23,8 @@ #include <sys/time.h> #include <unistd.h> /* for select() prototype */ #include "network.h" +#include "avstring.h" +#include "rtsp.h" #include "rtp_internal.h" @@ -75,13 +77,13 @@ static int rtsp_read_play(AVFormatContext *s); /* XXX: currently, the only way to change the protocols consists in changing this variable */ +#if LIBAVFORMAT_VERSION_INT < (53 << 16) int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_UDP); - -FFRTSPCallback *ff_rtsp_callback = NULL; +#endif static int rtsp_probe(AVProbeData *p) { - if (strstart(p->filename, "rtsp:", NULL)) + if (av_strstart(p->filename, "rtsp:", NULL)) return AVPROBE_SCORE_MAX; return 0; } @@ -167,11 +169,7 @@ static int sdp_parse_rtpmap(AVCodecContext *codec, RTSPStream *rtsp_st, int payl } else { /* We are in a standard case ( from http://www.iana.org/assignments/rtp-parameters) */ /* search into AVRtpPayloadTypes[] */ - for (i = 0; AVRtpPayloadTypes[i].pt >= 0; ++i) - if (!strcmp(buf, AVRtpPayloadTypes[i].enc_name) && (codec->codec_type == AVRtpPayloadTypes[i].codec_type)){ - codec->codec_id = AVRtpPayloadTypes[i].codec_id; - break; - } + codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type); } c = avcodec_find_decoder(codec->codec_id); @@ -339,7 +337,7 @@ static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end) char buf[256]; skip_spaces(&p); - if (!stristart(p, "npt=", &p)) + if (!av_stristart(p, "npt=", &p)) return; *start = AV_NOPTS_VALUE; @@ -407,11 +405,11 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, } break; case 's': - pstrcpy(s->title, sizeof(s->title), p); + av_strlcpy(s->title, p, sizeof(s->title)); break; case 'i': if (s->nb_streams == 0) { - pstrcpy(s->comment, sizeof(s->comment), p); + av_strlcpy(s->comment, p, sizeof(s->comment)); break; } break; @@ -443,7 +441,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, get_word(buf1, sizeof(buf1), &p); /* format list */ rtsp_st->sdp_payload_type = atoi(buf1); - if (!strcmp(AVRtpPayloadTypes[rtsp_st->sdp_payload_type].enc_name, "MP2T")) { + if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) { /* no corresponding stream */ } else { st = av_new_stream(s, 0); @@ -458,10 +456,10 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, } } /* put a default control url */ - pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), s->filename); + av_strlcpy(rtsp_st->control_url, s->filename, sizeof(rtsp_st->control_url)); break; case 'a': - if (strstart(p, "control:", &p) && s->nb_streams > 0) { + if (av_strstart(p, "control:", &p) && s->nb_streams > 0) { char proto[32]; /* get the control url */ st = s->streams[s->nb_streams - 1]; @@ -471,12 +469,12 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, url_split(proto, sizeof(proto), NULL, 0, NULL, 0, NULL, NULL, 0, p); if (proto[0] == '\0') { /* relative control URL */ - pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), "/"); - pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), p); + av_strlcat(rtsp_st->control_url, "/", sizeof(rtsp_st->control_url)); + av_strlcat(rtsp_st->control_url, p, sizeof(rtsp_st->control_url)); } else { - pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), p); + av_strlcpy(rtsp_st->control_url, p, sizeof(rtsp_st->control_url)); } - } else if (strstart(p, "rtpmap:", &p)) { + } else if (av_strstart(p, "rtpmap:", &p)) { /* NOTE: rtpmap is only supported AFTER the 'm=' tag */ get_word(buf1, sizeof(buf1), &p); payload_type = atoi(buf1); @@ -487,7 +485,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, sdp_parse_rtpmap(st->codec, rtsp_st, payload_type, p); } } - } else if (strstart(p, "fmtp:", &p)) { + } else if (av_strstart(p, "fmtp:", &p)) { /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */ get_word(buf1, sizeof(buf1), &p); payload_type = atoi(buf1); @@ -504,7 +502,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, } } } - } else if(strstart(p, "framesize:", &p)) { + } else if(av_strstart(p, "framesize:", &p)) { // let dynamic protocol handlers have a stab at the line. get_word(buf1, sizeof(buf1), &p); payload_type = atoi(buf1); @@ -517,7 +515,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, } } } - } else if(strstart(p, "range:", &p)) { + } else if(av_strstart(p, "range:", &p)) { int64_t start, end; // this is so that seeking on a streamed file can work. @@ -608,12 +606,19 @@ static void rtsp_parse_transport(RTSPHeader *reply, const char *p) "/", &p); if (*p == '/') p++; - get_word_sep(profile, sizeof(profile), "/;,", &p); - lower_transport[0] = '\0'; - if (*p == '/') { - p++; - get_word_sep(lower_transport, sizeof(lower_transport), - ";,", &p); + if (!strcasecmp (transport_protocol, "rtp")) { + get_word_sep(profile, sizeof(profile), "/;,", &p); + lower_transport[0] = '\0'; + /* rtp/avp/<protocol> */ + if (*p == '/') { + p++; + get_word_sep(lower_transport, sizeof(lower_transport), + ";,", &p); + } + } else if (!strcasecmp (transport_protocol, "x-pn-tng")) { + /* x-pn-tng/<protocol> */ + get_word_sep(lower_transport, sizeof(lower_transport), "/;,", &p); + profile[0] = '\0'; } if (!strcasecmp(lower_transport, "TCP")) th->protocol = RTSP_PROTOCOL_RTP_TCP; @@ -684,15 +689,15 @@ void rtsp_parse_line(RTSPHeader *reply, const char *buf) /* NOTE: we do case independent match for broken servers */ p = buf; - if (stristart(p, "Session:", &p)) { + if (av_stristart(p, "Session:", &p)) { get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p); - } else if (stristart(p, "Content-Length:", &p)) { + } else if (av_stristart(p, "Content-Length:", &p)) { reply->content_length = strtol(p, NULL, 10); - } else if (stristart(p, "Transport:", &p)) { + } else if (av_stristart(p, "Transport:", &p)) { rtsp_parse_transport(reply, p); - } else if (stristart(p, "CSeq:", &p)) { + } else if (av_stristart(p, "CSeq:", &p)) { reply->seq = strtol(p, NULL, 10); - } else if (stristart(p, "Range:", &p)) { + } else if (av_stristart(p, "Range:", &p)) { rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end); } } @@ -721,7 +726,7 @@ static void rtsp_skip_packet(AVFormatContext *s) ret = url_readbuf(rt->rtsp_hd, buf, 3); if (ret != 3) return; - len = (buf[1] << 8) | buf[2]; + len = AV_RB16(buf + 1); #ifdef DEBUG printf("skipping RTP packet len=%d\n", len); #endif @@ -751,14 +756,14 @@ static void rtsp_send_cmd(AVFormatContext *s, memset(reply, 0, sizeof(RTSPHeader)); rt->seq++; - pstrcpy(buf, sizeof(buf), cmd); + av_strlcpy(buf, cmd, sizeof(buf)); snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq); - pstrcat(buf, sizeof(buf), buf1); + av_strlcat(buf, buf1, sizeof(buf)); if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) { snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id); - pstrcat(buf, sizeof(buf), buf1); + av_strlcat(buf, buf1, sizeof(buf)); } - pstrcat(buf, sizeof(buf), "\r\n"); + av_strlcat(buf, "\r\n", sizeof(buf)); #ifdef DEBUG printf("Sending:\n%s--\n", buf); #endif @@ -797,14 +802,14 @@ static void rtsp_send_cmd(AVFormatContext *s, reply->status_code = atoi(buf1); } else { rtsp_parse_line(reply, p); - pstrcat(rt->last_reply, sizeof(rt->last_reply), p); - pstrcat(rt->last_reply, sizeof(rt->last_reply), "\n"); + av_strlcat(rt->last_reply, p, sizeof(rt->last_reply)); + av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply)); } line_count++; } if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0') - pstrcpy(rt->session_id, sizeof(rt->session_id), reply->session_id); + av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id)); content_length = reply->content_length; if (content_length > 0) { @@ -815,12 +820,8 @@ static void rtsp_send_cmd(AVFormatContext *s, } if (content_ptr) *content_ptr = content; -} - - -void rtsp_set_callback(FFRTSPCallback *rtsp_cb) -{ - ff_rtsp_callback = rtsp_cb; + else + av_free(content); } @@ -849,13 +850,13 @@ static int rtsp_read_header(AVFormatContext *s, AVFormatParameters *ap) { RTSPState *rt = s->priv_data; - char host[1024], path[1024], tcpname[1024], cmd[2048]; + char host[1024], path[1024], tcpname[1024], cmd[2048], *option_list, *option; URLContext *rtsp_hd; int port, i, j, ret, err; RTSPHeader reply1, *reply = &reply1; unsigned char *content = NULL; RTSPStream *rtsp_st; - int protocol_mask; + int protocol_mask = 0; AVStream *st; /* extract hostname and port */ @@ -864,10 +865,34 @@ static int rtsp_read_header(AVFormatContext *s, if (port < 0) port = RTSP_DEFAULT_PORT; + /* search for options */ + option_list = strchr(path, '?'); + if (option_list) { + /* remove the options from the path */ + *option_list++ = 0; + while(option_list) { + /* move the option pointer */ + option = option_list; + option_list = strchr(option_list, '&'); + if (option_list) + *(option_list++) = 0; + /* handle the options */ + if (strcmp(option, "udp") == 0) + protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP); + else if (strcmp(option, "multicast") == 0) + protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP_MULTICAST); + else if (strcmp(option, "tcp") == 0) + protocol_mask = (1<< RTSP_PROTOCOL_RTP_TCP); + } + } + + if (!protocol_mask) + protocol_mask = rtsp_default_protocols; + /* open the tcp connexion */ snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port); if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0) - return AVERROR_IO; + return AVERROR(EIO); rt->rtsp_hd = rtsp_hd; rt->seq = 0; @@ -894,8 +919,6 @@ static int rtsp_read_header(AVFormatContext *s, goto fail; } - protocol_mask = rtsp_default_protocols; - /* for each stream, make the setup request */ /* XXX: we assume the same server is used for the control of each RTSP stream */ @@ -915,9 +938,9 @@ static int rtsp_read_header(AVFormatContext *s, /* first try in specified port range */ if (RTSP_RTP_PORT_MIN != 0) { while(j <= RTSP_RTP_PORT_MAX) { - snprintf(buf, sizeof(buf), "rtp://?localport=%d", j); + snprintf(buf, sizeof(buf), "rtp://%s?localport=%d", host, j); + j += 2; /* we will use two port by rtp stream (rtp and rtcp) */ if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0) { - j += 2; /* we will use two port by rtp stream (rtp and rtcp) */ goto rtp_opened; } } @@ -933,7 +956,7 @@ static int rtsp_read_header(AVFormatContext *s, rtp_opened: port = rtp_get_local_port(rtsp_st->rtp_handle); if (transport[0] != '\0') - pstrcat(transport, sizeof(transport), ","); + av_strlcat(transport, ",", sizeof(transport)); snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1, "RTP/AVP/UDP;unicast;client_port=%d-%d", port, port + 1); @@ -942,14 +965,14 @@ static int rtsp_read_header(AVFormatContext *s, /* RTP/TCP */ else if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_TCP)) { if (transport[0] != '\0') - pstrcat(transport, sizeof(transport), ","); + av_strlcat(transport, ",", sizeof(transport)); snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1, "RTP/AVP/TCP"); } else if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST)) { if (transport[0] != '\0') - pstrcat(transport, sizeof(transport), ","); + av_strlcat(transport, ",", sizeof(transport)); snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1, "RTP/AVP/UDP;multicast"); @@ -1004,15 +1027,13 @@ static int rtsp_read_header(AVFormatContext *s, case RTSP_PROTOCOL_RTP_UDP_MULTICAST: { char url[1024]; - int ttl; + struct in_addr in; - ttl = reply->transports[0].ttl; - if (!ttl) - ttl = 16; + in.s_addr = htonl(reply->transports[0].destination); snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d", - host, - reply->transports[0].server_port_min, - ttl); + inet_ntoa(in), + reply->transports[0].port_min, + reply->transports[0].ttl); if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { err = AVERROR_INVALIDDATA; goto fail; @@ -1029,7 +1050,7 @@ static int rtsp_read_header(AVFormatContext *s, rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->rtp_handle, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data); if (!rtsp_st->rtp_ctx) { - err = AVERROR_NOMEM; + err = AVERROR(ENOMEM); goto fail; } else { if(rtsp_st->dynamic_handler) { @@ -1039,16 +1060,6 @@ static int rtsp_read_header(AVFormatContext *s, } } - /* use callback if available to extend setup */ - if (ff_rtsp_callback) { - if (ff_rtsp_callback(RTSP_ACTION_CLIENT_SETUP, rt->session_id, - NULL, 0, rt->last_reply) < 0) { - err = AVERROR_INVALIDDATA; - goto fail; - } - } - - rt->state = RTSP_STATE_IDLE; rt->seek_timestamp = 0; /* default is to start stream at position zero */ @@ -1093,7 +1104,7 @@ static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, if (ret != 3) return -1; id = buf[0]; - len = (buf[1] << 8) | buf[2]; + len = AV_RB16(buf + 1); #ifdef DEBUG_RTP_TCP printf("id=%d len=%d\n", id, len); #endif @@ -1128,7 +1139,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, for(;;) { if (url_interrupt_cb()) - return -1; + return AVERROR(EINTR); FD_ZERO(&rfds); fd_max = -1; for(i = 0; i < rt->nb_rtsp_streams; i++) { @@ -1189,12 +1200,12 @@ static int rtsp_read_packet(AVFormatContext *s, case RTSP_PROTOCOL_RTP_UDP: case RTSP_PROTOCOL_RTP_UDP_MULTICAST: len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf)); - if (rtsp_st->rtp_ctx) + if (len >=0 && rtsp_st->rtp_ctx) rtp_check_and_send_back_rr(rtsp_st->rtp_ctx, len); break; } if (len < 0) - return AVERROR_IO; + return len; ret = rtp_parse_packet(rtsp_st->rtp_ctx, pkt, buf, len); if (ret < 0) goto redo; @@ -1262,7 +1273,7 @@ static int rtsp_read_seek(AVFormatContext *s, int stream_index, { RTSPState *rt = s->priv_data; - rt->seek_timestamp = timestamp; + rt->seek_timestamp = av_rescale_q(timestamp, s->streams[stream_index]->time_base, AV_TIME_BASE_Q); switch(rt->state) { default: case RTSP_STATE_IDLE: @@ -1295,16 +1306,12 @@ static int rtsp_read_close(AVFormatContext *s) s->filename); rtsp_send_cmd(s, cmd, reply, NULL); - if (ff_rtsp_callback) { - ff_rtsp_callback(RTSP_ACTION_CLIENT_TEARDOWN, rt->session_id, - NULL, 0, NULL); - } - rtsp_close_streams(rt); url_close(rt->rtsp_hd); return 0; } +#ifdef CONFIG_RTSP_DEMUXER AVInputFormat rtsp_demuxer = { "rtsp", "RTSP input format", @@ -1318,6 +1325,7 @@ AVInputFormat rtsp_demuxer = { .read_play = rtsp_read_play, .read_pause = rtsp_read_pause, }; +#endif static int sdp_probe(AVProbeData *p1) { @@ -1325,7 +1333,7 @@ static int sdp_probe(AVProbeData *p1) /* we look for a line beginning "c=IN IP4" */ while (p < p_end && *p != '\0') { - if (p + sizeof("c=IN IP4") - 1 < p_end && strstart(p, "c=IN IP4", NULL)) + if (p + sizeof("c=IN IP4") - 1 < p_end && av_strstart(p, "c=IN IP4", NULL)) return AVPROBE_SCORE_MAX / 2; while(p < p_end - 1 && *p != '\n') p++; @@ -1352,7 +1360,7 @@ static int sdp_read_header(AVFormatContext *s, /* read the whole sdp file */ /* XXX: better loading */ content = av_malloc(SDP_MAX_SIZE); - size = get_buffer(&s->pb, content, SDP_MAX_SIZE - 1); + size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1); if (size <= 0) { av_free(content); return AVERROR_INVALIDDATA; @@ -1382,7 +1390,7 @@ static int sdp_read_header(AVFormatContext *s, s->ctx_flags |= AVFMTCTX_NOHEADER; rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->rtp_handle, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data); if (!rtsp_st->rtp_ctx) { - err = AVERROR_NOMEM; + err = AVERROR(ENOMEM); goto fail; } else { if(rtsp_st->dynamic_handler) { @@ -1422,6 +1430,7 @@ AVInputFormat sdp_demuxer = { }; #endif +#ifdef CONFIG_REDIR_DEMUXER /* dummy redirector format (used directly in av_open_input_file now) */ static int redir_probe(AVProbeData *pd) { @@ -1429,18 +1438,18 @@ static int redir_probe(AVProbeData *pd) p = pd->buf; while (redir_isspace(*p)) p++; - if (strstart(p, "http://", NULL) || - strstart(p, "rtsp://", NULL)) + if (av_strstart(p, "http://", NULL) || + av_strstart(p, "rtsp://", NULL)) return AVPROBE_SCORE_MAX; return 0; } -/* called from utils.c */ -int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f) +static int redir_read_header(AVFormatContext *s, AVFormatParameters *ap) { char buf[4096], *q; int c; AVFormatContext *ic = NULL; + ByteIOContext *f = s->pb; /* parse each URL and try to open it */ c = url_fgetc(f); @@ -1468,11 +1477,13 @@ int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f) if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0) break; } - *ic_ptr = ic; if (!ic) - return AVERROR_IO; - else - return 0; + return AVERROR(EIO); + + *s = *ic; + url_fclose(f); + + return 0; } AVInputFormat redir_demuxer = { @@ -1480,7 +1491,8 @@ AVInputFormat redir_demuxer = { "Redirector format", 0, redir_probe, - NULL, + redir_read_header, NULL, NULL, }; +#endif |