shithub: hj264

Download patch

ref: 97b0ebb4108acac122371253a54785ef54281648
parent: 70b1cf8ab9292b471f6414b17895f583bc61ccfc
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Sun Jul 16 16:27:39 EDT 2023

extend the image if its size is not modulo 16

--- a/hj264.c
+++ b/hj264.c
@@ -63,7 +63,7 @@
 };
 
 static uvlong tstart, debug;
-static int opt;
+static int opt, noenc;
 
 #pragma varargck type "ℏ" int
 static int
@@ -169,10 +169,6 @@
 		return nil;
 	}
 
-	/* YUV logic requires alignment */
-	ww = ((ww-1) | 15) + 1;
-	hh = ((hh-1) | 15) + 1;
-
 	szyuv = ww*hh*3/2;
 	if((h = calloc(1, sizeof(*h) + Align+szyuv + Align+szpersist + Align+szscratch)) == nil)
 		return nil;
@@ -253,6 +249,8 @@
 			free(img);
 		}
 
+		if(noenc)
+			continue;
 		if(hj264_encode(h, &data, &sz) != 0)
 			sysfatal("hj264_encode: %r");
 		if(h->fmt == FmtIVF){
@@ -287,15 +285,16 @@
 }
 
 static Img *
-imgread(int f, int w, int h)
+imgread(int f, int w, int h, int tw, int th)
 {
 	int r, n, e;
+	u8int *p, *tp;
 	Img *i;
 
+	i = malloc(sizeof(*i) + tw*th*4);
+	i->w = tw;
+	i->h = th;
 	e = w*h*4;
-	i = malloc(sizeof(*i) + e);
-	i->w = w;
-	i->h = h;
 	for(n = 0; n < e; n += r){
 		if((r = pread(f, i->bgrx+n, e-n, n+5*12)) <= 0){
 			free(i);
@@ -303,6 +302,15 @@
 		}
 	}
 	i->ns = tstart + npe_nanosec();
+	if(tw > w){
+		p = i->bgrx + w*h*4;
+		tp = i->bgrx + tw*h*4;
+		for(n = h-1; n > 0; n--){
+			p -= w*4;
+			tp -= tw*4;
+			memmove(tp, p, w*4);
+		}
+	}
 
 	return i;
 }
@@ -320,7 +328,7 @@
 	int nthreads, fps, kbps, denoise, quality, qp, gop;
 	uvlong fstart, fend, f₀, nframes;
 	char *s, tmp[61], *f[5];
-	int ww, hh, in, fmt;
+	int ww₀, hh₀, ww, hh, in, fmt;
 	u8int v[20];
 	Img *img;
 	Hj264 *h;
@@ -341,6 +349,9 @@
 	case 'D':
 		denoise++;
 		break;
+	case 'E':
+		noenc++;
+		break;
 	case 'f':
 		fps = atoi(EARGF(usage()));
 		break;
@@ -394,9 +405,13 @@
 		sysfatal("invalid image");
 	if(strcmp(f[0]+1, "8r8g8b8") != 0)
 		sysfatal("only [ax]8r8g8b8 is supported");
-	ww = atoi(f[3]) - atoi(f[1]);
-	hh = atoi(f[4]) - atoi(f[2]);
+	ww₀ = atoi(f[3]) - atoi(f[1]);
+	hh₀ = atoi(f[4]) - atoi(f[2]);
 
+	/* YUV logic requires alignment */
+	ww = ((ww₀-1) | 15) + 1;
+	hh = ((hh₀-1) | 15) + 1;
+
 	if((h = hj264new(nthreads, denoise, kbps, gop, ww, hh)) == nil)
 		sysfatal("hj264new: %r");
 	if(Binit(&h->out, 1, OWRITE) < 0)
@@ -417,10 +432,10 @@
 
 	if(h->fmt == FmtIVF){
 		Bwrite(&h->out, "DKIF\x00\x00\x20\x00AVC1", 12);
-		v[0] = ww;
-		v[1] = ww >> 8;
-		v[2] = hh;
-		v[3] = hh >> 8;
+		v[0] = ww₀;
+		v[1] = ww₀ >> 8;
+		v[2] = hh₀;
+		v[3] = hh₀ >> 8;
 		v[4] = TimedenumIVF;
 		v[5] = TimedenumIVF >> 8;
 		v[6] = TimedenumIVF >> 16;
@@ -439,7 +454,7 @@
 	tstart = nsec() - f₀;
 	for(nframes = 0;; nframes++){
 		fstart = npe_nanosec();
-		if((img = imgread(in, ww, hh)) == nil)
+		if((img = imgread(in, ww₀, hh₀, ww, hh)) == nil)
 			break;
 		if(sendp(h->frame, img) != 1)
 			break;
--- a/minih264e.h
+++ b/minih264e.h
@@ -11050,7 +11050,6 @@
     {
         return H264E_STATUS_SIZE_NOT_MULTIPLE_2; // frame size must be multiple of 2
     }
-/*
     if (((par->width | par->height) & 15) && !par->const_input_flag)
     {
         // if input buffer reused as scratch (par->const_input_flag == 0)
@@ -11057,7 +11056,6 @@
         // frame size must be multiple of 16
         return H264E_STATUS_SIZE_NOT_MULTIPLE_16;
     }
-*/
     return H264E_STATUS_SUCCESS;
 };