shithub: hj264

Download patch

ref: b88eb37f01e419092a2765fb135f486b2dc693db
parent: 9b69b3a085047cf76cccd16ed098cf040436c68d
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Mon Jul 19 04:53:46 EDT 2021

take yuv logic out; add -G option to specify gop; -d → -D (denoise), -d is debug

--- a/hj264.c
+++ b/hj264.c
@@ -6,6 +6,7 @@
 #include <bio.h>
 #include <draw.h>
 #include <tos.h>
+#include "yuv.h"
 
 void npe_nsleep(uvlong ns);
 uvlong npe_nanosec(void);
@@ -18,7 +19,6 @@
 enum {
 	Align = 64,
 	Maxquality = 10,
-	Gop = 20,
 };
 
 typedef struct Hjob Hjob;
@@ -41,7 +41,8 @@
 	H264E_persist_t *persist;
 	H264E_scratch_t *scratch;
 	H264E_run_param_t rp;
-	H264E_io_yuv_t yuv;
+	H264E_io_yuv_t ioyuv;
+	YUV yuv;
 	Biobuf out;
 	Channel *frame;
 	Channel *done;
@@ -57,59 +58,6 @@
 	u8int bgrx[];
 };
 
-static void
-xrgb2yuv(u8int *bgrx, int w, int h, H264E_io_yuv_t *io)
-{
-	u8int *py, *pu, *pv;
-	int x, y, r, g, b;
-
-	py = io->yuv[0];
-	pu = io->yuv[1];
-	pv = io->yuv[2];
-
-	for(y = 0; y < h;){
-		for(x = 0; x < w;){
-			b = bgrx[0];
-			g = bgrx[1];
-			r = bgrx[2];
-			bgrx += 4;
-
-#define YY ((( 77*r + 150*g +  29*b + 128) >> 8) +   0)
-#define UU (((-43*r -  84*g + 127*b + 128) >> 8) + 128)
-#define VV (((127*r - 106*g -  21*b + 128) >> 8) + 128)
-			py[x] = YY;
-			pu[x/2] = UU;
-			pv[x/2] = VV;
-			x++;
-
-			b = bgrx[0];
-			g = bgrx[1];
-			r = bgrx[2];
-			bgrx += 4;
-			py[x] = YY;
-			x++;
-		}
-		py += io->stride[0];
-		y++;
-
-		for(x = 0; x < w;){
-			b = bgrx[0];
-			g = bgrx[1];
-			r = bgrx[2];
-			bgrx += 4;
-			py[x] = YY;
-			x++;
-#undef YY
-#undef UU
-#undef VV
-		}
-		py += io->stride[0];
-		pu += io->stride[1];
-		pv += io->stride[2];
-		y++;
-	}
-}
-
 #pragma varargck type "ℏ" int
 static int
 hjerror(Fmt *f)
@@ -182,7 +130,7 @@
 {
 	int e;
 
-	if((e = H264E_encode(h->persist, h->scratch, &h->rp, &h->yuv, data, sz)) != 0){
+	if((e = H264E_encode(h->persist, h->scratch, &h->rp, &h->ioyuv, data, sz)) != 0){
 		werrstr("H264E_encode: %ℏ", e);
 		return -1;
 	}
@@ -191,7 +139,7 @@
 }
 
 static Hj264 *
-hj264new(int nthreads, int denoise, int kbps, int ww, int hh)
+hj264new(int nthreads, int denoise, int kbps, int gop, int ww, int hh)
 {
 	int i, e, szscratch, szpersist, szyuv;
 	H264E_create_param_t cp;
@@ -205,7 +153,7 @@
 
 	memset(&cp, 0, sizeof(cp));
 	cp.num_layers = 1;
-	cp.gop = Gop;
+	cp.gop = gop;
 	cp.max_threads = nthreads;
 	cp.temporal_denoise_flag = denoise;
 	cp.max_long_term_reference_frames = MAX_LONG_TERM_FRAMES;
@@ -227,12 +175,15 @@
 		return nil;
 
 	p = align(h->buf, Align);
-	h->yuv.yuv[0] = p;
-	h->yuv.stride[0] = ww;
-	h->yuv.yuv[1] = p + ww*hh;
-	h->yuv.stride[1] = ww/2;
-	h->yuv.yuv[2] = p + ww*hh*5/4;
-	h->yuv.stride[2] = ww/2;
+	h->ioyuv.yuv[0] = p;
+	h->ioyuv.stride[0] = ww;
+	h->ioyuv.yuv[1] = p + ww*hh;
+	h->ioyuv.stride[1] = ww/2;
+	h->ioyuv.yuv[2] = p + ww*hh*5/4;
+	h->ioyuv.stride[2] = ww/2;
+	h->yuv.y = h->ioyuv.yuv[0]; h->yuv.ys = h->ioyuv.stride[0];
+	h->yuv.u = h->ioyuv.yuv[1]; h->yuv.us = h->ioyuv.stride[1];
+	h->yuv.v = h->ioyuv.yuv[2]; h->yuv.vs = h->ioyuv.stride[2];
 	h->persist = align(p+szyuv, Align);
 	h->scratch = align(h->persist+szpersist, Align);
 
@@ -281,7 +232,7 @@
 	for(;;){
 		if((img = recvp(h->frame)) == nil)
 			break;
-		xrgb2yuv(img->bgrx, img->w, img->h, &h->yuv);
+		xrgb2yuv420(img->bgrx, img->w, img->h, &h->yuv);
 		free(img);
 
 		if(hj264_encode(h, &data, &sz) != 0)
@@ -321,11 +272,11 @@
 static void
 usage(void)
 {
-	fprint(2, "usage: %s [-d] [-f FPS] [-n THREADS] [-k KBPS] [-q 0…10] [-Q QP] FILE\n", argv0);
+	fprint(2, "usage: %s [-D] [-f FPS] [-g GOP] [-n THREADS] [-k KBPS] [-q 0…10] [-Q QP] FILE\n", argv0);
 	threadexitsall("usage");
 }
 
-static uvlong nframes, tstart;
+static uvlong nframes, tstart, debug;
 
 static int
 done(void *, char *msg)
@@ -333,8 +284,12 @@
 	uvlong s;
 	Hj264 *h;
 
-	if((s = (npe_nanosec() - tstart)/1000000000ULL) != 0)
-		fprint(2, "%llud fps\n", nframes / s);
+	if(debug){
+		s = npe_nanosec() - tstart;
+		s /= 1000000000ULL;
+		if(s != 0)
+			fprint(2, "%llud fps\n", nframes / s);
+	}
 	h = *threaddata();
 	Bflush(&h->out);
 	threadexitsall(msg);
@@ -344,7 +299,7 @@
 int
 main(int argc, char **argv)
 {
-	int nthreads, fps, kbps, denoise, quality, qp;
+	int nthreads, fps, kbps, denoise, quality, qp, gop;
 	char *s, tmp[61], *f[5];
 	uvlong fstart, fend;
 	int ww, hh, in;
@@ -358,13 +313,20 @@
 	kbps = 0;
 	fps = 30;
 	qp = 33;
+	gop = 20;
 	ARGBEGIN{
 	case 'd':
+		debug++;
+		break;
+	case 'D':
 		denoise++;
 		break;
 	case 'f':
 		fps = atoi(EARGF(usage()));
 		break;
+	case 'g':
+		gop = atoi(EARGF(usage()));
+		break;
 	case 'k':
 		kbps = atoi(EARGF(usage()));
 		break;
@@ -405,7 +367,7 @@
 	if(ww < 16 || hh < 16)
 		sysfatal("frame too small: %dx%d", ww, hh);
 
-	if((h = hj264new(nthreads, denoise, kbps, ww, hh)) == nil)
+	if((h = hj264new(nthreads, denoise, kbps, gop, ww, hh)) == nil)
 		sysfatal("hj264new: %r");
 	if(Binit(&h->out, 1, OWRITE) < 0)
 		sysfatal("Binit failed: %r");
--- a/mkfile
+++ b/mkfile
@@ -5,13 +5,14 @@
 TARG=hj264
 
 HFILES=\
-	stb_truetype.h\
+	builtins.h\
+	minih264e.h\
+	yuv.h\
 
-UPDATE=$HFILES
-
 OFILES=\
+	builtins`{test -f builtins.$objtype.s && echo -n .$objtype}.$O\
 	hj264.$O\
-	builtins`{test $objtype '=' amd64 && echo -n .$objtype}.$O\
+	yuv.$O\
 
 default:V: all
 
--- /dev/null
+++ b/yuv.c
@@ -1,0 +1,54 @@
+#include <u.h>
+#include <libc.h>
+#include "yuv.h"
+
+#define Y ((( 77*r + 150*g +  29*b + 128) >> 8) +   0)
+#define U (((-43*r -  84*g + 127*b + 128) >> 8) + 128)
+#define V (((127*r - 106*g -  21*b + 128) >> 8) + 128)
+
+void
+xrgb2yuv420(u8int *bgrx, int w, int h, YUV *yuv)
+{
+	u8int *py, *pu, *pv;
+	int x, y, r, g, b;
+
+	py = yuv->y;
+	pu = yuv->u;
+	pv = yuv->v;
+
+	for(y = 0; y < h;){
+		for(x = 0; x < w;){
+			b = bgrx[0];
+			g = bgrx[1];
+			r = bgrx[2];
+			bgrx += 4;
+
+			py[x] = Y;
+			pu[x/2] = U;
+			pv[x/2] = V;
+			x++;
+
+			b = bgrx[0];
+			g = bgrx[1];
+			r = bgrx[2];
+			bgrx += 4;
+			py[x] = Y;
+			x++;
+		}
+		py += yuv->ys;
+		y++;
+
+		for(x = 0; x < w;){
+			b = bgrx[0];
+			g = bgrx[1];
+			r = bgrx[2];
+			bgrx += 4;
+			py[x] = Y;
+			x++;
+		}
+		py += yuv->ys;
+		pu += yuv->us;
+		pv += yuv->vs;
+		y++;
+	}
+}
--- /dev/null
+++ b/yuv.h
@@ -1,0 +1,8 @@
+typedef struct YUV YUV;
+
+struct YUV {
+	u8int *y, *u, *v;
+	int ys, us, vs;
+};
+
+void xrgb2yuv420(u8int *bgrx, int w, int h, YUV *yuv);