ref: 917cb4e4f13a3ad14bc9a6e0e411a058233b26d8
parent: 6dd7fd3086ffa8c87a35c955ddaed3e9fa0e292d
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Sun Sep 6 18:28:01 EDT 2020
trying out yuv->rgb and resampling on frames in parallel
--- a/src/av19.c
+++ b/src/av19.c
@@ -5,7 +5,7 @@
#include <mouse.h>
#include <keyboard.h>
#include <tos.h>
-/* FIXME this one is slow as hell
+/* FIXME this one is slow as hell */
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#define STBIR_MALLOC(x,u) malloc(x)
#define STBIR_FREE(x,u) free(x)
@@ -12,12 +12,12 @@
#define STBIR_ASSERT(x) assert(x)
typedef uintptr size_t;
#include <stb_image_resize.h>
-*/
typedef struct Frame Frame;
typedef struct Player Player;
struct Frame {
Dav1dPicture pic;
+ uvlong n;
};
struct Player {
@@ -24,17 +24,25 @@
Dav1dData data;
Dav1dContext *c;
DemuxerContext *dc;
- Channel *frames;
Channel *done;
uvlong fps;
uvlong lastframe;
+ uvlong n;
};
// FIXME why does it need this much?
int mainstacksize = 512*1024;
+enum {
+ Maxframes = 30,
+};
+
static Player *curplayer;
-static Image *curframe;
+static Image *curim;
+static Channel *converters[Maxframes];
+static QLock framelock;
+static uvlong todisplay;
+static int resize = 1;
/* yuv→rgb by Adrien Descamps */
@@ -135,46 +143,6 @@
}
}
-static int
-dav1d_loadimage(Rectangle r, Image **oim, Dav1dPicture *p)
-{
- Image *im;
- uchar *rgb;
- int w, h;
-
- if(*oim == nil)
- *oim = allocimage(display, r, RGB24, 0, DNofill);
- im = *oim;
- w = p->p.w;
- h = p->p.h;
- if((rgb = malloc(w*h*3)) == nil)
- return -1;
-
- yuv420_rgb24(w, h, p->data[0], p->data[1], p->data[2], p->stride[0], p->stride[1], rgb, w*3);
-/*
- uchar *out;
- if((out = malloc(Dx(r)*Dy(r)*3)) == nil){
- free(rgb);
- return -1;
- }
- stbir_resize_uint8_generic(
- rgb, w, h, w*3,
- out, Dx(r), Dy(r), Dx(r)*3,
- 3, -1, 0,
- STBIR_EDGE_CLAMP, STBIR_FILTER_MITCHELL, STBIR_COLORSPACE_LINEAR,
- NULL);
- free(rgb);
- rgb = out;
-*/
-
- w = Dx(r);
- h = Dy(r);
- loadimage(im, Rect(0,0,w,h), rgb, w*h*3);
- free(rgb);
-
- return 0;
-}
-
static void
freeframe(Frame *f)
{
@@ -212,38 +180,22 @@
}
static void
-gotframe(Frame *f)
+drawframe(void)
{
- int res;
- Point size = subpt(screen->r.max, screen->r.min);
- Rectangle r = (Rectangle){Pt(0, 0), size};
- uvlong thisframe, start, dt;
+ uvlong thisframe, start;
static uvlong delay;
- start = nanosec();
thisframe = curplayer->lastframe + 1000000000ULL/curplayer->fps - delay;
+ while(nanosec() < thisframe)
+ sleep(10);
- dt = 0;
lockdisplay(display);
-
- r.max.x = f->pic.p.w;
- r.max.y = f->pic.p.h;
- res = dav1d_loadimage(r, &curframe, &f->pic);
- freeframe(f);
- dt += nanosec()-start;
-
- if(res == 0){
- while(nanosec() < thisframe)
- sleep(1000/curplayer->fps);
- dt += nanosec() - thisframe;
- start = nanosec();
- draw(screen, screen->r, curframe, nil, ZP);
- flushimage(display, 1);
- curplayer->lastframe = start;
- dt += nanosec()-start;
- }
+ start = nanosec();
+ draw(screen, screen->r, curim, nil, ZP);
+ flushimage(display, 1);
unlockdisplay(display);
- delay = dt;
+ delay = nanosec() - start;
+ curplayer->lastframe = start;
}
static void
@@ -268,7 +220,8 @@
break;
}
}else{
- sendp(p->frames, f);
+ f->n = p->n++;
+ sendp(converters[f->n % Maxframes], f);
}
}
}while(p->data.sz > 0 || input_read(p->dc, &p->data) == 0);
@@ -287,7 +240,6 @@
freeplayer(Player *p)
{
// FIXME
- chanfree(p->frames);
chanfree(p->done);
free(p);
}
@@ -319,7 +271,6 @@
goto err;
}
- p->frames = chancreate(sizeof(Frame*), 15); // FIXME prerender?
p->done = chancreate(sizeof(ulong), 0);
p->lastframe = 0;
@@ -332,11 +283,77 @@
return nil;
}
+static void
+rgbready(uchar *rgb, int w, int h, uvlong n)
+{
+ Rectangle r;
+
+ r = Rect(0,0,w,h);
+ for(;;){
+ qlock(&framelock);
+ if(todisplay == n){
+ if(curim != nil && Dx(curim->r) != w){
+ freeimage(curim);
+ curim = nil;
+ }
+ if(curim == nil)
+ curim = allocimage(display, r, RGB24, 0, DNofill);
+ loadimage(curim, r, rgb, w*h*3);
+ free(rgb);
+ drawframe();
+ todisplay++;
+ qunlock(&framelock);
+ break;
+ }
+ qunlock(&framelock);
+ sleep(10);
+ }
+}
+
+static void
+converterproc(void *c)
+{
+ Frame *f;
+ uchar *rgb;
+ Dav1dPicture *p;
+ uchar *out;
+ int w, h;
+
+ for(; (f = recvp(c)) != nil;){
+ p = &f->pic;
+ if((rgb = malloc(p->p.w * p->p.h * 3)) != nil){
+ yuv420_rgb24(p->p.w, p->p.h, p->data[0], p->data[1], p->data[2], p->stride[0], p->stride[1], rgb, p->p.w*3);
+ w = p->p.w;
+ h = p->p.h;
+
+ if(resize){
+ w = Dx(screen->r);
+ h = Dy(screen->r);
+ if((out = malloc(w*h*3)) != nil){
+ stbir_resize_uint8_generic(
+ rgb, p->p.w, p->p.h, p->p.w*3,
+ out, w, h, w*3,
+ 3, -1, 0,
+ STBIR_EDGE_CLAMP, STBIR_FILTER_MITCHELL, STBIR_COLORSPACE_LINEAR,
+ NULL);
+ }
+ free(rgb);
+ rgb = out;
+ }
+ if(rgb != nil)
+ rgbready(rgb, w, h, f->n);
+ }
+
+ freeframe(f);
+ }
+
+ threadexits(nil);
+}
+
void
threadmain(int argc, char **argv)
{
enum {
- Cplayerframes,
Cplayerdone,
Cmouse,
Ckeyboard,
@@ -345,13 +362,11 @@
};
Mousectl *mctl;
Keyboardctl *kctl;
- Frame *frame;
Rune key;
Mouse m;
int i, end, done;
Alt a[Cnum+1] =
{
- [Cplayerframes] = { nil, &frame, CHANRCV },
[Cplayerdone] = { nil, nil, CHANRCV },
[Cmouse] = { nil, &m, CHANRCV },
[Ckeyboard] = { nil, &key, CHANRCV },
@@ -379,19 +394,20 @@
a[Cresize].c = mctl->resizec;
a[Ckeyboard].c = kctl->c;
+ for(i = 0; i < nelem(converters); i++){
+ converters[i] = chancreate(sizeof(Frame*), 0);
+ proccreate(converterproc, converters[i], 4096);
+ }
+
for(end = i = 0; !end && i < argc; i++){
+ todisplay = 0;
if((curplayer = newplayer(argv[0])) == nil)
sysfatal("%r");
- a[Cplayerframes].c = curplayer->frames;
a[Cplayerdone].c = curplayer->done;
for(done = 0; !done && !end;){
switch(alt(a)){
- case Cplayerframes:
- gotframe(frame);
- break;
-
case Cplayerdone:
done = 1;
break;
@@ -404,13 +420,19 @@
end = 1;
break;
}
+ if(key == 'r')
+ resize = !resize;
break;
case Cresize:
+ qlock(&framelock);
if(getwindow(display, Refnone) < 0)
sysfatal("getwindow: %r");
- freeimage(curframe);
- curframe = nil;
+ lockdisplay(display);
+ freeimage(curim);
+ curim = nil;
+ unlockdisplay(display);
+ qunlock(&framelock);
break;
}
}
@@ -417,6 +439,9 @@
freeplayer(curplayer);
}
+
+ for(i = 0; i < nelem(converters); i++)
+ chanclose(converters[i]);
threadexitsall(nil);
}