Mercurial > libavformat.hg
changeset 5695:25062326d2f9 libavformat
Add an RTSP muxer
author | mstorsjo |
---|---|
date | Mon, 22 Feb 2010 21:28:19 +0000 |
parents | 70bd52594e2b |
children | bbe5b963f736 |
files | Makefile allformats.c avformat.h rtsp.c rtspenc.c |
diffstat | 5 files changed, 137 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Mon Feb 22 21:20:30 2010 +0000 +++ b/Makefile Mon Feb 22 21:28:19 2010 +0000 @@ -210,6 +210,7 @@ rtpenc_h264.o \ avc.o OBJS-$(CONFIG_RTSP_DEMUXER) += rtsp.o +OBJS-$(CONFIG_RTSP_MUXER) += rtsp.o rtspenc.o OBJS-$(CONFIG_SDP_DEMUXER) += rtsp.o \ rdt.o \ rtp.o \
--- a/allformats.c Mon Feb 22 21:20:30 2010 +0000 +++ b/allformats.c Mon Feb 22 21:28:19 2010 +0000 @@ -172,7 +172,7 @@ REGISTER_MUXDEMUX (ROQ, roq); REGISTER_DEMUXER (RPL, rpl); REGISTER_MUXER (RTP, rtp); - REGISTER_DEMUXER (RTSP, rtsp); + REGISTER_MUXDEMUX (RTSP, rtsp); REGISTER_DEMUXER (SDP, sdp); #if CONFIG_SDP_DEMUXER av_register_rtp_dynamic_payload_handlers();
--- a/avformat.h Mon Feb 22 21:20:30 2010 +0000 +++ b/avformat.h Mon Feb 22 21:28:19 2010 +0000 @@ -22,7 +22,7 @@ #define AVFORMAT_AVFORMAT_H #define LIBAVFORMAT_VERSION_MAJOR 52 -#define LIBAVFORMAT_VERSION_MINOR 52 +#define LIBAVFORMAT_VERSION_MINOR 53 #define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
--- a/rtsp.c Mon Feb 22 21:20:30 2010 +0000 +++ b/rtsp.c Mon Feb 22 21:28:19 2010 +0000 @@ -691,7 +691,7 @@ return 0; } -#if CONFIG_RTSP_DEMUXER +#if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER static int rtsp_probe(AVProbeData *p) { if (av_strstart(p->filename, "rtsp:", NULL)) @@ -1533,7 +1533,9 @@ } return err; } +#endif +#if CONFIG_RTSP_DEMUXER static int rtsp_read_header(AVFormatContext *s, AVFormatParameters *ap) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rtspenc.c Mon Feb 22 21:28:19 2010 +0000 @@ -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 <sys/time.h> +#if HAVE_SYS_SELECT_H +#include <sys/select.h> +#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, +}; +