173 lines
3.6 KiB
C
173 lines
3.6 KiB
C
#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;
|
|
}
|