#include #include #include #include #include #include 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; }