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