ref: 978f94bf9b2f384157f14c3ee436206a5d6b6450
dir: /decoder_vpx.c/
#include <vpx_codec.h> #include <vpx_decoder.h> #include <vpx_image.h> #include <vp8dx.h> #include "frame.h" #include "stream.h" #include "decoder.h" #include "misc.h" #pragma lib "../libvpx/libvpx.a" typedef struct Aux Aux; struct Aux { vpx_codec_ctx_t ctx; }; static void decode(void *x) { uvlong lasttimestamp; Decoder *d; Channel *c; Frame *f; Streamframe sf; Aux *a; int res; u8int *pic; vpx_codec_iter_t iter; uvlong start; vpx_image_t *im; threadsetname("decoder/vpx"); d = x; a = d->aux; lasttimestamp = 0; memset(&pic, 0, sizeof(pic)); for(res = 0; res >= 0 && (res = Sread(d->s, &sf)) == 0 && sf.sz > 0;){ start = nanosec(); if((res = vpx_codec_decode(&a->ctx, sf.buf, sf.sz, NULL, 0)) != 0){ werrstr("vpx_codec_decode failed"); break; } d->decodetime = nanosec() - start; for(iter = nil;;){ if((im = vpx_codec_get_frame(&a->ctx, &iter)) == nil) break; if(im->fmt != VPX_IMG_FMT_I420){ vpx_img_free(im); werrstr("images other than YUV420 aren't supported"); res = -1; break; } if((f = malloc(sizeof(*f) + im->w*im->h*3)) != nil){ f->w = im->w; f->h = im->h; f->crop.left = 0; f->crop.top = 0; f->crop.right = im->d_w; f->crop.bottom = im->d_h; yuv420_rgb24(im->d_w, im->d_h, im->planes[0], im->planes[1], im->planes[2], im->stride[0], im->stride[1], f->rgb, f->w*3); vpx_img_free(im); f->dt = (sf.timestamp - lasttimestamp) * d->timebase * 1000000000ULL; lasttimestamp = sf.timestamp; if(sendp(d->frames, f) < 0){ free(f); goto done; } } } } if(res != 0) fprint(2, "vpx: %r\n"); done: vpx_codec_destroy(&a->ctx); free(a); c = d->finished; sendp(c, res == 0 ? nil : "error"); chanclose(c); threadexits(nil); } static int vpxopen(Decoder *d) { Aux *a; vpx_codec_iface_t *iface; vpx_codec_dec_cfg_t cfg = {nproc, 0, 0}; a = calloc(1, sizeof(*a)); iface = d->s->fmt == FmtVP9 ? vpx_codec_vp9_dx() : vpx_codec_vp8_dx(); if(vpx_codec_dec_init(&a->ctx, iface, &cfg, 0) != 0){ werrstr("vpx_codec_dec_init failed"); free(a); return -1; } d->aux = a; proccreate(decode, d, 65536); return 0; } static void vpxclose(Decoder *d) { USED(d); } Decoderops vpxops = { .open = vpxopen, .close = vpxclose, };