All pastes #1603556 Raw Edit

ffmpeg patch mp4a-latm

public diff v1 · immutable
#1603556 ·published 2009-10-08 07:54 UTC
rendered paste body
diff --git a/libavformat/avformat.h b/libavformat/avformat.hindex 16170d4..5b3fa29 100644--- a/libavformat/avformat.h+++ b/libavformat/avformat.h@@ -566,6 +566,7 @@ typedef struct AVFormatContext { #define AVFMT_FLAG_GENPTS       0x0001 ///< Generate missing pts even if it requires parsing future frames. #define AVFMT_FLAG_IGNIDX       0x0002 ///< Ignore index. #define AVFMT_FLAG_NONBLOCK     0x0004 ///< Do not block when reading packets from input.+#define AVFMT_FLAG_LATM         0x0008 ///< Generate LATM rtp stream for mpeg4audio codec.      int loop_input;     /** decoding: size of data to probe; encoding: unused. */diff --git a/libavformat/avio.c b/libavformat/avio.cindex b6329a9..0e1c847 100644--- a/libavformat/avio.c+++ b/libavformat/avio.c@@ -87,6 +87,7 @@ int url_open_protocol (URLContext **puc, struct URLProtocol *up,     uc->flags = flags;     uc->is_streamed = 0; /* default = not streamed */     uc->max_packet_size = 0; /* default: stream file */+    uc->rtp_payload_type = -1; /* default: depends on codec */     err = up->url_open(uc, filename, flags);     if (err < 0) {         av_free(uc);@@ -232,6 +233,11 @@ int url_get_max_packet_size(URLContext *h)     return h->max_packet_size; } +int url_get_rtp_payload_type(URLContext *h)+{+    return h->rtp_payload_type;+}+ void url_get_filename(URLContext *h, char *buf, int buf_size) {     av_strlcpy(buf, h->filename, buf_size);diff --git a/libavformat/avio.h b/libavformat/avio.hindex d44e300..f8078e5 100644--- a/libavformat/avio.h+++ b/libavformat/avio.h@@ -49,6 +49,7 @@ typedef struct URLContext {     int flags;     int is_streamed;  /**< true if streamed (no seek possible), default = false */     int max_packet_size;  /**< if non zero, the stream is packetized with this max packet size */+    int rtp_payload_type;  /**< if non zero, the rtp stream is packetized with this payload type */     void *priv_data;     char *filename; /**< specified filename */ } URLContext;@@ -94,6 +95,17 @@ int url_get_file_handle(URLContext *h);  * @return maximum packet size in bytes  */ int url_get_max_packet_size(URLContext *h);++/**+ * Return the rtp payload type associated to packetized file+ * handle. If the file is not packetized (stream like HTTP or file on+ * disk), then -1 is returned.+ *+ * @param h file handle+ * @return rtp payload type+ */+int url_get_rtp_payload_type(URLContext *h);+ void url_get_filename(URLContext *h, char *buf, int buf_size);  /**@@ -198,6 +210,7 @@ typedef struct {     int write_flag;  /**< true if open for writing */     int is_streamed;     int max_packet_size;+    int rtp_payload_type;     unsigned long checksum;     unsigned char *checksum_ptr;     unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);@@ -355,6 +368,16 @@ URLContext *url_fileno(ByteIOContext *s);  */ int url_fget_max_packet_size(ByteIOContext *s); +/**+ * Return the payload type, associated to rtp packetized buffered file+ * handle. If the file is not packetized (stream like http or file on+ * disk), then -1 is returned.+ *+ * @param s buffered file handle+ * @return rtp payload type+ */+int url_fget_rtp_payload_type(ByteIOContext *s);+ int url_open_buf(ByteIOContext **s, uint8_t *buf, int buf_size, int flags);  /** return the written or read size */diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.cindex f270139..d734efc 100644--- a/libavformat/aviobuf.c+++ b/libavformat/aviobuf.c@@ -52,6 +52,7 @@ int init_put_byte(ByteIOContext *s,     s->error = 0;     s->is_streamed = 0;     s->max_packet_size = 0;+    s->rtp_payload_type = -1;     s->update_checksum= NULL;     if(!read_packet && !write_flag){         s->pos = buffer_size;@@ -529,10 +530,11 @@ uint64_t ff_get_v(ByteIOContext *bc){ int url_fdopen(ByteIOContext **s, URLContext *h) {     uint8_t *buffer;-    int buffer_size, max_packet_size;+    int buffer_size, max_packet_size, rtp_payload_type;       max_packet_size = url_get_max_packet_size(h);+    rtp_payload_type = url_get_rtp_payload_type(h);     if (max_packet_size) {         buffer_size = max_packet_size; /* no need to bufferize more than one packet */     } else {@@ -557,6 +559,7 @@ int url_fdopen(ByteIOContext **s, URLContext *h)     }     (*s)->is_streamed = h->is_streamed;     (*s)->max_packet_size = max_packet_size;+    (*s)->rtp_payload_type = rtp_payload_type;     if(h->prot) {         (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause;         (*s)->read_seek  = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek;@@ -666,6 +669,11 @@ int url_fget_max_packet_size(ByteIOContext *s)     return s->max_packet_size; } +int url_fget_rtp_payload_type(ByteIOContext *s)+{+    return s->rtp_payload_type;+}+ int av_url_read_fpause(ByteIOContext *s, int pause) {     if (!s->read_pause)diff --git a/libavformat/options.c b/libavformat/options.cindex 795d02b..b96d1dd 100644--- a/libavformat/options.c+++ b/libavformat/options.c@@ -46,6 +46,7 @@ static const AVOption options[]={ {"fflags", NULL, OFFSET(flags), FF_OPT_TYPE_FLAGS, DEFAULT, INT_MIN, INT_MAX, D|E, "fflags"}, {"ignidx", "ignore index", 0, FF_OPT_TYPE_CONST, AVFMT_FLAG_IGNIDX, INT_MIN, INT_MAX, D, "fflags"}, {"genpts", "generate pts", 0, FF_OPT_TYPE_CONST, AVFMT_FLAG_GENPTS, INT_MIN, INT_MAX, D, "fflags"},+{"latm", "packetize mpeg4audio to LATM (RFC 3016)", 0, FF_OPT_TYPE_CONST, AVFMT_FLAG_LATM, INT_MIN, INT_MAX, D, "fflags"}, #if LIBAVFORMAT_VERSION_INT < (53<<16) {"track", " set the track number", OFFSET(track), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, E}, {"year", "set the year", OFFSET(year), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, E},diff --git a/libavformat/rtp_aac.c b/libavformat/rtp_aac.cindex e19b286..8852857 100644--- a/libavformat/rtp_aac.c+++ b/libavformat/rtp_aac.c@@ -83,3 +83,45 @@ void ff_rtp_send_aac(AVFormatContext *s1, const uint8_t *buff, int size)         }     } }+++++/* latm muxer */+void ff_rtp_send_aac_latm(AVFormatContext *s1, const uint8_t *buff, int size)+{+    RTPMuxContext *s = s1->priv_data;+    int len, max_packet_size;+    uint8_t *p = s->buf;+    int latmhdrsize;++    /* skip ADTS header, if present */+    if ((s1->streams[0]->codec->extradata_size) == 0) {+        size -= 7;+        buff += 7;+    }++    latmhdrsize = size/0xff + 1;+    max_packet_size = s->max_payload_size - latmhdrsize;+    s->timestamp = s->cur_timestamp;+    +    while (size > 0) {+	len = FFMIN(size, max_packet_size);+	memcpy(p + latmhdrsize, buff, len);+	if(latmhdrsize) {+	    /* write latm header in 1st packet */+	    int tmp = size;+	    while (tmp > 0xfe){+		*p = 0xff;+		p++;+		tmp -= 0xff;+	    }+	    *p = tmp;+	}+	+        ff_rtp_send_data(s1, s->buf, len + latmhdrsize, (len == size));+        size -= len;+        buff += len;+	latmhdrsize = 0;+    }+}diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.cindex 2a0770e..d9788c4 100644--- a/libavformat/rtpenc.c+++ b/libavformat/rtpenc.c@@ -83,9 +83,12 @@ static int rtp_write_header(AVFormatContext *s1)         return -1;     } -    payload_type = ff_rtp_get_payload_type(st->codec);-    if (payload_type < 0)-        payload_type = RTP_PT_PRIVATE; /* private payload type */+    payload_type = url_fget_rtp_payload_type(s1->pb);+    if (payload_type < 0) {+	payload_type = ff_rtp_get_payload_type(st->codec);+	if (payload_type < 0)+	    payload_type = RTP_PT_PRIVATE; /* private payload type */+    }     s->payload_type = payload_type;  // following 2 FIXMEs could be set based on the current time, there is normally no info leak, as RTP will likely be transmitted immediately@@ -383,7 +386,10 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)         ff_rtp_send_mpegvideo(s1, buf1, size);         break;     case CODEC_ID_AAC:-        ff_rtp_send_aac(s1, buf1, size);+        if(s1->flags & AVFMT_FLAG_LATM)+	    ff_rtp_send_aac_latm(s1, buf1, size);+	else+            ff_rtp_send_aac(s1, buf1, size);         break;     case CODEC_ID_AMR_NB:     case CODEC_ID_AMR_WB:diff --git a/libavformat/rtpenc.h b/libavformat/rtpenc.hindex 5710160..905667f 100644--- a/libavformat/rtpenc.h+++ b/libavformat/rtpenc.h@@ -59,6 +59,7 @@ void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m); void ff_rtp_send_h264(AVFormatContext *s1, const uint8_t *buf1, int size); void ff_rtp_send_h263(AVFormatContext *s1, const uint8_t *buf1, int size); void ff_rtp_send_aac(AVFormatContext *s1, const uint8_t *buff, int size);+void ff_rtp_send_aac_latm(AVFormatContext *s1, const uint8_t *buff, int size); void ff_rtp_send_amr(AVFormatContext *s1, const uint8_t *buff, int size); void ff_rtp_send_mpegvideo(AVFormatContext *s1, const uint8_t *buf1, int size); diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.cindex 9d80ddf..ac0b3bd 100644--- a/libavformat/rtpproto.c+++ b/libavformat/rtpproto.c@@ -98,7 +98,7 @@ static void url_add_option(char *buf, int buf_size, const char *fmt, ...) static void build_udp_url(char *buf, int buf_size,                           const char *hostname, int port,                           int local_port, int ttl,-                          int max_packet_size)+                          int max_packet_size, int rtp_payload_type) {     snprintf(buf, buf_size, "udp://%s:%d", hostname, port);     if (local_port >= 0)@@ -107,6 +107,8 @@ static void build_udp_url(char *buf, int buf_size,         url_add_option(buf, buf_size, "ttl=%d", ttl);     if (max_packet_size >=0)         url_add_option(buf, buf_size, "pkt_size=%d", max_packet_size);+    if (rtp_payload_type >=0)+        url_add_option(buf, buf_size, "payload_type=%d", rtp_payload_type); }  /**@@ -120,7 +122,7 @@ static void build_udp_url(char *buf, int buf_size, static int rtp_open(URLContext *h, const char *uri, int flags) {     RTPContext *s;-    int port, is_output, ttl, local_port, max_packet_size;+    int port, is_output, ttl, local_port, max_packet_size, rtp_payload_type;     char hostname[256];     char buf[1024];     char path[1024];@@ -139,6 +141,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)     ttl = -1;     local_port = -1;     max_packet_size = -1;+    rtp_payload_type = -1;      p = strchr(uri, '?');     if (p) {@@ -151,10 +154,13 @@ static int rtp_open(URLContext *h, const char *uri, int flags)         if (find_info_tag(buf, sizeof(buf), "pkt_size", p)) {             max_packet_size = strtol(buf, NULL, 10);         }+        if (find_info_tag(buf, sizeof(buf), "payload_type", p)) {+            rtp_payload_type = strtol(buf, NULL, 10);+        }     }      build_udp_url(buf, sizeof(buf),-                  hostname, port, local_port, ttl, max_packet_size);+                  hostname, port, local_port, ttl, max_packet_size, rtp_payload_type);     if (url_open(&s->rtp_hd, buf, flags) < 0)         goto fail;     local_port = udp_get_local_port(s->rtp_hd);@@ -163,7 +169,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)     /* well, should suppress localport in path */      build_udp_url(buf, sizeof(buf),-                  hostname, port + 1, local_port + 1, ttl, max_packet_size);+                  hostname, port + 1, local_port + 1, ttl, max_packet_size, rtp_payload_type);     if (url_open(&s->rtcp_hd, buf, flags) < 0)         goto fail; @@ -172,6 +178,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)     s->rtp_fd = url_get_file_handle(s->rtp_hd);     s->rtcp_fd = url_get_file_handle(s->rtcp_hd); +    h->rtp_payload_type = url_get_rtp_payload_type(s->rtp_hd);     h->max_packet_size = url_get_max_packet_size(s->rtp_hd);     h->is_streamed = 1;     return 0;diff --git a/libavformat/sdp.c b/libavformat/sdp.cindex 67b10a2..cd0d443 100644--- a/libavformat/sdp.c+++ b/libavformat/sdp.c@@ -20,6 +20,8 @@  #include "libavutil/avstring.h" #include "libavutil/base64.h"+#include "libavcodec/get_bits.h"+#include "libavcodec/mpeg4audio.h" #include "avformat.h" #include "internal.h" #include "avc.h"@@ -163,10 +165,46 @@ static char *extradata2config(AVCodecContext *c)     return config; } -static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, int payload_type)+static char *extradata2latmConfig(AVCodecContext *c) {-    char *config = NULL;+    char *config;+    unsigned char binConfig[6];+    int sample_rate_index, channels_index, objecttype;+    GetBitContext gb;+    +    /* this for aac+, we have to look at extradata to detect AAC (not he-aac) samplerate and channels */+    init_get_bits(&gb, c->extradata, c->extradata_size * 8);+    objecttype = get_bits(&gb, 5) - 1;+    sample_rate_index = get_bits(&gb, 4);+    channels_index = get_bits(&gb, 4);+    //*channels = ff_mpeg4audio_channels[channels_index];+    //*sample_rate = ff_mpeg4audio_sample_rates[sample_rate_index];+    +    +    binConfig[0]=0x40;+    binConfig[1]=0;+    binConfig[2]=0x20|sample_rate_index;+    binConfig[3]=channels_index<<4;+    binConfig[4]=0x3f;+    binConfig[5]=0xc0;+    +    config = av_malloc(10 + 12);+    if (config == NULL) {+        av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n");+        return NULL;+    }+    +    memcpy(config, "; config=", 9);+    ff_data_to_hex(config + 9, binConfig, 6);+    config[9 + 12] = 0; +    return config;+}++static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, int payload_type, int latm)+{+    char *config = NULL;+         switch (c->codec_id) {         case CODEC_ID_H264:             if (c->extradata_size) {@@ -192,7 +230,11 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,             break;         case CODEC_ID_AAC:             if (c->extradata_size) {-                config = extradata2config(c);+		if(latm) {+		    config = extradata2latmConfig(c/*, &sample_rate, &channels*/);+		} else {+		    config = extradata2config(c);+		}             } else {                 /* FIXME: maybe we can forge config information based on the                  *        codec parameters...@@ -203,12 +245,20 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,             if (config == NULL) {                 return NULL;             }-            av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n"-                                    "a=fmtp:%d profile-level-id=1;"-                                    "mode=AAC-hbr;sizelength=13;indexlength=3;"-                                    "indexdeltalength=3%s\r\n",-                                     payload_type, c->sample_rate, c->channels,-                                     payload_type, config);+                if(latm) {+                    av_strlcatf(buff, size, "a=rtpmap:%d MP4A-LATM/%d/%d\r\n"+                                            "a=fmtp:%d profile-level-id=15;"+                                            "object=2; cpresent=0%s\r\n",+                                             payload_type, /*sample_rate, channels*/ c->sample_rate, c->channels,+                                             payload_type, config);+                } else {+                    av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n"+                                            "a=fmtp:%d profile-level-id=1;"+					    "mode=AAC-hbr;sizelength=13;indexlength=3;"+					    "indexdeltalength=3%s\r\n",+					     payload_type, c->sample_rate, c->channels,+					     payload_type, config);+		}             break;         case CODEC_ID_PCM_S16BE:             if (payload_type >= 96)@@ -250,15 +300,9 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,     return buff; } -static void sdp_write_media(char *buff, int size, AVCodecContext *c, const char *dest_addr, int port, int ttl)+static void sdp_write_media(char *buff, int size, AVCodecContext *c, const char *dest_addr, int port, int ttl, int payload_type, int latm) {     const char *type;-    int payload_type;--    payload_type = ff_rtp_get_payload_type(c);-    if (payload_type < 0) {-        payload_type = 96;  /* FIXME: how to assign a private pt? rtp.c is broken too */-    }      switch (c->codec_type) {         case CODEC_TYPE_VIDEO   : type = "video"      ; break;@@ -273,14 +317,14 @@ static void sdp_write_media(char *buff, int size, AVCodecContext *c, const char         av_strlcatf(buff, size, "b=AS:%d\r\n", c->bit_rate / 1000);     } -    sdp_write_media_attributes(buff, size, c, payload_type);+    sdp_write_media_attributes(buff, size, c, payload_type, latm); }  int avf_sdp_create(AVFormatContext *ac[], int n_files, char *buff, int size) {     AVMetadataTag *title = av_metadata_get(ac[0]->metadata, "title", NULL, 0);     struct sdp_session_level s;-    int i, j, port, ttl;+    int i, j, port, ttl, payload_type;     char dst[32];      memset(buff, 0, size);@@ -306,9 +350,17 @@ int avf_sdp_create(AVFormatContext *ac[], int n_files, char *buff, int size)             port = sdp_get_address(dst, sizeof(dst), &ttl, ac[i]->filename);         }         for (j = 0; j < ac[i]->nb_streams; j++) {+            payload_type = url_fget_rtp_payload_type(ac[i]->pb);+            if (payload_type < 0) {+                payload_type = ff_rtp_get_payload_type(ac[i]->streams[j]->codec);+                if (payload_type < 0)+                    payload_type = RTP_PT_PRIVATE; /* private payload type */+            }+									             sdp_write_media(buff, size,                                   ac[i]->streams[j]->codec, dst[0] ? dst : NULL,-                                  (port > 0) ? port + j * 2 : 0, ttl);+                                  (port > 0) ? port + j * 2 : 0, ttl,+				  payload_type, ac[i]->flags & AVFMT_FLAG_LATM ? 1 : 0);             if (port <= 0) {                 av_strlcatf(buff, size,                                    "a=control:streamid=%d\r\n", i + j);diff --git a/libavformat/udp.c b/libavformat/udp.cindex a89de00..89a8c4e 100644--- a/libavformat/udp.c+++ b/libavformat/udp.c@@ -383,6 +383,9 @@ static int udp_open(URLContext *h, const char *uri, int flags)         if (find_info_tag(buf, sizeof(buf), "buffer_size", p)) {             s->buffer_size = strtol(buf, NULL, 10);         }+        if (find_info_tag(buf, sizeof(buf), "payload_type", p)) {+            h->rtp_payload_type = strtol(buf, NULL, 10);+        }     }      /* fill the dest addr */