summaryrefslogtreecommitdiff
path: root/libavformat/sdp.c
diff options
context:
space:
mode:
authorJuan Carlos Rodriguez <ing.juancarlosrodriguez@hotmail.com>2011-05-18 15:00:03 +0300
committerMartin Storsjö <martin@martin.st>2011-06-10 10:49:20 +0300
commit0832122880fa50e66dfd62eb6aa5c814f83f68d9 (patch)
treed6584051af4edd2d15edd1c99a0524abc5aa67a3 /libavformat/sdp.c
parentcb7c11cc9e7e05c819fff487a3f486f11ab4b860 (diff)
rtpenc: MP4A-LATM payload support
This is enabled with an AVOption on the RTP muxer. The SDP generator looks for a latm flag in the rtpflags field. Signed-off-by: Martin Storsjö <martin@martin.st>
Diffstat (limited to 'libavformat/sdp.c')
-rw-r--r--libavformat/sdp.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/libavformat/sdp.c b/libavformat/sdp.c
index b996bf65f5..92690f58a3 100644
--- a/libavformat/sdp.c
+++ b/libavformat/sdp.c
@@ -23,7 +23,9 @@
#include "libavutil/base64.h"
#include "libavutil/dict.h"
#include "libavutil/parseutils.h"
+#include "libavutil/opt.h"
#include "libavcodec/xiph.h"
+#include "libavcodec/mpeg4audio.h"
#include "avformat.h"
#include "internal.h"
#include "avc.h"
@@ -300,6 +302,71 @@ xiph_fail:
return NULL;
}
+static int latm_context2profilelevel(AVCodecContext *c)
+{
+ /* MP4A-LATM
+ * The RTP payload format specification is described in RFC 3016
+ * The encoding specifications are provided in ISO/IEC 14496-3 */
+
+ int profile_level = 0x2B;
+
+ /* TODO: AAC Profile only supports AAC LC Object Type.
+ * Different Object Types should implement different Profile Levels */
+
+ if (c->sample_rate <= 24000) {
+ if (c->channels <= 2)
+ profile_level = 0x28; // AAC Profile, Level 1
+ } else if (c->sample_rate <= 48000) {
+ if (c->channels <= 2) {
+ profile_level = 0x29; // AAC Profile, Level 2
+ } else if (c->channels <= 5) {
+ profile_level = 0x2A; // AAC Profile, Level 4
+ }
+ } else if (c->sample_rate <= 96000) {
+ if (c->channels <= 5) {
+ profile_level = 0x2B; // AAC Profile, Level 5
+ }
+ }
+
+ return profile_level;
+}
+
+static char *latm_context2config(AVCodecContext *c)
+{
+ /* MP4A-LATM
+ * The RTP payload format specification is described in RFC 3016
+ * The encoding specifications are provided in ISO/IEC 14496-3 */
+
+ uint8_t config_byte[6];
+ int rate_index;
+ char *config;
+
+ for (rate_index = 0; rate_index < 16; rate_index++)
+ if (ff_mpeg4audio_sample_rates[rate_index] == c->sample_rate)
+ break;
+ if (rate_index == 16) {
+ av_log(c, AV_LOG_ERROR, "Unsupported sample rate\n");
+ return NULL;
+ }
+
+ config_byte[0] = 0x40;
+ config_byte[1] = 0;
+ config_byte[2] = 0x20 | rate_index;
+ config_byte[3] = c->channels << 4;
+ config_byte[4] = 0x3f;
+ config_byte[5] = 0xc0;
+
+ config = av_malloc(6*2+1);
+ if (!config) {
+ av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n");
+ return NULL;
+ }
+ ff_data_to_hex(config, config_byte, 6, 1);
+ config[12] = 0;
+
+ return config;
+}
+
static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, int payload_type, AVFormatContext *fmt)
{
char *config = NULL;
@@ -335,6 +402,16 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
payload_type, config ? config : "");
break;
case CODEC_ID_AAC:
+ if (fmt && fmt->oformat->priv_class &&
+ av_opt_flag_is_set(fmt->priv_data, "rtpflags", "latm")) {
+ config = latm_context2config(c);
+ if (!config)
+ return NULL;
+ av_strlcatf(buff, size, "a=rtpmap:%d MP4A-LATM/%d/%d\r\n"
+ "a=fmtp:%d profile-level-id=%d;cpresent=0;config=%s\r\n",
+ payload_type, c->sample_rate, c->channels,
+ payload_type, latm_context2profilelevel(c), config);
+ } else {
if (c->extradata_size) {
config = extradata2config(c);
} else {
@@ -353,6 +430,7 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
"indexdeltalength=3%s\r\n",
payload_type, c->sample_rate, c->channels,
payload_type, config);
+ }
break;
case CODEC_ID_PCM_S16BE:
if (payload_type >= RTP_PT_PRIVATE)