shithub: dav1d

Download patch

ref: 298977f391e79902b3bd3d3b9f1f6d9c8a3d3347
parent: 80719550be738385d1deddf193c6321a1e80f3a1
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Sun Sep 6 08:39:22 EDT 2020

put yuv2rgb code into av19

--- a/src/av19.c
+++ b/src/av19.c
@@ -4,7 +4,6 @@
 #include <memdraw.h>
 #include <mouse.h>
 #include <keyboard.h>
-#include <yuv_rgb.h> // FIXME this is most likely slow
 #include <tos.h>
 /* FIXME this one is slow as hell
 #define STB_IMAGE_RESIZE_IMPLEMENTATION
@@ -37,6 +36,21 @@
 static Player *curplayer;
 static Image *curframe;
 
+/* yuv→rgb by Adrien Descamps */
+
+#define clamp(v) ((v)<0?0 : ((v)>255?255:v))
+#define FIXED_POINT_VALUE(value, precision) ((int)(((value)*(1<<precision))+0.5))
+
+typedef struct
+{
+	u8int cb_factor;   // [(255*CbNorm)/CbRange]
+	u8int cr_factor;   // [(255*CrNorm)/CrRange]
+	u8int g_cb_factor; // [Bf/Gf*(255*CbNorm)/CbRange]
+	u8int g_cr_factor; // [Rf/Gf*(255*CrNorm)/CrRange]
+	u8int y_factor;    // [(YMax-YMin)/255]
+	u8int y_offset;    // YMin
+} YUV2RGBParam;
+
 static char *layout[] = {
 	[DAV1D_PIXEL_LAYOUT_I400] = "i400",
     [DAV1D_PIXEL_LAYOUT_I420] = "i420",
@@ -44,12 +58,89 @@
     [DAV1D_PIXEL_LAYOUT_I444] = "i444",
 };
 
+#define YUV2RGB_PARAM(Rf, Bf, YMin, YMax, CbCrRange) \
+{.cb_factor=FIXED_POINT_VALUE(255.0*(2.0*(1-Bf))/CbCrRange, 6), \
+.cr_factor=FIXED_POINT_VALUE(255.0*(2.0*(1-Rf))/CbCrRange, 6), \
+.g_cb_factor=FIXED_POINT_VALUE(Bf/(1.0-Bf-Rf)*255.0*(2.0*(1-Bf))/CbCrRange, 7), \
+.g_cr_factor=FIXED_POINT_VALUE(Rf/(1.0-Bf-Rf)*255.0*(2.0*(1-Rf))/CbCrRange, 7), \
+.y_factor=FIXED_POINT_VALUE(255.0/(YMax-YMin), 7), \
+.y_offset=YMin}
+
+static const YUV2RGBParam YUV2RGB[3] = {
+	// ITU-T T.871 (JPEG)
+	YUV2RGB_PARAM(0.299, 0.114, 0.0, 255.0, 255.0),
+	// ITU-R BT.601-7
+	YUV2RGB_PARAM(0.299, 0.114, 16.0, 235.0, 224.0),
+	// ITU-R BT.709-6
+	YUV2RGB_PARAM(0.2126, 0.0722, 16.0, 235.0, 224.0)
+};
+
+static void yuv420_rgb24(
+	u32int width, u32int height,
+	const u8int *Y, const u8int *U, const u8int *V, u32int Y_stride, u32int UV_stride,
+	u8int *RGB, u32int RGB_stride)
+{
+	const YUV2RGBParam *const param = &(YUV2RGB[0]);
+	u32int x, y;
+	for(y=0; y<(height-1); y+=2)
+	{
+		const u8int *y_ptr1=Y+y*Y_stride,
+			*y_ptr2=Y+(y+1)*Y_stride,
+			*u_ptr=U+(y/2)*UV_stride,
+			*v_ptr=V+(y/2)*UV_stride;
+
+		u8int *rgb_ptr1=RGB+y*RGB_stride,
+			*rgb_ptr2=RGB+(y+1)*RGB_stride;
+
+		for(x=0; x<(width-1); x+=2)
+		{
+			s8int u_tmp, v_tmp;
+			u_tmp = u_ptr[0]-128;
+			v_tmp = v_ptr[0]-128;
+
+			//compute Cb Cr color offsets, common to four pixels
+			s16int b_cb_offset, r_cr_offset, g_cbcr_offset;
+			b_cb_offset = (param->cb_factor*u_tmp)>>6;
+			r_cr_offset = (param->cr_factor*v_tmp)>>6;
+			g_cbcr_offset = (param->g_cb_factor*u_tmp + param->g_cr_factor*v_tmp)>>7;
+
+			s16int y_tmp;
+			y_tmp = (param->y_factor*(y_ptr1[0]-param->y_offset))>>7;
+			rgb_ptr1[2] = clamp(y_tmp + r_cr_offset);
+			rgb_ptr1[1] = clamp(y_tmp - g_cbcr_offset);
+			rgb_ptr1[0] = clamp(y_tmp + b_cb_offset);
+
+			y_tmp = (param->y_factor*(y_ptr1[1]-param->y_offset))>>7;
+			rgb_ptr1[5] = clamp(y_tmp + r_cr_offset);
+			rgb_ptr1[4] = clamp(y_tmp - g_cbcr_offset);
+			rgb_ptr1[3] = clamp(y_tmp + b_cb_offset);
+
+			y_tmp = (param->y_factor*(y_ptr2[0]-param->y_offset))>>7;
+			rgb_ptr2[2] = clamp(y_tmp + r_cr_offset);
+			rgb_ptr2[1] = clamp(y_tmp - g_cbcr_offset);
+			rgb_ptr2[0] = clamp(y_tmp + b_cb_offset);
+
+			y_tmp = (param->y_factor*(y_ptr2[1]-param->y_offset))>>7;
+			rgb_ptr2[5] = clamp(y_tmp + r_cr_offset);
+			rgb_ptr2[4] = clamp(y_tmp - g_cbcr_offset);
+			rgb_ptr2[3] = clamp(y_tmp + b_cb_offset);
+
+			rgb_ptr1 += 6;
+			rgb_ptr2 += 6;
+			y_ptr1 += 2;
+			y_ptr2 += 2;
+			u_ptr += 1;
+			v_ptr += 1;
+		}
+	}
+}
+
 static int
 dav1d_loadimage(Rectangle r, Image **oim, Dav1dPicture *p)
 {
 	Image *im;
-	uchar *rgb, t;
-	int w, h, i;
+	uchar *rgb;
+	int w, h;
 
 	if(*oim == nil)
 		*oim = allocimage(display, r, RGB24, 0, DNofill);
@@ -59,7 +150,7 @@
 	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, YCBCR_JPEG);
+	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){
@@ -78,11 +169,6 @@
 
 	w = Dx(r);
 	h = Dy(r);
-	for(i = 0; i < w*h; i++){
-		t = rgb[i*3+2];
-		rgb[i*3+2] = rgb[i*3+0];
-		rgb[i*3+0] = t;
-	}
 	loadimage(im, Rect(0,0,w,h), rgb, w*h*3);
 	free(rgb);