summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--recordmydesktop/ChangeLog1
-rw-r--r--recordmydesktop/doc/recordmydesktop.111
-rw-r--r--recordmydesktop/include/recordmydesktop.h61
-rw-r--r--recordmydesktop/src/bgr_to_yuv.c29
-rw-r--r--recordmydesktop/src/get_frame.c9
-rw-r--r--recordmydesktop/src/parseargs.c6
-rw-r--r--recordmydesktop/src/recordmydesktop.c4
-rw-r--r--recordmydesktop/src/update_image.c25
8 files changed, 120 insertions, 26 deletions
diff --git a/recordmydesktop/ChangeLog b/recordmydesktop/ChangeLog
index 0f06b4c..ac217b0 100644
--- a/recordmydesktop/ChangeLog
+++ b/recordmydesktop/ChangeLog
@@ -8,6 +8,7 @@ or missing pixels at borders has been corrected.
*The option to drop frames has been added.
*Default behavior now is to use shared memory when
size of image gets over 75% of total (or a user set threshold).
+*Many other minor bugfixes.
diff --git a/recordmydesktop/doc/recordmydesktop.1 b/recordmydesktop/doc/recordmydesktop.1
index 0bffe9a..81d7e35 100644
--- a/recordmydesktop/doc/recordmydesktop.1
+++ b/recordmydesktop/doc/recordmydesktop.1
@@ -198,6 +198,11 @@ Image Options:
.br
.TP
.B
+ \-\-no\-quick\-subsampling
+ Do subsampling of the chroma planes by averaging,not discarding extra pixels.
+.br
+.TP
+.B
\-fps N(number>0.0)
A positive number denoting desired framerate.
.br
@@ -297,7 +302,7 @@ If no other option is specified, filename can be given without the \-o switch.
.br
\-\-nosound| \-\-with\-shared| \-\-no\-cond\-shared| \-shared\-threshold n| \-\-full\-shots|
.br
-\-\-scshot| \-scale\-shot N| \-o filename]^filename
+\-\-no\-quick\-subsampling| \-\-scshot| \-scale\-shot N| \-o filename]^filename
.br
.br
.br
@@ -353,9 +358,7 @@ It can even perform resizing on the size of the recording, or change the overall
.br
.br
.SH BUGS
-Too resource intensive, straightforward subsampling of chroma plane degrades quality
-.br
-(though fixing this with averaraging would make the program even more cpu-hungry).
+Too resource intensive.
.br
.SH AUTHORS
John Varouhakis(biocrasher@gmail.com)
diff --git a/recordmydesktop/include/recordmydesktop.h b/recordmydesktop/include/recordmydesktop.h
index a3c9782..84b647b 100644
--- a/recordmydesktop/include/recordmydesktop.h
+++ b/recordmydesktop/include/recordmydesktop.h
@@ -115,6 +115,7 @@ typedef struct _ProgArgs{
int nocondshared; //de not use shared memory on large image aquititions
int shared_thres; //threshold to use shared memory
int full_shots; //do not poll damage, take full screenshots
+ int no_quick_subsample;//average pixels in chroma planes
int scshot; //take screenshot and exit(default 0)
int scale_shot; //screenshot subscale factor(default 1)
int v_bitrate,v_quality,s_quality;//video bitrate,video-sound quality
@@ -271,7 +272,8 @@ unsigned char Yr[256],Yg[256],Yb[256],
=(args)->width=(args)->height=(args)->quietmode\
=(args)->nosound=(args)->scshot=(args)->full_shots=0;\
(args)->noshared=(args)->scale_shot=1;\
- (args)->dropframes=(args)->nocondshared=0;\
+ (args)->dropframes=(args)->nocondshared==0;\
+ (args)->no_quick_subsample=0;\
(args)->filename=(char *)malloc(8);\
strcpy((args)->filename,"out.ogg");\
(args)->encoding=OGG_THEORA_VORBIS;\
@@ -300,6 +302,10 @@ unsigned char Yr[256],Yg[256],Yb[256],
(specstruct)->wpixel=XWhitePixel(display,(specstruct)->screen);\
}
+#define AVG_4_PIXELS(data_array,width_img,k_tm,i_tm,offset)\
+ ((data_array[(k_tm*width_img+i_tm)*4+offset]+data_array[((k_tm-1)*width_img+i_tm)*4+offset]\
+ +data_array[(k_tm*width_img+i_tm-1)*4+offset]+data_array[((k_tm-1)*width_img+i_tm-1)*4+offset])/4)
+
#define UPDATE_YUV_BUFFER_SH(yuv,data,x_tm,y_tm,width_tm,height_tm){\
int i,k;\
for(k=y_tm;k<y_tm+height_tm;k++){\
@@ -313,6 +319,27 @@ unsigned char Yr[256],Yg[256],Yb[256],
}\
}
+#define UPDATE_YUV_BUFFER_SH_AVG(yuv,data,x_tm,y_tm,width_tm,height_tm){\
+ int i,k;\
+ unsigned char avg0,avg1,avg2;\
+ for(k=y_tm;k<y_tm+height_tm;k++){\
+ for(i=x_tm;i<x_tm+width_tm;i++){\
+ yuv->y[i+k*yuv->y_width]=Yr[data[(i+k*yuv->y_width)*4+2]] + Yg[data[(i+k*yuv->y_width)*4+1]] + Yb[data[(i+k*yuv->y_width)*4]];\
+ if((k%2)&&(i%2)){\
+ avg2=AVG_4_PIXELS(data,(yuv->y_width),k,i,2);\
+ avg1=AVG_4_PIXELS(data,(yuv->y_width),k,i,1);\
+ avg0=AVG_4_PIXELS(data,(yuv->y_width),k,i,0);\
+ yuv->u[i/2+k/2*yuv->uv_width]=Ur[avg2] +\
+ Ug[avg1] +\
+ Ub[avg0] ;\
+ yuv->v[i/2+k/2*yuv->uv_width]=Vr[avg2] +\
+ Vg[avg1] +\
+ Vb[avg0] ;\
+ }\
+ }\
+ }\
+}
+
#define UPDATE_YUV_BUFFER_IM(yuv,data,x_tm,y_tm,width_tm,height_tm){\
int i,k,j=0;\
int x_2=x_tm/2,y_2=y_tm/2;\
@@ -331,6 +358,34 @@ unsigned char Yr[256],Yg[256],Yb[256],
}\
}
+
+
+#define UPDATE_YUV_BUFFER_IM_AVG(yuv,data,x_tm,y_tm,width_tm,height_tm){\
+ int i,k,j=0;\
+ unsigned char avg0,avg1,avg2;\
+ int x_2=x_tm/2,y_2=y_tm/2;\
+ for(k=0;k<height_tm;k++){\
+ for(i=0;i<width_tm;i++){\
+ yuv->y[x_tm+i+(k+y_tm)*yuv->y_width]=Yr[data[(j*4)+2]] + Yg[data[(j*4)+1]] + Yb[data[(j*4)]] ;\
+ if((k%2)&&(i%2)){\
+ avg2=AVG_4_PIXELS(data,width_tm,k,i,2);\
+ avg1=AVG_4_PIXELS(data,width_tm,k,i,1);\
+ avg0=AVG_4_PIXELS(data,width_tm,k,i,0);\
+ yuv->u[x_2+i/2+(k/2+y_2)*yuv->uv_width]=\
+ Ur[avg2] + Ug[avg1] +\
+ Ub[avg0];\
+ yuv->v[x_2+i/2+(k/2+y_2)*yuv->uv_width]=\
+ Vr[avg2] + Vg[avg1] +\
+ Vb[avg0];\
+ }\
+ \
+ j++;\
+ }\
+ }\
+}
+
+
+
#define DUMMY_POINTER_TO_YUV(yuv,data_tm,x_tm,y_tm,width_tm,height_tm,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;\
@@ -362,8 +417,8 @@ int RectInsert(RectArea **root,WGeometry *wgeom);
int CollideRects(WGeometry *wgeom1,WGeometry *wgeom2,WGeometry **wgeom_return,int *ngeoms);
void SetExpired(int signum);
void RegisterCallbacks(ProgArgs *args);
-void UpdateImage(Display * dpy,yuv_buffer *yuv,pthread_mutex_t *yuv_mutex,DisplaySpecs *specs,RectArea **root,BRWindow *brwin,EncData *enc,char *datatemp,int noshmem);
-void XImageToYUV(XImage *imgz,yuv_buffer *yuv);
+void UpdateImage(Display * dpy,yuv_buffer *yuv,pthread_mutex_t *yuv_mutex,DisplaySpecs *specs,RectArea **root,BRWindow *brwin,EncData *enc,char *datatemp,int noshmem,int no_quick_subsample);
+void XImageToYUV(XImage *imgz,yuv_buffer *yuv,int no_quick_subsample);
int GetZPixmap(Display *dpy,Window root,char *data,int x,int y,int width,int height);
int ParseArgs(int argc,char **argv,ProgArgs *arg_return);
int QueryExtensions(Display *dpy,ProgArgs *args,int *damage_event,int *damage_error);
diff --git a/recordmydesktop/src/bgr_to_yuv.c b/recordmydesktop/src/bgr_to_yuv.c
index 81c7fed..d2b14f4 100644
--- a/recordmydesktop/src/bgr_to_yuv.c
+++ b/recordmydesktop/src/bgr_to_yuv.c
@@ -27,19 +27,34 @@
#include <recordmydesktop.h>
-void XImageToYUV(XImage *imgz,yuv_buffer *yuv){
+void XImageToYUV(XImage *imgz,yuv_buffer *yuv,int no_quick_subsample){
unsigned char *dtap=(unsigned char *)imgz->data;
+ unsigned char avg2,avg1,avg0;
int i,k,j=0;
for(k=0;k<(imgz->width*imgz->height);k++){
yuv->y[k]=Yr[dtap[(k*4)+2]] + Yg[dtap[(k*4)+1]] + Yb[dtap[(k*4)]];
}
-
- for(i=0;i<(imgz->height);i+=2){
- for(k=0;k<(imgz->width);k+=2){
- yuv->u[j]=Ur[dtap[i*imgz->bytes_per_line+k*4+2]] + Ug[dtap[i*imgz->bytes_per_line+k*4+1]] + Ub[dtap[i*imgz->bytes_per_line+k*4]];
- yuv->v[j]=Vr[dtap[i*imgz->bytes_per_line+k*4+2]] + Vg[dtap[i*imgz->bytes_per_line+k*4+1]] + Vb[dtap[i*imgz->bytes_per_line+k*4]] ;
- j++;
+ if(!no_quick_subsample){
+ for(i=0;i<(imgz->height);i+=2){
+ for(k=0;k<(imgz->width);k+=2){
+ yuv->u[j]=Ur[dtap[i*imgz->bytes_per_line+k*4+2]] + Ug[dtap[i*imgz->bytes_per_line+k*4+1]] + Ub[dtap[i*imgz->bytes_per_line+k*4]];
+ yuv->v[j]=Vr[dtap[i*imgz->bytes_per_line+k*4+2]] + Vg[dtap[i*imgz->bytes_per_line+k*4+1]] + Vb[dtap[i*imgz->bytes_per_line+k*4]] ;
+ j++;
+ }
+ }
+ }
+ else{
+ for(i=0;i<(imgz->height);i+=2){
+ for(k=0;k<(imgz->width);k+=2){
+ avg2=AVG_4_PIXELS(dtap,(imgz->width),i,k,2);
+ avg1=AVG_4_PIXELS(dtap,(imgz->width),i,k,1);
+ avg0=AVG_4_PIXELS(dtap,(imgz->width),i,k,0);
+
+ yuv->u[j]=Ur[avg2] + Ug[avg1] + Ub[avg0];
+ yuv->v[j]=Vr[avg2] + Vg[avg1] + Vb[avg0] ;
+ j++;
+ }
}
}
}
diff --git a/recordmydesktop/src/get_frame.c b/recordmydesktop/src/get_frame.c
index 1d6a126..6a93ceb 100644
--- a/recordmydesktop/src/get_frame.c
+++ b/recordmydesktop/src/get_frame.c
@@ -99,7 +99,8 @@ void *GetFrame(void *pdata){
&((ProgData *)pdata)->brwin,
((ProgData *)pdata)->enc_data,
((((ProgData *)pdata)->args.noshared)?(((ProgData *)pdata)->datatemp):((ProgData *)pdata)->shimage->data),
- ((ProgData *)pdata)->args.noshared);
+ ((ProgData *)pdata)->args.noshared,
+ ((ProgData *)pdata)->args.no_quick_subsample);
else{
if(((ProgData *)pdata)->args.noshared){
GetZPixmap( ((ProgData *)pdata)->dpy,
@@ -110,12 +111,14 @@ void *GetFrame(void *pdata){
((ProgData *)pdata)->brwin.rgeom.width,
((ProgData *)pdata)->brwin.rgeom.height);
pthread_mutex_lock(&((ProgData *)pdata)->yuv_mutex);
- XImageToYUV(((ProgData *)pdata)->image,&((ProgData *)pdata)->enc_data->yuv);
+ XImageToYUV(((ProgData *)pdata)->image,&((ProgData *)pdata)->enc_data->yuv,
+ ((ProgData *)pdata)->args.no_quick_subsample);
pthread_mutex_unlock(&((ProgData *)pdata)->yuv_mutex);
}
else{
pthread_mutex_lock(&((ProgData *)pdata)->yuv_mutex);
- XImageToYUV(((ProgData *)pdata)->shimage,&((ProgData *)pdata)->enc_data->yuv);
+ XImageToYUV(((ProgData *)pdata)->shimage,&((ProgData *)pdata)->enc_data->yuv,
+ ((ProgData *)pdata)->args.no_quick_subsample);
pthread_mutex_unlock(&((ProgData *)pdata)->yuv_mutex);
}
}
diff --git a/recordmydesktop/src/parseargs.c b/recordmydesktop/src/parseargs.c
index 8125972..55dfbcd 100644
--- a/recordmydesktop/src/parseargs.c
+++ b/recordmydesktop/src/parseargs.c
@@ -36,7 +36,7 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){
"\t -v_quality n| -s_quality n| -v_bitrate n| --no-framedrop| -dummy-cursor color|\n"
"\t --no-dummy-cursor| -freq N(number>0)| -channels N(number>0)| -device SOUND_DEVICE|\n"
"\t --nosound| --with-shared| --no-cond-shared| -shared-threshold n| --full-shots|\n"
- "\t --scshot| -scale-shot N| -o filename]^filename\n\n\n"
+ "\t --no-quick-subsampling| --scshot| -scale-shot N| -o filename]^filename\n\n\n"
"General Options:\n"
"\t-h or --help\t\tPrint this help and exit.\n"
@@ -56,6 +56,7 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){
"\t--no-cond-shared\tDo not use the MIT-shared memory extension when aquiring large areas.\n"
"\t-shared-threshold n\tThreshold over which shared memory is used(default 75).\n"
"\t--full-shots\t\tTake full screenshot at every frame(Not recomended!).\n"
+ "\t--no-quick-subsampling\tDo subsampling of the chroma planes by averaging,not discarding.\n"
"\t-fps N(number>0.0)\tA positive number denoting desired framerate.\n\n"
"Sound Options:\n"
@@ -397,6 +398,9 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){
arg_return->scshot=1;
arg_return->nocondshared=1;
}
+ else if(!strcmp(argv[i],"--no-quick-subsampling")){
+ arg_return->no_quick_subsample=1;
+ }
else if(!strcmp(argv[i],"--help")||!strcmp(argv[i],"-h")){
fprintf(stderr,"%s",usage);
return 1;
diff --git a/recordmydesktop/src/recordmydesktop.c b/recordmydesktop/src/recordmydesktop.c
index 5588b52..9f6d596 100644
--- a/recordmydesktop/src/recordmydesktop.c
+++ b/recordmydesktop/src/recordmydesktop.c
@@ -140,9 +140,9 @@ int main(int argc,char **argv){
}
InitEncoder(&pdata,&enc_data);
if((pdata.args.nocondshared)&&(!pdata.args.noshared))
- XImageToYUV(pdata.shimage,&pdata.enc_data->yuv);
+ XImageToYUV(pdata.shimage,&pdata.enc_data->yuv,pdata.args.no_quick_subsample);
else
- XImageToYUV(pdata.shimage,&pdata.enc_data->yuv);
+ XImageToYUV(pdata.shimage,&pdata.enc_data->yuv,pdata.args.no_quick_subsample);
pdata.frametime=(1000000)/pdata.args.fps;
diff --git a/recordmydesktop/src/update_image.c b/recordmydesktop/src/update_image.c
index bf319e2..0de3f0a 100644
--- a/recordmydesktop/src/update_image.c
+++ b/recordmydesktop/src/update_image.c
@@ -35,7 +35,8 @@ void UpdateImage(Display * dpy,
BRWindow *brwin,
EncData *enc,
char *datatemp,
- int noshmem){
+ int noshmem,
+ int no_quick_subsample){
RectArea *temp;
unsigned char *dtap=(unsigned char*)datatemp;
temp=*root;
@@ -52,18 +53,30 @@ void UpdateImage(Display * dpy,
temp->geom.height);
pthread_mutex_lock(yuv_mutex);
-
- UPDATE_YUV_BUFFER_IM(yuv,dtap,
- (temp->geom.x-brwin->rgeom.x+enc->x_offset),(temp->geom.y-brwin->rgeom.y+enc->y_offset),
- (temp->geom.width),(temp->geom.height));
+ if(no_quick_subsample){
+ UPDATE_YUV_BUFFER_IM_AVG(yuv,dtap,
+ (temp->geom.x-brwin->rgeom.x+enc->x_offset),(temp->geom.y-brwin->rgeom.y+enc->y_offset),
+ (temp->geom.width),(temp->geom.height));
+ }
+ else{
+ UPDATE_YUV_BUFFER_IM(yuv,dtap,
+ (temp->geom.x-brwin->rgeom.x+enc->x_offset),(temp->geom.y-brwin->rgeom.y+enc->y_offset),
+ (temp->geom.width),(temp->geom.height));
+ }
pthread_mutex_unlock(yuv_mutex);
}
else{
+ if(no_quick_subsample){
+ UPDATE_YUV_BUFFER_SH_AVG(yuv,dtap,
+ (temp->geom.x-brwin->rgeom.x+enc->x_offset),(temp->geom.y-brwin->rgeom.y+enc->y_offset),
+ (temp->geom.width),(temp->geom.height));
+ }
+ else{
UPDATE_YUV_BUFFER_SH(yuv,dtap,
(temp->geom.x-brwin->rgeom.x+enc->x_offset),(temp->geom.y-brwin->rgeom.y+enc->y_offset),
(temp->geom.width),(temp->geom.height));
-
+ }
}
temp=temp->next;
© All Rights Reserved