ref: 49dc43fd64bb77001494be6721380895f1bba971
dir: /aac.c/
#include <u.h> #include <libc.h> #include <bio.h> #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 key) { int i, chanc, ratei, objt, sz; u16int x; char *c; USED(ts, key); if(ctx->frid == 0){ /* set up ADTS */ 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 */ ctx->adts[4] = (sz>>3) & 0xff; /* frame length */ ctx->adts[5] = (sz&7)<<5 | 0x1f; /* frame length, fullness */ if(Bwrite(out, ctx->adts, 7) != 7 || Bwrite(out, p->data, p->sz) != p->sz) goto err; } ctx->frid++; return 0; err: werrstr("aacpacket: adts: %r"); return -1; }