ref: f7bc176c6bb458b631d7792dd049aaa103eeeca4
parent: 5c91e882a725ff431be5abd6272e12b274307b72
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Thu Feb 18 08:22:12 EST 2021
aac: reconstruct adts header from matroska elements
--- a/aac.c
+++ b/aac.c
@@ -4,33 +4,94 @@
#include "common.h"
#include "packet.h"
+static int ratecfg[] = {
+ 96000,
+ 88200,
+ 64000,
+ 48000,
+ 44100,
+ 32000,
+ 24000,
+ 22050,
+ 16000,
+ 12000,
+ 11025,
+ 8000,
+ 7350,
+ -1,
+ -1,
+ -1,
+};
+
int
aacpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts)
{
int i, chanc, ratei, objt, sz;
u16int x;
+ char *c;
USED(ts);
if(ctx->frid == 0){ /* set up ADTS */
- if(ctx->codec.priv.sz < 2){
- /* FIXME we could reconstruct it from codec mapping and Audio element */
- werrstr("no codec private data to construct ADTS");
- return -1;
- }
- x = ctx->codec.priv.data[0]<<8 | ctx->codec.priv.data[1];
- chanc = (x>>3) & 0xf;
- ratei = (x>>7) & 0xf;
- objt = x>>11;
- if(objt > 4){
- werrstr("AAC object type %d, can't write ADTS", objt);
- return -1;
- }
ctx->adts[0] = 0xff; /* syncword */
ctx->adts[1] = 0xf1; /* syncword, mpeg4, no crc */
+ if(ctx->codec.priv.sz >= 2){ /* prefer code private data */
+ x = ctx->codec.priv.data[0]<<8 | ctx->codec.priv.data[1];
+ chanc = (x>>3) & 0xf;
+ ratei = (x>>7) & 0xf;
+ objt = x>>11;
+ if(chanc > 7){
+ werrstr("channel config out of range: %d", chanc);
+ goto err;
+ }
+ if(ratecfg[ratei] < 1){
+ werrstr("invalid rate config: %d", ratei);
+ goto err;
+ }
+ if(objt > 4){
+ werrstr("object type out of range: %d", objt);
+ goto err;
+ }
+ }else{
+ for(ratei = 0; ratei < nelem(ratecfg) && ratecfg[ratei] != ctx->audio.samplerate; ratei++);
+ if(ratei >= nelem(ratecfg) || ratecfg[ratei] < 1){
+ werrstr("unsupported sample rate: %d", (int)ctx->audio.samplerate);
+ goto err;
+ }
+
+ c = ctx->codec.name;
+ if(memcmp(c, "A_AAC/MPEG2/", 12) == 0){
+ ctx->adts[1] |= 1<<3;
+ }else if(memcmp(c, "A_AAC/MPEG4/", 12) != 0){
+badcodec:
+ werrstr("unsupported codec: %s", c);
+ goto err;
+ }
+ if(strcmp(c+12, "MAIN") == 0)
+ objt = 1;
+ else if(memcmp(c+12, "LC", 2) == 2 && (c[14] == 0 || strcmp(c+14, "/SBR") == 0))
+ objt = 2;
+ else if(strcmp(c+12, "SSR") == 0)
+ objt = 3;
+ else if(strcmp(c+12, "LTP") == 0)
+ objt = 4;
+ else
+ goto badcodec;
+
+ if(ctx->audio.channels >= 1 && ctx->audio.channels <= 6)
+ chanc = ctx->audio.channels;
+ else if(ctx->audio.channels == 8)
+ chanc = 7;
+ else{ /* FIXME is it possible to use 0 and provide a custom channel config? */
+ werrstr("unsupported number of channels: %d", ctx->audio.channels);
+ goto err;
+ }
+ }
+
ctx->adts[2] = (objt-1)<<6 | ratei<<2 | chanc>>2; /* object type, rate, channel config */
ctx->adts[3] = (chanc&3)<<6; /* channel config */
ctx->adts[6] = 0xfc; /* fullness, number of frames */
}
+
for(i = 0; i < np; i++, p++){
sz = 7+p->sz;
ctx->adts[3] = ctx->adts[3]&(3<<6) | (sz>>11)&3; /* channels, frame length */
@@ -43,6 +104,6 @@
return 0;
err:
- werrstr("aacpacket: %r");
+ werrstr("aacpacket: adts: %r");
return -1;
}