From 6f5a3d0a7bb2a1e9deb09f8204e2b0eb7a922e02 Mon Sep 17 00:00:00 2001 From: Martin Storsjö Date: Mon, 22 Feb 2010 21:28:19 +0000 Subject: Add an RTSP muxer Originally committed as revision 21971 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/rtspenc.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 libavformat/rtspenc.c (limited to 'libavformat/rtspenc.c') diff --git a/libavformat/rtspenc.c b/libavformat/rtspenc.c new file mode 100644 index 0000000000..c918b3e8c0 --- /dev/null +++ b/libavformat/rtspenc.c @@ -0,0 +1,131 @@ +/* + * RTSP muxer + * Copyright (c) 2010 Martin Storsjo + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avformat.h" + +#include +#if HAVE_SYS_SELECT_H +#include +#endif +#include "network.h" +#include "rtsp.h" + +static int rtsp_write_record(AVFormatContext *s) +{ + RTSPState *rt = s->priv_data; + RTSPMessageHeader reply1, *reply = &reply1; + char cmd[1024]; + + snprintf(cmd, sizeof(cmd), + "RECORD %s RTSP/1.0\r\n" + "Range: npt=%0.3f-\r\n", + s->filename, + (double) 0); + rtsp_send_cmd(s, cmd, reply, NULL); + if (reply->status_code != RTSP_STATUS_OK) + return -1; + rt->state = RTSP_STATE_STREAMING; + return 0; +} + +static int rtsp_write_header(AVFormatContext *s) +{ + RTSPState *rt = s->priv_data; + int ret; + + ret = rtsp_connect(s); + if (ret) + return ret; + + if (rtsp_write_record(s) < 0) { + rtsp_close_streams(s); + url_close(rt->rtsp_hd); + return AVERROR_INVALIDDATA; + } + return 0; +} + +static int rtsp_write_packet(AVFormatContext *s, AVPacket *pkt) +{ + RTSPState *rt = s->priv_data; + RTSPStream *rtsp_st; + fd_set rfds; + int n, tcp_fd; + struct timeval tv; + AVFormatContext *rtpctx; + + FD_ZERO(&rfds); + tcp_fd = url_get_file_handle(rt->rtsp_hd); + FD_SET(tcp_fd, &rfds); + + tv.tv_sec = 0; + tv.tv_usec = 0; + n = select(tcp_fd + 1, &rfds, NULL, NULL, &tv); + if (n > 0) { + if (FD_ISSET(tcp_fd, &rfds)) { + RTSPMessageHeader reply; + + if (rtsp_read_reply(s, &reply, NULL, 0) < 0) + return AVERROR(EPIPE); + /* XXX: parse message */ + if (rt->state != RTSP_STATE_STREAMING) + return AVERROR(EPIPE); + } + } + + if (pkt->stream_index < 0 || pkt->stream_index >= rt->nb_rtsp_streams) + return AVERROR_INVALIDDATA; + rtsp_st = rt->rtsp_streams[pkt->stream_index]; + rtpctx = rtsp_st->transport_priv; + + pkt->stream_index = 0; + return av_write_frame(rtpctx, pkt); +} + +static int rtsp_write_close(AVFormatContext *s) +{ + RTSPState *rt = s->priv_data; + char cmd[1024]; + + snprintf(cmd, sizeof(cmd), + "TEARDOWN %s RTSP/1.0\r\n", + s->filename); + rtsp_send_cmd_async(s, cmd); + + rtsp_close_streams(s); + url_close(rt->rtsp_hd); + return 0; +} + +AVOutputFormat rtsp_muxer = { + "rtsp", + NULL_IF_CONFIG_SMALL("RTSP output format"), + NULL, + NULL, + sizeof(RTSPState), + CODEC_ID_PCM_MULAW, + CODEC_ID_NONE, + rtsp_write_header, + rtsp_write_packet, + rtsp_write_close, + .flags = AVFMT_NOFILE | AVFMT_GLOBALHEADER, +}; + -- cgit v1.2.3