mwss/support.c

173 lines
3.6 KiB
C
Raw Permalink Normal View History

2024-12-21 22:43:09 +02:00
#include<stdlib.h>
#include<libavcodec/avcodec.h>
#include<libswscale/swscale.h>
#include<libavutil/imgutils.h>
#include<ogg/ogg.h>
#include<vorbis/codec.h>
struct veepie {
uint8_t *rgba;
uint16_t w;
uint16_t h;
uint16_t wOld, hOld;
const AVCodec *cdc;
AVCodecContext *ctx;
AVFrame *frame1, *frame2;
AVPacket pkt;
SwsContext *sws;
};
struct veepie *alloc_codec_vpx(int vp9) {
struct veepie *v = calloc(1, sizeof(*v));
v->cdc = avcodec_find_decoder_by_name(vp9 ? "vp9" : "vp8");
if(!v->cdc) return (void*) (uintptr_t) 1;
v->ctx = avcodec_alloc_context3(v->cdc);
if(!v->ctx) return (void*) (uintptr_t) 2;
if(avcodec_open2(v->ctx, v->cdc, 0) < 0) return (void*) (uintptr_t) 3;
v->frame1 = av_frame_alloc();
v->frame2 = av_frame_alloc();
return v;
}
int codec_vpx_push_packet(struct veepie *v, int kf, uint8_t *data, size_t len) {//, uint64_t pts) {
av_init_packet(&v->pkt);
v->pkt.data = data;
v->pkt.size = len;
v->pkt.pts = AV_NOPTS_VALUE;
v->pkt.dts = AV_NOPTS_VALUE;
if(kf) v->pkt.flags |= AV_PKT_FLAG_KEY;
avcodec_send_packet(v->ctx, &v->pkt);
av_packet_unref(&v->pkt);
int retframe = avcodec_receive_frame(v->ctx, v->frame1);
if(retframe) {
return 0;
}
v->w = v->frame1->width;
v->h = v->frame1->height;
if(v->w != v->wOld || v->h != v->hOld) {
v->sws = sws_getContext(v->w, v->h, v->frame1->format, v->w, v->h, AV_PIX_FMT_RGBA, SWS_FAST_BILINEAR, NULL, NULL, NULL);
av_image_fill_arrays(v->frame2->data, v->frame2->linesize, av_malloc(av_image_get_buffer_size(AV_PIX_FMT_RGBA, v->w, v->h, 4)), AV_PIX_FMT_RGBA, v->w, v->h, 4);
v->wOld = v->w;
v->hOld = v->h;
}
sws_scale(v->sws, v->frame1->data, v->frame1->linesize, 0, v->h, v->frame2->data, v->frame2->linesize);
v->rgba = v->frame2->data[0];
return 1;
}
struct vobie {
float **sampleBuffer;
uint32_t sampleCount;
vorbis_info vi;
vorbis_comment vc;
ogg_packet op;
vorbis_dsp_state dsp;
vorbis_block vb;
};
struct vobie *alloc_codec_vorbis(uint8_t *private, size_t privateLen) {
uint8_t numPacketsMinusOne = private[0];
if(numPacketsMinusOne != 2) return NULL;
size_t i = 1;
size_t len0 = 0;
while(private[i] == 0xFF) {
len0 += 0xFF;
i++;
}
len0 += private[i++];
size_t len1 = 0;
while(private[i] == 0xFF) {
len1 += 0xFF;
i++;
}
len1 += private[i++];
size_t len2 = privateLen - i - len0 - len1;
struct vobie *v = calloc(1, sizeof(*v));
vorbis_info_init(&v->vi);
vorbis_comment_init(&v->vc);
v->op.packet = private + i;
v->op.bytes = len0;
v->op.b_o_s = 1;
v->op.e_o_s = 0;
v->op.granulepos = 0;
v->op.packetno = 0;
if(vorbis_synthesis_headerin(&v->vi, &v->vc, &v->op)) {
return (void*) (uintptr_t) 1;
}
i += len0;
v->op.packet = private + i;
v->op.bytes = len1;
v->op.b_o_s = 0;
v->op.packetno++;
if(vorbis_synthesis_headerin(&v->vi, &v->vc, &v->op)) {
return (void*) (uintptr_t) 2;
}
i += len1;
v->op.packet = private + i;
v->op.bytes = len2;
v->op.packetno++;
if(vorbis_synthesis_headerin(&v->vi, &v->vc, &v->op)) {
return (void*) (uintptr_t) 3;
}
if(vorbis_synthesis_init(&v->dsp, &v->vi)) {
return (void*) (uintptr_t) 4;
}
if(vorbis_block_init(&v->dsp, &v->vb)) {
return (void*) (uintptr_t) 5;
}
return v;
}
int codec_vorbis_push_packet(struct vobie *v, uint8_t *pkt, size_t len) {
v->op.packet = pkt;
v->op.bytes = len;
v->op.packetno++;
if(vorbis_synthesis(&v->vb, &v->op)) {
return -1;
}
if(vorbis_synthesis_blockin(&v->dsp, &v->vb)) {
return -2;
}
v->sampleCount = vorbis_synthesis_pcmout(&v->dsp, &v->sampleBuffer);
v->op.granulepos += v->sampleCount;
vorbis_synthesis_read(&v->dsp, v->sampleCount);
return v->sampleCount;
}