Initial commit
This commit is contained in:
172
support.c
Normal file
172
support.c
Normal file
@@ -0,0 +1,172 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user