diff options
-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 |