summaryrefslogtreecommitdiff
path: root/recordmydesktop/src/rmd_get_frame.c
diff options
context:
space:
mode:
Diffstat (limited to 'recordmydesktop/src/rmd_get_frame.c')
-rw-r--r--recordmydesktop/src/rmd_get_frame.c994
1 files changed, 487 insertions, 507 deletions
diff --git a/recordmydesktop/src/rmd_get_frame.c b/recordmydesktop/src/rmd_get_frame.c
index a14b111..cd61dd2 100644
--- a/recordmydesktop/src/rmd_get_frame.c
+++ b/recordmydesktop/src/rmd_get_frame.c
@@ -52,7 +52,7 @@
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){\
+#define CLIP_DUMMY_POINTER_AREA(dummy_p_area,brwin,xrect) {\
(xrect)->x=((((dummy_p_area).x+\
(dummy_p_area).width>=(brwin)->rrect.x)&&\
((dummy_p_area).x<=(brwin)->rrect.x+\
@@ -83,9 +83,9 @@
(brwin)->rrect.y<(dummy_p_area).height)?\
(brwin)->rrect.height-(dummy_p_area).y+\
(brwin)->rrect.y:(dummy_p_area).height:0;\
- if((xrect)->width>(brwin)->rrect.width)\
+ if ((xrect)->width>(brwin)->rrect.width)\
(xrect)->width=(brwin)->rrect.width;\
- if((xrect)->height>(brwin)->rrect.height)\
+ if ((xrect)->height>(brwin)->rrect.height)\
(xrect)->height=(brwin)->rrect.height;\
}
@@ -97,22 +97,22 @@
height_tm,\
x_offset,\
y_offset,\
- column_discard_stride){\
+ 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++){\
+ 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]*\
+ (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)){\
+ if ((k%2)&&(i%2)) {\
avg3=AVG_4_PIXELS(data,\
(width_tm+column_discard_stride),\
k,i,__ABYTE);\
@@ -125,18 +125,18 @@
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]*\
+ (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]*\
+ (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 ) / \
@@ -152,13 +152,13 @@
width_tm,\
height_tm,\
buffer_width,\
- __bit_depth__){\
+ __bit_depth__) {\
int k,i;\
register u_int##__bit_depth__##_t\
*datapi=\
((u_int##__bit_depth__##_t *)data)+y_tm*buffer_width+x_tm;\
- for(k=0;k<height_tm;k++){\
- for(i=0;i<width_tm;i++){\
+ for(k=0;k<height_tm;k++) {\
+ for(i=0;i<width_tm;i++) {\
*datapi+=1;\
datapi++;\
}\
@@ -172,8 +172,8 @@
width_tm,\
height_tm,\
buffer_width,\
- __bit_depth__){\
- if((__bit_depth__==24)||(__bit_depth__==32)){\
+ __bit_depth__) {\
+ if ((__bit_depth__==24)||(__bit_depth__==32)) {\
MARK_BUFFER_AREA_C( data,\
x_tm,\
y_tm,\
@@ -182,7 +182,7 @@
buffer_width,\
32)\
}\
- else{\
+ else {\
MARK_BUFFER_AREA_C( data,\
x_tm,\
y_tm,\
@@ -196,108 +196,107 @@
//besides taking the first screenshot, this functions primary purpose is to
//initialize the structures and memory.
-static int rmdFirstFrame(ProgData *pdata,
- XImage **image,
- XShmSegmentInfo *shminfo) {
-
- if((pdata->args.noshared)){
- char *pxl_data;
-
- pxl_data=(char *)malloc(pdata->brwin.nbytes);
-
- (*image)=XCreateImage(pdata->dpy,
- pdata->specs.visual,
- pdata->specs.depth,
- ZPixmap,
- 0,
- pxl_data,
- pdata->brwin.rrect.width,
- pdata->brwin.rrect.height,
- 8,
- 0);
- XInitImage((*image));
- rmdGetZPixmap(pdata->dpy,pdata->specs.root,
- (*image)->data,
- pdata->brwin.rrect.x,
- pdata->brwin.rrect.y,
- pdata->brwin.rrect.width,
- pdata->brwin.rrect.height);
- }
- else{
- (*image)=XShmCreateImage(pdata->dpy,
- pdata->specs.visual,
- pdata->specs.depth,
- ZPixmap,
- NULL,
- shminfo,
- pdata->brwin.rrect.width,
- pdata->brwin.rrect.height);
- (*shminfo).shmid=shmget(IPC_PRIVATE,
- (*image)->bytes_per_line*
- (*image)->height,
- IPC_CREAT|0777);
- if((*shminfo).shmid==-1){
- fprintf(stderr,"Failed to obtain Shared Memory segment!\n");
- return 12;
- }
- (*shminfo).shmaddr=(*image)->data=shmat((*shminfo).shmid,
- NULL,0);
- (*shminfo).readOnly = False;
- if(!XShmAttach(pdata->dpy,shminfo)){
- fprintf(stderr,"Failed to attach shared memory to proccess.\n");
- return 12;
- }
- XShmGetImage(pdata->dpy,
- pdata->specs.root,
- (*image),
- pdata->brwin.rrect.x,
- pdata->brwin.rrect.y,
- AllPlanes);
- }
-
- UPDATE_YUV_BUFFER((&pdata->enc_data->yuv),
- ((unsigned char*)((*image))->data),NULL,
- (pdata->enc_data->x_offset),(pdata->enc_data->y_offset),
- (pdata->brwin.rrect.width),(pdata->brwin.rrect.height),
- (pdata->args.no_quick_subsample),
- pdata->specs.depth);
-
- return 0;
+static int rmdFirstFrame(ProgData *pdata, XImage **image, XShmSegmentInfo *shminfo) {
+
+ if ((pdata->args.noshared)) {
+ char *pxl_data;
+
+ pxl_data=(char *)malloc(pdata->brwin.nbytes);
+
+ (*image)=XCreateImage( pdata->dpy,
+ pdata->specs.visual,
+ pdata->specs.depth,
+ ZPixmap,
+ 0,
+ pxl_data,
+ pdata->brwin.rrect.width,
+ pdata->brwin.rrect.height,
+ 8,
+ 0);
+ XInitImage((*image));
+ rmdGetZPixmap( pdata->dpy,pdata->specs.root,
+ (*image)->data,
+ pdata->brwin.rrect.x,
+ pdata->brwin.rrect.y,
+ pdata->brwin.rrect.width,
+ pdata->brwin.rrect.height);
+ } else {
+ (*image)=XShmCreateImage( pdata->dpy,
+ pdata->specs.visual,
+ pdata->specs.depth,
+ ZPixmap,
+ NULL,
+ shminfo,
+ pdata->brwin.rrect.width,
+ pdata->brwin.rrect.height);
+
+ (*shminfo).shmid=shmget(IPC_PRIVATE,
+ (*image)->bytes_per_line*
+ (*image)->height,
+ IPC_CREAT|0777);
+
+ if ((*shminfo).shmid==-1) {
+ fprintf(stderr,"Failed to obtain Shared Memory segment!\n");
+ return 12;
+ }
+
+ (*shminfo).shmaddr=(*image)->data=shmat((*shminfo).shmid, NULL,0);
+ (*shminfo).readOnly = False;
+
+ if (!XShmAttach(pdata->dpy,shminfo)) {
+ fprintf(stderr,"Failed to attach shared memory to proccess.\n");
+ return 12;
+ }
+
+ XShmGetImage(pdata->dpy,
+ pdata->specs.root,
+ (*image),
+ pdata->brwin.rrect.x,
+ pdata->brwin.rrect.y,
+ AllPlanes);
+ }
+
+ UPDATE_YUV_BUFFER((&pdata->enc_data->yuv),
+ ((unsigned char*)((*image))->data),NULL,
+ (pdata->enc_data->x_offset),(pdata->enc_data->y_offset),
+ (pdata->brwin.rrect.width),(pdata->brwin.rrect.height),
+ (pdata->args.no_quick_subsample),
+ pdata->specs.depth);
+
+ return 0;
}
//make a deep copy
static void rmdBRWinCpy(BRWindow *target, BRWindow *source) {
- target->rect.x=source->rect.x;
- target->rect.y=source->rect.y;
- target->rect.width=source->rect.width;
- target->rect.height=source->rect.height;
- target->rrect.x=source->rrect.x;
- target->rrect.y=source->rrect.y;
- target->rrect.width=source->rrect.width;
- target->rrect.height=source->rrect.height;
- target->nbytes=source->nbytes;
- target->windowid=source->windowid;
+ target->rect.x=source->rect.x;
+ target->rect.y=source->rect.y;
+ target->rect.width=source->rect.width;
+ target->rect.height=source->rect.height;
+ target->rrect.x=source->rrect.x;
+ target->rrect.y=source->rrect.y;
+ target->rrect.width=source->rrect.width;
+ target->rrect.height=source->rrect.height;
+ target->nbytes=source->nbytes;
+ target->windowid=source->windowid;
}
//recenters the capture area to the mouse
//without exiting the display bounding box
-static void rmdMoveCaptureArea(BRWindow *brwin,
- int cursor_x,
- int cursor_y,
- int width,
- int height) {
- int t_x=0,t_y=0;
-
- t_x=cursor_x-brwin->rrect.width/2;
- t_x=(t_x>>1)<<1;
- brwin->rrect.x=(t_x<0)?0:((t_x+brwin->rrect.width>width)?
- width-brwin->rrect.width:t_x);
- t_y=cursor_y-brwin->rrect.height/2;
- t_y=(t_y>>1)<<1;
- brwin->rrect.y=(t_y<0)?0:((t_y+brwin->rrect.height>height)?
- height-brwin->rrect.height:t_y);
+static void rmdMoveCaptureArea( BRWindow *brwin,
+ int cursor_x,
+ int cursor_y,
+ int width,
+ int height) {
+ int t_x=0,t_y=0;
+
+ t_x=cursor_x-brwin->rrect.width/2;
+ t_x=(t_x>>1)<<1;
+ brwin->rrect.x=(t_x<0)?0:((t_x+brwin->rrect.width>width)? width-brwin->rrect.width:t_x);
+ t_y=cursor_y-brwin->rrect.height/2;
+ t_y=(t_y>>1)<<1;
+ brwin->rrect.y=(t_y<0)?0:((t_y+brwin->rrect.height>height)? height-brwin->rrect.height:t_y);
}
/**
@@ -313,398 +312,379 @@ static void rmdMoveCaptureArea(BRWindow *brwin,
*
* \param blocknum_y Height of image in blocks
*/
-static void rmdBlocksFromList (RectArea **root,
- unsigned int x_offset,
- unsigned int y_offset,
- unsigned int blocknum_x,
- unsigned int blocknum_y) {
-
- RectArea *temp;
- int i,
- j,
- blockno,
- row_start,
- row_end,
- column_start,
- column_end;
-
- temp = *root;
-
- for (i = 0; i < blocknum_x * blocknum_y; i++) {
- yblocks[i] = ublocks[i] = vblocks[i] = 0;
- }
-
- while (temp != NULL) {
-
- column_start = ((int)(temp->rect.x - x_offset)) / Y_UNIT_WIDTH;
- column_end = ((int)(temp->rect.x + (temp->rect.width - 1) - x_offset)) / Y_UNIT_WIDTH;
- row_start = ((int)(temp->rect.y - y_offset)) / Y_UNIT_WIDTH;
- row_end = ((int)(temp->rect.y + (temp->rect.height - 1) - y_offset)) / Y_UNIT_WIDTH;
-
- for (i = row_start; i < row_end + 1; i++) {
- for (j = column_start; j < column_end + 1; j++) {
- blockno = i * blocknum_x + j;
- yblocks[blockno] = 1;
- ublocks[blockno] = 1;
- vblocks[blockno] = 1;
- }
- }
-
- temp = temp->next;
- }
+static void rmdBlocksFromList( RectArea **root,
+ unsigned int x_offset,
+ unsigned int y_offset,
+ unsigned int blocknum_x,
+ unsigned int blocknum_y) {
+
+ RectArea *temp = *root;
+ int i, j, blockno, row_start, row_end, column_start, column_end;
+
+ for (i = 0; i < blocknum_x * blocknum_y; i++)
+ yblocks[i] = ublocks[i] = vblocks[i] = 0;
+
+ while (temp != NULL) {
+
+ column_start = ((int)(temp->rect.x - x_offset)) / Y_UNIT_WIDTH;
+ column_end = ((int)(temp->rect.x + (temp->rect.width - 1) - x_offset)) / Y_UNIT_WIDTH;
+ row_start = ((int)(temp->rect.y - y_offset)) / Y_UNIT_WIDTH;
+ row_end = ((int)(temp->rect.y + (temp->rect.height - 1) - y_offset)) / Y_UNIT_WIDTH;
+
+ for (i = row_start; i < row_end + 1; i++) {
+ for (j = column_start; j < column_end + 1; j++) {
+ blockno = i * blocknum_x + j;
+ yblocks[blockno] = 1;
+ ublocks[blockno] = 1;
+ vblocks[blockno] = 1;
+ }
+ }
+
+ temp = temp->next;
+ }
}
-void *rmdGetFrame(ProgData *pdata){
- int i=0,
- blocknum_x=pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH,
- blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH;
- unsigned int msk_ret;
- XRectangle mouse_pos_abs,mouse_pos_rel,mouse_pos_temp;
- BRWindow temp_brwin;
- Window root_ret,
- child_ret; //Frame
- XFixesCursorImage *xcim=NULL;
- XImage *image=NULL,*image_back=NULL; //the image that holds
- //the current full screenshot
- XShmSegmentInfo shminfo,shminfo_back;//info structure for the image above.
- int init_img1=0,init_img2=0,
- img_sel,d_buff;
-
- img_sel=d_buff=pdata->args.full_shots;
-
- if((init_img1=rmdFirstFrame(pdata,&image,&shminfo)!=0)){
- if(pdata->args.encOnTheFly){
- if(remove(pdata->args.filename)){
- perror("Error while removing file:\n");
- }
- else{
- fprintf(stderr,"SIGABRT received,file %s removed\n",
- pdata->args.filename);
- }
- }
- else{
- rmdPurgeCache(pdata->cache_data,!pdata->args.nosound);
- }
- exit(init_img1);
- }
- if(d_buff){
- if((init_img2=rmdFirstFrame(pdata,&image_back,&shminfo_back)!=0)){
- if(pdata->args.encOnTheFly){
- if(remove(pdata->args.filename)){
- perror("Error while removing file:\n");
- }
- else{
- fprintf(stderr,"SIGABRT received,file %s removed\n",
- pdata->args.filename);
- }
- }
- else{
- rmdPurgeCache(pdata->cache_data,!pdata->args.nosound);
- }
- exit(init_img2);
- }
-
- }
-
- if(!pdata->args.noframe){
- pdata->shaped_w=rmdFrameInit(pdata->dpy,
- pdata->specs.screen,
- pdata->specs.root,
- pdata->brwin.rrect.x,
- pdata->brwin.rrect.y,
- pdata->brwin.rrect.width,
- pdata->brwin.rrect.height);
- XSelectInput(pdata->dpy,pdata->shaped_w,ExposureMask);
- }
-
- mouse_pos_abs.x=mouse_pos_temp.x=0;
- mouse_pos_abs.y=mouse_pos_temp.y=0;
- mouse_pos_abs.width=mouse_pos_temp.width=pdata->dummy_p_size;
- mouse_pos_abs.height=mouse_pos_temp.height=pdata->dummy_p_size;
-
- //This is the the place where we call XSelectInput
- //and arrange so that we listen for damage on all
- //windows
- rmdInitEventsPolling(pdata);
-
- while(pdata->running){
-
- //if we are left behind we must not wait.
- //also before actually pausing we must make sure the streams
- //are synced. sound stops so this should only happen quickly.
- if(pdata->avd>0 || pdata->args.nosound){
- pthread_mutex_lock(&pdata->time_mutex);
- pthread_cond_wait(&pdata->time_cond, &pdata->time_mutex);
- pthread_mutex_unlock(&pdata->time_mutex);
- if (pdata->paused) {
- //this is necessary since event loop processes
- //the shortcuts which will unpause the program
- rmdEventLoop(pdata);
- continue;
- }
- }
- //read all events and construct list with damage
- //events (if not full_shots)
- rmdEventLoop(pdata);
-
- //switch back and front buffers (full_shots only)
- if(d_buff)
- img_sel=(img_sel)?0:1;
- pdata->capture_busy = TRUE;
-
- rmdBRWinCpy(&temp_brwin,&pdata->brwin);
-
-
- if(pdata->args.xfixes_cursor ||
- pdata->args.have_dummy_cursor||
- pdata->args.follow_mouse){
-
-
- // Pointer sequence:
- // * Mark previous position as dirty with rmdRectInsert()
- // * Update to new position
- // * Mark new position as dirty with rmdRectInsert()
- if (!pdata->args.full_shots &&
- mouse_pos_temp.x >=0 &&
- mouse_pos_temp.y >=0 &&
- mouse_pos_temp.width > 0 &&
- mouse_pos_temp.height > 0) {
- rmdRectInsert(&pdata->rect_root,&mouse_pos_temp);
- }
- if(pdata->args.xfixes_cursor){
- xcim=XFixesGetCursorImage(pdata->dpy);
- mouse_pos_abs.x=xcim->x-xcim->xhot;
- mouse_pos_abs.y=xcim->y-xcim->yhot;
- mouse_pos_abs.width=xcim->width;
- mouse_pos_abs.height=xcim->height;
- }
- else{
- XQueryPointer(pdata->dpy,
- pdata->specs.root,
- &root_ret,&child_ret,
- (int *)&mouse_pos_abs.x,(int *)&mouse_pos_abs.y,
- (int *)&mouse_pos_rel.x,(int *)&mouse_pos_rel.y,&msk_ret);
- }
-
- CLIP_DUMMY_POINTER_AREA(mouse_pos_abs, &temp_brwin, &mouse_pos_temp);
- if( mouse_pos_temp.x >=0 &&
- mouse_pos_temp.y >=0 &&
- mouse_pos_temp.width > 0 &&
- mouse_pos_temp.height > 0) {
-
- //there are 3 capture scenarios:
- // * Xdamage
- // * full-shots with double buffering
- // * full-shots on a single buffer
- //The last one cannot be reached through
- //this code (see above how the d_buf variable is set), but
- //even if it could, it would not be of interest regarding the
- //marking of the cursor area. Single buffer means full repaint
- //on every frame so there is no need for marking at all.
-
- if (!pdata->args.full_shots) {
-
- rmdRectInsert(&pdata->rect_root,&mouse_pos_temp);
-
- }
- else if(d_buff){
- unsigned char *back_buff=
- (img_sel)?((unsigned char*)image->data):
- ((unsigned char*)image_back->data);
-
- MARK_BUFFER_AREA( back_buff,
- (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,
- (temp_brwin.rrect.width),
- pdata->specs.depth)
- }
- }
- }
- if(pdata->args.follow_mouse){
- rmdMoveCaptureArea(&pdata->brwin,
- mouse_pos_abs.x+
- ((pdata->args.xfixes_cursor)?xcim->xhot:0),
- mouse_pos_abs.y+
- ((pdata->args.xfixes_cursor)?xcim->yhot:0),
- pdata->specs.width,
- pdata->specs.height);
- if(!pdata->args.noframe){
- rmdMoveFrame(pdata->dpy,
- pdata->shaped_w,
- temp_brwin.rrect.x,
- temp_brwin.rrect.y);
-
- }
- }
-
- if(!pdata->args.full_shots){
- pthread_mutex_lock(&pdata->yuv_mutex);
- rmdUpdateImage(pdata->dpy,
- &pdata->enc_data->yuv,
- &pdata->specs,
- &pdata->rect_root,
- &temp_brwin,
- pdata->enc_data,
- image->data,
- pdata->args.noshared,
- &shminfo,
- pdata->shm_opcode,
- pdata->args.no_quick_subsample);
- rmdBlocksFromList(&pdata->rect_root,
- temp_brwin.rrect.x,
- temp_brwin.rrect.y,
- pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH,
- pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH);
- pthread_mutex_unlock(&pdata->yuv_mutex);
- }
- else{
- unsigned char *front_buff=(!img_sel)?((unsigned char*)image->data):
- ((unsigned char*)image_back->data);
- unsigned char *back_buff=(!d_buff)?NULL:((img_sel)?
- ((unsigned char*)image->data):
- ((unsigned char*)image_back->data));
-
- if(!pdata->args.noshared){
- XShmGetImage(pdata->dpy,pdata->specs.root,
- ((!img_sel)?image:image_back),
- (temp_brwin.rrect.x),
- (temp_brwin.rrect.y),AllPlanes);
- }
- if(pdata->args.noshared){
- rmdGetZPixmap( pdata->dpy,
- pdata->specs.root,
- image->data,
- temp_brwin.rrect.x,
- temp_brwin.rrect.y,
- temp_brwin.rrect.width,
- 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;
- }
- UPDATE_YUV_BUFFER((&pdata->enc_data->yuv),
- front_buff,back_buff,
- (pdata->enc_data->x_offset),
- (pdata->enc_data->y_offset),
- (temp_brwin.rrect.width),
- (temp_brwin.rrect.height),
- pdata->args.no_quick_subsample,
- pdata->specs.depth);
- pthread_mutex_unlock(&pdata->yuv_mutex);
- }
- if(pdata->args.xfixes_cursor ||
- pdata->args.have_dummy_cursor){
- int mouse_xoffset,
- mouse_yoffset;
- //avoid segfaults
- CLIP_DUMMY_POINTER_AREA(mouse_pos_abs,&temp_brwin,
- &mouse_pos_temp);
- mouse_xoffset=mouse_pos_temp.x-mouse_pos_abs.x;
- mouse_yoffset=mouse_pos_temp.y-mouse_pos_abs.y;
- if((mouse_xoffset<0) || (mouse_xoffset>mouse_pos_abs.width))
- mouse_xoffset=0;
- if((mouse_yoffset<0) || (mouse_yoffset>mouse_pos_abs.height))
- mouse_yoffset=0;
- //draw the cursor
- if((mouse_pos_temp.x>=0)&&
- (mouse_pos_temp.y>=0)&&
- (mouse_pos_temp.width>0)&&
- (mouse_pos_temp.height>0)){
- if(pdata->args.xfixes_cursor){
- XFIXES_POINTER_TO_YUV((&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.width,
- mouse_pos_temp.height,
- mouse_xoffset,
- mouse_yoffset,
- (xcim->width-mouse_pos_temp.width));
- }
- else{
- DUMMY_POINTER_TO_YUV((&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.width,
- mouse_pos_temp.height,
- mouse_xoffset,
- mouse_yoffset,
- pdata->npxl);
- }
- if(d_buff){
- //make previous cursor position dirty
- //on the currently front buffer (which
- //will be the back buffer next time it's
- //used)
- unsigned char *front_buff=
- (!img_sel)?((unsigned char*)image->data):
- ((unsigned char*)image_back->data);
-
- MARK_BUFFER_AREA( front_buff,
- (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,
- (temp_brwin.rrect.width),
- pdata->specs.depth)
- }
-
- }
- if(pdata->args.xfixes_cursor){
- XFree(xcim);
- xcim=NULL;
- }
- }
- if(!pdata->args.full_shots){
- rmdClearList(&pdata->rect_root);
- }
- if (pdata->encoder_busy) {
- pdata->frames_lost++;
- }
- pthread_mutex_lock(&pdata->img_buff_ready_mutex);
- pthread_cond_broadcast(&pdata->image_buffer_ready);
- pthread_mutex_unlock(&pdata->img_buff_ready_mutex);
- pdata->capture_busy = FALSE;
- }
-
- if(!pdata->args.noframe){
- XDestroyWindow(pdata->dpy,pdata->shaped_w);
- }
-
-
- pthread_mutex_lock(&pdata->img_buff_ready_mutex);
- pthread_cond_broadcast(&pdata->image_buffer_ready);
- pthread_mutex_unlock(&pdata->img_buff_ready_mutex);
- if(!pdata->args.noshared){
- XShmDetach (pdata->dpy, &shminfo);
- shmdt (shminfo.shmaddr);
- shmctl (shminfo.shmid, IPC_RMID, 0);
- if(d_buff){
- XShmDetach (pdata->dpy, &shminfo_back);
- shmdt (shminfo_back.shmaddr);
- shmctl (shminfo_back.shmid, IPC_RMID, 0);
- }
- }
- pthread_exit(&errno);
+void *rmdGetFrame(ProgData *pdata) {
+ int i=0,
+ blocknum_x=pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH,
+ blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH;
+ unsigned int msk_ret;
+ XRectangle mouse_pos_abs,mouse_pos_rel,mouse_pos_temp;
+ BRWindow temp_brwin;
+ Window root_ret, child_ret; //Frame
+ XFixesCursorImage *xcim=NULL;
+ XImage *image=NULL,*image_back=NULL; //the image that holds
+ //the current full screenshot
+ XShmSegmentInfo shminfo,shminfo_back; //info structure for the image above.
+ int init_img1=0,init_img2=0, img_sel,d_buff;
+
+ img_sel=d_buff=pdata->args.full_shots;
+
+ if ((init_img1 = rmdFirstFrame(pdata,&image,&shminfo) != 0)) {
+ if (pdata->args.encOnTheFly) {
+ if (remove(pdata->args.filename)) {
+ perror("Error while removing file:\n");
+ } else {
+ fprintf(stderr, "SIGABRT received,file %s removed\n",
+ pdata->args.filename);
+ }
+ } else {
+ rmdPurgeCache(pdata->cache_data,!pdata->args.nosound);
+ }
+
+ exit(init_img1);
+ }
+
+ if (d_buff) {
+ if ((init_img2 = rmdFirstFrame(pdata, &image_back, &shminfo_back) != 0)) {
+ if (pdata->args.encOnTheFly) {
+ if (remove(pdata->args.filename)) {
+ perror("Error while removing file:\n");
+ } else{
+ fprintf(stderr, "SIGABRT received,file %s removed\n",
+ pdata->args.filename);
+ }
+ } else {
+ rmdPurgeCache(pdata->cache_data, !pdata->args.nosound);
+ }
+
+ exit(init_img2);
+ }
+ }
+
+ if (!pdata->args.noframe) {
+ pdata->shaped_w=rmdFrameInit( pdata->dpy,
+ pdata->specs.screen,
+ pdata->specs.root,
+ pdata->brwin.rrect.x,
+ pdata->brwin.rrect.y,
+ pdata->brwin.rrect.width,
+ pdata->brwin.rrect.height);
+
+ XSelectInput(pdata->dpy,pdata->shaped_w,ExposureMask);
+ }
+
+ mouse_pos_abs.x=mouse_pos_temp.x=0;
+ mouse_pos_abs.y=mouse_pos_temp.y=0;
+ mouse_pos_abs.width=mouse_pos_temp.width=pdata->dummy_p_size;
+ mouse_pos_abs.height=mouse_pos_temp.height=pdata->dummy_p_size;
+
+ //This is the the place where we call XSelectInput
+ //and arrange so that we listen for damage on all
+ //windows
+ rmdInitEventsPolling(pdata);
+
+ while (pdata->running) {
+
+ //if we are left behind we must not wait.
+ //also before actually pausing we must make sure the streams
+ //are synced. sound stops so this should only happen quickly.
+ if (pdata->avd>0 || pdata->args.nosound) {
+ pthread_mutex_lock(&pdata->time_mutex);
+ pthread_cond_wait(&pdata->time_cond, &pdata->time_mutex);
+ pthread_mutex_unlock(&pdata->time_mutex);
+
+ if (pdata->paused) {
+ //this is necessary since event loop processes
+ //the shortcuts which will unpause the program
+ rmdEventLoop(pdata);
+ continue;
+ }
+ }
+ //read all events and construct list with damage
+ //events (if not full_shots)
+ rmdEventLoop(pdata);
+
+ //switch back and front buffers (full_shots only)
+ if (d_buff)
+ img_sel=(img_sel)?0:1;
+
+ pdata->capture_busy = TRUE;
+
+ rmdBRWinCpy(&temp_brwin,&pdata->brwin);
+
+
+ if ( pdata->args.xfixes_cursor ||
+ pdata->args.have_dummy_cursor||
+ pdata->args.follow_mouse) {
+
+
+ // Pointer sequence:
+ // * Mark previous position as dirty with rmdRectInsert()
+ // * Update to new position
+ // * Mark new position as dirty with rmdRectInsert()
+ if ( !pdata->args.full_shots &&
+ mouse_pos_temp.x >=0 &&
+ mouse_pos_temp.y >=0 &&
+ mouse_pos_temp.width > 0 &&
+ mouse_pos_temp.height > 0) {
+ rmdRectInsert(&pdata->rect_root,&mouse_pos_temp);
+ }
+
+ if (pdata->args.xfixes_cursor) {
+ xcim=XFixesGetCursorImage(pdata->dpy);
+ mouse_pos_abs.x=xcim->x-xcim->xhot;
+ mouse_pos_abs.y=xcim->y-xcim->yhot;
+ mouse_pos_abs.width=xcim->width;
+ mouse_pos_abs.height=xcim->height;
+ } else {
+ XQueryPointer(pdata->dpy,
+ pdata->specs.root,
+ &root_ret,&child_ret,
+ (int *)&mouse_pos_abs.x,(int *)&mouse_pos_abs.y,
+ (int *)&mouse_pos_rel.x,(int *)&mouse_pos_rel.y,&msk_ret);
+ }
+
+ CLIP_DUMMY_POINTER_AREA(mouse_pos_abs, &temp_brwin, &mouse_pos_temp);
+ if ( mouse_pos_temp.x >=0 &&
+ mouse_pos_temp.y >=0 &&
+ mouse_pos_temp.width > 0 &&
+ mouse_pos_temp.height > 0) {
+
+ //there are 3 capture scenarios:
+ // * Xdamage
+ // * full-shots with double buffering
+ // * full-shots on a single buffer
+ //The last one cannot be reached through
+ //this code (see above how the d_buf variable is set), but
+ //even if it could, it would not be of interest regarding the
+ //marking of the cursor area. Single buffer means full repaint
+ //on every frame so there is no need for marking at all.
+
+ if (!pdata->args.full_shots) {
+ rmdRectInsert(&pdata->rect_root,&mouse_pos_temp);
+ } else if (d_buff) {
+ unsigned char *back_buff=
+ (img_sel)?((unsigned char*)image->data):
+ ((unsigned char*)image_back->data);
+
+ MARK_BUFFER_AREA(
+ back_buff,
+ (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, (temp_brwin.rrect.width),
+ pdata->specs.depth
+ );
+ }
+ }
+ }
+ if (pdata->args.follow_mouse) {
+ rmdMoveCaptureArea( &pdata->brwin,
+ mouse_pos_abs.x+
+ ((pdata->args.xfixes_cursor)?xcim->xhot:0),
+ mouse_pos_abs.y+
+ ((pdata->args.xfixes_cursor)?xcim->yhot:0),
+ pdata->specs.width,
+ pdata->specs.height);
+
+ if (!pdata->args.noframe)
+ rmdMoveFrame( pdata->dpy,
+ pdata->shaped_w,
+ temp_brwin.rrect.x,
+ temp_brwin.rrect.y);
+ }
+
+ if (!pdata->args.full_shots) {
+ pthread_mutex_lock(&pdata->yuv_mutex);
+ rmdUpdateImage( pdata->dpy,
+ &pdata->enc_data->yuv,
+ &pdata->specs,
+ &pdata->rect_root,
+ &temp_brwin,
+ pdata->enc_data,
+ image->data,
+ pdata->args.noshared,
+ &shminfo,
+ pdata->shm_opcode,
+ pdata->args.no_quick_subsample);
+
+ rmdBlocksFromList( &pdata->rect_root,
+ temp_brwin.rrect.x,
+ temp_brwin.rrect.y,
+ pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH,
+ pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH);
+
+ pthread_mutex_unlock(&pdata->yuv_mutex);
+ } else {
+ unsigned char *front_buff=(!img_sel)?((unsigned char*)image->data):
+ ((unsigned char*)image_back->data);
+ unsigned char *back_buff=(!d_buff)?NULL:((img_sel)?
+ ((unsigned char*)image->data):
+ ((unsigned char*)image_back->data));
+
+ if (!pdata->args.noshared)
+ XShmGetImage(pdata->dpy,pdata->specs.root,
+ ((!img_sel)?image:image_back),
+ (temp_brwin.rrect.x),
+ (temp_brwin.rrect.y),AllPlanes);
+
+ if (pdata->args.noshared)
+ rmdGetZPixmap( pdata->dpy,
+ pdata->specs.root,
+ image->data,
+ temp_brwin.rrect.x,
+ temp_brwin.rrect.y,
+ temp_brwin.rrect.width,
+ 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;
+
+ UPDATE_YUV_BUFFER( &pdata->enc_data->yuv,
+ front_buff,back_buff,
+ pdata->enc_data->x_offset,
+ pdata->enc_data->y_offset,
+ temp_brwin.rrect.width,
+ temp_brwin.rrect.height,
+ pdata->args.no_quick_subsample,
+ pdata->specs.depth);
+
+ pthread_mutex_unlock(&pdata->yuv_mutex);
+ }
+
+ if (pdata->args.xfixes_cursor || pdata->args.have_dummy_cursor) {
+ int mouse_xoffset, mouse_yoffset;
+ //avoid segfaults
+ CLIP_DUMMY_POINTER_AREA(mouse_pos_abs,&temp_brwin, &mouse_pos_temp);
+ mouse_xoffset=mouse_pos_temp.x-mouse_pos_abs.x;
+ mouse_yoffset=mouse_pos_temp.y-mouse_pos_abs.y;
+ if ((mouse_xoffset<0) || (mouse_xoffset>mouse_pos_abs.width))
+ mouse_xoffset=0;
+
+ if ((mouse_yoffset<0) || (mouse_yoffset>mouse_pos_abs.height))
+ mouse_yoffset=0;
+
+ //draw the cursor
+ if ( (mouse_pos_temp.x>=0)&&
+ (mouse_pos_temp.y>=0)&&
+ (mouse_pos_temp.width>0)&&
+ (mouse_pos_temp.height>0)) {
+
+ if (pdata->args.xfixes_cursor) {
+ XFIXES_POINTER_TO_YUV(
+ &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.width,
+ mouse_pos_temp.height,
+ mouse_xoffset,
+ mouse_yoffset,
+ xcim->width-mouse_pos_temp.width
+ );
+ } else {
+ DUMMY_POINTER_TO_YUV(
+ &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.width,
+ mouse_pos_temp.height,
+ mouse_xoffset,
+ mouse_yoffset,
+ pdata->npxl
+ );
+ }
+
+ if (d_buff) {
+ //make previous cursor position dirty
+ //on the currently front buffer (which
+ //will be the back buffer next time it's
+ //used)
+ unsigned char *front_buff = (!img_sel)?((unsigned char*)image->data):
+ ((unsigned char*)image_back->data);
+
+ MARK_BUFFER_AREA(
+ front_buff,
+ 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,
+ temp_brwin.rrect.width,
+ pdata->specs.depth
+ );
+ }
+
+ }
+
+ if (pdata->args.xfixes_cursor) {
+ XFree(xcim);
+ xcim=NULL;
+ }
+ }
+
+ if (!pdata->args.full_shots)
+ rmdClearList(&pdata->rect_root);
+
+ if (pdata->encoder_busy)
+ pdata->frames_lost++;
+
+ pthread_mutex_lock(&pdata->img_buff_ready_mutex);
+ pthread_cond_broadcast(&pdata->image_buffer_ready);
+ pthread_mutex_unlock(&pdata->img_buff_ready_mutex);
+ pdata->capture_busy = FALSE;
+ }
+
+ if (!pdata->args.noframe)
+ XDestroyWindow(pdata->dpy,pdata->shaped_w);
+
+ pthread_mutex_lock(&pdata->img_buff_ready_mutex);
+ pthread_cond_broadcast(&pdata->image_buffer_ready);
+ pthread_mutex_unlock(&pdata->img_buff_ready_mutex);
+ if (!pdata->args.noshared) {
+ XShmDetach (pdata->dpy, &shminfo);
+ shmdt (shminfo.shmaddr);
+ shmctl (shminfo.shmid, IPC_RMID, 0);
+ if (d_buff) {
+ XShmDetach (pdata->dpy, &shminfo_back);
+ shmdt (shminfo_back.shmaddr);
+ shmctl (shminfo_back.shmid, IPC_RMID, 0);
+ }
+ }
+ pthread_exit(&errno);
}
-
© All Rights Reserved