[FFmpeg-devel] [PATCH] avformat: Add rtp_mpegtsraw (MPEG-TS RAW Stream output)

Andreas Håkon andreas.hakon at protonmail.com
Mon Jan 9 21:59:37 EET 2017


Hi,

This patch adds a new MUXER named "rtp_mpegtsraw". This new muxer works with
the "mpegtsraw" input demuxer. The objective is enable direct bitstream
input-output of MPEG-TS for RTP+FEC. Using the recent support for Pro-MPEG CoP
FEC protocol, you can now use FFmpeg for streaming any UDP/RTP MPEG-TS stream.

Example:

ffmpeg -f mpegtsraw -i udp://239.8.8.8:12345 -map 0 -c copy -f rtp_mpegtsraw -fec prompeg=l=8:d=8 rtp://239.9.9.9:10000

In this example FFmpeg reads from the network one stream in UDP o RTP format
from the multicast address 239.8.8.8:12345 and re-encapsulates it without
remuxing to the multicast address 239.9.9.9 using RTP+FEC
(ports 10000 & 10001 are for the base RTP, port 10002 are for "row" and 10004
are for "column").

If you ever have had the need to do use FFmpeg in plain "bitstream" mode
with MPEG-TS streams, you have luck: know you can!

Please comment,
Andreas Håkon


Signed-off-by: Andreas Håkon <andreas.hakon at protonmail.com>
---
ffmpeg.c | 1 +
libavformat/allformats.c | 1 +
libavformat/mpegts.c | 2 +-
libavformat/rtpenc.c | 6 ++++++
libavformat/rtpenc_mpegts.c | 48 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/ffmpeg.c b/ffmpeg.c
index b85c314..838f4d2 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -3228,6 +3228,7 @@ static int init_output_stream_encode(OutputStream *ost)
}
break;
case AVMEDIA_TYPE_DATA:
+ av_log(NULL, AV_LOG_TRACE, "Using bitstream with codec %s\n", avcodec_get_name(enc_ctx->codec_id));
break;
default:
abort();
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 6a79b75..b58e178 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -269,6 +269,7 @@ void av_register_all(void)
REGISTER_MUXDEMUX(RSO, rso);
REGISTER_MUXDEMUX(RTP, rtp);
REGISTER_MUXER (RTP_MPEGTS, rtp_mpegts);
+ REGISTER_MUXER (RTP_MPEGTSRAW, rtp_mpegtsraw);
REGISTER_MUXDEMUX(RTSP, rtsp);
REGISTER_DEMUXER (SAMI, sami);
REGISTER_MUXDEMUX(SAP, sap);
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index 0aa0ad7..2c23a05 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -2663,7 +2663,7 @@ static int mpegts_read_header(AVFormatContext *s)
return AVERROR(ENOMEM);
avpriv_set_pts_info(st, 60, 1, 27000000);
st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
- st->codecpar->codec_id = AV_CODEC_ID_MPEG2TS;
+ st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;

/* we iterate until we find two PCRs to estimate the bitrate */
pcr_pid = -1;
diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c
index efa63a5..e465501 100644
--- a/libavformat/rtpenc.c
+++ b/libavformat/rtpenc.c
@@ -82,6 +82,7 @@ static int is_supported(enum AVCodecID id)
case AV_CODEC_ID_MJPEG:
case AV_CODEC_ID_SPEEX:
case AV_CODEC_ID_OPUS:
+ case AV_CODEC_ID_BIN_DATA:
return 1;
default:
return 0;
@@ -160,6 +161,7 @@ static int rtp_write_header(AVFormatContext *s1)
avpriv_set_pts_info(st, 32, 1, 90000);
}
s->buf_ptr = s->buf;
+ av_log(s1, AV_LOG_TRACE, "Using RTP muxer with codec %s\n", avcodec_get_name(st->codecpar->codec_id));
switch(st->codecpar->codec_id) {
case AV_CODEC_ID_MP2:
case AV_CODEC_ID_MP3:
@@ -571,6 +573,7 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
ff_rtp_send_amr(s1, pkt->data, size);
break;
case AV_CODEC_ID_MPEG2TS:
+ case AV_CODEC_ID_BIN_DATA:
rtp_send_mpegts_raw(s1, pkt->data, size);
break;
case AV_CODEC_ID_DIRAC:
@@ -624,6 +627,9 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
/* Intentional fallthrough */
default:
/* better than nothing : send the codec raw data */
+ av_log(s1, AV_LOG_WARNING,
+ "RTP output is unsupported with codec %s\n",
+ avcodec_get_name(st->codecpar->codec_id));
rtp_send_raw(s1, pkt->data, size);
break;
}
diff --git a/libavformat/rtpenc_mpegts.c b/libavformat/rtpenc_mpegts.c
index 7af02e0..1e7177c 100644
--- a/libavformat/rtpenc_mpegts.c
+++ b/libavformat/rtpenc_mpegts.c
@@ -143,6 +143,43 @@ static int rtp_mpegts_write_packet(AVFormatContext *s, AVPacket *pkt)
return ret;
}

+static int rtp_mpegtsraw_write_close(AVFormatContext *s)
+{
+ rtp_mpegts_write_close(s);
+ return 0;
+}
+
+static int rtp_mpegtsraw_write_header(AVFormatContext *s)
+{
+ struct MuxChain *chain = s->priv_data;
+ int ret = AVERROR(ENOMEM);
+
+ ret = rtp_mpegts_write_header(s);
+
+ if (ret < 0)
+ return ret;
+
+ if (chain->mpegts_ctx) {
+ av_write_trailer(chain->mpegts_ctx);
+ ffio_free_dyn_buf(&chain->mpegts_ctx->pb);
+ avformat_free_context(chain->mpegts_ctx);
+
+ chain->mpegts_ctx = NULL;
+ }
+
+ return ret;
+}
+
+static int rtp_mpegtsraw_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ struct MuxChain *chain = s->priv_data;
+ int ret = 0;
+
+ ret = av_write_frame(chain->rtp_ctx, pkt);
+
+ return ret;
+}
+
AVOutputFormat ff_rtp_mpegts_muxer = {
.name = "rtp_mpegts",
.long_name = NULL_IF_CONFIG_SMALL("RTP/mpegts output format"),
@@ -153,3 +190,14 @@ AVOutputFormat ff_rtp_mpegts_muxer = {
.write_packet = rtp_mpegts_write_packet,
.write_trailer = rtp_mpegts_write_close,
};
+
+AVOutputFormat ff_rtp_mpegtsraw_muxer = {
+ .name = "rtp_mpegtsraw",
+ .long_name = NULL_IF_CONFIG_SMALL("RTP/mpegts RAW-Stream output format"),
+ .priv_data_size = sizeof(struct MuxChain),
+ .audio_codec = AV_CODEC_ID_AAC,
+ .video_codec = AV_CODEC_ID_MPEG4,
+ .write_header = rtp_mpegtsraw_write_header,
+ .write_packet = rtp_mpegtsraw_write_packet,
+ .write_trailer = rtp_mpegtsraw_write_close,
+};

--


More information about the ffmpeg-devel mailing list