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