ref: fdff41e7018a893b62e37214199e58972228650c
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 Biobuf out; static int done(void*, char*) { Bflush(&out); return 0; } static void usage(void) { fprint(2, "usage: %s [-b] [-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, i, nobuffer; ulong insamples, outsz, insz; faacEncConfigurationPtr fmt; u8int *obuf, ph[7+1+4+8]; faacEncHandle e; s16int *pcm; Biobuf in; uvlong ns; char *s; nobuffer = 0; brate = 0; srate = 44100; nch = 2; type = LOW; q = 0; ARGBEGIN{ case 'b': nobuffer = 1; break; 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 '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"); atnotify(done, 1); ns = nsec(); for(;;){ for(n = 0; n == 0 || (n & (sizeof(*pcm)-1)) != 0; n += r){ if((r = Bread(&in, pcm+n, insz-n)) < 0) sysfatal("read: %r"); if(r == 0) break; } if(n == 0) break; if((sz = faacEncEncode(e, pcm, n/sizeof(*pcm), obuf, outsz)) < 0) sysfatal("faacEncEncode"); else if(sz == 0) continue; if(ns != 0){ memmove(ph, obuf, 7); /* set frame size */ ph[3] &= ~3; ph[4] = sizeof(ph)>>3; ph[5] = (ph[5]&~0xe0) | sizeof(ph)<<5; ph[7] = 0x04; /* DSE */ ph[8] = 'n'; ph[9] = 's'; ph[10] = 'e'; ph[11] = 'c'; for(i = 0; i < 8; i++, ns >>= 8) ph[12+i] = ns; ns = 0; if(Bwrite(&out, ph, sizeof(ph)) < 0) break; Bflush(&out); } if(Bwrite(&out, obuf, sz) < 0) break; if(nobuffer) Bflush(&out); } Bflush(&out); exits(nil); }