From 0526c6f7c7852730e4d3da3dd1d070deb00e5043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 29 Oct 2010 08:43:57 +0000 Subject: rtsp: Split out the RTSP demuxer functions to a separate, new file Originally committed as revision 25601 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/rtsp.c | 358 ++--------------------------------------------------- 1 file changed, 7 insertions(+), 351 deletions(-) (limited to 'libavformat/rtsp.c') diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index a604a7a..1f55016 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -411,7 +411,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, } } -static int sdp_parse(AVFormatContext *s, const char *content) +int ff_sdp_parse(AVFormatContext *s, const char *content) { const char *p; int letter; @@ -1177,98 +1177,6 @@ fail: return err; } -static int rtsp_read_play(AVFormatContext *s) -{ - RTSPState *rt = s->priv_data; - RTSPMessageHeader reply1, *reply = &reply1; - int i; - char cmd[1024]; - - av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state); - rt->nb_byes = 0; - - if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) { - if (rt->state == RTSP_STATE_PAUSED) { - cmd[0] = 0; - } else { - snprintf(cmd, sizeof(cmd), - "Range: npt=%0.3f-\r\n", - (double)rt->seek_timestamp / AV_TIME_BASE); - } - ff_rtsp_send_cmd(s, "PLAY", rt->control_uri, cmd, reply, NULL); - if (reply->status_code != RTSP_STATUS_OK) { - return -1; - } - if (rt->transport == RTSP_TRANSPORT_RTP) { - for (i = 0; i < rt->nb_rtsp_streams; i++) { - RTSPStream *rtsp_st = rt->rtsp_streams[i]; - RTPDemuxContext *rtpctx = rtsp_st->transport_priv; - AVStream *st = NULL; - if (!rtpctx) - continue; - if (rtsp_st->stream_index >= 0) - st = s->streams[rtsp_st->stream_index]; - ff_rtp_reset_packet_queue(rtpctx); - if (reply->range_start != AV_NOPTS_VALUE) { - rtpctx->last_rtcp_ntp_time = AV_NOPTS_VALUE; - rtpctx->first_rtcp_ntp_time = AV_NOPTS_VALUE; - if (st) - rtpctx->range_start_offset = - av_rescale_q(reply->range_start, AV_TIME_BASE_Q, - st->time_base); - } - } - } - } - rt->state = RTSP_STATE_STREAMING; - return 0; -} - -#if CONFIG_RTSP_DEMUXER -static int rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply) -{ - RTSPState *rt = s->priv_data; - char cmd[1024]; - unsigned char *content = NULL; - int ret; - - /* describe the stream */ - snprintf(cmd, sizeof(cmd), - "Accept: application/sdp\r\n"); - if (rt->server_type == RTSP_SERVER_REAL) { - /** - * The Require: attribute is needed for proper streaming from - * Realmedia servers. - */ - av_strlcat(cmd, - "Require: com.real.retain-entity-for-setup\r\n", - sizeof(cmd)); - } - ff_rtsp_send_cmd(s, "DESCRIBE", rt->control_uri, cmd, reply, &content); - if (!content) - return AVERROR_INVALIDDATA; - if (reply->status_code != RTSP_STATUS_OK) { - av_freep(&content); - return AVERROR_INVALIDDATA; - } - - av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", content); - /* now we got the SDP description, we parse it */ - ret = sdp_parse(s, (const char *)content); - av_freep(&content); - if (ret < 0) - return AVERROR_INVALIDDATA; - - return 0; -} -#else /* !CONFIG_RTSP_DEMUXER */ -/* A declaration of this function is needed so that the function is - * defined when parsing the call to it, even if dead code elimination - * will remove the call later. - */ -static int rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply); -#endif /* !CONFIG_RTSP_DEMUXER */ - void ff_rtsp_close_connections(AVFormatContext *s) { RTSPState *rt = s->priv_data; @@ -1485,7 +1393,7 @@ redirect: } if (s->iformat && CONFIG_RTSP_DEMUXER) - err = rtsp_setup_input_streams(s, reply); + err = ff_rtsp_setup_input_streams(s, reply); else if (CONFIG_RTSP_MUXER) err = ff_rtsp_setup_output_streams(s, host); if (err) @@ -1597,10 +1505,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, } } -static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, - uint8_t *buf, int buf_size); - -static int rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt) +int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt) { RTSPState *rt = s->priv_data; int ret, len; @@ -1653,7 +1558,7 @@ static int rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt) default: #if CONFIG_RTSP_DEMUXER case RTSP_LOWER_TRANSPORT_TCP: - len = tcp_read_packet(s, &rtsp_st, rt->recvbuf, RECVBUF_SIZE); + len = ff_rtsp_tcp_read_packet(s, &rtsp_st, rt->recvbuf, RECVBUF_SIZE); break; #endif case RTSP_LOWER_TRANSPORT_UDP: @@ -1716,255 +1621,6 @@ end: } #endif /* CONFIG_RTPDEC */ -#if CONFIG_RTSP_DEMUXER -static int rtsp_probe(AVProbeData *p) -{ - if (av_strstart(p->filename, "rtsp:", NULL)) - return AVPROBE_SCORE_MAX; - return 0; -} - -static int rtsp_read_header(AVFormatContext *s, - AVFormatParameters *ap) -{ - RTSPState *rt = s->priv_data; - int ret; - - ret = ff_rtsp_connect(s); - if (ret) - return ret; - - rt->real_setup_cache = av_mallocz(2 * s->nb_streams * sizeof(*rt->real_setup_cache)); - if (!rt->real_setup_cache) - return AVERROR(ENOMEM); - rt->real_setup = rt->real_setup_cache + s->nb_streams * sizeof(*rt->real_setup); - - if (ap->initial_pause) { - /* do not start immediately */ - } else { - if (rtsp_read_play(s) < 0) { - ff_rtsp_close_streams(s); - ff_rtsp_close_connections(s); - return AVERROR_INVALIDDATA; - } - } - - return 0; -} - -static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, - uint8_t *buf, int buf_size) -{ - RTSPState *rt = s->priv_data; - int id, len, i, ret; - RTSPStream *rtsp_st; - -#ifdef DEBUG_RTP_TCP - dprintf(s, "tcp_read_packet:\n"); -#endif -redo: - for (;;) { - RTSPMessageHeader reply; - - ret = ff_rtsp_read_reply(s, &reply, NULL, 1); - if (ret < 0) - return ret; - if (ret == 1) /* received '$' */ - break; - /* XXX: parse message */ - if (rt->state != RTSP_STATE_STREAMING) - return 0; - } - ret = url_read_complete(rt->rtsp_hd, buf, 3); - if (ret != 3) - return -1; - id = buf[0]; - len = AV_RB16(buf + 1); -#ifdef DEBUG_RTP_TCP - dprintf(s, "id=%d len=%d\n", id, len); -#endif - if (len > buf_size || len < 12) - goto redo; - /* get the data */ - ret = url_read_complete(rt->rtsp_hd, buf, len); - if (ret != len) - return -1; - if (rt->transport == RTSP_TRANSPORT_RDT && - ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL) < 0) - return -1; - - /* find the matching stream */ - for (i = 0; i < rt->nb_rtsp_streams; i++) { - rtsp_st = rt->rtsp_streams[i]; - if (id >= rtsp_st->interleaved_min && - id <= rtsp_st->interleaved_max) - goto found; - } - goto redo; -found: - *prtsp_st = rtsp_st; - return len; -} -static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt) -{ - RTSPState *rt = s->priv_data; - int ret; - RTSPMessageHeader reply1, *reply = &reply1; - char cmd[1024]; - - if (rt->server_type == RTSP_SERVER_REAL) { - int i; - - for (i = 0; i < s->nb_streams; i++) - rt->real_setup[i] = s->streams[i]->discard; - - if (!rt->need_subscription) { - if (memcmp (rt->real_setup, rt->real_setup_cache, - sizeof(enum AVDiscard) * s->nb_streams)) { - snprintf(cmd, sizeof(cmd), - "Unsubscribe: %s\r\n", - rt->last_subscription); - ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri, - cmd, reply, NULL); - if (reply->status_code != RTSP_STATUS_OK) - return AVERROR_INVALIDDATA; - rt->need_subscription = 1; - } - } - - if (rt->need_subscription) { - int r, rule_nr, first = 1; - - memcpy(rt->real_setup_cache, rt->real_setup, - sizeof(enum AVDiscard) * s->nb_streams); - rt->last_subscription[0] = 0; - - snprintf(cmd, sizeof(cmd), - "Subscribe: "); - for (i = 0; i < rt->nb_rtsp_streams; i++) { - rule_nr = 0; - for (r = 0; r < s->nb_streams; r++) { - if (s->streams[r]->priv_data == rt->rtsp_streams[i]) { - if (s->streams[r]->discard != AVDISCARD_ALL) { - if (!first) - av_strlcat(rt->last_subscription, ",", - sizeof(rt->last_subscription)); - ff_rdt_subscribe_rule( - rt->last_subscription, - sizeof(rt->last_subscription), i, rule_nr); - first = 0; - } - rule_nr++; - } - } - } - av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription); - ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri, - cmd, reply, NULL); - if (reply->status_code != RTSP_STATUS_OK) - return AVERROR_INVALIDDATA; - rt->need_subscription = 0; - - if (rt->state == RTSP_STATE_STREAMING) - rtsp_read_play (s); - } - } - - ret = rtsp_fetch_packet(s, pkt); - if (ret < 0) - return ret; - - /* send dummy request to keep TCP connection alive */ - if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) { - if (rt->server_type == RTSP_SERVER_WMS) { - ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL); - } else { - ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL); - } - } - - return 0; -} - -/* pause the stream */ -static int rtsp_read_pause(AVFormatContext *s) -{ - RTSPState *rt = s->priv_data; - RTSPMessageHeader reply1, *reply = &reply1; - - if (rt->state != RTSP_STATE_STREAMING) - return 0; - else if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) { - ff_rtsp_send_cmd(s, "PAUSE", rt->control_uri, NULL, reply, NULL); - if (reply->status_code != RTSP_STATUS_OK) { - return -1; - } - } - rt->state = RTSP_STATE_PAUSED; - return 0; -} - -static int rtsp_read_seek(AVFormatContext *s, int stream_index, - int64_t timestamp, int flags) -{ - RTSPState *rt = s->priv_data; - - 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: - break; - case RTSP_STATE_STREAMING: - if (rtsp_read_pause(s) != 0) - return -1; - rt->state = RTSP_STATE_SEEKING; - if (rtsp_read_play(s) != 0) - return -1; - break; - case RTSP_STATE_PAUSED: - rt->state = RTSP_STATE_IDLE; - break; - } - return 0; -} - -static int rtsp_read_close(AVFormatContext *s) -{ - RTSPState *rt = s->priv_data; - -#if 0 - /* NOTE: it is valid to flush the buffer here */ - if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) { - url_fclose(&rt->rtsp_gb); - } -#endif - ff_rtsp_send_cmd_async(s, "TEARDOWN", rt->control_uri, NULL); - - ff_rtsp_close_streams(s); - ff_rtsp_close_connections(s); - ff_network_close(); - rt->real_setup = NULL; - av_freep(&rt->real_setup_cache); - return 0; -} - -AVInputFormat rtsp_demuxer = { - "rtsp", - NULL_IF_CONFIG_SMALL("RTSP input format"), - sizeof(RTSPState), - rtsp_probe, - rtsp_read_header, - rtsp_read_packet, - rtsp_read_close, - rtsp_read_seek, - .flags = AVFMT_NOFILE, - .read_play = rtsp_read_play, - .read_pause = rtsp_read_pause, -}; -#endif /* CONFIG_RTSP_DEMUXER */ - #if CONFIG_SDP_DEMUXER static int sdp_probe(AVProbeData *p1) { @@ -2006,7 +1662,7 @@ static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap) } content[size] ='\0'; - sdp_parse(s, content); + ff_sdp_parse(s, content); av_free(content); /* open each RTP stream */ @@ -2047,7 +1703,7 @@ AVInputFormat sdp_demuxer = { sizeof(RTSPState), sdp_probe, sdp_read_header, - rtsp_fetch_packet, + ff_rtsp_fetch_packet, sdp_read_close, }; #endif /* CONFIG_SDP_DEMUXER */ @@ -2151,7 +1807,7 @@ AVInputFormat rtp_demuxer = { sizeof(RTSPState), rtp_probe, rtp_read_header, - rtsp_fetch_packet, + ff_rtsp_fetch_packet, sdp_read_close, .flags = AVFMT_NOFILE, }; -- cgit v1.1