86 lines
2.4 KiB
C
86 lines
2.4 KiB
C
|
#include"node.h"
|
||
|
|
||
|
#include<opus.h>
|
||
|
#include<string.h>
|
||
|
#include"img.h"
|
||
|
#include<stdlib.h>
|
||
|
#include<stdio.h>
|
||
|
|
||
|
struct CHiEncodeOpusNode {
|
||
|
CHiPubNode pubn;
|
||
|
|
||
|
size_t pcmSamples, pcmCapacity;
|
||
|
int16_t *pcmbuf;
|
||
|
|
||
|
size_t timestamp;
|
||
|
|
||
|
OpusEncoder *enc;
|
||
|
};
|
||
|
|
||
|
static int encodeopus_perform(CHiPubNode *pubn) {
|
||
|
struct CHiEncodeOpusNode *n = (struct CHiEncodeOpusNode*) pubn;
|
||
|
|
||
|
CHiImage *newpcm = CHi_Crawl(&pubn->sinks[0])->data.sample;
|
||
|
|
||
|
if(n->pcmSamples + newpcm->width > n->pcmCapacity) {
|
||
|
n->pcmbuf = realloc(n->pcmbuf, sizeof(*n->pcmbuf) * (n->pcmCapacity = ((n->pcmSamples + newpcm->width + 1023) & ~1023)));
|
||
|
}
|
||
|
|
||
|
memcpy(&n->pcmbuf[n->pcmSamples], newpcm->data16, sizeof(*n->pcmbuf) * newpcm->width);
|
||
|
n->pcmSamples += newpcm->width;
|
||
|
|
||
|
CHiBSFrames *frames = malloc(sizeof(*frames));
|
||
|
frames->count = 0;
|
||
|
|
||
|
size_t samp;
|
||
|
for(samp = 0; samp + 960 <= n->pcmSamples; samp += 960) {
|
||
|
frames = realloc(frames, sizeof(*frames) + sizeof(*frames->data) * (frames->count + 1));
|
||
|
frames->data[frames->count].timestamp = n->timestamp;
|
||
|
frames->data[frames->count].ptr = malloc(1276);
|
||
|
frames->data[frames->count].sz = opus_encode(n->enc, &n->pcmbuf[samp], 960, frames->data[frames->count].ptr, 1276);
|
||
|
if(frames->data[frames->count].sz < 0) puts("OPUS ERR");
|
||
|
frames->count++;
|
||
|
|
||
|
n->timestamp += 20;
|
||
|
}
|
||
|
|
||
|
memmove(n->pcmbuf, n->pcmbuf + samp, sizeof(*n->pcmbuf) * (n->pcmSamples - samp));
|
||
|
n->pcmSamples -= samp;
|
||
|
|
||
|
pubn->sources[0].type = CUTIHI_VAL_OPUSBS;
|
||
|
pubn->sources[0].data.bitstream = frames;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
CUTIVIS CHiPubNode *CHi_EncodeOpus() {
|
||
|
struct CHiEncodeOpusNode *ret = malloc(sizeof(*ret));
|
||
|
ret->pubn.type = CUTIHI_T('CEnc','Opus');
|
||
|
ret->pubn.Start = CHi_EncodeOpus_Start;
|
||
|
ret->pubn.Perform = &encodeopus_perform;
|
||
|
ret->pubn.Stop = CHi_EncodeOpus_Stop;
|
||
|
ret->pubn.clean = 0;
|
||
|
ret->pubn.sinks = calloc(sizeof(*ret->pubn.sinks), ret->pubn.sinkCount = 1);
|
||
|
ret->pubn.sources = calloc(sizeof(*ret->pubn.sources), ret->pubn.sourceCount = 1);
|
||
|
return &ret->pubn;
|
||
|
}
|
||
|
CUTIVIS int CHi_EncodeOpus_Start(CHiPubNode *pubn) {
|
||
|
struct CHiEncodeOpusNode *n = (struct CHiEncodeOpusNode*) pubn;
|
||
|
|
||
|
int error;
|
||
|
n->enc = opus_encoder_create(48000, 1, OPUS_APPLICATION_AUDIO, &error);
|
||
|
|
||
|
n->pcmSamples = 0;
|
||
|
n->pcmCapacity = 1024;
|
||
|
n->pcmbuf = malloc(sizeof(*n->pcmbuf) * n->pcmCapacity);
|
||
|
n->timestamp = 0;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
CUTIVIS int CHi_EncodeOpus_Stop(CHiPubNode *pubn) {
|
||
|
struct CHiEncodeOpusNode *n = (struct CHiEncodeOpusNode*) pubn;
|
||
|
opus_encoder_destroy(n->enc);
|
||
|
free(n->pcmbuf);
|
||
|
|
||
|
return 1;
|
||
|
}
|