ref: 74264a3a65e3a9911270ae3ce3ebefa4d4254e42
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;
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;){
if((res = vpx_codec_decode(&a->ctx, sf.buf, sf.sz, NULL, 0)) != 0){
werrstr("vpx_codec_decode failed");
break;
}
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,
};