142 lines
4.2 KiB
C
142 lines
4.2 KiB
C
#include"node.h"
|
|
|
|
#include<fdk-aac/aacenc_lib.h>
|
|
#include<string.h>
|
|
#include"img.h"
|
|
#include<stdlib.h>
|
|
#include<stdio.h>
|
|
#include<assert.h>
|
|
#include<stdbool.h>
|
|
#include<math.h>
|
|
|
|
typedef struct {
|
|
CHiPubNode pub;
|
|
|
|
HANDLE_AACENCODER enc;
|
|
|
|
int16_t *pcmbuf;
|
|
size_t pcmbufSz;
|
|
|
|
uint64_t timestamp; // In samples (48000 Hz)
|
|
|
|
AACENC_InfoStruct info;
|
|
bool extradataSent;
|
|
} Internal;
|
|
|
|
static int encodeaac_perform(CHiPubNode *pub) {
|
|
Internal *n = (Internal*) pub;
|
|
|
|
CHiImage *newpcm = CHi_Crawl(&pub->sinks[0])->data.sample;
|
|
if(newpcm && newpcm->width) {
|
|
n->pcmbuf = realloc(n->pcmbuf, sizeof(*n->pcmbuf) * (n->pcmbufSz + newpcm->width * newpcm->channels));
|
|
memcpy(n->pcmbuf + n->pcmbufSz, newpcm->data8, newpcm->width * newpcm->channels * sizeof(*n->pcmbuf));
|
|
/*for(size_t z = 0; z < newpcm->width; z++) {
|
|
static size_t lol = 0;
|
|
n->pcmbuf[n->pcmbufSz + z] = sinf(lol++ * 440.0 / 48000 * 2.0 * 3.14159) * 15000;
|
|
}*/
|
|
n->pcmbufSz += newpcm->width * newpcm->channels;
|
|
}
|
|
|
|
CHiBSFrames *frames = calloc(1, sizeof(*frames) + 1 * sizeof(CHiBSFrame));
|
|
|
|
if(!n->extradataSent) {
|
|
frames->count++;
|
|
|
|
frames->data[frames->count - 1].timestamp = 0;
|
|
frames->data[frames->count - 1].flags = CUTIHI_BS_SETUP_PACKET;
|
|
frames->data[frames->count - 1].ptr = n->info.confBuf;
|
|
frames->data[frames->count - 1].sz = n->info.confSize;
|
|
|
|
n->extradataSent = true;
|
|
}
|
|
|
|
while(n->pcmbufSz) {
|
|
int inIdentifier = IN_AUDIO_DATA;
|
|
int inSize = n->pcmbufSz * sizeof(*n->pcmbuf);
|
|
int inElSize = 2;
|
|
AACENC_BufDesc inbuf = { .numBufs = 1, .bufs = &n->pcmbuf, .bufferIdentifiers = &inIdentifier, .bufSizes = &inSize, .bufElSizes = &inElSize };
|
|
|
|
int outIdentifier = OUT_BITSTREAM_DATA;
|
|
int outSize = 2048;
|
|
int outElSize = 1;
|
|
void *outBuf = malloc(outSize);
|
|
AACENC_BufDesc outbuf = { .numBufs = 1, .bufs = &outBuf, .bufferIdentifiers = &outIdentifier, .bufSizes = &outSize, .bufElSizes = &outElSize };
|
|
|
|
AACENC_InArgs inargs = { .numInSamples = n->pcmbufSz };
|
|
AACENC_OutArgs outargs = {};
|
|
|
|
int err = aacEncEncode(n->enc, &inbuf, &outbuf, &inargs, &outargs);
|
|
|
|
if(err == AACENC_OK) {
|
|
if(outargs.numOutBytes > 0) {
|
|
frames = realloc(frames, sizeof(*frames) + (++frames->count) * sizeof(CHiBSFrame));
|
|
|
|
frames->data[frames->count - 1].timestamp = n->timestamp / 48; // ms
|
|
frames->data[frames->count - 1].flags = 0;
|
|
frames->data[frames->count - 1].ptr = outBuf;
|
|
frames->data[frames->count - 1].sz = outargs.numOutBytes;
|
|
}
|
|
if(outargs.numInSamples > 0) {
|
|
memmove(n->pcmbuf, n->pcmbuf + outargs.numInSamples, sizeof(*n->pcmbuf) * (n->pcmbufSz - outargs.numInSamples));
|
|
n->pcmbufSz -= outargs.numInSamples;
|
|
|
|
n->timestamp += outargs.numInSamples;
|
|
}
|
|
|
|
if(outargs.numOutBytes == 0 || outargs.numInSamples == 0) {
|
|
break;
|
|
}
|
|
} else if(err == AACENC_ENCODE_EOF) {
|
|
break;
|
|
} else {
|
|
abort();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
n->pub.sources[0].type = CUTIHI_VAL_AACBS;
|
|
n->pub.sources[0].data.bitstream = frames;
|
|
|
|
return 1;
|
|
}
|
|
static int encodeaac_start(CHiPubNode *pub) {
|
|
Internal *n = (Internal*) pub;
|
|
|
|
assert(aacEncOpen(&n->enc, 0, 1) == AACENC_OK);
|
|
assert(aacEncoder_SetParam(n->enc, AACENC_AOT, 2) == AACENC_OK); // Low complexity profile
|
|
assert(aacEncoder_SetParam(n->enc, AACENC_SAMPLERATE, 48000) == AACENC_OK);
|
|
assert(aacEncoder_SetParam(n->enc, AACENC_CHANNELMODE, MODE_1) == AACENC_OK);
|
|
assert(aacEncoder_SetParam(n->enc, AACENC_CHANNELORDER, 1) == AACENC_OK);
|
|
assert(aacEncoder_SetParam(n->enc, AACENC_BITRATEMODE, 3) == AACENC_OK);
|
|
|
|
assert(aacEncEncode(n->enc, NULL, NULL, NULL, NULL) == AACENC_OK);
|
|
|
|
memset(&n->info, 0, sizeof(n->info));
|
|
assert(aacEncInfo(n->enc, &n->info) == AACENC_OK);
|
|
|
|
n->pcmbuf = NULL;
|
|
n->pcmbufSz = 0;
|
|
|
|
n->timestamp = 0;
|
|
n->extradataSent = false;
|
|
|
|
return 1;
|
|
}
|
|
static int encodeaac_stop(CHiPubNode *pub) {
|
|
Internal *n = (Internal*) pub;
|
|
|
|
aacEncClose(&n->enc);
|
|
|
|
return 1;
|
|
}
|
|
CUTIVIS CHiPubNode *CHi_EncodeAAC() {
|
|
Internal *ret = calloc(1, sizeof(*ret));
|
|
ret->pub.type = CUTIHI_T('CEnc','AACL');
|
|
ret->pub.Start = encodeaac_start;
|
|
ret->pub.Perform = encodeaac_perform;
|
|
ret->pub.Stop = encodeaac_stop;
|
|
ret->pub.sinks = calloc(sizeof(*ret->pub.sinks), ret->pub.sinkCount = 1);
|
|
ret->pub.sources = calloc(sizeof(*ret->pub.sources), ret->pub.sourceCount = 1);
|
|
return &ret->pub;
|
|
}
|