shithub: dav1d

Download patch

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);
 }