ref: df60d269323a7eeb1b98de06ede657fc49a8407f
dir: /frontend/aacenc.c/
/* * FAAC - Freeware Advanced Audio Coder * Copyright (C) 2001 Menno Bakker * Copyright (C) 2002-2017 Krzysztof Nikiel * Copyright (C) 2004 Dan Villiom P. Christiansen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include <u.h> #include <libc.h> #include <bio.h> #include <faac.h> static int pesheader(Biobuf *o, int srate, int nfr, int sz) { u8int p[] = { 0x00, 0x00, 0x01, /* start code */ 0xc0, /* stream id: audio 0 */ 0, 0, /* packet length */ 0x00, /* a bunch of nothing */ 0x80, /* PTS included */ 5, /* PTS is 5 bytes */ 0, 0, 0, 0, 0, /* PTS value */ }; int plen; uvlong pts; plen = sizeof(p)-6 + sz; assert(plen < 65536); p[4] = plen >> 8; p[5] = plen; pts = nfr * 90000ULL / srate; p[9] = 1<<5 | (pts>>30)<<1 | 1; p[10] = pts>>22; p[11] = pts>>14 | 1; p[12] = pts>>7; p[13] = pts<<1 | 1; return Bwrite(o, p, sizeof(p)); } static void usage(void) { fprint(2, "usage: %s [-c CHAN] [-q QUANT] [-r RATE] [-t low|main|ltp] [-B BITRATE]\n", argv0); exits("usage"); } void main(int argc, char **argv) { int nch, srate, type, brate, sz, n, r, q, pes, frsz; ulong insamples, outsz, insz; faacEncConfigurationPtr fmt; faacEncHandle e; s16int *pcm; u8int *obuf; uvlong nfr; Biobuf out; Biobuf in; char *s; brate = 0; srate = 44100; nch = 2; type = LOW; pes = 0; q = 0; ARGBEGIN{ case 'B': if((brate = atoi(EARGF(usage()))) < 0) sysfatal("invalid bitrate %d", brate); break; case 'c': if((nch = atoi(EARGF(usage()))) < 1 || nch > 64) sysfatal("invalid number of channels %d", nch); break; case 'r': if((srate = atoi(EARGF(usage()))) < 1) sysfatal("invalid samplerate %d", srate); break; case 'p': pes = 1; break; case 'q': if((q = atoi(EARGF(usage()))) < 1) sysfatal("invalid quantization quality %d", q); break; case 't': s = EARGF(usage()); if(cistrcmp(s, "low") == 0) type = LOW; else if(cistrcmp(s, "main") == 0) type = MAIN; else if(cistrcmp(s, "ltp") == 0) type = LTP; else sysfatal("invalid type %s", s); break; default: usage(); }ARGEND if(argc != 0) usage(); if(Binit(&in, 0, OREAD) != 0 || Binit(&out, 1, OWRITE) != 0) sysfatal("io init failed"); setfcr(getfcr() & ~(FPINVAL|FPOVFL)); if((e = faacEncOpen(srate, nch, &insamples, &outsz)) == nil) sysfatal("faacEncOpen"); insz = insamples * sizeof(*pcm); if((pcm = malloc(insz)) == nil) sysfatal("memory"); if((obuf = malloc(outsz)) == nil) sysfatal("memory"); fmt = faacEncGetCurrentConfiguration(e); fmt->inputFormat = FAAC_INPUT_16BIT; fmt->mpegVersion = MPEG2; fmt->outputFormat = ADTS_STREAM; fmt->aacObjectType = type; if(brate > 0) fmt->bitRate = brate / nch; if(q > 0) fmt->quantqual = q; if(!faacEncSetConfiguration(e, fmt)) sysfatal("invalid encoder configuration"); frsz = insamples / nch; for(nfr = 0;;){ for(n = 0; n == 0 || (n & (sizeof(*pcm)-1)) != 0; n += r){ if((r = Bread(&in, pcm+n, insz-n)) <= 0) break; } if(n == 0) break; if((sz = faacEncEncode(e, pcm, n/sizeof(*pcm), obuf, outsz)) < 0) sysfatal("faacEncEncode"); if(pes){ if(pesheader(&out, srate, nfr, sz) < 0) break; n = n / sizeof(*pcm) / nch; nfr += n < frsz ? frsz : 0; } if(Bwrite(&out, obuf, sz) < 0) break; } Bflush(&out); exits(nil); }