ref: e821bea01a9696afb0bf8396e9ee6f7f499883a7
dir: /decoder_av1.c/
#include <dav1d.h> #include "frame.h" #include "stream.h" #include "decoder.h" #include "misc.h" #pragma lib "../dav1d/src/libdav1d.$M.a" typedef struct Aux Aux; struct Aux { Dav1dContext *c; }; static char *layouts[] = { [DAV1D_PIXEL_LAYOUT_I400] = "i400", [DAV1D_PIXEL_LAYOUT_I420] = "i420", [DAV1D_PIXEL_LAYOUT_I422] = "i422", [DAV1D_PIXEL_LAYOUT_I444] = "i444", }; static u8int * allocdata(void *data, int sz) { return dav1d_data_create(data, sz); } static int readframe(Stream *s, Dav1dData *data) { Streamframe f; s->ops.aux = data; if(Sread(s, &f) != 0) return -1; data->m.timestamp = f.timestamp; return 0; } static void decode(void *x) { uvlong lasttimestamp; Dav1dPicture pic; Dav1dData data; uvlong start; Decoder *d; Channel *c; Frame *f; Aux *a; int res; threadsetname("decoder/av1"); d = x; a = d->aux; lasttimestamp = 0; memset(&pic, 0, sizeof(pic)); for(res = 0, data.sz = 0; data.sz > 0 || (res = readframe(d->s, &data)) == 0;){ if(data.sz == 0) break; start = nanosec(); res = dav1d_get_picture(a->c, &pic); if(res < 0){ if(res != DAV1D_ERR(EAGAIN)){ werrstr("dav1d_get_picture: %d", res); break; } }else if(pic.p.layout != DAV1D_PIXEL_LAYOUT_I420){ if(pic.p.layout >= 0 && pic.p.layout < nelem(layouts)) werrstr("%s", layouts[pic.p.layout]); else werrstr("??? (%d)", pic.p.layout); werrstr("unsupported pixel layout: %r"); res = -1; break; }else if(pic.p.bpc != 8){ werrstr("unsupported bits per component: %d", pic.p.bpc); res = -1; break; }else{ if((f = newframe(pic.p.w, pic.p.h, pic.data, pic.stride[0], pic.stride[1])) != nil){ memset(&f->crop, 0, sizeof(f->crop)); f->dt = (pic.m.timestamp - lasttimestamp) * d->timebase * 1000000000ULL; lasttimestamp = pic.m.timestamp; if(sendp(d->frames, f) < 0){ dav1d_picture_unref(&pic); free(f); break; } dav1d_picture_unref(&pic); } } res = dav1d_send_data(a->c, &data); if(res < 0){ if(res != DAV1D_ERR(EAGAIN)){ werrstr("dav1d_send_data: %d", res); break; } }else{ d->decodetime = nanosec() - start; } } if(res != 0) fprint(2, "av1: %r\n"); if(data.sz > 0) dav1d_data_unref(&data); /* drain */ while(dav1d_get_picture(a->c, &pic) >= 0) dav1d_picture_unref(&pic); dav1d_close(&a->c); free(a); c = d->finished; sendp(c, res == 0 ? nil : "error"); chanclose(c); threadexits(nil); } static int av1open(Decoder *d) { Dav1dSettings av1s; Aux *a; int res; a = calloc(1, sizeof(*a)); dav1d_default_settings(&av1s); av1s.n_frame_threads = nproc; av1s.n_tile_threads = nproc; av1s.apply_grain = 0; if((res = dav1d_open(&a->c, &av1s)) != 0){ werrstr("dav1d_open: %d", res); free(a); return -1; } d->aux = a; d->s->ops.alloc = allocdata; proccreate(decode, d, 16384); return 0; } static void av1close(Decoder *d) { USED(d); } Decoderops av1ops = { .open = av1open, .close = av1close, };