[FFmpeg-cvslog] rtpdec: Split mpegts parsing to a normal depacketizer

Martin Storsjö git at videolan.org
Mon Jan 21 13:57:09 CET 2013


ffmpeg | branch: master | Martin Storsjö <martin at martin.st> | Thu Jan 17 14:34:59 2013 +0200| [2326558d5277ec87ba6d607a01ec6acfc51c694c] | committer: Martin Storsjö

rtpdec: Split mpegts parsing to a normal depacketizer

This gets rid of a number of special cases from the common rtpdec
code.

Signed-off-by: Martin Storsjö <martin at martin.st>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=2326558d5277ec87ba6d607a01ec6acfc51c694c
---

 libavformat/Makefile         |    1 +
 libavformat/rtpdec.c         |   56 ++++------------------
 libavformat/rtpdec.h         |    6 ---
 libavformat/rtpdec_formats.h |    1 +
 libavformat/rtpdec_mpegts.c  |  106 ++++++++++++++++++++++++++++++++++++++++++
 libavformat/rtsp.c           |   16 +++++--
 6 files changed, 131 insertions(+), 55 deletions(-)

diff --git a/libavformat/Makefile b/libavformat/Makefile
index 111380a..a8a7530 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -35,6 +35,7 @@ OBJS-$(CONFIG_RTPDEC)                    += rdt.o                       \
                                             rtpdec_jpeg.o               \
                                             rtpdec_latm.o               \
                                             rtpdec_mpeg4.o              \
+                                            rtpdec_mpegts.o             \
                                             rtpdec_qcelp.o              \
                                             rtpdec_qdm2.o               \
                                             rtpdec_qt.o                 \
diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c
index 28b4033..7fa0a93 100644
--- a/libavformat/rtpdec.c
+++ b/libavformat/rtpdec.c
@@ -24,7 +24,6 @@
 #include "libavutil/time.h"
 #include "libavcodec/get_bits.h"
 #include "avformat.h"
-#include "mpegts.h"
 #include "network.h"
 #include "srtp.h"
 #include "url.h"
@@ -76,6 +75,7 @@ void av_register_rtp_dynamic_payload_handlers(void)
     ff_register_dynamic_payload_handler(&ff_mp4a_latm_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_mp4v_es_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_mpeg4_generic_dynamic_handler);
+    ff_register_dynamic_payload_handler(&ff_mpegts_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfv_handler);
     ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfa_handler);
     ff_register_dynamic_payload_handler(&ff_qcelp_dynamic_handler);
@@ -481,8 +481,7 @@ int ff_rtp_send_rtcp_feedback(RTPDemuxContext *s, URLContext *fd,
 
 /**
  * open a new RTP parse context for stream 'st'. 'st' can be NULL for
- * MPEG2-TS streams to indicate that they should be demuxed inside the
- * rtp demux (otherwise AV_CODEC_ID_MPEG2TS packets are returned)
+ * MPEG2-TS streams.
  */
 RTPDemuxContext *ff_rtp_parse_open(AVFormatContext *s1, AVStream *st,
                                    int payload_type, int queue_size)
@@ -499,13 +498,7 @@ RTPDemuxContext *ff_rtp_parse_open(AVFormatContext *s1, AVStream *st,
     s->st                  = st;
     s->queue_size          = queue_size;
     rtp_init_statistics(&s->statistics, 0);
-    if (!strcmp(ff_rtp_enc_name(payload_type), "MP2T")) {
-        s->ts = ff_mpegts_parse_open(s->ic);
-        if (s->ts == NULL) {
-            av_free(s);
-            return NULL;
-        }
-    } else if (st) {
+    if (st) {
         switch (st->codec->codec_id) {
         case AV_CODEC_ID_MPEG1VIDEO:
         case AV_CODEC_ID_MPEG2VIDEO:
@@ -591,7 +584,7 @@ static int rtp_parse_packet_internal(RTPDemuxContext *s, AVPacket *pkt,
                                      const uint8_t *buf, int len)
 {
     unsigned int ssrc, h;
-    int payload_type, seq, ret, flags = 0;
+    int payload_type, seq, flags = 0;
     int ext;
     AVStream *st;
     uint32_t timestamp;
@@ -645,26 +638,11 @@ static int rtp_parse_packet_internal(RTPDemuxContext *s, AVPacket *pkt,
         buf += ext;
     }
 
-    if (!st) {
-        /* specific MPEG2-TS demux support */
-        ret = ff_mpegts_parse_packet(s->ts, pkt, buf, len);
-        /* The only error that can be returned from ff_mpegts_parse_packet
-         * is "no more data to return from the provided buffer", so return
-         * AVERROR(EAGAIN) for all errors */
-        if (ret < 0)
-            return AVERROR(EAGAIN);
-        if (ret < len) {
-            s->read_buf_size = FFMIN(len - ret, sizeof(s->buf));
-            memcpy(s->buf, buf + ret, s->read_buf_size);
-            s->read_buf_index = 0;
-            return 1;
-        }
-        return 0;
-    } else if (s->handler && s->handler->parse_packet) {
+    if (s->handler && s->handler->parse_packet) {
         rv = s->handler->parse_packet(s->ic, s->dynamic_protocol_context,
                                       s->st, pkt, &timestamp, buf, len, seq,
                                       flags);
-    } else {
+    } else if (st) {
         /* At this point, the RTP header has been stripped;
          * This is ASSUMING that there is only 1 CSRC, which isn't wise. */
         switch (st->codec->codec_id) {
@@ -704,6 +682,8 @@ static int rtp_parse_packet_internal(RTPDemuxContext *s, AVPacket *pkt,
         }
 
         pkt->stream_index = st->index;
+    } else {
+        return AVERROR(EINVAL);
     }
 
     // now perform timestamp things....
@@ -786,7 +766,7 @@ static int rtp_parse_one_packet(RTPDemuxContext *s, AVPacket *pkt,
                                 uint8_t **bufptr, int len)
 {
     uint8_t *buf = bufptr ? *bufptr : NULL;
-    int ret, flags = 0;
+    int flags = 0;
     uint32_t timestamp;
     int rv = 0;
 
@@ -797,7 +777,7 @@ static int rtp_parse_one_packet(RTPDemuxContext *s, AVPacket *pkt,
         if (s->prev_ret <= 0)
             return rtp_parse_queued_packet(s, pkt);
         /* return the next packets, if any */
-        if (s->st && s->handler && s->handler->parse_packet) {
+        if (s->handler && s->handler->parse_packet) {
             /* timestamp should be overwritten by parse_packet, if not,
              * the packet is left with pts == AV_NOPTS_VALUE */
             timestamp = RTP_NOTS_VALUE;
@@ -806,19 +786,6 @@ static int rtp_parse_one_packet(RTPDemuxContext *s, AVPacket *pkt,
                                                  flags);
             finalize_packet(s, pkt, timestamp);
             return rv;
-        } else {
-            // TODO: Move to a dynamic packet handler (like above)
-            if (s->read_buf_index >= s->read_buf_size)
-                return AVERROR(EAGAIN);
-            ret = ff_mpegts_parse_packet(s->ts, pkt, s->buf + s->read_buf_index,
-                                         s->read_buf_size - s->read_buf_index);
-            if (ret < 0)
-                return AVERROR(EAGAIN);
-            s->read_buf_index += ret;
-            if (s->read_buf_index < s->read_buf_size)
-                return 1;
-            else
-                return 0;
         }
     }
 
@@ -894,9 +861,6 @@ int ff_rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
 void ff_rtp_parse_close(RTPDemuxContext *s)
 {
     ff_rtp_reset_packet_queue(s);
-    if (!strcmp(ff_rtp_enc_name(s->payload_type), "MP2T")) {
-        ff_mpegts_parse_close(s->ts);
-    }
     ff_srtp_free(&s->srtp);
     av_free(s);
 }
diff --git a/libavformat/rtpdec.h b/libavformat/rtpdec.h
index eaef993..a93963a 100644
--- a/libavformat/rtpdec.h
+++ b/libavformat/rtpdec.h
@@ -160,9 +160,6 @@ struct RTPDemuxContext {
     int64_t  unwrapped_timestamp;
     int64_t  range_start_offset;
     int max_payload_size;
-    struct MpegTSContext *ts;   /* only used for MP2T payloads */
-    int read_buf_index;
-    int read_buf_size;
     /* used to send back RTCP RR */
     char hostname[256];
 
@@ -192,9 +189,6 @@ struct RTPDemuxContext {
     unsigned int last_octet_count;
     int64_t last_feedback_time;
 
-    /* buffer for partially parsed packets */
-    uint8_t buf[RTP_MAX_PACKET_LENGTH];
-
     /* dynamic payload stuff */
     const RTPDynamicProtocolHandler *handler;
     PayloadContext *dynamic_protocol_context;
diff --git a/libavformat/rtpdec_formats.h b/libavformat/rtpdec_formats.h
index e449ddf..6c07791 100644
--- a/libavformat/rtpdec_formats.h
+++ b/libavformat/rtpdec_formats.h
@@ -50,6 +50,7 @@ extern RTPDynamicProtocolHandler ff_jpeg_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler;
+extern RTPDynamicProtocolHandler ff_mpegts_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_ms_rtp_asf_pfa_handler;
 extern RTPDynamicProtocolHandler ff_ms_rtp_asf_pfv_handler;
 extern RTPDynamicProtocolHandler ff_qcelp_dynamic_handler;
diff --git a/libavformat/rtpdec_mpegts.c b/libavformat/rtpdec_mpegts.c
new file mode 100644
index 0000000..e2c8977
--- /dev/null
+++ b/libavformat/rtpdec_mpegts.c
@@ -0,0 +1,106 @@
+/*
+ * RTP MPEG2TS depacketizer
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "mpegts.h"
+#include "rtpdec_formats.h"
+
+struct PayloadContext {
+    struct MpegTSContext *ts;
+    int read_buf_index;
+    int read_buf_size;
+    uint8_t buf[RTP_MAX_PACKET_LENGTH];
+};
+
+static PayloadContext *mpegts_new_context(void)
+{
+    return av_mallocz(sizeof(PayloadContext));
+}
+
+static void mpegts_free_context(PayloadContext *data)
+{
+    if (!data)
+        return;
+    if (data->ts)
+        ff_mpegts_parse_close(data->ts);
+    av_free(data);
+}
+
+static int mpegts_init(AVFormatContext *ctx, int st_index, PayloadContext *data)
+{
+    data->ts = ff_mpegts_parse_open(ctx);
+    if (!data->ts)
+        return AVERROR(ENOMEM);
+    return 0;
+}
+
+static int mpegts_handle_packet(AVFormatContext *ctx, PayloadContext *data,
+                                AVStream *st, AVPacket *pkt, uint32_t *timestamp,
+                                const uint8_t *buf, int len, uint16_t seq,
+                                int flags)
+{
+    int ret;
+
+    // We don't want to use the RTP timestamps at all. If the mpegts demuxer
+    // doesn't set any pts/dts, the generic rtpdec code shouldn't try to
+    // fill it in either, since the mpegts and RTP timestamps are in totally
+    // different ranges.
+    *timestamp = RTP_NOTS_VALUE;
+
+    if (!data->ts)
+        return AVERROR(EINVAL);
+
+    if (!buf) {
+        if (data->read_buf_index >= data->read_buf_size)
+            return AVERROR(EAGAIN);
+        ret = ff_mpegts_parse_packet(data->ts, pkt, data->buf + data->read_buf_index,
+                                     data->read_buf_size - data->read_buf_index);
+        if (ret < 0)
+            return AVERROR(EAGAIN);
+        data->read_buf_index += ret;
+        if (data->read_buf_index < data->read_buf_size)
+            return 1;
+        else
+            return 0;
+    }
+
+    ret = ff_mpegts_parse_packet(data->ts, pkt, buf, len);
+    /* The only error that can be returned from ff_mpegts_parse_packet
+     * is "no more data to return from the provided buffer", so return
+     * AVERROR(EAGAIN) for all errors */
+    if (ret < 0)
+        return AVERROR(EAGAIN);
+    if (ret < len) {
+        data->read_buf_size = FFMIN(len - ret, sizeof(data->buf));
+        memcpy(data->buf, buf + ret, data->read_buf_size);
+        data->read_buf_index = 0;
+        return 1;
+    }
+    return 0;
+}
+
+RTPDynamicProtocolHandler ff_mpegts_dynamic_handler = {
+    .codec_type        = AVMEDIA_TYPE_DATA,
+    .parse_packet      = mpegts_handle_packet,
+    .alloc             = mpegts_new_context,
+    .init              = mpegts_init,
+    .free              = mpegts_free_context,
+    .static_payload_id = 33,
+};
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 9a657fb..1ce28d6 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -180,7 +180,8 @@ static void init_rtp_handler(RTPDynamicProtocolHandler *handler,
 {
     if (!handler)
         return;
-    codec->codec_id          = handler->codec_id;
+    if (codec)
+        codec->codec_id          = handler->codec_id;
     rtsp_st->dynamic_handler = handler;
     if (handler->alloc) {
         rtsp_st->dynamic_protocol_context = handler->alloc();
@@ -382,8 +383,17 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
 
         if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
             /* no corresponding stream */
-            if (rt->transport == RTSP_TRANSPORT_RAW && !rt->ts && CONFIG_RTPDEC)
-                rt->ts = ff_mpegts_parse_open(s);
+            if (rt->transport == RTSP_TRANSPORT_RAW) {
+                if (!rt->ts && CONFIG_RTPDEC)
+                    rt->ts = ff_mpegts_parse_open(s);
+            } else {
+                RTPDynamicProtocolHandler *handler;
+                handler = ff_rtp_handler_find_by_id(
+                              rtsp_st->sdp_payload_type, AVMEDIA_TYPE_DATA);
+                init_rtp_handler(handler, rtsp_st, NULL);
+                if (handler && handler->init)
+                    handler->init(s, -1, rtsp_st->dynamic_protocol_context);
+            }
         } else if (rt->server_type == RTSP_SERVER_WMS &&
                    codec_type == AVMEDIA_TYPE_DATA) {
             /* RTX stream, a stream that carries all the other actual



More information about the ffmpeg-cvslog mailing list