[Ffmpeg-cvslog] r6798 - in trunk/libavformat: allformats.c allformats.h rtp.c rtp.h rtp_internal.h rtsp.c

gpoirier subversion
Thu Oct 26 20:36:04 CEST 2006


Author: gpoirier
Date: Thu Oct 26 20:36:03 2006
New Revision: 6798

Added:
   trunk/libavformat/rtp_internal.h
Modified:
   trunk/libavformat/allformats.c
   trunk/libavformat/allformats.h
   trunk/libavformat/rtp.c
   trunk/libavformat/rtp.h
   trunk/libavformat/rtsp.c

Log:
Add support for H264 over RTP
Patch by Ryan Martell % rdm4 A martellventures P com %
Original thread:
Date: Oct 9, 2006 4:55 PM
Subject: [Ffmpeg-devel] RTP patches & RFC
Actual committed patch:
Date: Oct 26, 2006 4:29 PM


Modified: trunk/libavformat/allformats.c
==============================================================================
--- trunk/libavformat/allformats.c	(original)
+++ trunk/libavformat/allformats.c	Thu Oct 26 20:36:03 2006
@@ -416,6 +416,7 @@
 #ifdef CONFIG_REDIR_DEMUXER
     av_register_input_format(&redir_demuxer);
 #endif
+    av_register_rtp_dynamic_payload_handlers();
 #endif /* CONFIG_NETWORK */
 #ifdef CONFIG_SEGAFILM_DEMUXER
     av_register_input_format(&segafilm_demuxer);

Modified: trunk/libavformat/allformats.h
==============================================================================
--- trunk/libavformat/allformats.h	(original)
+++ trunk/libavformat/allformats.h	Thu Oct 26 20:36:03 2006
@@ -170,6 +170,9 @@
 
 /* rtsp.c */
 int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f);
+/* rtp.c */
+void av_register_rtp_dynamic_payload_handlers();
+
 
 #if 0
 extern AVImageFormat pnm_image_format;

Modified: trunk/libavformat/rtp.c
==============================================================================
--- trunk/libavformat/rtp.c	(original)
+++ trunk/libavformat/rtp.c	Thu Oct 26 20:36:03 2006
@@ -33,6 +33,13 @@
 #endif
 #include <netdb.h>
 
+#include "rtp_internal.h"
+
+//#define RTP_H264
+#ifdef RTP_H264
+    #include "rtp_h264.h"
+#endif
+
 //#define DEBUG
 
 
@@ -179,42 +186,26 @@
   {-1, "",           CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1}
 };
 
-AVRtpDynamicPayloadType_t AVRtpDynamicPayloadTypes[]=
+/* statistics functions */
+RTPDynamicProtocolHandler *RTPFirstDynamicPayloadHandler= NULL;
+
+static RTPDynamicProtocolHandler mp4v_es_handler= {"MP4V-ES", CODEC_TYPE_VIDEO, CODEC_ID_MPEG4};
+static RTPDynamicProtocolHandler mpeg4_generic_handler= {"mpeg4-generic", CODEC_TYPE_AUDIO, CODEC_ID_MPEG4AAC};
+
+static void register_dynamic_payload_handler(RTPDynamicProtocolHandler *handler)
 {
-    {"MP4V-ES", CODEC_TYPE_VIDEO, CODEC_ID_MPEG4},
-    {"mpeg4-generic", CODEC_TYPE_AUDIO, CODEC_ID_MPEG4AAC},
-    {"", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE}
-};
+    handler->next= RTPFirstDynamicPayloadHandler;
+    RTPFirstDynamicPayloadHandler= handler;
+}
 
-struct RTPDemuxContext {
-    AVFormatContext *ic;
-    AVStream *st;
-    int payload_type;
-    uint32_t ssrc;
-    uint16_t seq;
-    uint32_t timestamp;
-    uint32_t base_timestamp;
-    uint32_t cur_timestamp;
-    int max_payload_size;
-    MpegTSContext *ts; /* only used for MP2T payloads */
-    int read_buf_index;
-    int read_buf_size;
-
-    /* rtcp sender statistics receive */
-    int64_t last_rtcp_ntp_time;
-    int64_t first_rtcp_ntp_time;
-    uint32_t last_rtcp_timestamp;
-    /* rtcp sender statistics */
-    unsigned int packet_count;
-    unsigned int octet_count;
-    unsigned int last_octet_count;
-    int first_packet;
-    /* buffer for output */
-    uint8_t buf[RTP_MAX_PACKET_LENGTH];
-    uint8_t *buf_ptr;
-    /* special infos for au headers parsing */
-    rtp_payload_data_t *rtp_payload_data;
-};
+void av_register_rtp_dynamic_payload_handlers()
+{
+    register_dynamic_payload_handler(&mp4v_es_handler);
+    register_dynamic_payload_handler(&mpeg4_generic_handler);
+#ifdef RTP_H264
+    register_dynamic_payload_handler(&ff_h264_dynamic_handler);
+#endif
+}
 
 int rtp_get_codec_info(AVCodecContext *codec, int payload_type)
 {
@@ -271,6 +262,7 @@
  * open a new RTP parse context for stream 'st'. 'st' can be NULL for
  * MPEG2TS streams to indicate that they should be demuxed inside the
  * rtp demux (otherwise CODEC_ID_MPEG2TS packets are returned)
+ * TODO: change this to not take rtp_payload data, and use the new dynamic payload system.
  */
 RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, int payload_type, rtp_payload_data_t *rtp_payload_data)
 {
@@ -298,6 +290,9 @@
         case CODEC_ID_MP2:
         case CODEC_ID_MP3:
         case CODEC_ID_MPEG4:
+#ifdef RTP_H264
+        case CODEC_ID_H264:
+#endif
             st->need_parsing = 1;
             break;
         default:
@@ -374,6 +369,9 @@
 
     if (!buf) {
         /* return the next packets, if any */
+        if(s->st && s->parse_packet) {
+            return s->parse_packet(s, pkt, 0, NULL, 0);
+        } else {
         if (s->read_buf_index >= s->read_buf_size)
             return -1;
         ret = mpegts_parse_packet(s->ts, pkt, s->buf + s->read_buf_index,
@@ -385,6 +383,7 @@
             return 1;
         else
             return 0;
+        }
     }
 
     if (len < 12)
@@ -428,6 +427,7 @@
             return 1;
         }
     } else {
+        // at this point, the RTP header has been stripped;  This is ASSUMING that there is only 1 CSRC, which in't wise.
         switch(st->codec->codec_id) {
         case CODEC_ID_MP2:
             /* better than nothing: skip mpeg audio RTP header */
@@ -457,8 +457,12 @@
             memcpy(pkt->data, buf, len);
             break;
         default:
+            if(s->parse_packet) {
+                return s->parse_packet(s, pkt, timestamp, buf, len);
+            } else {
             av_new_packet(pkt, len);
             memcpy(pkt->data, buf, len);
+            }
             break;
         }
 
@@ -511,6 +515,7 @@
 
 void rtp_parse_close(RTPDemuxContext *s)
 {
+    // TODO: fold this into the protocol specific data fields.
     if (!strcmp(AVRtpPayloadTypes[s->payload_type].enc_name, "MP2T")) {
         mpegts_parse_close(s->ts);
     }

Modified: trunk/libavformat/rtp.h
==============================================================================
--- trunk/libavformat/rtp.h	(original)
+++ trunk/libavformat/rtp.h	Thu Oct 26 20:36:03 2006
@@ -89,13 +89,6 @@
     int audio_channels;
 } AVRtpPayloadType_t;
 
-typedef struct AVRtpDynamicPayloadType_s /* payload type >= 96 */
-{
-    const char enc_name[50]; /* XXX: still why 50 ? ;-) */
-    enum CodecType codec_type;
-    enum CodecID codec_id;
-} AVRtpDynamicPayloadType_t;
-
 #if 0
 typedef enum {
   RTCP_SR   = 200,
@@ -122,6 +115,4 @@
 #endif
 
 extern AVRtpPayloadType_t AVRtpPayloadTypes[];
-extern AVRtpDynamicPayloadType_t AVRtpDynamicPayloadTypes[];
-
 #endif /* RTP_H */

Added: trunk/libavformat/rtp_internal.h
==============================================================================
--- (empty file)
+++ trunk/libavformat/rtp_internal.h	Thu Oct 26 20:36:03 2006
@@ -0,0 +1,86 @@
+/*
+ * RTP definitions
+ * Copyright (c) 2006 Ryan Martell <rdm4 at martellventures.com>
+ *
+ * This library 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 of the License, or (at your option) any later version.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+// this is a bit of a misnomer, because rtp & rtsp internal structures and prototypes are in here.
+#ifndef RTP_INTERNAL_H
+#define RTP_INTERNAL_H
+
+typedef int (*DynamicPayloadPacketHandlerProc) (struct RTPDemuxContext * s,
+                                                AVPacket * pkt,
+                                                uint32_t timestamp,
+                                                const uint8_t * buf,
+                                                int len);
+
+typedef struct RTPDynamicProtocolHandler_s {
+    // fields from AVRtpDynamicPayloadType_s
+    const char enc_name[50];    /* XXX: still why 50 ? ;-) */
+    enum CodecType codec_type;
+    enum CodecID codec_id;
+
+    // may be null
+    int (*parse_sdp_a_line) (AVStream * stream,
+                             void *protocol_data,
+                             const char *line); ///< Parse the a= line from the sdp field
+    void *(*open) (); ///< allocate any data needed by the rtp parsing for this dynamic data.
+    void (*close)(void *protocol_data); ///< free any data needed by the rtp parsing for this dynamic data.
+    DynamicPayloadPacketHandlerProc parse_packet; ///< parse handler for this dynamic packet.
+
+    struct RTPDynamicProtocolHandler_s *next;
+} RTPDynamicProtocolHandler;
+
+// moved out of rtp.c, because the h264 decoder needs to know about this structure..
+struct RTPDemuxContext {
+    AVFormatContext *ic;
+    AVStream *st;
+    int payload_type;
+    uint32_t ssrc;
+    uint16_t seq;
+    uint32_t timestamp;
+    uint32_t base_timestamp;
+    uint32_t cur_timestamp;
+    int max_payload_size;
+    struct MpegTSContext *ts;   /* only used for MP2T payloads */
+    int read_buf_index;
+    int read_buf_size;
+
+    /* rtcp sender statistics receive */
+    int64_t last_rtcp_ntp_time;    // TODO: move into statistics
+    int64_t first_rtcp_ntp_time;   // TODO: move into statistics
+    uint32_t last_rtcp_timestamp;  // TODO: move into statistics
+
+    /* rtcp sender statistics */
+    unsigned int packet_count;     // TODO: move into statistics (outgoing)
+    unsigned int octet_count;      // TODO: move into statistics (outgoing)
+    unsigned int last_octet_count; // TODO: move into statistics (outgoing)
+    int first_packet;
+    /* buffer for output */
+    uint8_t buf[RTP_MAX_PACKET_LENGTH];
+    uint8_t *buf_ptr;
+
+    /* special infos for au headers parsing */
+    rtp_payload_data_t *rtp_payload_data; // TODO: Move into dynamic payload handlers
+
+    /* dynamic payload stuff */
+    DynamicPayloadPacketHandlerProc parse_packet;     ///< This is also copied from the dynamic protocol handler structure
+    void *dynamic_protocol_context;        ///< This is a copy from the values setup from the sdp parsing, in rtsp.c don't free me.
+};
+
+extern RTPDynamicProtocolHandler *RTPFirstDynamicPayloadHandler;
+#endif /* RTP_INTERNAL_H */
+

Modified: trunk/libavformat/rtsp.c
==============================================================================
--- trunk/libavformat/rtsp.c	(original)
+++ trunk/libavformat/rtsp.c	Thu Oct 26 20:36:03 2006
@@ -30,6 +30,8 @@
 # include "barpainet.h"
 #endif
 
+#include "rtp_internal.h"
+
 //#define DEBUG
 //#define DEBUG_RTP_TCP
 
@@ -69,6 +71,9 @@
     int sdp_ttl;  /* IP TTL (from SDP content - not used in RTSP) */
     int sdp_payload_type; /* payload type - only used in SDP */
     rtp_payload_data_t rtp_payload_data; /* rtp payload parsing infos from SDP */
+
+    RTPDynamicProtocolHandler *dynamic_handler; ///< Only valid if it's a dynamic protocol. (This is the handler structure)
+    void *dynamic_protocol_context; ///< Only valid if it's a dynamic protocol. (This is any private data associated with the dynamic protocol)
 } RTSPStream;
 
 static int rtsp_read_play(AVFormatContext *s);
@@ -142,7 +147,7 @@
 
 /* parse the rtpmap description: <codec_name>/<clock_rate>[/<other
    params>] */
-static int sdp_parse_rtpmap(AVCodecContext *codec, int payload_type, const char *p)
+static int sdp_parse_rtpmap(AVCodecContext *codec, RTSPStream *rtsp_st, int payload_type, const char *p)
 {
     char buf[256];
     int i;
@@ -153,12 +158,18 @@
        see if we can handle this kind of payload */
     get_word_sep(buf, sizeof(buf), "/", &p);
     if (payload_type >= RTP_PT_PRIVATE) {
-        /* We are in dynmaic payload type case ... search into AVRtpDynamicPayloadTypes[] */
-        for (i = 0; AVRtpDynamicPayloadTypes[i].codec_id != CODEC_ID_NONE; ++i)
-            if (!strcmp(buf, AVRtpDynamicPayloadTypes[i].enc_name) && (codec->codec_type == AVRtpDynamicPayloadTypes[i].codec_type)) {
-                codec->codec_id = AVRtpDynamicPayloadTypes[i].codec_id;
+        RTPDynamicProtocolHandler *handler= RTPFirstDynamicPayloadHandler;
+        while(handler) {
+            if (!strcmp(buf, handler->enc_name) && (codec->codec_type == handler->codec_type)) {
+                codec->codec_id = handler->codec_id;
+                rtsp_st->dynamic_handler= handler;
+                if(handler->open) {
+                    rtsp_st->dynamic_protocol_context= handler->open();
+                }
                 break;
             }
+            handler= handler->next;
+        }
     } else {
         /* We are in a standard case ( from http://www.iana.org/assignments/rtp-parameters) */
         /* search into AVRtpPayloadTypes[] */
@@ -440,7 +451,7 @@
                 st = s->streams[i];
                 rtsp_st = st->priv_data;
                 if (rtsp_st->sdp_payload_type == payload_type) {
-                    sdp_parse_rtpmap(st->codec, payload_type, p);
+                    sdp_parse_rtpmap(st->codec, rtsp_st, payload_type, p);
                 }
             }
         } else if (strstart(p, "fmtp:", &p)) {
@@ -451,7 +462,13 @@
                 st = s->streams[i];
                 rtsp_st = st->priv_data;
                 if (rtsp_st->sdp_payload_type == payload_type) {
+                    if(rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) {
+                        if(!rtsp_st->dynamic_handler->parse_sdp_a_line(st, rtsp_st->dynamic_protocol_context, buf)) {
+                            sdp_parse_fmtp(st, p);
+                        }
+                    } else {
                     sdp_parse_fmtp(st, p);
+                    }
                 }
             }
         }
@@ -788,6 +805,8 @@
                 rtp_parse_close(rtsp_st->rtp_ctx);
             if (rtsp_st->rtp_handle)
                 url_close(rtsp_st->rtp_handle);
+            if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context)
+                rtsp_st->dynamic_handler->close(rtsp_st->dynamic_protocol_context);
         }
         av_free(rtsp_st);
     }
@@ -980,6 +999,11 @@
         if (!rtsp_st->rtp_ctx) {
             err = AVERROR_NOMEM;
             goto fail;
+        } else {
+            if(rtsp_st->dynamic_handler) {
+                rtsp_st->rtp_ctx->dynamic_protocol_context= rtsp_st->dynamic_protocol_context;
+                rtsp_st->rtp_ctx->parse_packet= rtsp_st->dynamic_handler->parse_packet;
+            }
         }
     }
 
@@ -1326,6 +1350,11 @@
         if (!rtsp_st->rtp_ctx) {
             err = AVERROR_NOMEM;
             goto fail;
+        } else {
+            if(rtsp_st->dynamic_handler) {
+                rtsp_st->rtp_ctx->dynamic_protocol_context= rtsp_st->dynamic_protocol_context;
+                rtsp_st->rtp_ctx->parse_packet= rtsp_st->dynamic_handler->parse_packet;
+            }
         }
     }
     return 0;




More information about the ffmpeg-cvslog mailing list