diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2020-06-23 17:07:35 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2020-07-11 13:36:41 -0700 |
commit | 5322492387de537aad9663da403e34546b5571d4 (patch) | |
tree | 405c3939206525fd1c6e06947f005c2a6486a630 /recordmydesktop | |
parent | bd92626fb30437b06084c948cb93ecc30c4fa63d (diff) |
*: try restore some sanity to YUV macros
The public macros didn't need to be macros, so they've been
turned into functions.
All the big ugly YUV macro stuff that can be justified as macros has
been moved to rmd_yuv_utils.c where they're privately used.
They've also had a first pass at formatting them sanely...
Diffstat (limited to 'recordmydesktop')
-rw-r--r-- | recordmydesktop/src/rmd_get_frame.c | 103 | ||||
-rw-r--r-- | recordmydesktop/src/rmd_update_image.c | 10 | ||||
-rw-r--r-- | recordmydesktop/src/rmd_yuv_utils.c | 450 | ||||
-rw-r--r-- | recordmydesktop/src/rmd_yuv_utils.h | 359 |
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 |