shithub: treason

Download patch

ref: 52f33c04acdec0e9123f9566f6eddfa86d707cdb
parent: 978f94bf9b2f384157f14c3ee436206a5d6b6450
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Mon Dec 14 10:05:06 EST 2020

copy YUV frames and convert to rgb on main thread

--- a/decoder_av1.c
+++ b/decoder_av1.c
@@ -79,11 +79,8 @@
 			werrstr("unsupported bits per component: %d", pic.p.bpc);
 			res = -1;
 			break;
-		}else if((f = malloc(sizeof(*f) + pic.p.w*pic.p.h*3)) != nil){
-			f->w = pic.p.w;
-			f->h = pic.p.h;
+		}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));
-			yuv420_rgb24(f->w, f->h, pic.data[0], pic.data[1], pic.data[2], pic.stride[0], pic.stride[1], f->rgb, f->w*3);
 			f->dt = (pic.m.timestamp - lasttimestamp) * d->timebase * 1000000000ULL;
 			lasttimestamp = pic.m.timestamp;
 			dav1d_picture_unref(&pic);
--- a/decoder_h264.c
+++ b/decoder_h264.c
@@ -192,17 +192,14 @@
 
 		w = a->info.UsrData.sSystemBuffer.iWidth;
 		h = a->info.UsrData.sSystemBuffer.iHeight;
-		if((f = malloc(sizeof(*f) + w*h*3)) == nil)
+		stride = a->info.UsrData.sSystemBuffer.iStride;
+		if((f = newframe(w, h, a->data, stride[0], stride[1])) == nil)
 			continue;
 
-		stride = a->info.UsrData.sSystemBuffer.iStride;
-		f->w = w;
-		f->h = h;
 		f->crop.left = a->ctx.sFrameCrop.iLeftOffset;
 		f->crop.top = a->ctx.sFrameCrop.iTopOffset;
 		f->crop.right = a->ctx.sFrameCrop.iRightOffset;
 		f->crop.bottom = a->ctx.sFrameCrop.iBottomOffset;
-		yuv420_rgb24(w, h, a->data[0], a->data[1], a->data[2], stride[0], stride[1], f->rgb, w*3);
 		f->dt = (sf.timestamp - lasttimestamp) * d->timebase * 1000000000ULL;
 		lasttimestamp = sf.timestamp;
 
--- a/decoder_vpx.c
+++ b/decoder_vpx.c
@@ -53,17 +53,14 @@
 				break;
 			}
 
-			if((f = malloc(sizeof(*f) + im->w*im->h*3)) != nil){
-				f->w = im->w;
-				f->h = im->h;
+			if((f = newframe(im->w, im->h, im->planes, im->stride[0], im->stride[1])) != nil){
 				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;
+				vpx_img_free(im);
 
 				if(sendp(d->frames, f) < 0){
 					free(f);
--- /dev/null
+++ b/frame.c
@@ -1,0 +1,25 @@
+#include <u.h>
+#include <libc.h>
+#include "frame.h"
+
+Frame *
+newframe(int w, int h, u8int *yuv[3], int ystride, int uvstride)
+{
+	Frame *f;
+
+	if((f = malloc(sizeof(*f) + (ystride+uvstride)*h)) == nil)
+		return nil;
+
+	f->w = w;
+	f->h = h;
+	f->yuv[0] = f->data;
+	memmove(f->yuv[0], yuv[0], ystride*h);
+	f->yuv[1] = f->data + ystride*h;
+	memmove(f->yuv[1], yuv[1], uvstride*h/2);
+	f->yuv[2] = f->data + ystride*h + uvstride*h/2;
+	memmove(f->yuv[2], yuv[2], uvstride*h/2);
+	f->ystride = ystride;
+	f->uvstride = uvstride;
+
+	return f;
+}
--- a/frame.h
+++ b/frame.h
@@ -6,5 +6,12 @@
 	struct {
 		int left, top, right, bottom;
 	}crop;
-	u8int rgb[1];
+
+	u8int *yuv[3];
+	int ystride;
+	int uvstride;
+
+	u8int data[1];
 };
+
+Frame *newframe(int w, int h, u8int *yuv[3], int ystride, int vstride);
--- a/main.c
+++ b/main.c
@@ -13,6 +13,7 @@
 int mainstacksize = 128*1024;
 
 static Image *curim;
+static u8int *rgb;
 static uvlong lastframe;
 static int audiofd = -1;
 static Channel *audiosync;
@@ -59,9 +60,9 @@
 		lastframe = x;
 
 	end = lastframe + f->dt - dispdelay;
-	if(dispdelay > 0 && x >= end+dispdelay){
+	if(x >= end+dispdelay){
 		late = x - (end+dispdelay);
-		if(framedrop)
+		if(late > 0 && framedrop)
 			goto drop;
 	}else{
 		late = 0;
@@ -72,23 +73,28 @@
 	if(curim != nil && (Dx(curim->r) != f->w || Dy(curim->r) != f->h)){
 		freeimage(curim);
 		curim = nil;
+		free(rgb);
+		rgb = nil;
 	}
 	r = Rect(0,0,f->w,f->h);
 	if(curim == nil)
 		curim = allocimage(display, r, RGB24, 0, DNofill);
-	loadimage(curim, r, f->rgb, f->w*f->h*3);
+	if(rgb == nil)
+		rgb = malloc(f->w*f->h*3);
+	yuv420_rgb24(f->w, f->h, f->yuv[0], f->yuv[1], f->yuv[2], f->ystride, f->uvstride, rgb, f->w*3);
+	loadimage(curim, r, rgb, f->w*f->h*3);
 
+	dispdelay = nanosec() - x;
+
 	while(1){
 		x = nanosec();
-		if(x >= end)
+		if(x >= end - 1*1000ULL*1000ULL)
 			break;
 		left = end - x;
-		if(left > 750000000ULL)
+		if(left > 80ULL*1000ULL*1000ULL)
 			sleep(70);
-		else if(left > 250000000ULL)
+		else if(left > 30ULL*1000ULL*1000ULL)
 			sleep(20);
-		else if(left > 100000000ULL)
-			sleep(1);
 	}
 
 	clip = Rect(f->crop.left, f->crop.top, f->crop.right, f->crop.bottom);
@@ -96,7 +102,6 @@
 		clip = curim->r;
 	replclipr(curim, 0, clip);
 
-	x = nanosec();
 	if(Dx(clip) < Dx(screen->r) && Dy(clip) < Dy(screen->r))
 		r = rectsubpt(screen->r, divpt(Pt(Dx(clip)-Dx(screen->r), Dy(clip)-Dy(screen->r)), 2));
 	else
@@ -107,7 +112,7 @@
 	flushimage(display, 1);
 	unlockdisplay(display);
 
-	dispdelay = nanosec() - x;
+	dispdelay += nanosec() - x;
 drop:
 	if(audiosync != nil)
 		sendp(audiosync, nil);
@@ -245,7 +250,7 @@
 					d->decodetime/1000000ULL,
 					dispdelay/1000000ULL,
 					yuv→rgb/1000000ULL,
-					(d->decodetime + dispdelay + yuv→rgb)/1000000ULL,
+					(d->decodetime + dispdelay)/1000000ULL,
 					late/1000000ULL,
 					frame->w, frame->h,
 					d->info,
--- a/mkfile
+++ b/mkfile
@@ -19,6 +19,7 @@
 	decoder_av1.$O\
 	decoder_h264.$O\
 	decoder_vpx.$O\
+	frame.$O\
 	main.$O\
 	misc.$O\
 	stream.$O\