summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--recordmydesktop/src/rmd_get_frame.c103
-rw-r--r--recordmydesktop/src/rmd_update_image.c10
-rw-r--r--recordmydesktop/src/rmd_yuv_utils.c450
-rw-r--r--recordmydesktop/src/rmd_yuv_utils.h359
4 files changed, 500 insertions, 422 deletions
diff --git a/recordmydesktop/src/rmd_get_frame.c b/recordmydesktop/src/rmd_get_frame.c
index e153d15..be199c0 100644
--- a/recordmydesktop/src/rmd_get_frame.c
+++ b/recordmydesktop/src/rmd_get_frame.c
@@ -46,12 +46,6 @@
#include <stdlib.h>
-#define AVG_4_PIXELS(data_array,width_img,k_tm,i_tm,offset)\
- ((data_array[(k_tm*width_img+i_tm)*RMD_ULONG_SIZE_T+offset]+\
- data_array[((k_tm-1)*width_img+i_tm)*RMD_ULONG_SIZE_T+offset]+\
- data_array[(k_tm*width_img+i_tm-1)*RMD_ULONG_SIZE_T+offset]+\
- data_array[((k_tm-1)*width_img+i_tm-1)*RMD_ULONG_SIZE_T+offset])/4)
-
#define CLIP_DUMMY_POINTER_AREA(dummy_p_area,brwin,xrect) {\
(xrect)->x=((((dummy_p_area).x+\
(dummy_p_area).width>=(brwin)->rrect.x)&&\
@@ -89,63 +83,6 @@
(xrect)->height=(brwin)->rrect.height;\
}
-#define XFIXES_POINTER_TO_YUV(yuv,\
- data,\
- x_tm,\
- y_tm,\
- width_tm,\
- height_tm,\
- x_offset,\
- y_offset,\
- column_discard_stride) {\
- int i,k,j=0;\
- unsigned char avg0,avg1,avg2,avg3;\
- int x_2=x_tm/2,y_2=y_tm/2;\
- for(k=y_offset;k<y_offset+height_tm;k++) {\
- for(i=x_offset;i<x_offset+width_tm;i++) {\
- j=k*(width_tm+column_discard_stride)+i;\
- (yuv)->y[x_tm+(i-x_offset)+(k+y_tm-y_offset)*(yuv)->y_width]=\
- ((yuv)->y[x_tm+(i-x_offset)+(k-y_offset+y_tm)*(yuv)->y_width]*\
- (UCHAR_MAX-data[(j*RMD_ULONG_SIZE_T)+__ABYTE])+\
- ( ( Yr[data[(j*RMD_ULONG_SIZE_T)+__RBYTE]]+\
- Yg[data[(j*RMD_ULONG_SIZE_T)+__GBYTE]] +\
- Yb[data[(j*RMD_ULONG_SIZE_T)+__BBYTE]] ) % \
- ( UCHAR_MAX + 1 ) ) * \
- data[(j*RMD_ULONG_SIZE_T)+__ABYTE])/UCHAR_MAX ;\
- if ((k%2)&&(i%2)) {\
- avg3=AVG_4_PIXELS(data,\
- (width_tm+column_discard_stride),\
- k,i,__ABYTE);\
- avg2=AVG_4_PIXELS(data,\
- (width_tm+column_discard_stride),\
- k,i,__RBYTE);\
- avg1=AVG_4_PIXELS(data,\
- (width_tm+column_discard_stride),\
- k,i,__GBYTE);\
- avg0=AVG_4_PIXELS(data,\
- (width_tm+column_discard_stride),\
- k,i,__BBYTE);\
- (yuv)->u[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*\
- (yuv)->uv_width]=\
- ((yuv)->u[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*\
- (yuv)->uv_width]*\
- (UCHAR_MAX-avg3)+\
- ( (Ur[avg2] + Ug[avg1] + UbVr[avg0]) % \
- ( UCHAR_MAX + 1 ) ) * avg3 ) / \
- UCHAR_MAX;\
- (yuv)->v[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*\
- (yuv)->uv_width]=\
- ((yuv)->v[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*\
- (yuv)->uv_width]*\
- (UCHAR_MAX-avg3)+\
- ( ( UbVr[avg2] + Vg[avg1] + Vb[avg0] ) % \
- ( UCHAR_MAX + 1 ) ) * avg3 ) / \
- UCHAR_MAX; \
- }\
- }\
- }\
-}
-
#define MARK_BUFFER_AREA_C( data,\
x_tm,\
y_tm,\
@@ -268,12 +205,15 @@ static int rmdFirstFrame(ProgData *pdata, XImage **image, XShmSegmentInfo *shmin
AllPlanes);
}
- UPDATE_YUV_BUFFER((&pdata->enc_data->yuv),
- ((unsigned char*)((*image))->data),NULL,
- (pdata->enc_data->x_offset),(pdata->enc_data->y_offset),
- (brwin->rrect.width),(brwin->rrect.height),
- (pdata->args.no_quick_subsample),
- pdata->specs.depth);
+ rmdUpdateYuvBuffer( &pdata->enc_data->yuv,
+ ((unsigned char*)((*image))->data),
+ NULL,
+ pdata->enc_data->x_offset,
+ pdata->enc_data->y_offset,
+ rrect->width,
+ rrect->height,
+ pdata->args.no_quick_subsample,
+ pdata->specs.depth);
return 0;
}
@@ -568,11 +508,12 @@ void *rmdGetFrame(ProgData *pdata) {
temp_brwin.rrect.height);
pthread_mutex_lock(&pdata->yuv_mutex);
- for(i=0;i<blocknum_x*blocknum_y;i++)
- yblocks[i]=ublocks[i]=vblocks[i]=0;
+ for(i = 0;i < blocknum_x * blocknum_y; i++)
+ yblocks[i] = ublocks[i] = vblocks[i] = 0;
- UPDATE_YUV_BUFFER( &pdata->enc_data->yuv,
- front_buff,back_buff,
+ rmdUpdateYuvBuffer( &pdata->enc_data->yuv,
+ front_buff,
+ back_buff,
pdata->enc_data->x_offset,
pdata->enc_data->y_offset,
temp_brwin.rrect.width,
@@ -602,15 +543,11 @@ void *rmdGetFrame(ProgData *pdata) {
(mouse_pos_temp.height>0)) {
if (pdata->args.xfixes_cursor) {
- XFIXES_POINTER_TO_YUV(
+ rmdXFixesPointerToYuv(
&pdata->enc_data->yuv,
((unsigned char*)xcim->pixels),
- (mouse_pos_temp.x-
- temp_brwin.rrect.x+
- pdata->enc_data->x_offset),
- (mouse_pos_temp.y-
- temp_brwin.rrect.y+
- pdata->enc_data->y_offset),
+ mouse_pos_temp.x - temp_brwin.rrect.x + pdata->enc_data->x_offset,
+ mouse_pos_temp.y - temp_brwin.rrect.y + pdata->enc_data->y_offset,
mouse_pos_temp.width,
mouse_pos_temp.height,
mouse_xoffset,
@@ -618,11 +555,11 @@ void *rmdGetFrame(ProgData *pdata) {
xcim->width-mouse_pos_temp.width
);
} else {
- DUMMY_POINTER_TO_YUV(
+ rmdDummyPointerToYuv(
&pdata->enc_data->yuv,
pdata->dummy_pointer,
- mouse_pos_temp.x- temp_brwin.rrect.x+ pdata->enc_data->x_offset,
- mouse_pos_temp.y- temp_brwin.rrect.y+ pdata->enc_data->y_offset,
+ mouse_pos_temp.x - temp_brwin.rrect.x + pdata->enc_data->x_offset,
+ mouse_pos_temp.y - temp_brwin.rrect.y + pdata->enc_data->y_offset,
mouse_pos_temp.width,
mouse_pos_temp.height,
mouse_xoffset,
diff --git a/recordmydesktop/src/rmd_update_image.c b/recordmydesktop/src/rmd_update_image.c
index 657868d..3b5c39f 100644
--- a/recordmydesktop/src/rmd_update_image.c
+++ b/recordmydesktop/src/rmd_update_image.c
@@ -73,10 +73,12 @@ void rmdUpdateImage( Display * dpy,
temp->rect.height);
}
- UPDATE_YUV_BUFFER(
- yuv,dtap,NULL,
- temp->rect.x-brwin->rrect.x+enc->x_offset,
- temp->rect.y-brwin->rrect.y+enc->y_offset,
+ rmdUpdateYuvBuffer(
+ yuv,
+ dtap,
+ NULL,
+ temp->rect.x - brwin->rrect.x + enc->x_offset,
+ temp->rect.y - brwin->rrect.y + enc->y_offset,
temp->rect.width,
temp->rect.height,
no_quick_subsample,
diff --git a/recordmydesktop/src/rmd_yuv_utils.c b/recordmydesktop/src/rmd_yuv_utils.c
index 491d9f1..d406254 100644
--- a/recordmydesktop/src/rmd_yuv_utils.c
+++ b/recordmydesktop/src/rmd_yuv_utils.c
@@ -3,7 +3,7 @@
*******************************************************************************
* *
* Copyright (C) 2006,2007,2008 John Varouhakis *
-* Copyright (C) 2008 Luca Bonavita *
+* Copyright (C) 2008 Luca Bonavita *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@@ -44,26 +44,26 @@ u_int32_t *yblocks,
void rmdMakeMatrices (void) {
int i;
-
+
/* assuming 8-bit precision */
float Yscale = 219.0, Yoffset = 16.0;
float Cscale = 224.0, Coffset = 128.0;
float RGBscale = 255.0;
-
+
float r, g, b;
float yr, yg, yb;
float ur, ug, ub;
float vg, vb; /* vr intentionally missing */
-
+
/* as for ITU-R BT-601-6 specifications: */
r = 0.299;
b = 0.114;
g = 1.0 - r - b;
-
+
/* as a note, here are the coefficients
as for ITU-R BT-709 specifications:
r=0.2126; b=0.0722; g=1.0-r-b; */
-
+
yr = r * Yscale / RGBscale;
yg = g * Yscale / RGBscale;
yb = b * Yscale / RGBscale;
@@ -73,7 +73,7 @@ void rmdMakeMatrices (void) {
/* vr = ub so UbVr = ub*i = vr*i */
vg = ( -0.5 * g / ( 1 - r ) ) * Cscale / RGBscale;
vb = ( -0.5 * b / ( 1 - r ) ) * Cscale / RGBscale;
-
+
for (i = 0; i < 256; i++) {
Yr[i] = (unsigned char) rmdRoundf( Yoffset + yr * i );
Yg[i] = (unsigned char) rmdRoundf( yg * i );
@@ -87,3 +87,439 @@ void rmdMakeMatrices (void) {
Vb[i] = (unsigned char) rmdRoundf( Coffset + vb * i );
}
}
+
+
+static inline int blocknum(int xv, int yv, int widthv, int blocksize)
+{
+ return ((yv/blocksize) * (widthv/blocksize) + (xv/blocksize));
+}
+
+/* These at least make some sense as macros since they need duplication for
+ * the multiple depths, so I've just moved and reformatted them here for now.
+ */
+
+#define UPDATE_Y_PLANE( data, \
+ x_tm, \
+ y_tm, \
+ height_tm, \
+ width_tm, \
+ yuv, \
+ __depth__){ \
+ \
+ register u_int##__depth__##_t t_val; \
+ register unsigned char *yuv_Y = (yuv)->y + x_tm + y_tm * (yuv)->y_width, \
+ *_yr = Yr, *_yg = Yg, *_yb = Yb; \
+ register u_int##__depth__##_t *datapi = (u_int##__depth__##_t *)data; \
+ \
+ for(int k = 0; k < height_tm; k++) { \
+ for(int i = 0; i < width_tm; i++) { \
+ t_val = *datapi; \
+ *yuv_Y = _yr[__RVALUE_##__depth__(t_val)] + \
+ _yg[__GVALUE_##__depth__(t_val)] + \
+ _yb[__BVALUE_##__depth__(t_val)]; \
+ datapi++; \
+ yuv_Y++; \
+ } \
+ yuv_Y += (yuv)->y_width - width_tm; \
+ } \
+}
+
+//when adding the r values, we go beyond
+//the (16 bit)range of the t_val variable, but we are performing
+//32 bit arithmetics, so there's no problem.
+//(This note is useless, I'm just adding because
+//the addition of the A components in CALC_TVAL_AVG_32,
+//now removed as uneeded, produced an overflow which would have caused
+//color distrtion, where it one of the R,G or B components)
+#define CALC_TVAL_AVG_16(t_val, datapi, datapi_next) { \
+ register u_int16_t t1, t2, t3, t4; \
+ \
+ t1 = *datapi; \
+ t2 = *(datapi + 1); \
+ t3 = *datapi_next; \
+ t4 = *(datapi_next + 1); \
+ \
+ t_val = ((((t1 & __R16_MASK) + (t2 & __R16_MASK) + \
+ (t3 & __R16_MASK) + (t4 & __R16_MASK)) / 4) & __R16_MASK) + \
+ ((((t1 & __G16_MASK) + (t2 & __G16_MASK)+ \
+ (t3 & __G16_MASK) + (t4 & __G16_MASK)) / 4) & __G16_MASK) + \
+ ((((t1 & __B16_MASK) + (t2 & __B16_MASK) + \
+ (t3 & __B16_MASK) + (t4 & __B16_MASK)) / 4) & __B16_MASK); \
+}
+
+//the 4 most significant bytes represent the A component which
+//does not need to be added on t_val, as it is always unused
+#define CALC_TVAL_AVG_32(t_val, datapi, datapi_next) { \
+ register unsigned int t1, t2, t3, t4; \
+ \
+ t1 = *datapi; \
+ t2 = *(datapi + 1); \
+ t3 = *datapi_next; \
+ t4 = *(datapi_next + 1); \
+ \
+ t_val= ((((t1 & 0x00ff0000) +(t2 & 0x00ff0000) + \
+ (t3 & 0x00ff0000)+ (t4 & 0x00ff0000)) / 4) & 0x00ff0000) + \
+ ((((t1 & 0x0000ff00) + (t2 & 0x0000ff00) + \
+ (t3 & 0x0000ff00)+ (t4 & 0x0000ff00)) / 4) & 0x0000ff00) + \
+ ((((t1 & 0x000000ff) + (t2 & 0x000000ff) + \
+ (t3 & 0x000000ff)+ (t4 & 0x000000ff)) / 4) & 0x000000ff); \
+}
+
+#define UPDATE_A_UV_PIXEL( yuv_U, \
+ yuv_V, \
+ t_val, \
+ datapi, \
+ datapi_next, \
+ _ur,_ug,_ubvr,_vg,_vb, \
+ sampling, \
+ __depth__) \
+ \
+ if(sampling == __PXL_AVERAGE) { \
+ CALC_TVAL_AVG_##__depth__(t_val, datapi, datapi_next) \
+ } else \
+ t_val = *(datapi); \
+ \
+ *(yuv_U) = _ur[__RVALUE_##__depth__(t_val)] + \
+ _ug[__GVALUE_##__depth__(t_val)] + \
+ _ubvr[__BVALUE_##__depth__(t_val)]; \
+ \
+ *(yuv_V) = _ubvr[__RVALUE_##__depth__(t_val)] + \
+ _vg[__GVALUE_##__depth__(t_val)] + \
+ _vb[__BVALUE_##__depth__(t_val)];
+
+
+#define UPDATE_UV_PLANES( data, \
+ x_tm, \
+ y_tm, \
+ height_tm, \
+ width_tm, \
+ yuv, \
+ sampling, \
+ __depth__) { \
+ \
+ register u_int##__depth__##_t t_val; \
+ register unsigned char *yuv_U = (yuv)->u + x_tm / 2 + \
+ (y_tm * (yuv)->uv_width) / 2, \
+ *yuv_V = (yuv)->v + x_tm / 2 + \
+ (y_tm * (yuv)->uv_width) / 2, \
+ *_ur = Ur, *_ug = Ug, *_ubvr = UbVr, \
+ *_vg = Vg, *_vb = Vb; \
+ register u_int##__depth__##_t *datapi = (u_int##__depth__##_t *)data, \
+ *datapi_next = NULL; \
+ \
+ if(sampling == __PXL_AVERAGE) \
+ datapi_next = datapi + width_tm; \
+ \
+ for(int k = 0; k < height_tm; k += 2) { \
+ for(int i = 0; i < width_tm; i += 2) { \
+ UPDATE_A_UV_PIXEL( yuv_U, \
+ yuv_V, \
+ t_val, \
+ datapi, \
+ datapi_next, \
+ _ur, _ug, _ubvr, _vg, _vb, \
+ sampling, \
+ __depth__); \
+ \
+ datapi += 2; \
+ if(sampling==__PXL_AVERAGE) \
+ datapi_next += 2; \
+ yuv_U++; \
+ yuv_V++; \
+ } \
+ \
+ yuv_U += ((yuv)->y_width-width_tm) / 2; \
+ yuv_V += ((yuv)->y_width-width_tm) / 2; \
+ datapi += width_tm; \
+ \
+ if(sampling==__PXL_AVERAGE) \
+ datapi_next+=width_tm; \
+ } \
+}
+
+#define UPDATE_Y_PLANE_DBUF( data, \
+ data_back, \
+ x_tm, \
+ y_tm, \
+ height_tm, \
+ width_tm, \
+ yuv, \
+ __depth__) { \
+ \
+ register u_int##__depth__##_t t_val; \
+ register unsigned char *yuv_Y = (yuv)->y + x_tm + y_tm * (yuv)->y_width, \
+ *_yr = Yr, *_yg = Yg, *_yb = Yb; \
+ register u_int##__depth__##_t *datapi = (u_int##__depth__##_t *)data, \
+ *datapi_back = (u_int##__depth__##_t *)data_back; \
+ \
+ for(int k = 0; k < height_tm; k++) { \
+ for(int i = 0; i < width_tm; i++) { \
+ if(*datapi != *datapi_back) { \
+ t_val = *datapi; \
+ *yuv_Y = _yr[__RVALUE_##__depth__(t_val)] + \
+ _yg[__GVALUE_##__depth__(t_val)] + \
+ _yb[__BVALUE_##__depth__(t_val)]; \
+ yblocks[blocknum(i, k, width_tm, Y_UNIT_WIDTH)] = 1; \
+ } \
+ datapi++; \
+ datapi_back++; \
+ yuv_Y++; \
+ } \
+ yuv_Y += (yuv)->y_width-width_tm; \
+ } \
+}
+
+#define UPDATE_UV_PLANES_DBUF( data, \
+ data_back, \
+ x_tm, \
+ y_tm, \
+ height_tm, \
+ width_tm, \
+ yuv, \
+ sampling, \
+ __depth__) { \
+ \
+ register u_int##__depth__##_t t_val; \
+ register unsigned char *yuv_U = (yuv)->u + x_tm / 2 + \
+ (y_tm * (yuv)->uv_width) / 2, \
+ *yuv_V = (yuv)->v + x_tm / 2 + \
+ (y_tm * (yuv)->uv_width) / 2, \
+ *_ur = Ur, *_ug = Ug, *_ubvr = UbVr, \
+ *_vg = Vg, *_vb = Vb; \
+ \
+ register u_int##__depth__##_t *datapi = (u_int##__depth__##_t *)data, \
+ *datapi_next = NULL, \
+ *datapi_back = (u_int##__depth__##_t *)data_back, \
+ *datapi_back_next = NULL; \
+ \
+ if (sampling == __PXL_AVERAGE) { \
+ datapi_next = datapi + width_tm; \
+ datapi_back_next = datapi_back + width_tm; \
+ \
+ for (int k = 0; k < height_tm; k += 2) { \
+ for(int i = 0; i < width_tm; i += 2) { \
+ if( ( (*datapi != *datapi_back) || \
+ (*(datapi + 1) != *(datapi_back + 1)) || \
+ (*datapi_next != *datapi_back_next) || \
+ (*(datapi_next + 1) != *(datapi_back_next + 1)))) { \
+ \
+ UPDATE_A_UV_PIXEL( yuv_U, \
+ yuv_V, \
+ t_val, \
+ datapi, \
+ datapi_next, \
+ _ur,_ug,_ubvr,_vg,_vb, \
+ sampling, \
+ __depth__); \
+ \
+ ublocks[blocknum(i, k, width_tm, Y_UNIT_WIDTH)] = 1; \
+ vblocks[blocknum(i, k, width_tm, Y_UNIT_WIDTH)] = 1; \
+ } \
+ \
+ datapi += 2; \
+ datapi_back += 2; \
+ if (sampling == __PXL_AVERAGE) { \
+ datapi_next += 2; \
+ datapi_back_next += 2; \
+ } \
+ yuv_U++; \
+ yuv_V++; \
+ } \
+ \
+ yuv_U += ((yuv)->y_width - width_tm) / 2; \
+ yuv_V += ((yuv)->y_width - width_tm) / 2; \
+ datapi += width_tm; \
+ datapi_back += width_tm; \
+ \
+ if (sampling == __PXL_AVERAGE) { \
+ datapi_next += width_tm; \
+ datapi_back_next += width_tm; \
+ } \
+ } \
+ } else { \
+ for (int k = 0; k < height_tm; k += 2) { \
+ for (int i = 0; i < width_tm; i += 2) { \
+ if ((*datapi != *datapi_back)) { \
+ UPDATE_A_UV_PIXEL( yuv_U, \
+ yuv_V, \
+ t_val, \
+ datapi, \
+ datapi_next, \
+ _ur,_ug,_ubvr,_vg,_vb, \
+ sampling, \
+ __depth__); \
+ \
+ ublocks[blocknum(i, k, width_tm, Y_UNIT_WIDTH)] = 1; \
+ vblocks[blocknum(i, k, width_tm, Y_UNIT_WIDTH)] = 1; \
+ } \
+ datapi += 2; \
+ datapi_back += 2; \
+ if (sampling == __PXL_AVERAGE) { \
+ datapi_next += 2; \
+ datapi_back_next += 2; \
+ } \
+ yuv_U++; \
+ yuv_V++; \
+ } \
+ yuv_U += ((yuv)->y_width-width_tm)/2; \
+ yuv_V += ((yuv)->y_width-width_tm)/2; \
+ datapi += width_tm; \
+ datapi_back += width_tm; \
+ if (sampling == __PXL_AVERAGE) { \
+ datapi_next += width_tm; \
+ datapi_back_next += width_tm; \
+ } \
+ } \
+ } \
+}
+
+
+void rmdUpdateYuvBuffer( yuv_buffer *yuv,
+ unsigned char *data,
+ unsigned char *data_back,
+ int x_tm,
+ int y_tm,
+ int width_tm,
+ int height_tm,
+ int sampling_type,
+ int color_depth) {
+
+ if (data_back == NULL) {
+ switch (color_depth) {
+ case 24:
+ case 32:
+ UPDATE_Y_PLANE(data, x_tm, y_tm, height_tm, width_tm, yuv, 32);
+ UPDATE_UV_PLANES(data, x_tm, y_tm, height_tm, width_tm, yuv, sampling_type, 32);
+ break;
+ case 16:
+ UPDATE_Y_PLANE(data, x_tm, y_tm, height_tm, width_tm, yuv, 16);
+ UPDATE_UV_PLANES(data, x_tm, y_tm, height_tm, width_tm, yuv, sampling_type, 16);
+ break;
+ default:
+ assert(0);
+ }
+ } else {
+ switch (color_depth) {
+ case 24:
+ case 32:
+ UPDATE_Y_PLANE_DBUF(data, data_back, x_tm, y_tm, height_tm, width_tm, yuv, 32);
+ UPDATE_UV_PLANES_DBUF(data, data_back, x_tm, y_tm, height_tm, width_tm, yuv, sampling_type, 32);
+ break;
+ case 16:
+ UPDATE_Y_PLANE_DBUF(data, data_back, x_tm, y_tm, height_tm, width_tm, yuv, 16);
+ UPDATE_UV_PLANES_DBUF(data, data_back, x_tm, y_tm, height_tm, width_tm, yuv, sampling_type, 16);
+ break;
+ default:
+ assert(0);
+ }
+ }
+}
+
+
+void rmdDummyPointerToYuv( yuv_buffer *yuv,
+ unsigned char *data_tm,
+ int x_tm,
+ int y_tm,
+ int width_tm,
+ int height_tm,
+ int x_offset,
+ int y_offset,
+ unsigned char no_pixel) {
+
+ int i, k, j = 0;
+ int x_2 = x_tm / 2, y_2 = y_tm / 2, y_width_2 = yuv->y_width/2;
+
+ for (k = y_offset; k < y_offset + height_tm; k++) {
+ for (i = x_offset; i < x_offset + width_tm; i++) {
+ j = k * 16 + i;
+
+ if (data_tm[j * 4] != no_pixel) {
+ yuv->y[x_tm + (i - x_offset) + ((k - y_offset) + y_tm) * yuv->y_width] =
+ Yr[data_tm[j * 4 + __RBYTE]] +
+ Yg[data_tm[j * 4 + __GBYTE]] +
+ Yb[data_tm[j * 4 + __BBYTE]];
+
+ if ((k % 2) && (i % 2)) {
+ yuv->u[x_2 + (i - x_offset) / 2 + ((k - y_offset) / 2 + y_2) * y_width_2] =
+ Ur[data_tm[(k * width_tm + i) * 4 + __RBYTE]] +
+ Ug[data_tm[(k * width_tm + i) * 4 + __GBYTE]] +
+ UbVr[data_tm[(k * width_tm + i) * 4 + __BBYTE]];
+ yuv->v[x_2 + (i - x_offset) / 2 + ((k - y_offset) / 2 + y_2) * y_width_2] =
+ UbVr[data_tm[(k * width_tm + i) * 4 + __RBYTE]] +
+ Vg[data_tm[(k * width_tm + i) * 4 + __GBYTE]] +
+ Vb[data_tm[(k * width_tm + i) * 4 + __BBYTE]] ;
+ }
+ }
+ }
+ }
+
+}
+
+static inline unsigned char avg_4_pixels( unsigned char *data_array,
+ int width_img,
+ int k_tm,
+ int i_tm,
+ int offset)
+{
+
+ return ((data_array[(k_tm*width_img+i_tm)*RMD_ULONG_SIZE_T+offset]+
+ data_array[((k_tm-1)*width_img+i_tm)*RMD_ULONG_SIZE_T+offset]+
+ data_array[(k_tm*width_img+i_tm-1)*RMD_ULONG_SIZE_T+offset]+
+ data_array[((k_tm-1)*width_img+i_tm-1)*RMD_ULONG_SIZE_T+offset])/4);
+}
+
+void rmdXFixesPointerToYuv( yuv_buffer *yuv,
+ unsigned char *data_tm,
+ int x_tm,
+ int y_tm,
+ int width_tm,
+ int height_tm,
+ int x_offset,
+ int y_offset,
+ int column_discard_stride) {
+
+ unsigned char avg0, avg1, avg2, avg3;
+ int x_2 = x_tm / 2, y_2 = y_tm / 2;
+
+ for (int k = y_offset; k < y_offset + height_tm; k++) {
+ for (int i = x_offset;i < x_offset + width_tm; i++) {
+ int j = k * (width_tm + column_discard_stride) + i;
+
+ yuv->y[x_tm + (i - x_offset) + (k + y_tm - y_offset) * yuv->y_width] =
+ (yuv->y[x_tm + (i - x_offset) + (k - y_offset + y_tm) * yuv->y_width] *
+ (UCHAR_MAX - data_tm[(j * RMD_ULONG_SIZE_T) + __ABYTE]) +
+ ( ( Yr[data_tm[(j * RMD_ULONG_SIZE_T) + __RBYTE]] +
+ Yg[data_tm[(j * RMD_ULONG_SIZE_T) + __GBYTE]] +
+ Yb[data_tm[(j * RMD_ULONG_SIZE_T) + __BBYTE]] ) %
+ ( UCHAR_MAX + 1 ) ) *
+ data_tm[(j * RMD_ULONG_SIZE_T) + __ABYTE]) / UCHAR_MAX;
+
+ if ((k % 2) && (i % 2)) {
+ int idx = x_2 + (i - x_offset) / 2 + ((k - y_offset) / 2 + y_2) * yuv->uv_width;
+
+ avg3 = avg_4_pixels( data_tm,
+ (width_tm + column_discard_stride),
+ k, i, __ABYTE);
+ avg2 = avg_4_pixels( data_tm,
+ (width_tm + column_discard_stride),
+ k, i, __RBYTE);
+ avg1 = avg_4_pixels( data_tm,
+ (width_tm + column_discard_stride),
+ k, i, __GBYTE);
+ avg0 = avg_4_pixels( data_tm,
+ (width_tm + column_discard_stride),
+ k, i, __BBYTE);
+
+ yuv->u[idx] =
+ (yuv->u[idx] * (UCHAR_MAX - avg3) +
+ ((Ur[avg2] + Ug[avg1] + UbVr[avg0]) % (UCHAR_MAX + 1))
+ * avg3) / UCHAR_MAX;
+
+ yuv->v[idx]=
+ (yuv->u[idx] * (UCHAR_MAX - avg3) +
+ ((UbVr[avg2] + Vg[avg1] + Vb[avg0]) % (UCHAR_MAX + 1))
+ * avg3) / UCHAR_MAX;
+ }
+ }
+ }
+}
diff --git a/recordmydesktop/src/rmd_yuv_utils.h b/recordmydesktop/src/rmd_yuv_utils.h
index f0c9130..36070b6 100644
--- a/recordmydesktop/src/rmd_yuv_utils.h
+++ b/recordmydesktop/src/rmd_yuv_utils.h
@@ -39,342 +39,45 @@ extern unsigned char Yr[256], Yg[256], Yb[256],
// We keep these global for now. FIXME: Isolate them.
-extern u_int32_t *yblocks,
+extern u_int32_t *yblocks, /* XXX FIXME why is this u_int32_t when it seems to be simple bool flags? */
*ublocks,
*vblocks;
-#define POINT_IN_BLOCK(xv,yv,widthv,blocksize) ((yv/blocksize)*\
- (widthv/blocksize)+\
- (xv/blocksize))
-
-//when adding the r values, we go beyond
-//the (16 bit)range of the t_val variable, but we are performing
-//32 bit arithmetics, so there's no problem.
-//(This note is useless, I'm just adding because
-//the addition of the A components in CALC_TVAL_AVG_32,
-//now removed as uneeded, produced an overflow which would have caused
-//color distrtion, where it one of the R,G or B components)
-#define CALC_TVAL_AVG_16(t_val,datapi,datapi_next){\
- register u_int16_t t1,t2,t3,t4;\
- t1=*datapi;\
- t2=*(datapi+1);\
- t3=*datapi_next;\
- t4=*(datapi_next+1);\
- t_val=((((t1&__R16_MASK) +(t2&__R16_MASK)+\
- (t3&__R16_MASK)+(t4&__R16_MASK))/4)&__R16_MASK)+\
- ((((t1&__G16_MASK) +(t2&__G16_MASK)+\
- (t3&__G16_MASK)+(t4&__G16_MASK))/4)&__G16_MASK)+\
- ((((t1&__B16_MASK) +(t2&__B16_MASK)+\
- (t3&__B16_MASK)+(t4&__B16_MASK))/4)&__B16_MASK);\
-}
-
-//the 4 most significant bytes represent the A component which
-//does not need to be added on t_val, as it is always unused
-#define CALC_TVAL_AVG_32(t_val,datapi,datapi_next){\
- register unsigned int t1,t2,t3,t4;\
- t1=*datapi;\
- t2=*(datapi+1);\
- t3=*datapi_next;\
- t4=*(datapi_next+1);\
- t_val=((((t1&0x00ff0000) +(t2&0x00ff0000)+\
- (t3&0x00ff0000)+(t4&0x00ff0000))/4)&0x00ff0000)+\
- ((((t1&0x0000ff00) +(t2&0x0000ff00)+\
- (t3&0x0000ff00)+(t4&0x0000ff00))/4)&0x0000ff00)+\
- ((((t1&0x000000ff) +(t2&0x000000ff)+\
- (t3&0x000000ff)+(t4&0x000000ff))/4)&0x000000ff);\
-}
-
-#define UPDATE_Y_PLANE(data,\
- x_tm,\
- y_tm,\
- height_tm,\
- width_tm,\
- yuv,\
- __bit_depth__){ \
- int k,i;\
- register u_int##__bit_depth__##_t t_val;\
- register unsigned char *yuv_y=(yuv)->y+x_tm+y_tm*(yuv)->y_width,\
- *_yr=Yr,*_yg=Yg,*_yb=Yb;\
- register u_int##__bit_depth__##_t *datapi=(u_int##__bit_depth__##_t *)data;\
- for(k=0;k<height_tm;k++){\
- for(i=0;i<width_tm;i++){\
- t_val=*datapi;\
- *yuv_y=_yr[__RVALUE_##__bit_depth__(t_val)] +\
- _yg[__GVALUE_##__bit_depth__(t_val)] +\
- _yb[__BVALUE_##__bit_depth__(t_val)] ;\
- datapi++;\
- yuv_y++;\
- }\
- yuv_y+=(yuv)->y_width-width_tm;\
- }\
-}
-
-#define UPDATE_A_UV_PIXEL(yuv_u,\
- yuv_v,\
- t_val,\
- datapi,\
- datapi_next,\
- _ur,_ug,_ubvr,_vg,_vb,\
- __sampling_type,\
- __bit_depth__)\
- if(__sampling_type==__PXL_AVERAGE){\
- CALC_TVAL_AVG_##__bit_depth__(t_val,datapi,datapi_next)\
- }\
- else\
- t_val=*datapi;\
- *yuv_u=\
- _ur[__RVALUE_##__bit_depth__(t_val)] +\
- _ug[__GVALUE_##__bit_depth__(t_val)] +\
- _ubvr[__BVALUE_##__bit_depth__(t_val)];\
- *yuv_v=\
- _ubvr[__RVALUE_##__bit_depth__(t_val)] +\
- _vg[__GVALUE_##__bit_depth__(t_val)] +\
- _vb[__BVALUE_##__bit_depth__(t_val)];\
-
-
-#define UPDATE_UV_PLANES(data,\
- x_tm,\
- y_tm,\
- height_tm,\
- width_tm,\
- yuv,\
- __sampling_type,\
- __bit_depth__){ \
- int k,i;\
- register u_int##__bit_depth__##_t t_val;\
- register unsigned char *yuv_u=(yuv)->u+x_tm/2+(y_tm*(yuv)->uv_width)/2,\
- *yuv_v=(yuv)->v+x_tm/2+(y_tm*(yuv)->uv_width)/2,\
- *_ur=Ur,*_ug=Ug,*_ubvr=UbVr,\
- *_vg=Vg,*_vb=Vb;\
- register u_int##__bit_depth__##_t *datapi=(u_int##__bit_depth__##_t *)data,\
- *datapi_next=NULL;\
- if(__sampling_type==__PXL_AVERAGE){\
- datapi_next=datapi+width_tm;\
- }\
- for(k=0;k<height_tm;k+=2){\
- for(i=0;i<width_tm;i+=2){\
- UPDATE_A_UV_PIXEL( yuv_u,\
- yuv_v,\
- t_val,\
- datapi,\
- datapi_next,\
- _ur,_ug,_ubvr,_vg,_vb,\
- __sampling_type,\
- __bit_depth__)\
- datapi+=2;\
- if(__sampling_type==__PXL_AVERAGE)\
- datapi_next+=2;\
- yuv_u++;\
- yuv_v++;\
- }\
- yuv_u+=((yuv)->y_width-width_tm)/2;\
- yuv_v+=((yuv)->y_width-width_tm)/2;\
- datapi+=width_tm;\
- if(__sampling_type==__PXL_AVERAGE)\
- datapi_next+=width_tm;\
- }\
-}
-
-#define UPDATE_YUV_BUFFER(yuv,\
- data,\
- data_back,\
- x_tm,\
- y_tm,\
- width_tm,\
- height_tm,\
- __sampling_type,\
- __color_depth){\
- if(data_back==NULL){\
- if((__color_depth==24)||(__color_depth==32)){\
- UPDATE_Y_PLANE(data,x_tm,y_tm,height_tm,width_tm,yuv,32)\
- UPDATE_UV_PLANES(data,x_tm,y_tm,height_tm,width_tm,\
- yuv,__sampling_type,32)\
- }\
- else if(__color_depth==16){\
- UPDATE_Y_PLANE(data,x_tm,y_tm,height_tm,width_tm,yuv,16)\
- UPDATE_UV_PLANES(data,x_tm,y_tm,height_tm,width_tm,\
- yuv,__sampling_type,16)\
- }\
- }\
- else{\
- if((__color_depth==24)||(__color_depth==32)){\
- UPDATE_Y_PLANE_DBUF(data,data_back,x_tm,y_tm,\
- height_tm,width_tm,yuv,32)\
- UPDATE_UV_PLANES_DBUF(data,data_back,x_tm,y_tm,height_tm,width_tm,\
- yuv,__sampling_type,32)\
- }\
- else if(__color_depth==16){\
- UPDATE_Y_PLANE_DBUF(data,data_back,x_tm,y_tm,\
- height_tm,width_tm,yuv,16)\
- UPDATE_UV_PLANES_DBUF(data,data_back,x_tm,y_tm,height_tm,width_tm,\
- yuv,__sampling_type,16)\
- }\
- }\
-}
-
-#define DUMMY_POINTER_TO_YUV(yuv,\
- data_tm,\
- x_tm,\
- y_tm,\
- width_tm,\
- height_tm,\
- x_offset,\
- y_offset,\
- no_pixel){\
- int i,k,j=0;\
- int x_2=x_tm/2,y_2=y_tm/2,y_width_2=(yuv)->y_width/2;\
- for(k=y_offset;k<y_offset+height_tm;k++){\
- for(i=x_offset;i<x_offset+width_tm;i++){\
- j=k*16+i;\
- if(data_tm[(j*4)]!=(no_pixel)){\
- (yuv)->y[x_tm+(i-x_offset)+((k-y_offset)+y_tm)*(yuv)->y_width]=\
- Yr[data_tm[(j*4)+__RBYTE]] +\
- Yg[data_tm[(j*4)+__GBYTE]] +\
- Yb[data_tm[(j*4)+__BBYTE]];\
- if((k%2)&&(i%2)){\
- (yuv)->u[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*y_width_2]=\
- Ur[data_tm[(k*width_tm+i)*4+__RBYTE]] +\
- Ug[data_tm[(k*width_tm+i)*4+__GBYTE]] +\
- UbVr[data_tm[(k*width_tm+i)*4+__BBYTE]];\
- (yuv)->v[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*y_width_2]=\
- UbVr[data_tm[(k*width_tm+i)*4+__RBYTE]] +\
- Vg[data_tm[(k*width_tm+i)*4+__GBYTE]] +\
- Vb[data_tm[(k*width_tm+i)*4+__BBYTE]] ;\
- }\
- }\
- }\
- }\
-}
-
-#define UPDATE_Y_PLANE_DBUF(data,\
- data_back,\
- x_tm,\
- y_tm,\
- height_tm,\
- width_tm,\
- yuv,\
- __bit_depth__){ \
- int k,i;\
- register u_int##__bit_depth__##_t t_val;\
- register unsigned char *yuv_y=(yuv)->y+x_tm+y_tm*(yuv)->y_width,\
- *_yr=Yr,*_yg=Yg,*_yb=Yb;\
- register u_int##__bit_depth__##_t *datapi=(u_int##__bit_depth__##_t *)data,\
- *datapi_back=(u_int##__bit_depth__##_t *)data_back;\
- for(k=0;k<height_tm;k++){\
- for(i=0;i<width_tm;i++){\
- if(*datapi!=*datapi_back){\
- t_val=*datapi;\
- *yuv_y=_yr[__RVALUE_##__bit_depth__(t_val)] +\
- _yg[__GVALUE_##__bit_depth__(t_val)] +\
- _yb[__BVALUE_##__bit_depth__(t_val)] ;\
- yblocks[POINT_IN_BLOCK(i,k,width_tm,Y_UNIT_WIDTH)]=1;\
- }\
- datapi++;\
- datapi_back++;\
- yuv_y++;\
- }\
- yuv_y+=(yuv)->y_width-width_tm;\
- }\
-}
-
-#define UPDATE_UV_PLANES_DBUF( data,\
- data_back,\
- x_tm,\
- y_tm,\
- height_tm,\
- width_tm,\
- yuv,\
- __sampling_type,\
- __bit_depth__){ \
- int k,i;\
- register u_int##__bit_depth__##_t t_val;\
- register unsigned char *yuv_u=(yuv)->u+x_tm/2+(y_tm*(yuv)->uv_width)/2,\
- *yuv_v=(yuv)->v+x_tm/2+(y_tm*(yuv)->uv_width)/2,\
- *_ur=Ur,*_ug=Ug,*_ubvr=UbVr,\
- *_vg=Vg,*_vb=Vb;\
- register u_int##__bit_depth__##_t *datapi=(u_int##__bit_depth__##_t *)data,\
- *datapi_next=NULL,\
- *datapi_back=(u_int##__bit_depth__##_t *)data_back,\
- *datapi_back_next=NULL;\
- if(__sampling_type==__PXL_AVERAGE){\
- datapi_next=datapi+width_tm;\
- datapi_back_next=datapi_back+width_tm;\
- for(k=0;k<height_tm;k+=2){\
- for(i=0;i<width_tm;i+=2){\
- if(( (*datapi!=*datapi_back) ||\
- (*(datapi+1)!=*(datapi_back+1)) ||\
- (*datapi_next!=*datapi_back_next) ||\
- (*(datapi_next+1)!=*(datapi_back_next+1)))){\
- UPDATE_A_UV_PIXEL( yuv_u,\
- yuv_v,\
- t_val,\
- datapi,\
- datapi_next,\
- _ur,_ug,_ubvr,_vg,_vb,\
- __sampling_type,\
- __bit_depth__)\
- ublocks[POINT_IN_BLOCK(i,k,width_tm,Y_UNIT_WIDTH)]=1;\
- vblocks[POINT_IN_BLOCK(i,k,width_tm,Y_UNIT_WIDTH)]=1;\
- }\
- datapi+=2;\
- datapi_back+=2;\
- if(__sampling_type==__PXL_AVERAGE){\
- datapi_next+=2;\
- datapi_back_next+=2;\
- }\
- yuv_u++;\
- yuv_v++;\
- }\
- yuv_u+=((yuv)->y_width-width_tm)/2;\
- yuv_v+=((yuv)->y_width-width_tm)/2;\
- datapi+=width_tm;\
- datapi_back+=width_tm;\
- if(__sampling_type==__PXL_AVERAGE){\
- datapi_next+=width_tm;\
- datapi_back_next+=width_tm;\
- }\
- }\
- }\
- else{\
- for(k=0;k<height_tm;k+=2){\
- for(i=0;i<width_tm;i+=2){\
- if ((*datapi!=*datapi_back)){\
- UPDATE_A_UV_PIXEL( yuv_u,\
- yuv_v,\
- t_val,\
- datapi,\
- datapi_next,\
- _ur,_ug,_ubvr,_vg,_vb,\
- __sampling_type,\
- __bit_depth__)\
- ublocks[POINT_IN_BLOCK(i,k,width_tm,Y_UNIT_WIDTH)]=1;\
- vblocks[POINT_IN_BLOCK(i,k,width_tm,Y_UNIT_WIDTH)]=1;\
- }\
- datapi+=2;\
- datapi_back+=2;\
- if(__sampling_type==__PXL_AVERAGE){\
- datapi_next+=2;\
- datapi_back_next+=2;\
- }\
- yuv_u++;\
- yuv_v++;\
- }\
- yuv_u+=((yuv)->y_width-width_tm)/2;\
- yuv_v+=((yuv)->y_width-width_tm)/2;\
- datapi+=width_tm;\
- datapi_back+=width_tm;\
- if(__sampling_type==__PXL_AVERAGE){\
- datapi_next+=width_tm;\
- datapi_back_next+=width_tm;\
- }\
- }\
- }\
-}
/**
* Fill Yr,Yg,Yb,Ur,Ug.Ub,Vr,Vg,Vb arrays(globals) with values.
*/
void rmdMakeMatrices(void);
+/* update yuv from data and optionally data_back */
+void rmdUpdateYuvBuffer( yuv_buffer *yuv,
+ unsigned char *data,
+ unsigned char *data_back,
+ int x_tm,
+ int y_tm,
+ int width_tm,
+ int height_tm,
+ int sampling_type,
+ int color_depth);
+
+void rmdDummyPointerToYuv( yuv_buffer *yuv,
+ unsigned char *data_tm,
+ int x_tm,
+ int y_tm,
+ int width_tm,
+ int height_tm,
+ int x_offset,
+ int y_offset,
+ unsigned char no_pixel);
+
+void rmdXFixesPointerToYuv( yuv_buffer *yuv,
+ unsigned char *data_tm,
+ int x_tm,
+ int y_tm,
+ int width_tm,
+ int height_tm,
+ int x_offset,
+ int y_offset,
+ int column_discard_stride);
#endif
© All Rights Reserved