@@ -40,6 +40,7 @@ static int is_supported(enum CodecID id)
case CODEC_ID_MPEG2VIDEO:
case CODEC_ID_MPEG4:
case CODEC_ID_AAC:
+ case CODEC_ID_AAC_LATM:
case CODEC_ID_MP2:
case CODEC_ID_MP3:
case CODEC_ID_PCM_ALAW:
@@ -406,6 +407,9 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
case CODEC_ID_AAC:
ff_rtp_send_aac(s1, pkt->data, size);
break;
+ case CODEC_ID_AAC_LATM:
+ rtp_send_raw(s1, pkt->data, size);
+ break;
case CODEC_ID_AMR_NB:
case CODEC_ID_AMR_WB:
ff_rtp_send_amr(s1, pkt->data, size);
@@ -23,6 +23,7 @@
#include "libavutil/base64.h"
#include "libavutil/parseutils.h"
#include "libavcodec/xiph.h"
+#include "libavcodec/mpeg4audio.h"
#include "avformat.h"
#include "internal.h"
#include "avc.h"
@@ -299,6 +300,59 @@ 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 */
+
+ char *config;
+
+ if (!c->extradata) {
+ av_log(c, AV_LOG_ERROR, "No LATM extradata present.\n");
+ return NULL;
+ }
+
+ config = av_malloc(c->extradata_size*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, c->extradata, c->extradata_size, 1);
+ config[c->extradata_size*2] = 0;
+
+ return config;
+}
+
static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, int payload_type)
{
char *config = NULL;
@@ -353,6 +407,15 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
payload_type, c->sample_rate, c->channels,
payload_type, config);
break;
+ case CODEC_ID_AAC_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);
+ break;
case CODEC_ID_PCM_S16BE:
if (payload_type >= RTP_PT_PRIVATE)
av_strlcatf(buff, size, "a=rtpmap:%d L16/%d/%d\r\n",
From: Juan Carlos Rodriguez <ing.juancarlosrodriguez@hotmail.com> --- libavformat/rtpenc.c | 4 +++ libavformat/sdp.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 0 deletions(-)