Skip to content

Instantly share code, notes, and snippets.

@alfredh
Created November 27, 2019 20:52
Show Gist options
  • Save alfredh/90dd76b912ef86a38dee61e7252c5e71 to your computer and use it in GitHub Desktop.
Save alfredh/90dd76b912ef86a38dee61e7252c5e71 to your computer and use it in GitHub Desktop.
diff --git a/mk/modules.mk b/mk/modules.mk
index f5487f9..026c140 100644
--- a/mk/modules.mk
+++ b/mk/modules.mk
@@ -65,7 +65,7 @@ USE_L16 := 1
ifneq ($(OS),win32)
USE_AAC := $(shell [ -f $(SYSROOT)/include/fdk-aac/FDK_audio.h ] || \
- [ -f $(SYSROOT)/local/include/fdk-aac/FDK_audio.h ] || \
+ [ -f $(SYSROOT_LOCAL)/include/fdk-aac/FDK_audio.h ] || \
[ -f $(SYSROOT_ALT)/include/fdk-aac/FDK_audio.h ] && echo "yes")
USE_ALSA := $(shell [ -f $(SYSROOT)/include/alsa/asoundlib.h ] || \
[ -f $(SYSROOT_ALT)/include/alsa/asoundlib.h ] && echo "yes")
diff --git a/modules/aac/aac.c b/modules/aac/aac.c
index 64a2d28..5b94430 100644
--- a/modules/aac/aac.c
+++ b/modules/aac/aac.c
@@ -17,9 +17,9 @@
static struct aucodec aac = {
- .name = "MP4A-LATM",
+ .name = "mpeg4-generic",
.srate = AAC_SRATE,
- .crate = 90000,
+ .crate = AAC_SRATE,
.ch = AAC_CHANNELS,
.pch = 1,
.encupdh = aac_encode_update,
diff --git a/modules/aac/aac.h b/modules/aac/aac.h
index 40996c6..bf84add 100644
--- a/modules/aac/aac.h
+++ b/modules/aac/aac.h
@@ -7,7 +7,7 @@
enum {
AAC_BITRATE = 64000,
- AAC_SRATE = 48000,
+ AAC_SRATE = 16000,
AAC_CHANNELS = 1,
};
diff --git a/modules/aac/decode.c b/modules/aac/decode.c
index 9147186..066966f 100644
--- a/modules/aac/decode.c
+++ b/modules/aac/decode.c
@@ -12,6 +12,11 @@
#include "aac.h"
+struct hdr {
+ size_t bits;
+};
+
+
struct audec_state {
HANDLE_AACDECODER dec;
};
@@ -26,6 +31,44 @@ static void destructor(void *arg)
}
+/* todo: use sizeLength from SDP */
+static int hdr_decode(struct hdr *hdr, const uint8_t *p, size_t len)
+{
+ size_t bits;
+
+ if (len < 4)
+ return EPROTO;
+
+ if (p[0] != 0x00 || p[1] != 0x10)
+ return EPROTO;
+
+ bits = ntohs(*(uint16_t *)(void *)&p[2]);
+
+ if (bits < 1 || bits > 16384) {
+ warning("aac: decode: invalid bits (bits=%zu)\n", bits);
+ return EBADMSG;
+ }
+
+ if (bits/8 > len-4) {
+ warning("aac: decode: short packet (%zu > %zu)\n",
+ bits/8, len-4);
+ return ENODATA;
+ }
+
+ hdr->bits = bits;
+
+ size_t left = len - 4;
+
+ if (bits/8 != left) {
+ warning("multiple access units per packet\n");
+ re_printf("decode: bytes = %zu\n", bits/8);
+ re_printf(" left = %zu\n", len-4);
+ }
+
+ return 0;
+}
+
+
int aac_decode_update(struct audec_state **adsp, const struct aucodec *ac,
const char *fmtp)
{
@@ -45,13 +88,48 @@ int aac_decode_update(struct audec_state **adsp, const struct aucodec *ac,
if (!ads)
return ENOMEM;
- ads->dec = aacDecoder_Open(TT_MP4_LATM_MCP1, 1);
+ ads->dec = aacDecoder_Open(TT_MP4_RAW, 1);
if (!ads->dec) {
warning("aac: error opening decoder\n");
err = ENOMEM;
goto out;
}
+ info("aac: decode update: fmtp='%s'\n", fmtp);
+
+ struct pl config;
+ char config_str[64];
+ uint8_t config_bin[4];
+
+ err = re_regex(fmtp, str_len(fmtp), "config=[0-9a-f]+", &config);
+ if (err)
+ goto out;
+
+ err = pl_strcpy(&config, config_str, sizeof(config_str));
+ if (err)
+ goto out;
+
+ info("aac: config string = '%s'\n", config_str);
+
+ err = str_hex(config_bin, sizeof(config_bin), config_str);
+ if (err)
+ goto out;
+
+ info("aac: config binary = '%w'\n", config_bin, sizeof(config_bin));
+
+ UCHAR *conf = config_bin;
+ const UINT length = (UINT)sizeof(config_bin);
+
+ AAC_DECODER_ERROR error;
+
+ error = aacDecoder_ConfigRaw(ads->dec, &conf, &length);
+ if (error != AAC_DEC_OK) {
+ warning("aac: decode: config error: 0x%x\n", error);
+ err = EPROTO;
+ goto out;
+ }
+
+
out:
if (err)
mem_deref(ads);
@@ -66,14 +144,18 @@ int aac_decode_frm(struct audec_state *ads,
int fmt, void *sampv, size_t *sampc,
const uint8_t *buf, size_t len)
{
- UCHAR *pBuffer = (UCHAR *)buf;
- UINT bufferSize = (UINT)len;
- UINT valid = (UINT)len;
+ UCHAR *pBuffer;
+ UINT bufferSize;
+ UINT valid;
AAC_DECODER_ERROR error;
size_t nsamp = 0;
unsigned i;
int16_t *s16 = sampv;
int size;
+ struct hdr hdr;
+ //unsigned bits;
+ size_t bytes;
+ int err = 0;
if (!ads || !sampv || !sampc || !buf)
return EINVAL;
@@ -81,6 +163,20 @@ int aac_decode_frm(struct audec_state *ads,
if (fmt != AUFMT_S16LE)
return ENOTSUP;
+ err = hdr_decode(&hdr, buf, len);
+ if (err) {
+ warning("aac: decode: invalid header, %zu bytes (%m)\n",
+ len, err);
+ return err;
+ }
+
+ //bytes = hdr.bits / 8;
+ bytes = len - 4;
+
+ pBuffer = (UCHAR *)&buf[4];
+ bufferSize = (UINT)bytes;
+ valid = (UINT)bytes;
+
error = aacDecoder_Fill(ads->dec, &pBuffer, &bufferSize, &valid);
if (error != AAC_DEC_OK) {
warning("aac: aacDecoder_Fill() failed: 0x%x\n", error);
@@ -89,13 +185,15 @@ int aac_decode_frm(struct audec_state *ads,
size = (int)*sampc;
- for (i=0; i<8; i++) {
+ for (i=0; i<2; i++) {
CStreamInfo *info;
error = aacDecoder_DecodeFrame(ads->dec, &s16[nsamp], size, 0);
- if (error == AAC_DEC_NOT_ENOUGH_BITS)
+ if (error == AAC_DEC_NOT_ENOUGH_BITS) {
+ //warning("not enought bits\n");
break;
+ }
if (error != AAC_DEC_OK) {
warning("aac: aacDecoder_DecodeFrame() failed: 0x%x\n",
@@ -109,11 +207,17 @@ int aac_decode_frm(struct audec_state *ads,
return EBADMSG;
}
+ if (info->aot != AOT_ER_AAC_ELD) {
+ warning("aac: decode wrong aot %d\n", info->aot);
+ return EPROTO;
+ }
+#if 0
if (info->sampleRate != AAC_SRATE) {
warning("aac: decode samplerate mismatch (%d != %d)\n",
info->sampleRate, AAC_SRATE);
return EPROTO;
}
+#endif
if (info->numChannels != AAC_CHANNELS) {
warning("aac: decode channels mismatch (%d != %d)\n",
info->numChannels, AAC_CHANNELS);
diff --git a/modules/aac/encode.c b/modules/aac/encode.c
index 6c64b0c..7d5454a 100644
--- a/modules/aac/encode.c
+++ b/modules/aac/encode.c
@@ -4,6 +4,7 @@
* Copyright (C) 2010 Creytiv.com
*/
+#include <string.h>
#include <re.h>
#include <rem.h>
#include <baresip.h>
@@ -11,9 +12,9 @@
#include "aac.h"
-enum {
- FRAME_SIZE = 480
-};
+//enum {
+ //FRAME_SIZE = 480
+//};
struct auenc_state {
@@ -30,10 +31,20 @@ static void destructor(void *arg)
}
+static void hdr_encode(uint8_t *p, size_t bits)
+{
+ p[0] = 0x00;
+ p[1] = 0x10;
+
+ *(uint16_t *)(void *)&p[2] = htons(bits);
+}
+
+
int aac_encode_update(struct auenc_state **aesp, const struct aucodec *ac,
struct auenc_param *param, const char *fmtp)
{
struct auenc_state *aes;
+ AACENC_InfoStruct enc_info;
AACENC_ERROR error;
int err = 0;
@@ -59,21 +70,35 @@ int aac_encode_update(struct auenc_state **aesp, const struct aucodec *ac,
goto out;
}
- error |= aacEncoder_SetParam(aes->enc, AACENC_AOT, AOT_ER_AAC_LD);
- error |= aacEncoder_SetParam(aes->enc, AACENC_TRANSMUX,
- TT_MP4_LATM_MCP1);
+ error |= aacEncoder_SetParam(aes->enc, AACENC_AOT, AOT_ER_AAC_ELD);
error |= aacEncoder_SetParam(aes->enc, AACENC_SAMPLERATE, ac->srate);
error |= aacEncoder_SetParam(aes->enc, AACENC_CHANNELMODE,
AAC_CHANNELS);
- error |= aacEncoder_SetParam(aes->enc, AACENC_GRANULE_LENGTH,
- FRAME_SIZE);
- error |= aacEncoder_SetParam(aes->enc, AACENC_TPSUBFRAMES, 2);
error |= aacEncoder_SetParam(aes->enc, AACENC_BITRATE, AAC_BITRATE);
+ error |= aacEncoder_SetParam(aes->enc, AACENC_TRANSMUX,
+ TT_MP4_RAW);
+ error |= aacEncoder_SetParam(aes->enc, AACENC_GRANULE_LENGTH,
+ 480);
+ if (error != AACENC_OK) {
+ err = EINVAL;
+ goto out;
+ }
+
+ if (aacEncEncode(aes->enc, NULL, NULL, NULL, NULL) != AACENC_OK) {
+ fprintf(stderr, "Unable to initialize the encoder\n");
+ return 1;
+ }
+
+ error = aacEncInfo(aes->enc, &enc_info);
if (error != AACENC_OK) {
+ warning("aac: encode: could not get info (0x%x)\n", error);
err = EINVAL;
goto out;
}
+
+ info("aac: encoder config: %w\n", enc_info.confBuf, enc_info.confSize);
+
*aesp = aes;
out:
@@ -96,6 +121,7 @@ int aac_encode_frm(struct auenc_state *aes, uint8_t *buf, size_t *len,
const int16_t *s16 = sampv;
size_t total = 0;
size_t i;
+ size_t bits;
if (!aes || !buf || !len || !sampv)
return EINVAL;
@@ -103,9 +129,16 @@ int aac_encode_frm(struct auenc_state *aes, uint8_t *buf, size_t *len,
if (fmt != AUFMT_S16LE)
return ENOTSUP;
- for (i=0; i<sampc; i+=FRAME_SIZE) {
+#if 0
+ *len = 0;
+ return 0;
+#endif
+
+ uint8_t *payload = buf + 4;
+
+ for (i=0; i<2; i++) {
- in_size = sizeof(int16_t) * FRAME_SIZE;
+ in_size = sizeof(int16_t) * (UINT)sampc;
in_buf.numBufs = 1;
in_buf.bufs = (void **)&s16;
@@ -116,12 +149,12 @@ int aac_encode_frm(struct auenc_state *aes, uint8_t *buf, size_t *len,
out_size = (INT)*len;
out_buf.numBufs = 1;
- out_buf.bufs = (void **)&buf;
+ out_buf.bufs = (void **)&(payload);
out_buf.bufferIdentifiers = &out_id;
out_buf.bufSizes = &out_size;
out_buf.bufElSizes = &out_elem_size;
- in_args.numInSamples = FRAME_SIZE;
+ in_args.numInSamples = (UINT)sampc;
in_args.numAncBytes = 0;
error = aacEncEncode(aes->enc, &in_buf, &out_buf, &in_args,
@@ -131,13 +164,30 @@ int aac_encode_frm(struct auenc_state *aes, uint8_t *buf, size_t *len,
return EINVAL;
}
- s16 += FRAME_SIZE;
+ s16 += out_args.numInSamples;
+ sampc -= out_args.numInSamples;
- buf += out_args.numOutBytes;
- total += out_args.numOutBytes;
+ payload += out_args.numOutBytes;
+ total += out_args.numOutBytes;
+
+ re_printf(".... numInSamples: %d\n", out_args.numInSamples);
+ re_printf(" numOutBytes: %d\n", out_args.numOutBytes);
+
+ if (sampc == 0)
+ break;
+ }
+
+ if (total == 0) {
+ *len = 0;
+ return 0;
}
- *len = total;
+ bits = total * 8;
+
+ hdr_encode(buf, bits);
+
+
+ *len = 4 + total;
return 0;
}
diff --git a/modules/aac/sdp.c b/modules/aac/sdp.c
index 60613f2..357e930 100644
--- a/modules/aac/sdp.c
+++ b/modules/aac/sdp.c
@@ -10,6 +10,12 @@
#include "aac.h"
+enum {
+ STREAMTYPE_AUDIO = 0x05,
+ PROFILE = 76,
+};
+
+
static unsigned param_value(const char *fmtp, const char *name)
{
struct pl pl, val;
@@ -29,6 +35,8 @@ static unsigned param_value(const char *fmtp, const char *name)
int aac_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt,
bool offer, void *arg)
{
+ const char *config = "F8EE2000";
+
(void)offer;
(void)arg;
@@ -36,8 +44,14 @@ int aac_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt,
return 0;
return mbuf_printf(mb, "a=fmtp:%s "
- "profile-level-id=24;object=%i;bitrate=%u\r\n",
- fmt->id, AOT_ER_AAC_LD, AAC_BITRATE);
+
+ "streamType=%d"
+ ";profile-level-id=%d"
+ ";config=%s"
+ ";mode=AAC-hbr"
+
+ "\r\n",
+ fmt->id, STREAMTYPE_AUDIO, PROFILE, config);
}
@@ -46,11 +60,20 @@ bool aac_fmtp_cmp(const char *lfmtp, const char *rfmtp, void *arg)
(void)lfmtp;
(void)arg;
+ info("aac: compare: %s\n", rfmtp);
+
+#if 0
if (param_value(rfmtp, "object") != AOT_ER_AAC_LD)
return false;
if (param_value(rfmtp, "bitrate") != AAC_BITRATE)
return false;
+#endif
return true;
}
+
+
+/*
+a=fmtp:96 config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5.
+ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment