diff options
Diffstat (limited to 'recordmydesktop/src')
37 files changed, 4805 insertions, 5020 deletions
diff --git a/recordmydesktop/src/rmd.c b/recordmydesktop/src/rmd.c index 339244b..f7c806f 100644 --- a/recordmydesktop/src/rmd.c +++ b/recordmydesktop/src/rmd.c @@ -46,148 +46,139 @@ #include <string.h> #include <errno.h> -int main(int argc,char **argv){ - ProgData pdata; - int exit_status = 0; - - rmdSetupDefaultArgs(&pdata.args); - - if (!rmdParseArgs(argc, argv, &pdata.args)) { - exit(1); - } - if (pdata.args.rescue_path != NULL) { - exit(rmdRescue(pdata.args.rescue_path)); - } - if(XInitThreads ()==0){ - fprintf(stderr,"Couldn't initialize thread support!\n"); - exit(7); - } - if(pdata.args.display!=NULL){ - pdata.dpy = XOpenDisplay(pdata.args.display); - XSetErrorHandler(rmdErrorHandler); - } - else{ - fprintf(stderr,"No display specified for connection!\n"); - exit(8); - } - if (pdata.dpy == NULL) { - fprintf(stderr, "Cannot connect to X server %s\n",pdata.args.display); - exit(9); - } - else{ - EncData enc_data; - CacheData cache_data; +int main(int argc, char **argv){ + ProgData pdata; + EncData enc_data; + CacheData cache_data; + int exit_status = 0; + #ifdef HAVE_LIBJACK - JackData jdata; + JackData jdata; - // Give jack access to program data, mainly for program state - jdata.pdata = &pdata; - pdata.jdata = &jdata; + // Give jack access to program data, mainly for program state + jdata.pdata = &pdata; + pdata.jdata = &jdata; #endif - // Query display specs - pdata.specs.screen = DefaultScreen(pdata.dpy); - pdata.specs.width = DisplayWidth(pdata.dpy, pdata.specs.screen); - pdata.specs.height = DisplayHeight(pdata.dpy, pdata.specs.screen); - pdata.specs.root = RootWindow(pdata.dpy, pdata.specs.screen); - pdata.specs.visual = DefaultVisual(pdata.dpy, pdata.specs.screen); - pdata.specs.gc = DefaultGC(pdata.dpy, pdata.specs.screen); - pdata.specs.depth = DefaultDepth(pdata.dpy, pdata.specs.screen); - - if((pdata.specs.depth!=32)&& - (pdata.specs.depth!=24)&& - (pdata.specs.depth!=16)){ - fprintf(stderr,"Only 32bpp,24bpp and 16bpp" - " color depth modes are currently supported.\n"); - exit(10); - } - if (!rmdSetBRWindow(pdata.dpy, &pdata.brwin, &pdata.specs, &pdata.args)) - exit(11); - - if( !pdata.args.nowmcheck && - rmdWMIsCompositing( pdata.dpy, pdata.specs.screen ) ) { - - fprintf(stderr,"\nDetected compositing window manager.\n" - "Reverting to full screen capture at every frame.\n" - "To disable this check run with --no-wm-check\n" - "(though that is not advised, since it will " - "probably produce faulty results).\n\n"); - pdata.args.full_shots=1; - pdata.args.noshared=0; - - } - - rmdQueryExtensions(pdata.dpy, - &pdata.args, - &pdata.damage_event, - &pdata.damage_error, - &pdata.shm_opcode); - - - if((exit_status=rmdInitializeData(&pdata,&enc_data,&cache_data))==0){ - - if(!strcmp(pdata.args.pause_shortcut, - pdata.args.stop_shortcut)|| - rmdRegisterShortcut(pdata.dpy, - pdata.specs.root, - pdata.args.pause_shortcut, - &(pdata.pause_key)) || - rmdRegisterShortcut(pdata.dpy, - pdata.specs.root, - pdata.args.stop_shortcut, - &(pdata.stop_key))){ - - fprintf(stderr,"Invalid shortcut," - " or shortcuts are the same!\n\n" - "Using defaults.\n"); - - rmdRegisterShortcut(pdata.dpy, - pdata.specs.root, - "Control+Mod1+p", - &(pdata.pause_key)); - rmdRegisterShortcut(pdata.dpy, - pdata.specs.root, - "Control+Mod1+s", - &(pdata.stop_key)); - } - - //this is where the capturing happens. - rmdThreads(&pdata); - - XCloseDisplay(pdata.dpy); - fprintf(stderr,".\n"); - - //encode and then cleanup cache - if(!pdata.args.encOnTheFly && !pdata.args.no_encode){ - if (!pdata.aborted) { - rmdEncodeCache(&pdata); - } - fprintf(stderr,"Cleanning up cache...\n"); - if(rmdPurgeCache(pdata.cache_data,!pdata.args.nosound)) - fprintf(stderr,"Some error occured " - "while cleaning up cache!\n"); - fprintf(stderr,"Done!!!\n"); - } - - - if (pdata.aborted && pdata.args.encOnTheFly) { - if(remove(pdata.args.filename)){ - perror("Error while removing file:\n"); - return 1; - } - else{ - fprintf(stderr,"SIGABRT received,file %s removed\n", - pdata.args.filename); - return 0; - } - } - else - fprintf(stderr,"Goodbye!\n"); - - - rmdCleanUp(); - } - } - - return exit_status; + rmdSetupDefaultArgs(&pdata.args); + + if (!rmdParseArgs(argc, argv, &pdata.args)) + exit(1); + + if (pdata.args.rescue_path != NULL) + exit(rmdRescue(pdata.args.rescue_path)); + + if (XInitThreads()==0) { + fprintf(stderr, "Couldn't initialize thread support!\n"); + exit(7); + } + + if (pdata.args.display != NULL) { + pdata.dpy = XOpenDisplay(pdata.args.display); + XSetErrorHandler(rmdErrorHandler); + } else { + fprintf(stderr, "No display specified for connection!\n"); + exit(8); + } + + if (pdata.dpy == NULL) { + fprintf(stderr, "Cannot connect to X server %s\n", pdata.args.display); + exit(9); + } + + // Query display specs + pdata.specs.screen = DefaultScreen(pdata.dpy); + pdata.specs.width = DisplayWidth(pdata.dpy, pdata.specs.screen); + pdata.specs.height = DisplayHeight(pdata.dpy, pdata.specs.screen); + pdata.specs.root = RootWindow(pdata.dpy, pdata.specs.screen); + pdata.specs.visual = DefaultVisual(pdata.dpy, pdata.specs.screen); + pdata.specs.gc = DefaultGC(pdata.dpy, pdata.specs.screen); + pdata.specs.depth = DefaultDepth(pdata.dpy, pdata.specs.screen); + + if (pdata.specs.depth != 32 && pdata.specs.depth != 24 && pdata.specs.depth != 16) { + fprintf(stderr, + "Only 32bpp, 24bpp, and 16bpp" + " color depth modes are currently supported.\n"); + exit(10); + } + + if (!rmdSetBRWindow(pdata.dpy, &pdata.brwin, &pdata.specs, &pdata.args)) + exit(11); + + if (!pdata.args.nowmcheck && rmdWMIsCompositing( pdata.dpy, pdata.specs.screen ) ) { + + fprintf(stderr, "\nDetected compositing window manager.\n" + "Reverting to full screen capture at every frame.\n" + "To disable this check run with --no-wm-check\n" + "(though that is not advised, since it will " + "probably produce faulty results).\n\n"); + pdata.args.full_shots=1; + pdata.args.noshared=0; + } + + rmdQueryExtensions( pdata.dpy, + &pdata.args, + &pdata.damage_event, + &pdata.damage_error, + &pdata.shm_opcode); + + exit_status = rmdInitializeData(&pdata, &enc_data, &cache_data); + if (exit_status) + exit(exit_status); + + if ( !strcmp(pdata.args.pause_shortcut, pdata.args.stop_shortcut) || + rmdRegisterShortcut( pdata.dpy, pdata.specs.root, + pdata.args.pause_shortcut, + &(pdata.pause_key)) || + rmdRegisterShortcut( pdata.dpy, + pdata.specs.root, + pdata.args.stop_shortcut, + &(pdata.stop_key))) { + + fprintf(stderr, "Invalid shortcut, or shortcuts are the same!\n\nUsing defaults.\n"); + + rmdRegisterShortcut( pdata.dpy, + pdata.specs.root, + "Control+Mod1+p", + &(pdata.pause_key)); + + rmdRegisterShortcut( pdata.dpy, + pdata.specs.root, + "Control+Mod1+s", + &(pdata.stop_key)); + } + + //this is where the capturing happens. + rmdThreads(&pdata); + + XCloseDisplay(pdata.dpy); + fprintf(stderr, ".\n"); + + //encode and then cleanup cache + if (!pdata.args.encOnTheFly && !pdata.args.no_encode) { + if (!pdata.aborted) + rmdEncodeCache(&pdata); + + fprintf(stderr,"Cleanning up cache...\n"); + if (rmdPurgeCache(pdata.cache_data,!pdata.args.nosound)) + fprintf(stderr,"Some error occured while cleaning up cache!\n"); + + fprintf(stderr,"Done!!!\n"); + } + + if (pdata.aborted && pdata.args.encOnTheFly) { + if (remove(pdata.args.filename)) { + perror("Error while removing file:\n"); + return 1; + } else { + fprintf(stderr, "SIGABRT received,file %s removed\n", + pdata.args.filename); + return 0; + } + } else + fprintf(stderr,"Goodbye!\n"); + + rmdCleanUp(); + + return exit_status; } diff --git a/recordmydesktop/src/rmd_cache.c b/recordmydesktop/src/rmd_cache.c index 61111b7..22c7200 100644 --- a/recordmydesktop/src/rmd_cache.c +++ b/recordmydesktop/src/rmd_cache.c @@ -49,180 +49,176 @@ * */ static void rmdCacheFileN(char *name, char **newname, int n) { // Nth cache file - char numbuf[8]; - strcpy(*newname,name); - strcat(*newname,"."); - snprintf( numbuf, 8, "%d", n ); - strcat(*newname,numbuf); -} + char numbuf[8]; -int rmdSwapCacheFilesWrite(char *name,int n,gzFile **fp,FILE **ucfp){ - char *newname=malloc(strlen(name)+10); - rmdCacheFileN(name,&newname,n); - if(*fp==NULL){ - fflush(*ucfp); - fclose(*ucfp); - *ucfp=fopen(newname,"wb"); - } - else{ - gzflush(*fp,Z_FINISH); - gzclose(*fp); - *fp=gzopen(newname,"wb0f"); - } - free(newname); - return ((*fp==NULL)&&(*ucfp==NULL)); + strcpy(*newname, name); + strcat(*newname, "."); + snprintf(numbuf, 8, "%d", n); + strcat(*newname, numbuf); } -int rmdSwapCacheFilesRead(char *name,int n,gzFile **fp,FILE **ucfp){ - char *newname=malloc(strlen(name)+10); - rmdCacheFileN(name,&newname,n); - if(*fp==NULL){ - fclose(*ucfp); - *ucfp=fopen(newname,"rb"); - } - else{ - - gzclose(*fp); - *fp=gzopen(newname,"rb"); - } - free(newname); - return ((*fp==NULL)&&(*ucfp==NULL)); +int rmdSwapCacheFilesWrite(char *name, int n, gzFile **fp, FILE **ucfp) { + char *newname = malloc(strlen(name) + 10); + + rmdCacheFileN(name, &newname, n); + if (*fp == NULL) { + fflush(*ucfp); + fclose(*ucfp); + *ucfp = fopen(newname, "wb"); + } else { + gzflush(*fp, Z_FINISH); + gzclose(*fp); + *fp = gzopen(newname, "wb0f"); + } + free(newname); + + return ((*fp == NULL) && (*ucfp == NULL)); } -int rmdPurgeCache(CacheData *cache_data_t,int sound){ - struct stat buff; - char *fname; - fname=malloc(strlen(cache_data_t->imgdata)+10); - strcpy(fname,cache_data_t->imgdata); - int exit_value=0; - int nth_cache=1; - - while (stat(fname,&buff)==0){ - if(remove(fname)){ - fprintf(stderr,"Couldn't remove temporary file %s", - cache_data_t->imgdata); - exit_value=1; - } - rmdCacheFileN(cache_data_t->imgdata,&fname,nth_cache); - nth_cache++; - } - free(fname); - if(sound){ - if(remove(cache_data_t->audiodata)){ - fprintf(stderr,"Couldn't remove temporary file %s", - cache_data_t->audiodata); - exit_value=1; - } - } - if(remove(cache_data_t->specsfile)){ - fprintf(stderr,"Couldn't remove temporary file %s", - cache_data_t->specsfile); - exit_value=1; - } - if(remove(cache_data_t->projname)){ - fprintf(stderr,"Couldn't remove temporary directory %s", - cache_data_t->projname); - exit_value=1; - } - return exit_value; +int rmdSwapCacheFilesRead(char *name, int n, gzFile **fp, FILE **ucfp) { + char *newname = malloc(strlen(name) + 10); + + rmdCacheFileN(name, &newname, n); + if (*fp == NULL) { + fclose(*ucfp); + *ucfp = fopen(newname, "rb"); + } else { + gzclose(*fp); + *fp = gzopen(newname, "rb"); + } + free(newname); + + return ((*fp == NULL) && (*ucfp == NULL)); } -void rmdInitCacheData(ProgData *pdata, - EncData *enc_data_t, - CacheData *cache_data_t){ - int width,height,offset_x,offset_y,pid; - char pidbuf[8]; - - //we set the buffer only since there's - //no need to initialize the encoder from now. - width=((pdata->brwin.rrect.width + 15) >>4)<<4; - height=((pdata->brwin.rrect.height + 15) >>4)<<4; - offset_x=((width-pdata->brwin.rrect.width)/2)&~1; - offset_y=((height-pdata->brwin.rrect.height)/2)&~1; - - (pdata)->enc_data=enc_data_t; - - enc_data_t->yuv.y=(unsigned char *)malloc(height*width); - enc_data_t->yuv.u=(unsigned char *)malloc(height*width/4); - enc_data_t->yuv.v=(unsigned char *)malloc(height*width/4); - enc_data_t->yuv.y_width=width; - enc_data_t->yuv.y_height=height; - enc_data_t->yuv.y_stride=width; - - enc_data_t->yuv.uv_width=width/2; - enc_data_t->yuv.uv_height=height/2; - enc_data_t->yuv.uv_stride=width/2; - enc_data_t->x_offset=offset_x; - enc_data_t->y_offset=offset_y; - - - //now we set the cache files - (pdata)->cache_data=cache_data_t; - - cache_data_t->workdir=(pdata->args).workdir; - pid=getpid(); - - snprintf( pidbuf, 8, "%d", pid ); - //names are stored relatively to current dir(i.e. no chdir) - cache_data_t->projname=malloc(strlen(cache_data_t->workdir)+ - 12+strlen(pidbuf)+3); - //projname - strcpy(cache_data_t->projname,cache_data_t->workdir); - strcat(cache_data_t->projname,"/"); - strcat(cache_data_t->projname,"rMD-session-"); - strcat(cache_data_t->projname,pidbuf); - strcat(cache_data_t->projname,"/"); - //image data - cache_data_t->imgdata=malloc(strlen(cache_data_t->projname)+11); - strcpy(cache_data_t->imgdata,cache_data_t->projname); - strcat(cache_data_t->imgdata,"img.out"); - //audio data - cache_data_t->audiodata=malloc(strlen(cache_data_t->projname)+10); - strcpy(cache_data_t->audiodata,cache_data_t->projname); - strcat(cache_data_t->audiodata,"audio.pcm"); - //specsfile - cache_data_t->specsfile=malloc(strlen(cache_data_t->projname)+10); - strcpy(cache_data_t->specsfile,cache_data_t->projname); - strcat(cache_data_t->specsfile,"specs.txt"); - - //now that've got out buffers and our filenames we start - //creating the needed files - - if(mkdir(cache_data_t->projname,0777)){ - fprintf(stderr,"Could not create temporary directory %s !!!\n", - cache_data_t->projname); - exit(13); - } - if(!pdata->args.zerocompression){ - cache_data_t->ifp=gzopen(cache_data_t->imgdata,"wb0f"); - if(cache_data_t->ifp==NULL){ - fprintf(stderr,"Could not create temporary file %s !!!\n", - cache_data_t->imgdata); - exit(13); - } - } - else{ - cache_data_t->uncifp=fopen(cache_data_t->imgdata,"wb0f"); - if(cache_data_t->uncifp==NULL){ - fprintf(stderr,"Could not create temporary file %s !!!\n", - cache_data_t->imgdata); - exit(13); - } - } - if(!pdata->args.nosound){ - cache_data_t->afp=fopen(cache_data_t->audiodata,"wb"); - if(cache_data_t->afp==NULL){ - fprintf(stderr,"Could not create temporary file %s !!!\n", - cache_data_t->audiodata); - exit(13); - } - } - if(rmdWriteSpecsFile(pdata)){ - fprintf(stderr,"Could not write specsfile %s !!!\n", - cache_data_t->specsfile); - exit(13); - } +int rmdPurgeCache(CacheData *cache_data_t, int sound) { + struct stat buff; + char *fname; + int exit_value = 0; + int nth_cache = 1; + + fname = malloc(strlen(cache_data_t->imgdata) + 10); + strcpy(fname, cache_data_t->imgdata); + + while (stat(fname, &buff) == 0) { + if (remove(fname)) { + fprintf(stderr, "Couldn't remove temporary file %s", cache_data_t->imgdata); + exit_value = 1; + } + rmdCacheFileN(cache_data_t->imgdata, &fname, nth_cache); + nth_cache++; + } + + free(fname); + + if (sound) { + if (remove(cache_data_t->audiodata)) { + fprintf(stderr, "Couldn't remove temporary file %s", cache_data_t->audiodata); + exit_value = 1; + } + } + + if (remove(cache_data_t->specsfile)) { + fprintf(stderr, "Couldn't remove temporary file %s", cache_data_t->specsfile); + exit_value = 1; + } + + if (remove(cache_data_t->projname)) { + fprintf(stderr, "Couldn't remove temporary directory %s", cache_data_t->projname); + exit_value = 1; + } + + return exit_value; +} +void rmdInitCacheData(ProgData *pdata, EncData *enc_data_t, CacheData *cache_data_t) { + int width, height, offset_x, offset_y, pid; + char pidbuf[8]; + + //we set the buffer only since there's + //no need to initialize the encoder from now. + width = ((pdata->brwin.rrect.width + 15) >>4)<<4; + height = ((pdata->brwin.rrect.height + 15) >>4)<<4; + offset_x = ((width-pdata->brwin.rrect.width)/2)&~1; + offset_y = ((height-pdata->brwin.rrect.height)/2)&~1; + + (pdata)->enc_data = enc_data_t; + + enc_data_t->yuv.y = (unsigned char *)malloc(height*width); + enc_data_t->yuv.u = (unsigned char *)malloc(height*width/4); + enc_data_t->yuv.v = (unsigned char *)malloc(height*width/4); + enc_data_t->yuv.y_width = width; + enc_data_t->yuv.y_height = height; + enc_data_t->yuv.y_stride = width; + + enc_data_t->yuv.uv_width = width/2; + enc_data_t->yuv.uv_height = height/2; + enc_data_t->yuv.uv_stride = width/2; + enc_data_t->x_offset = offset_x; + enc_data_t->y_offset = offset_y; + + //now we set the cache files + (pdata)->cache_data = cache_data_t; + + cache_data_t->workdir = (pdata->args).workdir; + pid = getpid(); + + snprintf( pidbuf, 8, "%d", pid ); + //names are stored relatively to current dir(i.e. no chdir) + cache_data_t->projname = malloc(strlen(cache_data_t->workdir) + 12 + strlen(pidbuf) + 3); + //projname + strcpy(cache_data_t->projname, cache_data_t->workdir); + strcat(cache_data_t->projname, "/"); + strcat(cache_data_t->projname, "rMD-session-"); + strcat(cache_data_t->projname, pidbuf); + strcat(cache_data_t->projname, "/"); + //image data + cache_data_t->imgdata = malloc(strlen(cache_data_t->projname) + 11); + strcpy(cache_data_t->imgdata, cache_data_t->projname); + strcat(cache_data_t->imgdata, "img.out"); + //audio data + cache_data_t->audiodata = malloc(strlen(cache_data_t->projname) + 10); + strcpy(cache_data_t->audiodata, cache_data_t->projname); + strcat(cache_data_t->audiodata, "audio.pcm"); + //specsfile + cache_data_t->specsfile = malloc(strlen(cache_data_t->projname) + 10); + strcpy(cache_data_t->specsfile, cache_data_t->projname); + strcat(cache_data_t->specsfile, "specs.txt"); + + //now that've got out buffers and our filenames we start + //creating the needed files + + if (mkdir(cache_data_t->projname, 0777)) { + fprintf(stderr, "Could not create temporary directory %s !!!\n", cache_data_t->projname); + exit(13); + } + + if (!pdata->args.zerocompression) { + cache_data_t->ifp = gzopen(cache_data_t->imgdata, "wb0f"); + if (cache_data_t->ifp == NULL) { + fprintf(stderr, "Could not create temporary file %s !!!\n", cache_data_t->imgdata); + exit(13); + } + } else { + cache_data_t->uncifp = fopen(cache_data_t->imgdata, "wb0f"); + if (cache_data_t->uncifp == NULL) { + fprintf(stderr, "Could not create temporary file %s !!!\n", cache_data_t->imgdata); + exit(13); + } + } + + if (!pdata->args.nosound) { + cache_data_t->afp = fopen(cache_data_t->audiodata, "wb"); + if (cache_data_t->afp == NULL) { + fprintf(stderr, "Could not create temporary file %s !!!\n", cache_data_t->audiodata); + exit(13); + } + } + + if (rmdWriteSpecsFile(pdata)) { + fprintf(stderr, "Could not write specsfile %s !!!\n", cache_data_t->specsfile); + exit(13); + } } diff --git a/recordmydesktop/src/rmd_cache_audio.c b/recordmydesktop/src/rmd_cache_audio.c index aad5496..042c734 100644 --- a/recordmydesktop/src/rmd_cache_audio.c +++ b/recordmydesktop/src/rmd_cache_audio.c @@ -38,75 +38,73 @@ -void *rmdCacheSoundBuffer(ProgData *pdata){ +void *rmdCacheSoundBuffer(ProgData *pdata) { + size_t write_size = pdata->periodsize * pdata->sound_framesize; + +#ifdef HAVE_LIBJACK + if (pdata->args.use_jack) + write_size = pdata->sound_framesize * pdata->jdata->buffersize; +#endif + //We are simply going to throw sound on the disk. //It's sound is tiny compared to that of image, so //compressing would reducethe overall size by only an //insignificant fraction. + #ifdef HAVE_LIBJACK - void *jackbuf=NULL; - if(pdata->args.use_jack){ - jackbuf=malloc(pdata->sound_framesize*pdata->jdata->buffersize); - } + void *jackbuf = NULL; + if (pdata->args.use_jack) + jackbuf=malloc(pdata->sound_framesize * pdata->jdata->buffersize); #endif - while((pdata->running)){ - SndBuffer *buff=NULL; - - if (pdata->paused) { - pthread_mutex_lock(&pdata->pause_mutex); - pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); - pthread_mutex_unlock(&pdata->pause_mutex); - } - if(!pdata->args.use_jack){ - if(pdata->sound_buffer==NULL){ - pdata->v_enc_thread_waiting=1; - pthread_mutex_lock(&pdata->snd_buff_ready_mutex); - pthread_cond_wait(&pdata->sound_data_read, - &pdata->snd_buff_ready_mutex); - pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); - pdata->v_enc_thread_waiting=0; - } - if(pdata->sound_buffer==NULL || !pdata->running){ - break; - } - pthread_mutex_lock(&pdata->sound_buffer_mutex); - buff=pdata->sound_buffer; - //advance the list - pdata->sound_buffer=pdata->sound_buffer->next; - pthread_mutex_unlock(&pdata->sound_buffer_mutex); - fwrite(buff->data,1,pdata->periodsize*pdata->sound_framesize, - pdata->cache_data->afp); - free(buff->data); - free(buff); - } - else{ + + while (pdata->running) { + SndBuffer *buff = NULL; + + if (pdata->paused) { + pthread_mutex_lock(&pdata->pause_mutex); + pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); + pthread_mutex_unlock(&pdata->pause_mutex); + } + + if (!pdata->args.use_jack) { + if (pdata->sound_buffer == NULL) { + pdata->v_enc_thread_waiting = 1; + pthread_mutex_lock(&pdata->snd_buff_ready_mutex); + pthread_cond_wait(&pdata->sound_data_read, &pdata->snd_buff_ready_mutex); + pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); + pdata->v_enc_thread_waiting = 0; + } + + if (pdata->sound_buffer == NULL || !pdata->running) + break; + + pthread_mutex_lock(&pdata->sound_buffer_mutex); + buff = pdata->sound_buffer; + //advance the list + pdata->sound_buffer = pdata->sound_buffer->next; + pthread_mutex_unlock(&pdata->sound_buffer_mutex); + fwrite(buff->data, 1, write_size, pdata->cache_data->afp); + free(buff->data); + free(buff); + } else { #ifdef HAVE_LIBJACK - if((*jack_ringbuffer_read_space)(pdata->jdata->sound_buffer)>= - (pdata->sound_framesize*pdata->jdata->buffersize)){ - (*jack_ringbuffer_read)(pdata->jdata->sound_buffer, - jackbuf, - (pdata->sound_framesize* - pdata->jdata->buffersize)); - fwrite(jackbuf,1,(pdata->sound_framesize* - pdata->jdata->buffersize), - pdata->cache_data->afp); - } - else{ - pdata->v_enc_thread_waiting=1; - pthread_mutex_lock(&pdata->snd_buff_ready_mutex); - pthread_cond_wait(&pdata->sound_data_read, - &pdata->snd_buff_ready_mutex); - pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); - pdata->v_enc_thread_waiting=0; - continue; - } + if ((*jack_ringbuffer_read_space)(pdata->jdata->sound_buffer) >= write_size) { + (*jack_ringbuffer_read)(pdata->jdata->sound_buffer, jackbuf, write_size); + fwrite(jackbuf, 1, write_size, pdata->cache_data->afp); + } else { + pdata->v_enc_thread_waiting=1; + pthread_mutex_lock(&pdata->snd_buff_ready_mutex); + pthread_cond_wait(&pdata->sound_data_read, &pdata->snd_buff_ready_mutex); + pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); + pdata->v_enc_thread_waiting=0; + + continue; + } #endif - } - pdata->avd-=pdata->periodtime; - } + } + pdata->avd-=pdata->periodtime; + } - fclose(pdata->cache_data->afp); - pthread_exit(&errno); + fclose(pdata->cache_data->afp); + pthread_exit(&errno); } - - diff --git a/recordmydesktop/src/rmd_cache_frame.c b/recordmydesktop/src/rmd_cache_frame.c index 18ae934..3c4c219 100644 --- a/recordmydesktop/src/rmd_cache_frame.c +++ b/recordmydesktop/src/rmd_cache_frame.c @@ -44,266 +44,272 @@ #define CACHE_FILE_SIZE_LIMIT (500 * 1024 * 1024) -static int rmdFlushBlock(unsigned char *buf, - int blockno, - int width, - int height, - int blockwidth, - gzFile *fp, - FILE *ucfp, - int flush) { - int j,i, - bytes_written=0, - block_i=(!blockwidth)?0:(blockno/(width/blockwidth)),//place on the grid - block_k=(!blockwidth)?0:(blockno%(width/blockwidth)); - register unsigned char *buf_reg=(&buf[(block_i* - width+ - block_k)*blockwidth]); - static unsigned char out_buffer[CACHE_OUT_BUFFER_SIZE]; - static unsigned int out_buffer_bytes=0; - - if(out_buffer_bytes+pow(blockwidth,2)>=CACHE_OUT_BUFFER_SIZE || - (flush && out_buffer_bytes)){ - if(ucfp==NULL) - gzwrite(fp,(void *)out_buffer,out_buffer_bytes); - else - fwrite((void *)out_buffer,1,out_buffer_bytes,ucfp); - bytes_written=out_buffer_bytes; - out_buffer_bytes=0; - } - if(!flush){ - register unsigned char *out_buf_reg=&out_buffer[out_buffer_bytes]; - for(j=0;j<blockwidth;j++){ - for(i=0;i<blockwidth;i++) - (*out_buf_reg++)=(*buf_reg++); - out_buffer_bytes+=blockwidth; - buf_reg+=width-blockwidth; - } - } - - return bytes_written; +static int rmdFlushBlock( + unsigned char *buf, + int blockno, + int width, + int height, + int blockwidth, + gzFile *fp, + FILE *ucfp, + int flush) { + + int j,i, + bytes_written=0, + block_i=(!blockwidth)?0:(blockno/(width/blockwidth)),//place on the grid + block_k=(!blockwidth)?0:(blockno%(width/blockwidth)); + register unsigned char *buf_reg = (&buf[(block_i * width + block_k) * blockwidth]); + static unsigned char out_buffer[CACHE_OUT_BUFFER_SIZE]; + static unsigned int out_buffer_bytes=0; + + if (out_buffer_bytes+pow(blockwidth,2)>=CACHE_OUT_BUFFER_SIZE || (flush && out_buffer_bytes)) { + if (ucfp==NULL) + gzwrite(fp,(void *)out_buffer,out_buffer_bytes); + else + fwrite((void *)out_buffer,1,out_buffer_bytes,ucfp); + + bytes_written=out_buffer_bytes; + out_buffer_bytes=0; + } + if (!flush) { + register unsigned char *out_buf_reg=&out_buffer[out_buffer_bytes]; + + for(j=0;j<blockwidth;j++) { + + for(i=0;i<blockwidth;i++) + (*out_buf_reg++)=(*buf_reg++); + + out_buffer_bytes+=blockwidth; + buf_reg+=width-blockwidth; + } + } + + return bytes_written; } -void *rmdCacheImageBuffer(ProgData *pdata){ - - gzFile *fp=NULL; - FILE *ucfp=NULL; - int index_entry_size=sizeof(u_int32_t), - blocknum_x=pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH, - blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH, - firstrun=1, - frameno=0, - nbytes=0, - nth_cache=1; - u_int32_t ynum,unum,vnum, - y_short_blocks[blocknum_x*blocknum_y], - u_short_blocks[blocknum_x*blocknum_y], - v_short_blocks[blocknum_x*blocknum_y]; - unsigned long long int total_bytes = 0; - unsigned long long int total_received_bytes = 0; - - if(!pdata->args.zerocompression){ - fp=pdata->cache_data->ifp; - if(fp==NULL)exit(13); - } - else{ - ucfp=pdata->cache_data->uncifp; - if(ucfp==NULL)exit(13); - } - - - while(pdata->running){ - int j; - FrameHeader fheader; - ynum=unum=vnum=0; - - pdata->th_enc_thread_waiting=1; - pthread_mutex_lock(&pdata->img_buff_ready_mutex); - pthread_cond_wait(&pdata->image_buffer_ready, - &pdata->img_buff_ready_mutex); - pthread_mutex_unlock(&pdata->img_buff_ready_mutex); - pdata->th_enc_thread_waiting=0; - - if (pdata->paused) { - pthread_mutex_lock(&pdata->pause_mutex); - pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); - pthread_mutex_unlock(&pdata->pause_mutex); - } - - pthread_mutex_lock(&pdata->yuv_mutex); - - //find and flush different blocks - if(firstrun){ - firstrun=0; - for(j=0;j<blocknum_x*blocknum_y;j++){ - ynum++; - yblocks[ynum-1]=1; - y_short_blocks[ynum-1]=j; - unum++; - ublocks[unum-1]=1; - u_short_blocks[ynum-1]=j; - vnum++; - vblocks[vnum-1]=1; - v_short_blocks[ynum-1]=j; - } - } - else{ - /**COMPRESS ARRAYS*/ - for(j=0;j<blocknum_x*blocknum_y;j++){ - if(yblocks[j]){ - ynum++; - y_short_blocks[ynum-1]=j; - } - if(ublocks[j]){ - unum++; - u_short_blocks[unum-1]=j; - } - if(vblocks[j]){ - vnum++; - v_short_blocks[vnum-1]=j; - } - } - } - - /**WRITE FRAME TO DISK*/ - if(!pdata->args.zerocompression){ - if(ynum*4+unum+vnum>(blocknum_x*blocknum_y*6)/10) - gzsetparams (fp,1,Z_FILTERED); - else - gzsetparams (fp,0,Z_FILTERED); - } - - strncpy(fheader.frame_prefix,"FRAM",4); - fheader.frameno=++frameno; - fheader.current_total = pdata->frames_total; - - fheader.Ynum=ynum; - fheader.Unum=unum; - fheader.Vnum=vnum; - if(!pdata->args.zerocompression){ - nbytes+=gzwrite(fp,(void*)&fheader,sizeof(FrameHeader)); - //flush indexes - if(ynum)nbytes+=gzwrite(fp, - (void*)y_short_blocks, - ynum*index_entry_size); - if(unum)nbytes+=gzwrite(fp, - (void*)u_short_blocks, - unum*index_entry_size); - if(vnum)nbytes+=gzwrite(fp, - (void*)v_short_blocks, - vnum*index_entry_size); - } - else{ - nbytes+=sizeof(FrameHeader)* - fwrite((void*)&fheader,sizeof(FrameHeader),1,ucfp); - //flush indexes - if(ynum)nbytes+=index_entry_size* - fwrite(y_short_blocks,index_entry_size,ynum,ucfp); - if(unum)nbytes+=index_entry_size* - fwrite(u_short_blocks,index_entry_size,unum,ucfp); - if(vnum)nbytes+=index_entry_size* - fwrite(v_short_blocks,index_entry_size,vnum,ucfp); - } - //flush the blocks for each buffer - if(ynum){ - for(j=0;j<ynum;j++) - nbytes+=rmdFlushBlock(pdata->enc_data->yuv.y,y_short_blocks[j], - pdata->enc_data->yuv.y_width, - pdata->enc_data->yuv.y_height, - Y_UNIT_WIDTH, - fp, - ucfp, - 0); - } - if(unum){ - for(j=0;j<unum;j++) - nbytes+=rmdFlushBlock(pdata->enc_data->yuv.u,u_short_blocks[j], - pdata->enc_data->yuv.uv_width, - pdata->enc_data->yuv.uv_height, - UV_UNIT_WIDTH, - fp, - ucfp, - 0); - } - if(vnum){ - for(j=0;j<vnum;j++) - nbytes+=rmdFlushBlock(pdata->enc_data->yuv.v,v_short_blocks[j], - pdata->enc_data->yuv.uv_width, - pdata->enc_data->yuv.uv_height, - UV_UNIT_WIDTH, - fp, - ucfp, - 0); - } - //release main buffer - pthread_mutex_unlock(&pdata->yuv_mutex); - - nbytes+=rmdFlushBlock(NULL,0,0,0,0,fp,ucfp,1); - /**@________________@**/ - pdata->avd+=pdata->frametime; - if(nbytes>CACHE_FILE_SIZE_LIMIT){ - if(rmdSwapCacheFilesWrite(pdata->cache_data->imgdata, - nth_cache,&fp,&ucfp)){ - fprintf(stderr,"New cache file could not be created.\n" - "Ending recording...\n"); - fflush(stderr); - raise(SIGINT); //if for some reason we cannot make a new file - //we have to stop. If we are out of space, - //which means - //that encoding cannot happen either, - //InitEncoder will cause an abrupt end with an - //error code and the cache will remain intact. - //If we've chosen separate two-stages, - //the program will make a - //clean exit. - //In either case data will be preserved so if - //space is freed the recording - //can be proccessed later. - } - total_bytes += nbytes; - nth_cache++; - nbytes=0; - } - } - total_bytes += nbytes; - - { - unsigned int bytes_per_pixel = pdata->specs.depth >= 24 ? 4 : 2; - unsigned int pixels_per_frame = pdata->brwin.rrect.width * pdata->brwin.rrect.height; - - total_received_bytes = ((unsigned long long int)frameno) * bytes_per_pixel * pixels_per_frame; - } - - if(total_received_bytes){ - double percent_of_data_left = (total_bytes / (double)total_received_bytes) * 100; - - fprintf(stderr, - "\n" - "*********************************************\n" - "\n" - "Cached %llu MB, from %llu MB that were received.\n" - "Average cache compression ratio: %.1f %%\n" - "\n" - "*********************************************\n", - total_bytes / BYTES_PER_MB, - total_received_bytes / BYTES_PER_MB, - 100 - percent_of_data_left); - - } - - fprintf(stderr, - "Saved %d frames in a total of %d requests\n", - frameno, - pdata->frames_total); - fflush(stderr); - - if(!pdata->args.zerocompression){ - gzflush(fp,Z_FINISH); - gzclose(fp); - } - else{ - fflush(ucfp); - fclose(ucfp); - } - pthread_exit(&errno); +void *rmdCacheImageBuffer(ProgData *pdata) { + + gzFile *fp=NULL; + FILE *ucfp=NULL; + int index_entry_size=sizeof(u_int32_t), + blocknum_x=pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH, + blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH, + firstrun=1, + frameno=0, + nbytes=0, + nth_cache=1; + u_int32_t ynum,unum,vnum, + y_short_blocks[blocknum_x*blocknum_y], + u_short_blocks[blocknum_x*blocknum_y], + v_short_blocks[blocknum_x*blocknum_y]; + unsigned long long int total_bytes = 0; + unsigned long long int total_received_bytes = 0; + + if (!pdata->args.zerocompression) { + fp=pdata->cache_data->ifp; + + if (fp==NULL) + exit(13); + } else { + ucfp=pdata->cache_data->uncifp; + + if (ucfp==NULL) + exit(13); + } + + while (pdata->running) { + int j; + + FrameHeader fheader; + ynum=unum=vnum=0; + + pdata->th_enc_thread_waiting=1; + pthread_mutex_lock(&pdata->img_buff_ready_mutex); + pthread_cond_wait(&pdata->image_buffer_ready, &pdata->img_buff_ready_mutex); + pthread_mutex_unlock(&pdata->img_buff_ready_mutex); + pdata->th_enc_thread_waiting=0; + + if (pdata->paused) { + pthread_mutex_lock(&pdata->pause_mutex); + pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); + pthread_mutex_unlock(&pdata->pause_mutex); + } + + pthread_mutex_lock(&pdata->yuv_mutex); + + //find and flush different blocks + if (firstrun) { + firstrun=0; + for(j=0;j<blocknum_x*blocknum_y;j++) { + ynum++; + yblocks[ynum-1]=1; + y_short_blocks[ynum-1]=j; + unum++; + ublocks[unum-1]=1; + u_short_blocks[ynum-1]=j; + vnum++; + vblocks[vnum-1]=1; + v_short_blocks[ynum-1]=j; + } + } else { + /**COMPRESS ARRAYS*/ + for(j=0;j<blocknum_x*blocknum_y;j++) { + if (yblocks[j]) { + ynum++; + y_short_blocks[ynum-1]=j; + } + if (ublocks[j]) { + unum++; + u_short_blocks[unum-1]=j; + } + if (vblocks[j]) { + vnum++; + v_short_blocks[vnum-1]=j; + } + } + } + + /**WRITE FRAME TO DISK*/ + if (!pdata->args.zerocompression) { + if (ynum*4+unum+vnum>(blocknum_x*blocknum_y*6)/10) + gzsetparams (fp,1,Z_FILTERED); + else + gzsetparams (fp,0,Z_FILTERED); + } + + strncpy(fheader.frame_prefix,"FRAM",4); + fheader.frameno=++frameno; + fheader.current_total = pdata->frames_total; + + fheader.Ynum=ynum; + fheader.Unum=unum; + fheader.Vnum=vnum; + + if (!pdata->args.zerocompression) { + nbytes+=gzwrite(fp,(void*)&fheader,sizeof(FrameHeader)); + //flush indexes + if (ynum) + nbytes+=gzwrite(fp, (void*)y_short_blocks, ynum*index_entry_size); + + if (unum) + nbytes+=gzwrite(fp, (void*)u_short_blocks, unum*index_entry_size); + + if (vnum) + nbytes+=gzwrite(fp, (void*)v_short_blocks, vnum*index_entry_size); + } else { + nbytes+=sizeof(FrameHeader)* + fwrite((void*)&fheader,sizeof(FrameHeader),1,ucfp); + //flush indexes + if (ynum) + nbytes+=index_entry_size* fwrite(y_short_blocks,index_entry_size,ynum,ucfp); + + if (unum) + nbytes+=index_entry_size* fwrite(u_short_blocks,index_entry_size,unum,ucfp); + + if (vnum) + nbytes+=index_entry_size* fwrite(v_short_blocks,index_entry_size,vnum,ucfp); + } + //flush the blocks for each buffer + if (ynum) { + for(j=0;j<ynum;j++) + nbytes+=rmdFlushBlock( pdata->enc_data->yuv.y,y_short_blocks[j], + pdata->enc_data->yuv.y_width, + pdata->enc_data->yuv.y_height, + Y_UNIT_WIDTH, + fp, + ucfp, + 0); + } + + if (unum) { + for(j=0;j<unum;j++) + nbytes+=rmdFlushBlock( pdata->enc_data->yuv.u,u_short_blocks[j], + pdata->enc_data->yuv.uv_width, + pdata->enc_data->yuv.uv_height, + UV_UNIT_WIDTH, + fp, + ucfp, + 0); + } + + if (vnum) { + for(j=0;j<vnum;j++) + nbytes+=rmdFlushBlock( pdata->enc_data->yuv.v,v_short_blocks[j], + pdata->enc_data->yuv.uv_width, + pdata->enc_data->yuv.uv_height, + UV_UNIT_WIDTH, + fp, + ucfp, + 0); + } + + //release main buffer + pthread_mutex_unlock(&pdata->yuv_mutex); + + nbytes+=rmdFlushBlock(NULL,0,0,0,0,fp,ucfp,1); + /**@________________@**/ + pdata->avd+=pdata->frametime; + + if (nbytes>CACHE_FILE_SIZE_LIMIT) { + if (rmdSwapCacheFilesWrite(pdata->cache_data->imgdata, nth_cache,&fp,&ucfp)) { + fprintf(stderr,"New cache file could not be created.\n" + "Ending recording...\n"); + fflush(stderr); + raise(SIGINT); //if for some reason we cannot make a new file + //we have to stop. If we are out of space, + //which means + //that encoding cannot happen either, + //InitEncoder will cause an abrupt end with an + //error code and the cache will remain intact. + //If we've chosen separate two-stages, + //the program will make a + //clean exit. + //In either case data will be preserved so if + //space is freed the recording + //can be proccessed later. + } + total_bytes += nbytes; + nth_cache++; + nbytes=0; + } + } + total_bytes += nbytes; + + { + unsigned int bytes_per_pixel = pdata->specs.depth >= 24 ? 4 : 2; + unsigned int pixels_per_frame = pdata->brwin.rrect.width * pdata->brwin.rrect.height; + + total_received_bytes = ((unsigned long long int)frameno) * bytes_per_pixel * pixels_per_frame; + } + + if (total_received_bytes) { + double percent_of_data_left = (total_bytes / (double)total_received_bytes) * 100; + + fprintf(stderr, "\n" + "*********************************************\n" + "\n" + "Cached %llu MB, from %llu MB that were received.\n" + "Average cache compression ratio: %.1f %%\n" + "\n" + "*********************************************\n", + total_bytes / BYTES_PER_MB, + total_received_bytes / BYTES_PER_MB, + 100 - percent_of_data_left); + + } + + fprintf(stderr, "Saved %d frames in a total of %d requests\n", + frameno, + pdata->frames_total); + fflush(stderr); + + if (!pdata->args.zerocompression) { + gzflush(fp,Z_FINISH); + gzclose(fp); + } else { + fflush(ucfp); + fclose(ucfp); + } + + pthread_exit(&errno); } diff --git a/recordmydesktop/src/rmd_capture_sound.c b/recordmydesktop/src/rmd_capture_sound.c index e4498c0..c1faa44 100644 --- a/recordmydesktop/src/rmd_capture_sound.c +++ b/recordmydesktop/src/rmd_capture_sound.c @@ -40,140 +40,135 @@ #include <stdlib.h> -void *rmdCaptureSound(ProgData *pdata){ +void *rmdCaptureSound(ProgData *pdata) { #ifdef HAVE_LIBASOUND - int frames=pdata->periodsize; + int frames=pdata->periodsize; #endif - //start capturing only after first frame is taken - usleep(pdata->frametime); + //start capturing only after first frame is taken + usleep(pdata->frametime); - while(pdata->running){ - int sret=0; - SndBuffer *newbuf,*tmp; - if (pdata->paused) { + while (pdata->running) { + int sret=0; + SndBuffer *newbuf,*tmp; + + if (pdata->paused) { #ifdef HAVE_LIBASOUND - if(!pdata->hard_pause){ - snd_pcm_pause(pdata->sound_handle,1); - pthread_mutex_lock(&pdata->pause_mutex); - pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); - pthread_mutex_unlock(&pdata->pause_mutex); - snd_pcm_pause(pdata->sound_handle,0); - } - else{//device doesn't support pause(is this the norm?mine doesn't) - snd_pcm_close(pdata->sound_handle); - pthread_mutex_lock(&pdata->pause_mutex); - pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); - pthread_mutex_unlock(&pdata->pause_mutex); - pdata->sound_handle= - rmdOpenDev(pdata->args.device, - &pdata->args.channels, - &pdata->args.frequency, - &pdata->args.buffsize, - NULL, - NULL, - NULL//let's hope that the device capabilities - //didn't magically change - ); - if(pdata->sound_handle==NULL){ - fprintf(stderr,"Couldn't reopen sound device.Exiting\n"); - pdata->running = FALSE; - errno=3; - pthread_exit(&errno); - } - } + if (!pdata->hard_pause) { + snd_pcm_pause(pdata->sound_handle,1); + pthread_mutex_lock(&pdata->pause_mutex); + pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); + pthread_mutex_unlock(&pdata->pause_mutex); + snd_pcm_pause(pdata->sound_handle,0); + } else {//device doesn't support pause(is this the norm?mine doesn't) + snd_pcm_close(pdata->sound_handle); + pthread_mutex_lock(&pdata->pause_mutex); + pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); + pthread_mutex_unlock(&pdata->pause_mutex); + pdata->sound_handle= + rmdOpenDev(pdata->args.device, + &pdata->args.channels, + &pdata->args.frequency, + &pdata->args.buffsize, + NULL, + NULL, + NULL//let's hope that the device capabilities + //didn't magically change + ); + if (pdata->sound_handle==NULL) { + fprintf(stderr,"Couldn't reopen sound device.Exiting\n"); + pdata->running = FALSE; + errno=3; + pthread_exit(&errno); + } + } #else - close(pdata->sound_handle); - pthread_mutex_lock(&pdata->pause_mutex); - pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); - pthread_mutex_unlock(&pdata->pause_mutex); - pdata->sound_handle= - rmdOpenDev(pdata->args.device, - pdata->args.channels, - pdata->args.frequency); - if(pdata->sound_handle<0){ - fprintf(stderr,"Couldn't reopen sound device.Exiting\n"); - pdata->running = FALSE; - errno=3; - pthread_exit(&errno); - } + close(pdata->sound_handle); + pthread_mutex_lock(&pdata->pause_mutex); + pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); + pthread_mutex_unlock(&pdata->pause_mutex); + pdata->sound_handle= + rmdOpenDev(pdata->args.device, + pdata->args.channels, + pdata->args.frequency); + if (pdata->sound_handle<0) { + fprintf(stderr,"Couldn't reopen sound device.Exiting\n"); + pdata->running = FALSE; + errno=3; + pthread_exit(&errno); + } #endif - } + } - //create new buffer - newbuf=(SndBuffer *)malloc(sizeof(SndBuffer)); + //create new buffer + newbuf=(SndBuffer *)malloc(sizeof(SndBuffer)); #ifdef HAVE_LIBASOUND - newbuf->data=(signed char *)malloc(frames*pdata->sound_framesize); + newbuf->data=(signed char *)malloc(frames*pdata->sound_framesize); #else - newbuf->data=(signed char *)malloc(((pdata->args.buffsize<<1)* - pdata->args.channels)); + newbuf->data=(signed char *)malloc(((pdata->args.buffsize<<1)* + pdata->args.channels)); #endif - newbuf->next=NULL; + newbuf->next=NULL; - //read data into new buffer + //read data into new buffer #ifdef HAVE_LIBASOUND - while(sret<frames){ - int temp_sret=snd_pcm_readi(pdata->sound_handle, - newbuf->data+pdata->sound_framesize*sret, - frames-sret); - if(temp_sret==-EPIPE){ - fprintf(stderr,"%s: Overrun occurred.\n", - snd_strerror(temp_sret)); - snd_pcm_prepare(pdata->sound_handle); - } - else if (temp_sret<0){ - fprintf(stderr,"An error occured while reading sound data:\n" - " %s\n", - snd_strerror(temp_sret)); - snd_pcm_prepare(pdata->sound_handle); - } - else - sret+=temp_sret; - } + while (sret<frames) { + int temp_sret=snd_pcm_readi(pdata->sound_handle, + newbuf->data+pdata->sound_framesize*sret, + frames-sret); + if (temp_sret==-EPIPE) { + fprintf(stderr,"%s: Overrun occurred.\n", + snd_strerror(temp_sret)); + snd_pcm_prepare(pdata->sound_handle); + } else if (temp_sret<0) { + fprintf(stderr,"An error occured while reading sound data:\n" + " %s\n", + snd_strerror(temp_sret)); + snd_pcm_prepare(pdata->sound_handle); + } else + sret+=temp_sret; + } #else - sret=0; - //oss recording loop - do{ - int temp_sret=read(pdata->sound_handle, - &newbuf->data[sret], - ((pdata->args.buffsize<<1)* - pdata->args.channels)-sret); - if(temp_sret<0){ - fprintf(stderr,"An error occured while reading from soundcard" - "%s\n" - "Error description:\n" - "%s\n",pdata->args.device,strerror(errno)); - } - else - sret+=temp_sret; - }while(sret<((pdata->args.buffsize<<1)* - pdata->args.channels)); + sret=0; + //oss recording loop + do { + int temp_sret=read(pdata->sound_handle, + &newbuf->data[sret], + ((pdata->args.buffsize<<1)* + pdata->args.channels)-sret); + if (temp_sret<0) { + fprintf(stderr,"An error occured while reading from soundcard" + "%s\n" + "Error description:\n" + "%s\n",pdata->args.device,strerror(errno)); + } else + sret+=temp_sret; + } while (sret<((pdata->args.buffsize<<1)* + pdata->args.channels)); #endif - //queue the new buffer - pthread_mutex_lock(&pdata->sound_buffer_mutex); - tmp=pdata->sound_buffer; - if(pdata->sound_buffer==NULL) - pdata->sound_buffer=newbuf; - else{ - while(tmp->next!=NULL) - tmp=tmp->next; - tmp->next=newbuf; - } - pthread_mutex_unlock(&pdata->sound_buffer_mutex); + //queue the new buffer + pthread_mutex_lock(&pdata->sound_buffer_mutex); + tmp=pdata->sound_buffer; + if (pdata->sound_buffer==NULL) + pdata->sound_buffer=newbuf; + else { + while (tmp->next!=NULL) + tmp=tmp->next; + + tmp->next=newbuf; + } + pthread_mutex_unlock(&pdata->sound_buffer_mutex); - //signal that there are data to be proccessed - pthread_mutex_lock(&pdata->snd_buff_ready_mutex); - pthread_cond_signal(&pdata->sound_data_read); - pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); - } + //signal that there are data to be proccessed + pthread_mutex_lock(&pdata->snd_buff_ready_mutex); + pthread_cond_signal(&pdata->sound_data_read); + pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); + } #ifdef HAVE_LIBASOUND - snd_pcm_close(pdata->sound_handle); + snd_pcm_close(pdata->sound_handle); #else - close(pdata->sound_handle); + close(pdata->sound_handle); #endif - pthread_exit(&errno); + pthread_exit(&errno); } - - - diff --git a/recordmydesktop/src/rmd_encode_cache.c b/recordmydesktop/src/rmd_encode_cache.c index adf6063..fdcb782 100644 --- a/recordmydesktop/src/rmd_encode_cache.c +++ b/recordmydesktop/src/rmd_encode_cache.c @@ -40,35 +40,33 @@ void rmdEncodeCache(ProgData *pdata){ - pthread_t flush_to_ogg_t, - load_cache_t; - fprintf(stderr,"STATE:ENCODING\n");fflush(stderr); - fprintf(stderr,"Encoding started!\nThis may take several minutes.\n" - "Pressing Ctrl-C will cancel the procedure" - " (resuming will not be possible, but\n" - "any portion of the video, which is already encoded won't be deleted).\n" - "Please wait...\n"); - pdata->running = TRUE; - rmdInitEncoder(pdata,pdata->enc_data,1); - //load encoding and flushing threads - if(!pdata->args.nosound){ - //before we start loading again - //we need to free any left-overs - while(pdata->sound_buffer!=NULL){ - free(pdata->sound_buffer->data); - pdata->sound_buffer=pdata->sound_buffer->next; - } - } - pthread_create(&flush_to_ogg_t,NULL,(void *)rmdFlushToOgg,(void *)pdata); + pthread_t flush_to_ogg_t, load_cache_t; - //start loading image and audio - pthread_create(&load_cache_t,NULL,(void *)rmdLoadCache,(void *)pdata); + fprintf(stderr,"STATE:ENCODING\n"); + fprintf(stderr, "Encoding started!\nThis may take several minutes.\n" + "Pressing Ctrl-C will cancel the procedure" + " (resuming will not be possible, but\n" + "any portion of the video, which is already encoded won't be deleted).\n" + "Please wait...\n"); - //join and finish - pthread_join(load_cache_t,NULL); - fprintf(stderr,"Encoding finished!\nWait a moment please...\n"); - pthread_join(flush_to_ogg_t,NULL); - -} + pdata->running = TRUE; + rmdInitEncoder(pdata,pdata->enc_data,1); + //load encoding and flushing threads + if (!pdata->args.nosound) { + //before we start loading again + //we need to free any left-overs + while (pdata->sound_buffer!=NULL) { + free(pdata->sound_buffer->data); + pdata->sound_buffer=pdata->sound_buffer->next; + } + } + pthread_create(&flush_to_ogg_t,NULL,(void *)rmdFlushToOgg,(void *)pdata); + //start loading image and audio + pthread_create(&load_cache_t,NULL,(void *)rmdLoadCache,(void *)pdata); + //join and finish + pthread_join(load_cache_t,NULL); + fprintf(stderr,"Encoding finished!\nWait a moment please...\n"); + pthread_join(flush_to_ogg_t,NULL); +} diff --git a/recordmydesktop/src/rmd_encode_image_buffer.c b/recordmydesktop/src/rmd_encode_image_buffer.c index 9c984ea..b96db25 100644 --- a/recordmydesktop/src/rmd_encode_image_buffer.c +++ b/recordmydesktop/src/rmd_encode_image_buffer.c @@ -32,65 +32,62 @@ #include <errno.h> -void *rmdEncodeImageBuffer(ProgData *pdata){ - pdata->th_encoding_clean=0; - while(pdata->running){ - pdata->th_enc_thread_waiting=1; - pthread_mutex_lock(&pdata->img_buff_ready_mutex); - pthread_cond_wait(&pdata->image_buffer_ready, - &pdata->img_buff_ready_mutex); - pthread_mutex_unlock(&pdata->img_buff_ready_mutex); - pdata->th_enc_thread_waiting=0; - pdata->encoder_busy = TRUE; - if (pdata->paused) { - pthread_mutex_lock(&pdata->pause_mutex); - pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); - pthread_mutex_unlock(&pdata->pause_mutex); - } - pthread_mutex_lock(&pdata->yuv_mutex); +void *rmdEncodeImageBuffer(ProgData *pdata) { + pdata->th_encoding_clean=0; + while (pdata->running) { + pdata->th_enc_thread_waiting=1; + pthread_mutex_lock(&pdata->img_buff_ready_mutex); + pthread_cond_wait(&pdata->image_buffer_ready, + &pdata->img_buff_ready_mutex); + pthread_mutex_unlock(&pdata->img_buff_ready_mutex); + pdata->th_enc_thread_waiting=0; + pdata->encoder_busy = TRUE; + if (pdata->paused) { + pthread_mutex_lock(&pdata->pause_mutex); + pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); + pthread_mutex_unlock(&pdata->pause_mutex); + } + pthread_mutex_lock(&pdata->yuv_mutex); - if(theora_encode_YUVin(&pdata->enc_data->m_th_st, - &pdata->enc_data->yuv)){ - fprintf(stderr,"Encoder not ready!\n"); - pthread_mutex_unlock(&pdata->yuv_mutex); - } - else{ - pthread_mutex_unlock(&pdata->yuv_mutex); - if(theora_encode_packetout(&pdata->enc_data->m_th_st,0, - &pdata->enc_data->m_ogg_pckt1)==1){ - pthread_mutex_lock(&pdata->libogg_mutex); - ogg_stream_packetin(&pdata->enc_data->m_ogg_ts, - &pdata->enc_data->m_ogg_pckt1); - pthread_mutex_unlock(&pdata->libogg_mutex); - pdata->avd+=pdata->frametime; - } - } - pdata->encoder_busy = FALSE; - } - //last packet - pdata->th_encoding_clean=1; - pthread_mutex_lock(&pdata->theora_lib_mutex); - pthread_cond_signal(&pdata->theora_lib_clean); - pthread_mutex_unlock(&pdata->theora_lib_mutex); - pthread_exit(&errno); + if (theora_encode_YUVin(&pdata->enc_data->m_th_st, &pdata->enc_data->yuv)) { + fprintf(stderr,"Encoder not ready!\n"); + pthread_mutex_unlock(&pdata->yuv_mutex); + } else { + pthread_mutex_unlock(&pdata->yuv_mutex); + if (theora_encode_packetout(&pdata->enc_data->m_th_st, 0, &pdata->enc_data->m_ogg_pckt1)==1) { + pthread_mutex_lock(&pdata->libogg_mutex); + ogg_stream_packetin(&pdata->enc_data->m_ogg_ts, + &pdata->enc_data->m_ogg_pckt1); + pthread_mutex_unlock(&pdata->libogg_mutex); + pdata->avd+=pdata->frametime; + } + } + pdata->encoder_busy = FALSE; + } + //last packet + pdata->th_encoding_clean=1; + pthread_mutex_lock(&pdata->theora_lib_mutex); + pthread_cond_signal(&pdata->theora_lib_clean); + pthread_mutex_unlock(&pdata->theora_lib_mutex); + pthread_exit(&errno); } //this function is meant to be called normally //not through a thread of it's own -void rmdSyncEncodeImageBuffer(ProgData *pdata){ - if(theora_encode_YUVin(&pdata->enc_data->m_th_st, - &pdata->enc_data->yuv)){ - fprintf(stderr,"Encoder not ready!\n"); - } - else{ - if(theora_encode_packetout(&pdata->enc_data->m_th_st,!pdata->running, - &pdata->enc_data->m_ogg_pckt1)==1){ - pthread_mutex_lock(&pdata->libogg_mutex); - ogg_stream_packetin(&pdata->enc_data->m_ogg_ts, - &pdata->enc_data->m_ogg_pckt1); - if(!pdata->running)pdata->enc_data->m_ogg_ts.e_o_s=1; - pthread_mutex_unlock(&pdata->libogg_mutex); - pdata->avd+=pdata->frametime; - } - } +void rmdSyncEncodeImageBuffer(ProgData *pdata) { + if (theora_encode_YUVin(&pdata->enc_data->m_th_st, &pdata->enc_data->yuv)) { + fprintf(stderr,"Encoder not ready!\n"); + return; + } + + if (theora_encode_packetout(&pdata->enc_data->m_th_st, !pdata->running, &pdata->enc_data->m_ogg_pckt1)==1) { + pthread_mutex_lock(&pdata->libogg_mutex); + ogg_stream_packetin(&pdata->enc_data->m_ogg_ts, &pdata->enc_data->m_ogg_pckt1); + + if (!pdata->running) + pdata->enc_data->m_ogg_ts.e_o_s=1; + + pthread_mutex_unlock(&pdata->libogg_mutex); + pdata->avd+=pdata->frametime; + } } diff --git a/recordmydesktop/src/rmd_encode_sound_buffer.c b/recordmydesktop/src/rmd_encode_sound_buffer.c index 1d88a59..c68eae0 100644 --- a/recordmydesktop/src/rmd_encode_sound_buffer.c +++ b/recordmydesktop/src/rmd_encode_sound_buffer.c @@ -36,158 +36,145 @@ #include <errno.h> -void *rmdEncodeSoundBuffer(ProgData *pdata){ - int sampread=pdata->periodsize; +void *rmdEncodeSoundBuffer(ProgData *pdata) { + int sampread=pdata->periodsize; #ifdef HAVE_LIBJACK - void *jackbuf=NULL; - if(pdata->args.use_jack){ - jackbuf=malloc(pdata->sound_framesize*pdata->jdata->buffersize); - } + void *jackbuf=NULL; + + if (pdata->args.use_jack) { + jackbuf=malloc(pdata->sound_framesize*pdata->jdata->buffersize); + } #endif - pdata->v_encoding_clean=0; - while((pdata->running)){ - float **vorbis_buffer; - int count=0,i,j; - SndBuffer *buff=NULL; - - if (pdata->paused) { - pthread_mutex_lock(&pdata->pause_mutex); - pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); - pthread_mutex_unlock(&pdata->pause_mutex); - } - if(!pdata->args.use_jack){ - if(pdata->sound_buffer==NULL){ - pdata->v_enc_thread_waiting=1; - pthread_mutex_lock(&pdata->snd_buff_ready_mutex); - pthread_cond_wait(&pdata->sound_data_read, - &pdata->snd_buff_ready_mutex); - pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); - pdata->v_enc_thread_waiting=0; - } - if(pdata->sound_buffer==NULL || !pdata->running) - break; - pthread_mutex_lock(&pdata->sound_buffer_mutex); - buff=pdata->sound_buffer; - //advance the list - pdata->sound_buffer=pdata->sound_buffer->next; - pthread_mutex_unlock(&pdata->sound_buffer_mutex); - - vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp, - sampread); - - for(i=0;i<sampread;i++){ - for(j=0;j<pdata->args.channels;j++){ - vorbis_buffer[j][i]=((buff->data[count+1]<<8)| - (0x00ff&(int)buff->data[count]))/ - 32768.f; - count+=2; - } - } - free(buff->data); - free(buff); - } - else{ + + pdata->v_encoding_clean=0; + while ((pdata->running)) { + float **vorbis_buffer; + int count=0,i,j; + SndBuffer *buff=NULL; + + if (pdata->paused) { + pthread_mutex_lock(&pdata->pause_mutex); + pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); + pthread_mutex_unlock(&pdata->pause_mutex); + } + if (!pdata->args.use_jack) { + if (pdata->sound_buffer==NULL) { + pdata->v_enc_thread_waiting=1; + pthread_mutex_lock(&pdata->snd_buff_ready_mutex); + pthread_cond_wait(&pdata->sound_data_read, + &pdata->snd_buff_ready_mutex); + pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); + pdata->v_enc_thread_waiting=0; + } + + if (pdata->sound_buffer==NULL || !pdata->running) + break; + + pthread_mutex_lock(&pdata->sound_buffer_mutex); + buff=pdata->sound_buffer; + //advance the list + pdata->sound_buffer=pdata->sound_buffer->next; + pthread_mutex_unlock(&pdata->sound_buffer_mutex); + + vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp, sampread); + + for (i=0;i<sampread;i++) { + for (j=0;j<pdata->args.channels;j++) { + vorbis_buffer[j][i]=((buff->data[count+1]<<8)| (0x00ff&(int)buff->data[count]))/ 32768.f; + count+=2; + } + } + free(buff->data); + free(buff); + } else { #ifdef HAVE_LIBJACK - if((*jack_ringbuffer_read_space)(pdata->jdata->sound_buffer)>= - (pdata->sound_framesize*pdata->jdata->buffersize)){ - (*jack_ringbuffer_read)(pdata->jdata->sound_buffer, - jackbuf, - (pdata->sound_framesize* - pdata->jdata->buffersize)); - vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp, - sampread); - for(j=0;j<pdata->args.channels;j++){ - for(i=0;i<sampread;i++){ - vorbis_buffer[j][i]=((float*)jackbuf)[count]; - count++; - } - } - } - else{ - pdata->v_enc_thread_waiting=1; - pthread_mutex_lock(&pdata->snd_buff_ready_mutex); - pthread_cond_wait(&pdata->sound_data_read, - &pdata->snd_buff_ready_mutex); - pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); - pdata->v_enc_thread_waiting=0; - continue; - } + if ((*jack_ringbuffer_read_space)(pdata->jdata->sound_buffer)>= + (pdata->sound_framesize*pdata->jdata->buffersize)) { + (*jack_ringbuffer_read)(pdata->jdata->sound_buffer, + jackbuf, + (pdata->sound_framesize* + pdata->jdata->buffersize)); + vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp, + sampread); + for (j=0;j<pdata->args.channels;j++) { + for (i=0;i<sampread;i++) { + vorbis_buffer[j][i]=((float*)jackbuf)[count]; + count++; + } + } + } else { + pdata->v_enc_thread_waiting=1; + pthread_mutex_lock(&pdata->snd_buff_ready_mutex); + pthread_cond_wait(&pdata->sound_data_read, + &pdata->snd_buff_ready_mutex); + pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); + pdata->v_enc_thread_waiting=0; + continue; + } #endif - } - vorbis_analysis_wrote(&pdata->enc_data->m_vo_dsp,sampread); - - pthread_mutex_lock(&pdata->libogg_mutex); - while(vorbis_analysis_blockout(&pdata->enc_data->m_vo_dsp, - &pdata->enc_data->m_vo_block)==1){ + } + vorbis_analysis_wrote(&pdata->enc_data->m_vo_dsp,sampread); - vorbis_analysis(&pdata->enc_data->m_vo_block,NULL); - vorbis_bitrate_addblock(&pdata->enc_data->m_vo_block); + pthread_mutex_lock(&pdata->libogg_mutex); + while (vorbis_analysis_blockout(&pdata->enc_data->m_vo_dsp, &pdata->enc_data->m_vo_block)==1) { - while(vorbis_bitrate_flushpacket(&pdata->enc_data->m_vo_dsp, - &pdata->enc_data->m_ogg_pckt2)){ - ogg_stream_packetin(&pdata->enc_data->m_ogg_vs, - &pdata->enc_data->m_ogg_pckt2); - } - } - pthread_mutex_unlock(&pdata->libogg_mutex); + vorbis_analysis(&pdata->enc_data->m_vo_block,NULL); + vorbis_bitrate_addblock(&pdata->enc_data->m_vo_block); - pdata->avd-=pdata->periodtime; + while (vorbis_bitrate_flushpacket(&pdata->enc_data->m_vo_dsp, &pdata->enc_data->m_ogg_pckt2)) { + ogg_stream_packetin(&pdata->enc_data->m_ogg_vs, &pdata->enc_data->m_ogg_pckt2); + } + } + pthread_mutex_unlock(&pdata->libogg_mutex); + pdata->avd-=pdata->periodtime; + } - } - - pdata->v_encoding_clean=1; - pthread_mutex_lock(&pdata->vorbis_lib_mutex); - pthread_cond_signal(&pdata->vorbis_lib_clean); - pthread_mutex_unlock(&pdata->vorbis_lib_mutex); - pthread_exit(&errno); + pdata->v_encoding_clean=1; + pthread_mutex_lock(&pdata->vorbis_lib_mutex); + pthread_cond_signal(&pdata->vorbis_lib_clean); + pthread_mutex_unlock(&pdata->vorbis_lib_mutex); + pthread_exit(&errno); } -void rmdSyncEncodeSoundBuffer(ProgData *pdata,signed char *buff){ - float **vorbis_buffer; - int count=0,i,j; - int sampread=(buff!=NULL)?pdata->periodsize:0; - - vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,sampread); - - if(!pdata->args.use_jack){ - for(i=0;i<sampread;i++){ - for(j=0;j<pdata->args.channels;j++){ - vorbis_buffer[j][i]=((buff[count+1]<<8)| - (0x00ff&(int)buff[count]))/ - 32768.f; - count+=2; - } - } - } - else{ - for(j=0;j<pdata->args.channels;j++){ - for(i=0;i<sampread;i++){ - vorbis_buffer[j][i]=((float*)buff)[count]; - count++; - } - } - } - - vorbis_analysis_wrote(&pdata->enc_data->m_vo_dsp,sampread); - - pthread_mutex_lock(&pdata->libogg_mutex); - while(vorbis_analysis_blockout(&pdata->enc_data->m_vo_dsp, - &pdata->enc_data->m_vo_block)==1){ - - vorbis_analysis(&pdata->enc_data->m_vo_block,NULL); - vorbis_bitrate_addblock(&pdata->enc_data->m_vo_block); - - while(vorbis_bitrate_flushpacket(&pdata->enc_data->m_vo_dsp, - &pdata->enc_data->m_ogg_pckt2)){ - ogg_stream_packetin(&pdata->enc_data->m_ogg_vs, - &pdata->enc_data->m_ogg_pckt2); - } - } - pthread_mutex_unlock(&pdata->libogg_mutex); - - if(!pdata->running)pdata->enc_data->m_ogg_vs.e_o_s=1; - - pdata->avd-=pdata->periodtime; +void rmdSyncEncodeSoundBuffer(ProgData *pdata,signed char *buff) { + float **vorbis_buffer; + int count=0,i,j; + int sampread=(buff!=NULL)?pdata->periodsize:0; + + vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,sampread); + + if (!pdata->args.use_jack) { + for (i=0;i<sampread;i++) { + for (j=0;j<pdata->args.channels;j++) { + vorbis_buffer[j][i]=((buff[count+1]<<8)| (0x00ff&(int)buff[count]))/ 32768.f; + count+=2; + } + } + } else { + for (j=0;j<pdata->args.channels;j++) { + for (i=0;i<sampread;i++) { + vorbis_buffer[j][i]=((float*)buff)[count]; + count++; + } + } + } + + vorbis_analysis_wrote(&pdata->enc_data->m_vo_dsp,sampread); + + pthread_mutex_lock(&pdata->libogg_mutex); + while (vorbis_analysis_blockout(&pdata->enc_data->m_vo_dsp, &pdata->enc_data->m_vo_block)==1) { + + vorbis_analysis(&pdata->enc_data->m_vo_block,NULL); + vorbis_bitrate_addblock(&pdata->enc_data->m_vo_block); + + while (vorbis_bitrate_flushpacket(&pdata->enc_data->m_vo_dsp, &pdata->enc_data->m_ogg_pckt2)) + ogg_stream_packetin(&pdata->enc_data->m_ogg_vs, &pdata->enc_data->m_ogg_pckt2); + } + pthread_mutex_unlock(&pdata->libogg_mutex); + + if (!pdata->running) + pdata->enc_data->m_ogg_vs.e_o_s=1; + + pdata->avd-=pdata->periodtime; } - diff --git a/recordmydesktop/src/rmd_error.c b/recordmydesktop/src/rmd_error.c index 44144bf..e9705cc 100644 --- a/recordmydesktop/src/rmd_error.c +++ b/recordmydesktop/src/rmd_error.c @@ -35,26 +35,25 @@ -int rmdErrorHandler( Display *dpy, XErrorEvent *e ) +int rmdErrorHandler(Display *dpy, XErrorEvent *e) { - char error_desc[1024]; - XGetErrorText(dpy,e->error_code,error_desc,sizeof(error_desc)); - fprintf(stderr,"X Error: %s\n",error_desc); - fflush(stderr); - if((e->error_code==BadWindow)&&(e->request_code==X_GetWindowAttributes)){ - fprintf(stderr,"BadWindow on XGetWindowAttributes.\nIgnoring...\n"); - fflush(stderr); - return 0; - } - else if((e->error_code==BadAccess)&&(e->request_code==X_GrabKey)){ - fprintf(stderr,"Bad Access on XGrabKey.\n" - "Shortcut already assigned.\n"); - fflush(stderr); - return 0; - } - else - exit(1); -} + char error_desc[1024]; + + XGetErrorText(dpy,e->error_code,error_desc,sizeof(error_desc)); + fprintf(stderr,"X Error: %s\n",error_desc); + fflush(stderr); + if ((e->error_code==BadWindow)&&(e->request_code==X_GetWindowAttributes)) { + fprintf(stderr,"BadWindow on XGetWindowAttributes.\nIgnoring...\n"); + fflush(stderr); + return 0; + } + if ((e->error_code==BadAccess)&&(e->request_code==X_GrabKey)) { + fprintf(stderr,"Bad Access on XGrabKey.\n" "Shortcut already assigned.\n"); + fflush(stderr); + return 0; + } + exit(1); +} diff --git a/recordmydesktop/src/rmd_flush_to_ogg.c b/recordmydesktop/src/rmd_flush_to_ogg.c index 9a443b1..fa6b42e 100644 --- a/recordmydesktop/src/rmd_flush_to_ogg.c +++ b/recordmydesktop/src/rmd_flush_to_ogg.c @@ -45,176 +45,184 @@ //both streams at every time in //order to do correct multiplexing static void ogg_page_cp(ogg_page *new, ogg_page *old) { - int i=0; - register unsigned char *newp,*oldp; - - new->header_len=old->header_len; - new->header=malloc(new->header_len); - new->body_len=old->body_len; - new->body=malloc(new->body_len); - - newp=new->header; - oldp=old->header; - for(i=0;i<new->header_len;i++) - *(newp++)=*(oldp++); - newp=new->body; - oldp=old->body; - for(i=0;i<new->body_len;i++) - *(newp++)=*(oldp++); + int i=0; + register unsigned char *newp,*oldp; + + new->header_len=old->header_len; + new->header=malloc(new->header_len); + new->body_len=old->body_len; + new->body=malloc(new->body_len); + + newp=new->header; + oldp=old->header; + for(i=0;i<new->header_len;i++) + *(newp++)=*(oldp++); + newp=new->body; + oldp=old->body; + for(i=0;i<new->body_len;i++) + *(newp++)=*(oldp++); } //free our copy static void ogg_page_cp_free(ogg_page *pg) { - pg->header_len=pg->body_len=0; - free(pg->header); - free(pg->body); + pg->header_len=pg->body_len=0; + free(pg->header); + free(pg->body); } -void *rmdFlushToOgg(ProgData *pdata){ - int videoflag=0,audioflag=0; - double video_bytesout=0,audio_bytesout=0; - ogg_page videopage,//owned by libogg - videopage_copy,//owned by the application - audiopage,//owned by libogg - audiopage_copy;//owned by the application - - double audiotime=0; - double videotime=0; - int working=1, - th_st_fin=0, - v_st_fin=(pdata->args.nosound); - while(working){ - int audio_or_video=0; - if(pdata->running){ - pthread_mutex_lock(&pdata->libogg_mutex); - if(!videoflag){ - videoflag=ogg_stream_pageout(&pdata->enc_data->m_ogg_ts, - &videopage); - videotime=(videoflag)? - theora_granule_time(&pdata->enc_data->m_th_st, - ogg_page_granulepos(&videopage)):-1; - if(videoflag)ogg_page_cp(&videopage_copy,&videopage); - } - if(!pdata->args.nosound) - if(!audioflag){ - audioflag=ogg_stream_pageout(&pdata->enc_data->m_ogg_vs, - &audiopage); - audiotime=(audioflag)? - vorbis_granule_time(&pdata->enc_data->m_vo_dsp, - ogg_page_granulepos(&audiopage)):-1; - if(audioflag)ogg_page_cp(&audiopage_copy,&audiopage); - } - pthread_mutex_unlock(&pdata->libogg_mutex); - } - else{ - if(!th_st_fin && !videoflag){ - pthread_mutex_lock(&pdata->libogg_mutex); - videoflag=ogg_stream_flush(&pdata->enc_data->m_ogg_ts, - &videopage); - videotime=(videoflag)? - theora_granule_time(&pdata->enc_data->m_th_st, - ogg_page_granulepos(&videopage)):-1; - if(videoflag)ogg_page_cp(&videopage_copy,&videopage); - pthread_mutex_unlock(&pdata->libogg_mutex); - //we need the last page to properly close the stream - if(!videoflag){ - if(!pdata->th_encoding_clean){ - pthread_mutex_lock(&pdata->theora_lib_mutex); - pthread_cond_wait(&pdata->theora_lib_clean, - &pdata->theora_lib_mutex); - pthread_mutex_unlock(&pdata->theora_lib_mutex); - } - rmdSyncEncodeImageBuffer(pdata); - } - } - if(!pdata->args.nosound && !v_st_fin &&!audioflag){ - pthread_mutex_lock(&pdata->libogg_mutex); - audioflag=ogg_stream_flush(&pdata->enc_data->m_ogg_vs, - &audiopage); - audiotime=(audioflag)? - vorbis_granule_time(&pdata->enc_data->m_vo_dsp, - ogg_page_granulepos(&audiopage)):-1; - if(audioflag)ogg_page_cp(&audiopage_copy,&audiopage); - pthread_mutex_unlock(&pdata->libogg_mutex); - //we need the last page to properly close the stream - if(!audioflag){ - if(!pdata->v_encoding_clean){ - pthread_mutex_lock(&pdata->vorbis_lib_mutex); - pthread_cond_wait(&pdata->vorbis_lib_clean, - &pdata->vorbis_lib_mutex); - pthread_mutex_unlock(&pdata->vorbis_lib_mutex); - } - rmdSyncEncodeSoundBuffer(pdata,NULL); - } - } - } - if(th_st_fin)videoflag=0; - if(v_st_fin)audioflag=0; - if((!audioflag && !v_st_fin && !pdata->args.nosound)|| - (!videoflag && !th_st_fin)){ - usleep(10000); - continue; - } - if(!audioflag){ - audio_or_video=1; - } - else if(!videoflag) { - audio_or_video=0; - } - else{ - if(audiotime<videotime) - audio_or_video=0; - else - audio_or_video=1; - } - if(audio_or_video==1){ - video_bytesout+=fwrite(videopage_copy.header,1, - videopage_copy.header_len, - pdata->enc_data->fp); - video_bytesout+=fwrite(videopage_copy.body,1, - videopage_copy.body_len, - pdata->enc_data->fp); - videoflag=0; - if(!pdata->running){ - pthread_mutex_lock(&pdata->libogg_mutex); - if(ogg_page_eos(&videopage_copy)) - th_st_fin=1; - pthread_mutex_unlock(&pdata->libogg_mutex); - } - ogg_page_cp_free(&videopage_copy); - } - else{ - audio_bytesout+=fwrite(audiopage_copy.header,1, - audiopage_copy.header_len, - pdata->enc_data->fp); - audio_bytesout+=fwrite(audiopage_copy.body,1, - audiopage_copy.body_len, - pdata->enc_data->fp); - audioflag=0; - if(!pdata->running){ - pthread_mutex_lock(&pdata->libogg_mutex); - if(ogg_page_eos(&audiopage_copy)) - v_st_fin=1; - pthread_mutex_unlock(&pdata->libogg_mutex); - } - ogg_page_cp_free(&audiopage_copy); - } - working=(!th_st_fin || !v_st_fin); - - } - pthread_mutex_lock(&pdata->libogg_mutex); - ogg_stream_clear(&pdata->enc_data->m_ogg_ts); - if(!pdata->args.nosound) - ogg_stream_clear(&pdata->enc_data->m_ogg_vs); - pthread_mutex_unlock(&pdata->libogg_mutex); +void *rmdFlushToOgg(ProgData *pdata) { + int videoflag=0,audioflag=0; + double video_bytesout=0,audio_bytesout=0; + ogg_page videopage,//owned by libogg + videopage_copy,//owned by the application + audiopage,//owned by libogg + audiopage_copy;//owned by the application + + double audiotime=0; + double videotime=0; + int working=1, + th_st_fin=0, + v_st_fin=(pdata->args.nosound); + while (working) { + int audio_or_video=0; + if (pdata->running) { + pthread_mutex_lock(&pdata->libogg_mutex); + if (!videoflag) { + videoflag=ogg_stream_pageout(&pdata->enc_data->m_ogg_ts, + &videopage); + videotime=(videoflag)? + theora_granule_time(&pdata->enc_data->m_th_st, + ogg_page_granulepos(&videopage)):-1; + if (videoflag)ogg_page_cp(&videopage_copy,&videopage); + } + if (!pdata->args.nosound) + if (!audioflag) { + audioflag=ogg_stream_pageout(&pdata->enc_data->m_ogg_vs, + &audiopage); + audiotime=(audioflag)? + vorbis_granule_time(&pdata->enc_data->m_vo_dsp, + ogg_page_granulepos(&audiopage)):-1; + if (audioflag)ogg_page_cp(&audiopage_copy,&audiopage); + } + pthread_mutex_unlock(&pdata->libogg_mutex); + } else { + if (!th_st_fin && !videoflag) { + pthread_mutex_lock(&pdata->libogg_mutex); + videoflag=ogg_stream_flush(&pdata->enc_data->m_ogg_ts, + &videopage); + videotime=(videoflag)? + theora_granule_time(&pdata->enc_data->m_th_st, + ogg_page_granulepos(&videopage)):-1; + if (videoflag)ogg_page_cp(&videopage_copy,&videopage); + pthread_mutex_unlock(&pdata->libogg_mutex); + //we need the last page to properly close the stream + if (!videoflag) { + if (!pdata->th_encoding_clean) { + pthread_mutex_lock(&pdata->theora_lib_mutex); + pthread_cond_wait(&pdata->theora_lib_clean, + &pdata->theora_lib_mutex); + pthread_mutex_unlock(&pdata->theora_lib_mutex); + } + rmdSyncEncodeImageBuffer(pdata); + } + } + if (!pdata->args.nosound && !v_st_fin &&!audioflag) { + pthread_mutex_lock(&pdata->libogg_mutex); + audioflag=ogg_stream_flush(&pdata->enc_data->m_ogg_vs, + &audiopage); + audiotime=(audioflag)? + vorbis_granule_time(&pdata->enc_data->m_vo_dsp, + ogg_page_granulepos(&audiopage)):-1; + if (audioflag)ogg_page_cp(&audiopage_copy,&audiopage); + pthread_mutex_unlock(&pdata->libogg_mutex); + //we need the last page to properly close the stream + if (!audioflag) { + if (!pdata->v_encoding_clean) { + pthread_mutex_lock(&pdata->vorbis_lib_mutex); + pthread_cond_wait(&pdata->vorbis_lib_clean, + &pdata->vorbis_lib_mutex); + pthread_mutex_unlock(&pdata->vorbis_lib_mutex); + } + rmdSyncEncodeSoundBuffer(pdata,NULL); + } + } + } + if (th_st_fin) + videoflag=0; + + if (v_st_fin) + audioflag=0; + + if ((!audioflag && !v_st_fin && !pdata->args.nosound) || (!videoflag && !th_st_fin)) { + usleep(10000); + continue; + } + + if (!audioflag) { + audio_or_video=1; + } else if (!videoflag) { + audio_or_video=0; + } else { + if (audiotime<videotime) + audio_or_video=0; + else + audio_or_video=1; + } + + if (audio_or_video==1) { + video_bytesout+=fwrite( videopage_copy.header,1, + videopage_copy.header_len, + pdata->enc_data->fp); + + video_bytesout+=fwrite( videopage_copy.body,1, + videopage_copy.body_len, + pdata->enc_data->fp); + videoflag=0; + + if (!pdata->running) { + pthread_mutex_lock(&pdata->libogg_mutex); + if (ogg_page_eos(&videopage_copy)) + th_st_fin=1; + pthread_mutex_unlock(&pdata->libogg_mutex); + } + ogg_page_cp_free(&videopage_copy); + } else { + audio_bytesout+=fwrite( audiopage_copy.header,1, + audiopage_copy.header_len, + pdata->enc_data->fp); + + audio_bytesout+=fwrite( audiopage_copy.body,1, + audiopage_copy.body_len, + pdata->enc_data->fp); + audioflag=0; + + if (!pdata->running) { + pthread_mutex_lock(&pdata->libogg_mutex); + if (ogg_page_eos(&audiopage_copy)) + v_st_fin=1; + pthread_mutex_unlock(&pdata->libogg_mutex); + } + ogg_page_cp_free(&audiopage_copy); + } + working=(!th_st_fin || !v_st_fin); + + } + pthread_mutex_lock(&pdata->libogg_mutex); + ogg_stream_clear(&pdata->enc_data->m_ogg_ts); + + if (!pdata->args.nosound) + ogg_stream_clear(&pdata->enc_data->m_ogg_vs); + + pthread_mutex_unlock(&pdata->libogg_mutex); //this always gives me a segfault :( -// theora_clear(&pdata->enc_data->m_th_st); - - if(pdata->enc_data->fp)fclose(pdata->enc_data->fp); - fprintf(stderr,"\r \nDone.\nWritten %.0f bytes\n" - "(%.0f of which were video data " - "and %.0f audio data)\n\n", - video_bytesout+audio_bytesout, - video_bytesout,audio_bytesout); - pthread_exit(&errno); +// theora_clear(&pdata->enc_data->m_th_st); + + if (pdata->enc_data->fp) + fclose(pdata->enc_data->fp); + + fprintf(stderr, "\r \nDone.\nWritten %.0f bytes\n" + "(%.0f of which were video data and %.0f audio data)\n\n", + video_bytesout+audio_bytesout, + video_bytesout,audio_bytesout); + pthread_exit(&errno); } diff --git a/recordmydesktop/src/rmd_frame.c b/recordmydesktop/src/rmd_frame.c index 740dacf..ce2e204 100644 --- a/recordmydesktop/src/rmd_frame.c +++ b/recordmydesktop/src/rmd_frame.c @@ -38,121 +38,105 @@ #define OUTLINE_WIDTH 1 -void rmdDrawFrame(Display *dpy, - int screen, - Window win, - int width, - int height){ - - GC gc; - XGCValues gcv; - XColor white, white_e, - black, black_e ; - unsigned long gcmask=GCForeground; - - XAllocNamedColor(dpy,DefaultColormap(dpy, screen),"white", &white, &white_e); - XAllocNamedColor(dpy,DefaultColormap(dpy, screen),"black", &black, &black_e); - - gcv.foreground = black.pixel; - gc = XCreateGC(dpy,win, gcmask,&gcv); - XFillRectangle(dpy, - win, - gc, - OUTLINE_WIDTH, - OUTLINE_WIDTH, - width+(BORDER_WIDTH-OUTLINE_WIDTH)*2, - height+(BORDER_WIDTH-OUTLINE_WIDTH)*2); - gcv.foreground = white.pixel; - XChangeGC(dpy,gc,gcmask,&gcv); - XFillRectangle(dpy, - win, - gc, - BORDER_WIDTH-OUTLINE_WIDTH, - BORDER_WIDTH-OUTLINE_WIDTH, - width+OUTLINE_WIDTH*2, - height+OUTLINE_WIDTH*2); - - XFreeGC(dpy, gc); +void rmdDrawFrame( Display *dpy, + int screen, + Window win, + int width, + int height) { + + GC gc; + XGCValues gcv; + XColor white, white_e, black, black_e; + unsigned long gcmask=GCForeground; + + XAllocNamedColor(dpy,DefaultColormap(dpy, screen),"white", &white, &white_e); + XAllocNamedColor(dpy,DefaultColormap(dpy, screen),"black", &black, &black_e); + + gcv.foreground = black.pixel; + gc = XCreateGC(dpy,win, gcmask,&gcv); + XFillRectangle( dpy, + win, + gc, + OUTLINE_WIDTH, + OUTLINE_WIDTH, + width+(BORDER_WIDTH-OUTLINE_WIDTH)*2, + height+(BORDER_WIDTH-OUTLINE_WIDTH)*2); + gcv.foreground = white.pixel; + XChangeGC(dpy,gc,gcmask,&gcv); + XFillRectangle( dpy, + win, + gc, + BORDER_WIDTH-OUTLINE_WIDTH, + BORDER_WIDTH-OUTLINE_WIDTH, + width+OUTLINE_WIDTH*2, + height+OUTLINE_WIDTH*2); + + XFreeGC(dpy, gc); } +void rmdMoveFrame( Display *dpy, + Window win, + int x, + int y) { -void rmdMoveFrame(Display *dpy, - Window win, - int x, - int y){ - - XMoveWindow(dpy, - win, - x-BORDER_WIDTH, - y-BORDER_WIDTH); - -// XSync(pdata->dpy,False); - + XMoveWindow(dpy, win, x-BORDER_WIDTH, y-BORDER_WIDTH); +// XSync(pdata->dpy,False); } -Window rmdFrameInit(Display *dpy, - int screen, - Window root, - int x, - int y, - int width, - int height){ - - XSetWindowAttributes attribs; - XColor white, white_e; - Window win; - unsigned long valuemask=CWBackPixmap|CWBackPixel| - CWSaveUnder|CWOverrideRedirect|CWColormap; - - XAllocNamedColor(dpy,DefaultColormap(dpy, screen),"white", &white, &white_e); - - attribs.background_pixmap=None; - attribs.background_pixel=white.pixel; - attribs.save_under=True; - attribs.override_redirect=True; - attribs.colormap=DefaultColormap(dpy,screen); - - win = XCreateWindow(dpy, - root, - x-BORDER_WIDTH, - y-BORDER_WIDTH, - width+BORDER_WIDTH*2, - height+BORDER_WIDTH*2, - 0, - CopyFromParent, - InputOutput, - CopyFromParent, - valuemask, - &attribs); - - - XRectangle rect; - rect.x=rect.y=BORDER_WIDTH; - rect.width=width; - rect.height=height; - - XShapeCombineRectangles(dpy, - win, - ShapeBounding, - 0, - 0, - &rect, - 1, - ShapeSubtract, - 0); - - XMapWindow(dpy, win); - - rmdDrawFrame(dpy,screen,win,width,height); - - return win; +Window rmdFrameInit( Display *dpy, + int screen, + Window root, + int x, + int y, + int width, + int height) { + + XSetWindowAttributes attribs; + XColor white, white_e; + Window win; + unsigned long valuemask=CWBackPixmap|CWBackPixel| + CWSaveUnder|CWOverrideRedirect|CWColormap; + + XAllocNamedColor(dpy,DefaultColormap(dpy, screen),"white", &white, &white_e); + + attribs.background_pixmap=None; + attribs.background_pixel=white.pixel; + attribs.save_under=True; + attribs.override_redirect=True; + attribs.colormap=DefaultColormap(dpy,screen); + + win = XCreateWindow( dpy, + root, + x-BORDER_WIDTH, + y-BORDER_WIDTH, + width+BORDER_WIDTH*2, + height+BORDER_WIDTH*2, + 0, + CopyFromParent, + InputOutput, + CopyFromParent, + valuemask, + &attribs); + + XRectangle rect; + rect.x=rect.y=BORDER_WIDTH; + rect.width=width; + rect.height=height; + + XShapeCombineRectangles( dpy, + win, + ShapeBounding, + 0, + 0, + &rect, + 1, + ShapeSubtract, + 0); + + XMapWindow(dpy, win); + + rmdDrawFrame(dpy,screen,win,width,height); + + return win; } - - - - - - - - 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); } - diff --git a/recordmydesktop/src/rmd_getzpixmap.c b/recordmydesktop/src/rmd_getzpixmap.c index 89cb48e..fa7c809 100644 --- a/recordmydesktop/src/rmd_getzpixmap.c +++ b/recordmydesktop/src/rmd_getzpixmap.c @@ -37,77 +37,84 @@ -int rmdGetZPixmap(Display *dpy, - Window root, - char *data, - int x, - int y, - int width, - int height){ - xGetImageReply reply; - xGetImageReq *request; - long nbytes; - - LockDisplay(dpy); - GetReq(GetImage,request); - request->drawable=root; - request->x=x; - request->y=y; - request->width=width; - request->height=height; - request->planeMask=AllPlanes; - request->format=ZPixmap; - if((!_XReply(dpy,(xReply *)&reply,0,xFalse))||(!reply.length)){ - UnlockDisplay(dpy); - SyncHandle(); - return 1; - } - nbytes=(long)reply.length<<2; - _XReadPad(dpy,data,nbytes); - UnlockDisplay(dpy); - SyncHandle(); - return 0; +int rmdGetZPixmap( Display *dpy, + Window root, + char *data, + int x, + int y, + int width, + int height) { + + xGetImageReply reply; + xGetImageReq *request; + long nbytes; + + LockDisplay(dpy); + GetReq(GetImage,request); + request->drawable=root; + request->x=x; + request->y=y; + request->width=width; + request->height=height; + request->planeMask=AllPlanes; + request->format=ZPixmap; + + if (!_XReply(dpy,(xReply *)&reply,0,xFalse) || !reply.length) { + UnlockDisplay(dpy); + SyncHandle(); + + return 1; + } + + nbytes=(long)reply.length<<2; + _XReadPad(dpy,data,nbytes); + UnlockDisplay(dpy); + SyncHandle(); + + return 0; } -int rmdGetZPixmapSHM(Display *dpy, - Window root, - XShmSegmentInfo *shminfo, - int shm_opcode, - char *data, - int x, - int y, - int width, - int height){ - xShmGetImageReply reply; - xShmGetImageReq *request=NULL; - long nbytes; - - LockDisplay(dpy); - GetReq(ShmGetImage,request); - - request->reqType=shm_opcode; - request->shmReqType=X_ShmGetImage; - request->shmseg=shminfo->shmseg; - - request->drawable=root; - request->x=x; - request->y=y; - request->width=width; - request->height=height; - request->planeMask=AllPlanes; - request->format=ZPixmap; - request->offset=data-shminfo->shmaddr; - - if((!_XReply(dpy,(xReply *)&reply,0,xFalse))||(!reply.length)){ - UnlockDisplay(dpy); - SyncHandle(); - return 1; - } - - nbytes=(long)reply.length << 2; - _XReadPad(dpy,data,nbytes); - UnlockDisplay(dpy); - SyncHandle(); - - return 0; +int rmdGetZPixmapSHM( Display *dpy, + Window root, + XShmSegmentInfo *shminfo, + int shm_opcode, + char *data, + int x, + int y, + int width, + int height) { + + xShmGetImageReply reply; + xShmGetImageReq *request=NULL; + long nbytes; + + LockDisplay(dpy); + GetReq(ShmGetImage,request); + + request->reqType=shm_opcode; + request->shmReqType=X_ShmGetImage; + request->shmseg=shminfo->shmseg; + + request->drawable=root; + request->x=x; + request->y=y; + request->width=width; + request->height=height; + request->planeMask=AllPlanes; + request->format=ZPixmap; + request->offset=data-shminfo->shmaddr; + + if ((!_XReply(dpy,(xReply *)&reply,0,xFalse))||(!reply.length)) { + UnlockDisplay(dpy); + SyncHandle(); + + return 1; + } + + nbytes=(long)reply.length << 2; + _XReadPad(dpy,data,nbytes); + UnlockDisplay(dpy); + SyncHandle(); + + return 0; } diff --git a/recordmydesktop/src/rmd_init_encoder.c b/recordmydesktop/src/rmd_init_encoder.c index 036009f..dee0ba3 100644 --- a/recordmydesktop/src/rmd_init_encoder.c +++ b/recordmydesktop/src/rmd_init_encoder.c @@ -38,337 +38,313 @@ - - static void m_add_fishead_packet(ogg_stream_state *m_ogg_state) { + fishead_packet skel_fp; - fishead_packet skel_fp; - - skel_fp.ptime_n=skel_fp.btime_n=0; - skel_fp.ptime_d=skel_fp.btime_d=1000; - - add_fishead_to_stream(m_ogg_state,&skel_fp); - + skel_fp.ptime_n=skel_fp.btime_n=0; + skel_fp.ptime_d=skel_fp.btime_d=1000; + add_fishead_to_stream(m_ogg_state,&skel_fp); } static int rmdIncrementalNaming(char **name) { - struct stat buff; - char *base_name__; - int i=0, - fname_length=strlen(*name)-4; - - base_name__=malloc(fname_length+1); - strncpy(base_name__,*name,fname_length); - base_name__[fname_length]='\0'; - - - //this will go on an endless loop if you have 65536? - //files with the same name - //or it will crash and die.anyone interested in trying ? - while (stat(*name,&buff)==0){ - //create new name - char *tname=malloc(strlen(*name)+10); - char numbuf[8]; - - strcpy(tname,base_name__); - strcat(tname,"-"); - i++; - snprintf( numbuf, 8, "%d", i ); - strcat(tname,numbuf); - strcat(tname,".ogv"); - //save new name - - free(*name); - *name=malloc(strlen(tname)+1); - strcpy(*name,tname); - free(tname); - } - - free(base_name__); - return 0; + struct stat buff; + char *base_name__; + int i=0, fname_length=strlen(*name)-4; + + base_name__=malloc(fname_length+1); + strncpy(base_name__,*name,fname_length); + base_name__[fname_length]='\0'; + + //this will go on an endless loop if you have 65536? + //files with the same name + //or it will crash and die.anyone interested in trying ? + while (stat(*name,&buff)==0) { + //create new name + char *tname=malloc(strlen(*name)+10); + char numbuf[8]; + + strcpy(tname,base_name__); + strcat(tname,"-"); + i++; + snprintf( numbuf, 8, "%d", i ); + strcat(tname,numbuf); + strcat(tname,".ogv"); + //save new name + + free(*name); + *name=malloc(strlen(tname)+1); + strcpy(*name,tname); + free(tname); + } + + free(base_name__); + return 0; } -void rmdInitEncoder(ProgData *pdata,EncData *enc_data_t,int buffer_ready){ - - int y0, - y1, - y2, - fname_length; - ogg_stream_state m_ogg_skel; - ogg_page skel_og_pg; - fisbone_packet skel_fbv, //video fisbone packet - skel_fba ; //audio fisbone packet - - (pdata)->enc_data=enc_data_t; - - fname_length=strlen(pdata->args.filename); - if(!(fname_length>4 && - pdata->args.filename[fname_length-4] == '.' && - (pdata->args.filename[fname_length-3] == 'o' || - pdata->args.filename[fname_length-3] == 'O') && - (pdata->args.filename[fname_length-2] == 'g' || - pdata->args.filename[fname_length-2] == 'G') && - (pdata->args.filename[fname_length-1] == 'v' || - pdata->args.filename[fname_length-1] == 'V'))){ - - char *new_name=malloc(fname_length+5); - strcpy(new_name,pdata->args.filename); - strcat(new_name,".ogv"); - - free(pdata->args.filename); - pdata->args.filename=new_name; - - - } - - if (!pdata->args.overwrite) { - rmdIncrementalNaming(&(pdata)->args.filename); - fprintf(stderr, "Output file: %s\n", pdata->args.filename); - } - - enc_data_t->fp=fopen((pdata)->args.filename,"w"); - if(enc_data_t->fp==NULL){ - fprintf(stderr,"Cannot open file %s for writting!\n", - (pdata)->args.filename); - exit(13); - } - - //each stream must have a unique - srand(time(NULL)); - y0=rand()+1; - y1=rand()+1; - y2=rand()+1; - y2+=(y1==y2); - y0=(((y0==y1)||(y0==y2))?(y1+y2):y0); - - //init ogg streams - //skeleton first - ogg_stream_init(&m_ogg_skel,y0); - m_add_fishead_packet(&m_ogg_skel); - if(ogg_stream_pageout(&m_ogg_skel,&skel_og_pg)!= 1){ - fprintf (stderr, "Internal Ogg library error.\n"); - exit (2); - } - fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp); - fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp); - - - - ogg_stream_init(&enc_data_t->m_ogg_ts,y1); - if(!pdata->args.nosound) - ogg_stream_init(&enc_data_t->m_ogg_vs,y2); - - - theora_info_init(&enc_data_t->m_th_inf); - enc_data_t->m_th_inf.frame_width = pdata->brwin.rrect.width; - enc_data_t->m_th_inf.frame_height = pdata->brwin.rrect.height; - enc_data_t->m_th_inf.width = ((enc_data_t->m_th_inf.frame_width + 15) >> 4) << 4; - enc_data_t->m_th_inf.height = ((enc_data_t->m_th_inf.frame_height + 15) >> 4) << 4; - enc_data_t->m_th_inf.offset_x = 0; - enc_data_t->m_th_inf.offset_y = 0; - - enc_data_t->m_th_inf.fps_numerator = pdata->args.fps * 100.0; - enc_data_t->m_th_inf.fps_denominator = 100; - enc_data_t->m_th_inf.aspect_numerator = 1; - enc_data_t->m_th_inf.aspect_denominator = 1; - - enc_data_t->m_th_inf.colorspace = OC_CS_UNSPECIFIED; - enc_data_t->m_th_inf.pixelformat = OC_PF_420; - - enc_data_t->m_th_inf.target_bitrate = pdata->args.v_bitrate; - enc_data_t->m_th_inf.quality = pdata->args.v_quality; - enc_data_t->m_th_inf.dropframes_p = 0; - enc_data_t->m_th_inf.quick_p = 1; - enc_data_t->m_th_inf.keyframe_auto_p = 1; - enc_data_t->m_th_inf.keyframe_frequency = 64; - enc_data_t->m_th_inf.keyframe_frequency_force = 64; - enc_data_t->m_th_inf.keyframe_data_target_bitrate = enc_data_t->m_th_inf.quality * 1.5; - enc_data_t->m_th_inf.keyframe_auto_threshold = 80; - enc_data_t->m_th_inf.keyframe_mindistance = 8; - enc_data_t->m_th_inf.noise_sensitivity = 1; - enc_data_t->m_th_inf.sharpness = 2; - - theora_encode_init(&enc_data_t->m_th_st,&enc_data_t->m_th_inf); - - - if(!pdata->args.nosound){ - int ret; - vorbis_info_init(&enc_data_t->m_vo_inf); - ret = vorbis_encode_init_vbr(&enc_data_t->m_vo_inf, - pdata->args.channels, - pdata->args.frequency, - (float)pdata->args.s_quality*0.1); - if(ret){ - fprintf(stderr,"Error while setting up vorbis stream quality!\n"); - exit(2); - } - vorbis_comment_init(&enc_data_t->m_vo_cmmnt); - vorbis_analysis_init(&enc_data_t->m_vo_dsp,&enc_data_t->m_vo_inf); - vorbis_block_init(&enc_data_t->m_vo_dsp,&enc_data_t->m_vo_block); - } - - - theora_encode_header(&enc_data_t->m_th_st,&enc_data_t->m_ogg_pckt1); - ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1); - if(ogg_stream_pageout(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pg)!=1){ - fprintf(stderr,"Internal Ogg library error.\n"); - exit(2); - } - fwrite(enc_data_t->m_ogg_pg.header,1, - enc_data_t->m_ogg_pg.header_len, - enc_data_t->fp); - fwrite(enc_data_t->m_ogg_pg.body,1, - enc_data_t->m_ogg_pg.body_len, - enc_data_t->fp); - - theora_comment_init(&enc_data_t->m_th_cmmnt); - theora_comment_add_tag(&enc_data_t->m_th_cmmnt,"recordMyDesktop",VERSION); - theora_encode_comment(&enc_data_t->m_th_cmmnt,&enc_data_t->m_ogg_pckt1); - ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1); - theora_encode_tables(&enc_data_t->m_th_st,&enc_data_t->m_ogg_pckt1); - ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1); - - - if(!pdata->args.nosound){ - ogg_packet header; - ogg_packet header_comm; - ogg_packet header_code; - - vorbis_analysis_headerout(&enc_data_t->m_vo_dsp, - &enc_data_t->m_vo_cmmnt, - &header,&header_comm, - &header_code); - ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header); - if(ogg_stream_pageout(&enc_data_t->m_ogg_vs,&enc_data_t->m_ogg_pg)!=1){ - fprintf(stderr,"Internal Ogg library error.\n"); - exit(2); - } - fwrite(enc_data_t->m_ogg_pg.header,1, - enc_data_t->m_ogg_pg.header_len, - enc_data_t->fp); - fwrite(enc_data_t->m_ogg_pg.body,1, - enc_data_t->m_ogg_pg.body_len, - enc_data_t->fp); - - ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header_comm); - ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header_code); - } - - //fishbone packets go here - memset(&skel_fbv,0,sizeof(skel_fbv)); - skel_fbv.serial_no=enc_data_t->m_ogg_ts.serialno; - skel_fbv.nr_header_packet=3; - skel_fbv.granule_rate_n=enc_data_t->m_th_inf.fps_numerator; - skel_fbv.granule_rate_d=enc_data_t->m_th_inf.fps_denominator; - skel_fbv.start_granule=0; - skel_fbv.preroll=0; - skel_fbv.granule_shift=theora_granule_shift(&enc_data_t->m_th_inf); - add_message_header_field(&skel_fbv, - "Content-Type", - "video/theora"); - - add_fisbone_to_stream(&m_ogg_skel,&skel_fbv); - - if(!pdata->args.nosound){ - - memset(&skel_fba,0,sizeof(skel_fba)); - skel_fba.serial_no=enc_data_t->m_ogg_vs.serialno; - skel_fba.nr_header_packet=3; - skel_fba.granule_rate_n=pdata->args.frequency; - skel_fba.granule_rate_d=(ogg_int64_t)1; - skel_fba.start_granule=0; - skel_fba.preroll=2; - skel_fba.granule_shift=0; - add_message_header_field(&skel_fba, - "Content-Type", - "audio/vorbis"); - - add_fisbone_to_stream(&m_ogg_skel,&skel_fba); - - } - - while(1){ - int result = ogg_stream_flush(&m_ogg_skel, &skel_og_pg); - if(result<0){ - fprintf (stderr, "Internal Ogg library error.\n"); - exit(2); - } - if(result==0) - break; - fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp); - fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp); +void rmdInitEncoder(ProgData *pdata,EncData *enc_data_t,int buffer_ready) { + int y0, y1, y2, fname_length; + ogg_stream_state m_ogg_skel; + ogg_page skel_og_pg; + fisbone_packet skel_fbv, //video fisbone packet + skel_fba; //audio fisbone packet + const char *fname; + + (pdata)->enc_data=enc_data_t; + + fname = pdata->args.filename; + fname_length=strlen(fname); + if (!(fname_length>4 && !strcasecmp(&fname[fname_length-3], "ogv"))) { + + char *new_name=malloc(fname_length+5); + strcpy(new_name,fname); + strcat(new_name,".ogv"); + + free(pdata->args.filename); + pdata->args.filename=new_name; } + if (!pdata->args.overwrite) { + rmdIncrementalNaming(&(pdata)->args.filename); + fprintf(stderr, "Output file: %s\n", pdata->args.filename); + } + + enc_data_t->fp=fopen((pdata)->args.filename,"w"); + if (enc_data_t->fp==NULL) { + fprintf(stderr,"Cannot open file %s for writting!\n", (pdata)->args.filename); + exit(13); + } + //each stream must have a unique + srand(time(NULL)); + y0=rand()+1; + y1=rand()+1; + y2=rand()+1; + y2+=(y1==y2); + y0=(((y0==y1)||(y0==y2))?(y1+y2):y0); + + //init ogg streams + //skeleton first + ogg_stream_init(&m_ogg_skel,y0); + m_add_fishead_packet(&m_ogg_skel); + if (ogg_stream_pageout(&m_ogg_skel,&skel_og_pg)!= 1) { + fprintf (stderr, "Internal Ogg library error.\n"); + exit (2); + } + fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp); + fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp); + + + + ogg_stream_init(&enc_data_t->m_ogg_ts,y1); + if (!pdata->args.nosound) + ogg_stream_init(&enc_data_t->m_ogg_vs,y2); + + theora_info_init(&enc_data_t->m_th_inf); + enc_data_t->m_th_inf.frame_width = pdata->brwin.rrect.width; + enc_data_t->m_th_inf.frame_height = pdata->brwin.rrect.height; + enc_data_t->m_th_inf.width = ((enc_data_t->m_th_inf.frame_width + 15) >> 4) << 4; + enc_data_t->m_th_inf.height = ((enc_data_t->m_th_inf.frame_height + 15) >> 4) << 4; + enc_data_t->m_th_inf.offset_x = 0; + enc_data_t->m_th_inf.offset_y = 0; + + enc_data_t->m_th_inf.fps_numerator = pdata->args.fps * 100.0; + enc_data_t->m_th_inf.fps_denominator = 100; + enc_data_t->m_th_inf.aspect_numerator = 1; + enc_data_t->m_th_inf.aspect_denominator = 1; + + enc_data_t->m_th_inf.colorspace = OC_CS_UNSPECIFIED; + enc_data_t->m_th_inf.pixelformat = OC_PF_420; + + enc_data_t->m_th_inf.target_bitrate = pdata->args.v_bitrate; + enc_data_t->m_th_inf.quality = pdata->args.v_quality; + enc_data_t->m_th_inf.dropframes_p = 0; + enc_data_t->m_th_inf.quick_p = 1; + enc_data_t->m_th_inf.keyframe_auto_p = 1; + enc_data_t->m_th_inf.keyframe_frequency = 64; + enc_data_t->m_th_inf.keyframe_frequency_force = 64; + enc_data_t->m_th_inf.keyframe_data_target_bitrate = enc_data_t->m_th_inf.quality * 1.5; + enc_data_t->m_th_inf.keyframe_auto_threshold = 80; + enc_data_t->m_th_inf.keyframe_mindistance = 8; + enc_data_t->m_th_inf.noise_sensitivity = 1; + enc_data_t->m_th_inf.sharpness = 2; + + theora_encode_init(&enc_data_t->m_th_st,&enc_data_t->m_th_inf); + + + if (!pdata->args.nosound) { + int ret; + vorbis_info_init(&enc_data_t->m_vo_inf); + ret = vorbis_encode_init_vbr( &enc_data_t->m_vo_inf, + pdata->args.channels, + pdata->args.frequency, + (float)pdata->args.s_quality*0.1); + if (ret) { + fprintf(stderr,"Error while setting up vorbis stream quality!\n"); + exit(2); + } + vorbis_comment_init(&enc_data_t->m_vo_cmmnt); + vorbis_analysis_init(&enc_data_t->m_vo_dsp,&enc_data_t->m_vo_inf); + vorbis_block_init(&enc_data_t->m_vo_dsp,&enc_data_t->m_vo_block); + } - while(1){ - int result = ogg_stream_flush(&enc_data_t->m_ogg_ts, - &enc_data_t->m_ogg_pg); - if(result<0){ - fprintf(stderr,"Internal Ogg library error.\n"); - exit(2); - } - if(result==0)break; - fwrite(enc_data_t->m_ogg_pg.header,1, - enc_data_t->m_ogg_pg.header_len, - enc_data_t->fp); - fwrite(enc_data_t->m_ogg_pg.body,1, - enc_data_t->m_ogg_pg.body_len, - enc_data_t->fp); - } - - if(!pdata->args.nosound){ - while(1){ - int result=ogg_stream_flush(&enc_data_t->m_ogg_vs, - &enc_data_t->m_ogg_pg); - if(result<0){ - fprintf(stderr,"Internal Ogg library error.\n"); - exit(2); - } - if(result==0)break; - fwrite(enc_data_t->m_ogg_pg.header,1, - enc_data_t->m_ogg_pg.header_len, - enc_data_t->fp); - fwrite(enc_data_t->m_ogg_pg.body,1, - enc_data_t->m_ogg_pg.body_len, - enc_data_t->fp); - } - } - - //skeleton eos - add_eos_packet_to_stream(&m_ogg_skel); - if(ogg_stream_flush(&m_ogg_skel,&skel_og_pg)<0){ - fprintf(stderr,"Internal Ogg library error.\n"); - exit(2); - } - fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp); - fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp); - - - //theora buffer allocation, if any - if(!buffer_ready){ - enc_data_t->yuv.y=(unsigned char *)malloc(enc_data_t->m_th_inf.height* - enc_data_t->m_th_inf.width); - enc_data_t->yuv.u=(unsigned char *)malloc(enc_data_t->m_th_inf.height* - enc_data_t->m_th_inf.width/4); - enc_data_t->yuv.v=(unsigned char *)malloc(enc_data_t->m_th_inf.height* - enc_data_t->m_th_inf.width/4); - enc_data_t->yuv.y_width=enc_data_t->m_th_inf.width; - enc_data_t->yuv.y_height=enc_data_t->m_th_inf.height; - enc_data_t->yuv.y_stride=enc_data_t->m_th_inf.width; - - enc_data_t->yuv.uv_width=enc_data_t->m_th_inf.width/2; - enc_data_t->yuv.uv_height=enc_data_t->m_th_inf.height/2; - enc_data_t->yuv.uv_stride=enc_data_t->m_th_inf.width/2; - enc_data_t->x_offset=enc_data_t->m_th_inf.offset_x; - enc_data_t->y_offset=enc_data_t->m_th_inf.offset_y; - } - theora_info_clear(&enc_data_t->m_th_inf); -} + theora_encode_header(&enc_data_t->m_th_st,&enc_data_t->m_ogg_pckt1); + ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1); + if (ogg_stream_pageout(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pg)!=1) { + fprintf(stderr,"Internal Ogg library error.\n"); + exit(2); + } + fwrite(enc_data_t->m_ogg_pg.header,1, + enc_data_t->m_ogg_pg.header_len, + enc_data_t->fp); + fwrite(enc_data_t->m_ogg_pg.body,1, + enc_data_t->m_ogg_pg.body_len, + enc_data_t->fp); + + theora_comment_init(&enc_data_t->m_th_cmmnt); + theora_comment_add_tag(&enc_data_t->m_th_cmmnt,"recordMyDesktop",VERSION); + theora_encode_comment(&enc_data_t->m_th_cmmnt,&enc_data_t->m_ogg_pckt1); + ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1); + theora_encode_tables(&enc_data_t->m_th_st,&enc_data_t->m_ogg_pckt1); + ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1); + + if (!pdata->args.nosound) { + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + + vorbis_analysis_headerout(&enc_data_t->m_vo_dsp, + &enc_data_t->m_vo_cmmnt, + &header,&header_comm, + &header_code); + ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header); + if (ogg_stream_pageout(&enc_data_t->m_ogg_vs,&enc_data_t->m_ogg_pg)!=1) { + fprintf(stderr,"Internal Ogg library error.\n"); + exit(2); + } + + fwrite(enc_data_t->m_ogg_pg.header,1, + enc_data_t->m_ogg_pg.header_len, + enc_data_t->fp); + + fwrite(enc_data_t->m_ogg_pg.body,1, + enc_data_t->m_ogg_pg.body_len, + enc_data_t->fp); + + ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header_comm); + ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header_code); + } + + //fishbone packets go here + memset(&skel_fbv,0,sizeof(skel_fbv)); + skel_fbv.serial_no=enc_data_t->m_ogg_ts.serialno; + skel_fbv.nr_header_packet=3; + skel_fbv.granule_rate_n=enc_data_t->m_th_inf.fps_numerator; + skel_fbv.granule_rate_d=enc_data_t->m_th_inf.fps_denominator; + skel_fbv.start_granule=0; + skel_fbv.preroll=0; + skel_fbv.granule_shift=theora_granule_shift(&enc_data_t->m_th_inf); + add_message_header_field(&skel_fbv, "Content-Type", "video/theora"); + + add_fisbone_to_stream(&m_ogg_skel,&skel_fbv); + + if (!pdata->args.nosound) { + + memset(&skel_fba,0,sizeof(skel_fba)); + skel_fba.serial_no=enc_data_t->m_ogg_vs.serialno; + skel_fba.nr_header_packet=3; + skel_fba.granule_rate_n=pdata->args.frequency; + skel_fba.granule_rate_d=(ogg_int64_t)1; + skel_fba.start_granule=0; + skel_fba.preroll=2; + skel_fba.granule_shift=0; + add_message_header_field(&skel_fba, "Content-Type", "audio/vorbis"); + + add_fisbone_to_stream(&m_ogg_skel,&skel_fba); + } + + while (1) { + int result = ogg_stream_flush(&m_ogg_skel, &skel_og_pg); + if (result<0) { + fprintf (stderr, "Internal Ogg library error.\n"); + exit(2); + } + + if (result==0) + break; + fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp); + fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp); + } + while (1) { + int result = ogg_stream_flush(&enc_data_t->m_ogg_ts, + &enc_data_t->m_ogg_pg); + if (result<0) { + fprintf(stderr,"Internal Ogg library error.\n"); + exit(2); + } + + if (result==0) + break; + + fwrite( enc_data_t->m_ogg_pg.header,1, + enc_data_t->m_ogg_pg.header_len, + enc_data_t->fp); + fwrite( enc_data_t->m_ogg_pg.body,1, + enc_data_t->m_ogg_pg.body_len, + enc_data_t->fp); + } + if (!pdata->args.nosound) { + while (1) { + int result=ogg_stream_flush(&enc_data_t->m_ogg_vs, + &enc_data_t->m_ogg_pg); + if (result<0) { + fprintf(stderr,"Internal Ogg library error.\n"); + exit(2); + } + + if (result==0) + break; + + fwrite( enc_data_t->m_ogg_pg.header,1, + enc_data_t->m_ogg_pg.header_len, + enc_data_t->fp); + fwrite( enc_data_t->m_ogg_pg.body,1, + enc_data_t->m_ogg_pg.body_len, + enc_data_t->fp); + } + } + //skeleton eos + add_eos_packet_to_stream(&m_ogg_skel); + if (ogg_stream_flush(&m_ogg_skel,&skel_og_pg)<0) { + fprintf(stderr,"Internal Ogg library error.\n"); + exit(2); + } + fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp); + + + //theora buffer allocation, if any + if (!buffer_ready) { + enc_data_t->yuv.y=(unsigned char *)malloc(enc_data_t->m_th_inf.height* + enc_data_t->m_th_inf.width); + enc_data_t->yuv.u=(unsigned char *)malloc(enc_data_t->m_th_inf.height* + enc_data_t->m_th_inf.width/4); + enc_data_t->yuv.v=(unsigned char *)malloc(enc_data_t->m_th_inf.height* + enc_data_t->m_th_inf.width/4); + enc_data_t->yuv.y_width=enc_data_t->m_th_inf.width; + enc_data_t->yuv.y_height=enc_data_t->m_th_inf.height; + enc_data_t->yuv.y_stride=enc_data_t->m_th_inf.width; + + enc_data_t->yuv.uv_width=enc_data_t->m_th_inf.width/2; + enc_data_t->yuv.uv_height=enc_data_t->m_th_inf.height/2; + enc_data_t->yuv.uv_stride=enc_data_t->m_th_inf.width/2; + enc_data_t->x_offset=enc_data_t->m_th_inf.offset_x; + enc_data_t->y_offset=enc_data_t->m_th_inf.offset_y; + } + theora_info_clear(&enc_data_t->m_th_inf); +} diff --git a/recordmydesktop/src/rmd_initialize_data.c b/recordmydesktop/src/rmd_initialize_data.c index 4fef385..69f4fce 100644 --- a/recordmydesktop/src/rmd_initialize_data.c +++ b/recordmydesktop/src/rmd_initialize_data.c @@ -43,220 +43,211 @@ #ifdef HAVE_LIBASOUND static void rmdFixBufferSize(snd_pcm_uframes_t *buffsize) { - snd_pcm_uframes_t buffsize_t=*buffsize, + snd_pcm_uframes_t buffsize_t=*buffsize, #else static void rmdFixBufferSize(u_int32_t *buffsize) { - u_int32_t buffsize_t=*buffsize, + u_int32_t buffsize_t=*buffsize, #endif - buffsize_ret=1; - while(buffsize_t>1){ - buffsize_t>>=1; - buffsize_ret<<=1; - } - fprintf(stderr,"Buffer size adjusted to %d from %d frames.\n", - (int)buffsize_ret,(int)*buffsize); + buffsize_ret=1; + + while (buffsize_t>1) { + buffsize_t>>=1; + buffsize_ret<<=1; + } + fprintf(stderr,"Buffer size adjusted to %d from %d frames.\n", + (int)buffsize_ret,(int)*buffsize); } -int rmdInitializeData(ProgData *pdata, - EncData *enc_data, - CacheData *cache_data){ - int i; - - fprintf(stderr,"Initializing...\n"); - rmdMakeMatrices(); - if(pdata->args.have_dummy_cursor){ - pdata->dummy_pointer = rmdMakeDummyPointer(pdata->dpy, - &pdata->specs, - 16, - pdata->args.cursor_color, - 0, - &pdata->npxl); - pdata->dummy_p_size=16; - } - else - pdata->dummy_p_size=0; - - - pdata->rect_root=NULL; - pthread_mutex_init(&pdata->sound_buffer_mutex,NULL); - pthread_mutex_init(&pdata->snd_buff_ready_mutex,NULL); - pthread_mutex_init(&pdata->img_buff_ready_mutex,NULL); - pthread_mutex_init(&pdata->theora_lib_mutex,NULL); - pthread_mutex_init(&pdata->vorbis_lib_mutex,NULL); - pthread_mutex_init(&pdata->libogg_mutex,NULL); - pthread_mutex_init(&pdata->yuv_mutex,NULL); - pthread_mutex_init(&pdata->pause_mutex, NULL); - pthread_mutex_init(&pdata->time_mutex, NULL); - pthread_cond_init(&pdata->time_cond,NULL); - pthread_cond_init(&pdata->pause_cond,NULL); - pthread_cond_init(&pdata->image_buffer_ready,NULL); - pthread_cond_init(&pdata->sound_data_read,NULL); - pthread_cond_init(&pdata->theora_lib_clean,NULL); - pthread_cond_init(&pdata->vorbis_lib_clean,NULL); - pdata->th_encoding_clean=pdata->v_encoding_clean=1; - pdata->avd=0; - pdata->sound_buffer=NULL; - pdata->running = TRUE; - pdata->paused = FALSE; - pdata->aborted = FALSE; - pdata->pause_state_changed = FALSE; - pdata->frames_total = 0; - pdata->frames_lost = 0; - pdata->encoder_busy = FALSE; - pdata->capture_busy = FALSE; - - if(!pdata->args.nosound){ - if(!pdata->args.use_jack){ - rmdFixBufferSize(&pdata->args.buffsize); +int rmdInitializeData(ProgData *pdata, EncData *enc_data, CacheData *cache_data) { + int i; + + fprintf(stderr,"Initializing...\n"); + rmdMakeMatrices(); + if (pdata->args.have_dummy_cursor) { + pdata->dummy_pointer = rmdMakeDummyPointer( pdata->dpy, + &pdata->specs, + 16, + pdata->args.cursor_color, + 0, + &pdata->npxl); + pdata->dummy_p_size=16; + } else + pdata->dummy_p_size=0; + + pdata->rect_root=NULL; + pthread_mutex_init(&pdata->sound_buffer_mutex,NULL); + pthread_mutex_init(&pdata->snd_buff_ready_mutex,NULL); + pthread_mutex_init(&pdata->img_buff_ready_mutex,NULL); + pthread_mutex_init(&pdata->theora_lib_mutex,NULL); + pthread_mutex_init(&pdata->vorbis_lib_mutex,NULL); + pthread_mutex_init(&pdata->libogg_mutex,NULL); + pthread_mutex_init(&pdata->yuv_mutex,NULL); + pthread_mutex_init(&pdata->pause_mutex, NULL); + pthread_mutex_init(&pdata->time_mutex, NULL); + pthread_cond_init(&pdata->time_cond,NULL); + pthread_cond_init(&pdata->pause_cond,NULL); + pthread_cond_init(&pdata->image_buffer_ready,NULL); + pthread_cond_init(&pdata->sound_data_read,NULL); + pthread_cond_init(&pdata->theora_lib_clean,NULL); + pthread_cond_init(&pdata->vorbis_lib_clean,NULL); + pdata->th_encoding_clean=pdata->v_encoding_clean=1; + pdata->avd=0; + pdata->sound_buffer=NULL; + pdata->running = TRUE; + pdata->paused = FALSE; + pdata->aborted = FALSE; + pdata->pause_state_changed = FALSE; + pdata->frames_total = 0; + pdata->frames_lost = 0; + pdata->encoder_busy = FALSE; + pdata->capture_busy = FALSE; + + if (!pdata->args.nosound) { + if (!pdata->args.use_jack) { + rmdFixBufferSize(&pdata->args.buffsize); #ifdef HAVE_LIBASOUND - pdata->sound_handle=rmdOpenDev(pdata->args.device, - &pdata->args.channels, - &pdata->args.frequency, - &pdata->args.buffsize, - &pdata->periodsize, - &pdata->periodtime, - &pdata->hard_pause); - pdata->sound_framesize=((snd_pcm_format_width( - SND_PCM_FORMAT_S16_LE))/8)* - pdata->args.channels; - - if(pdata->sound_handle==NULL){ + pdata->sound_handle=rmdOpenDev(pdata->args.device, + &pdata->args.channels, + &pdata->args.frequency, + &pdata->args.buffsize, + &pdata->periodsize, + &pdata->periodtime, + &pdata->hard_pause); + pdata->sound_framesize=((snd_pcm_format_width( + SND_PCM_FORMAT_S16_LE))/8)* + pdata->args.channels; + + if (pdata->sound_handle==NULL) { #else - pdata->sound_handle=rmdOpenDev(pdata->args.device, - pdata->args.channels, - pdata->args.frequency); - pdata->periodtime=(1000000*pdata->args.buffsize)/ - ((pdata->args.channels<<1)*pdata->args.frequency); - //when using OSS periodsize serves as an alias of buffsize - pdata->periodsize=pdata->args.buffsize; - pdata->sound_framesize=pdata->args.channels<<1; - if(pdata->sound_handle<0){ + pdata->sound_handle=rmdOpenDev( pdata->args.device, + pdata->args.channels, + pdata->args.frequency); + + pdata->periodtime=(1000000*pdata->args.buffsize)/ + ((pdata->args.channels<<1)*pdata->args.frequency); + //when using OSS periodsize serves as an alias of buffsize + pdata->periodsize=pdata->args.buffsize; + pdata->sound_framesize=pdata->args.channels<<1; + if (pdata->sound_handle<0) { #endif - fprintf(stderr,"Error while opening/configuring soundcard %s\n" - "Try running with the --no-sound or specify a " - "correct device.\n", - pdata->args.device); - return 3; - } - } - else{ + fprintf(stderr,"Error while opening/configuring soundcard %s\n" + "Try running with the --no-sound or specify a " + "correct device.\n", + pdata->args.device); + return 3; + } + } else { #ifdef HAVE_LIBJACK - int jack_error=0; - pdata->jdata->port_names=pdata->args.jack_port_names; - pdata->jdata->nports=pdata->args.jack_nports; - pdata->jdata->ringbuffer_secs=pdata->args.jack_ringbuffer_secs; - pdata->jdata->snd_buff_ready_mutex=&pdata->snd_buff_ready_mutex; - pdata->jdata->sound_data_read=&pdata->sound_data_read; - pdata->jdata->capture_started=0; - - if((jack_error=rmdStartJackClient(pdata->jdata))!=0) - return jack_error; - - pdata->args.buffsize=pdata->jdata->buffersize; - pdata->periodsize=pdata->args.buffsize; - pdata->args.frequency=pdata->jdata->frequency; - pdata->args.channels=pdata->jdata->nports; - pdata->periodtime=(1000000*pdata->args.buffsize)/ - pdata->args.frequency; - pdata->sound_framesize=sizeof(jack_default_audio_sample_t)* - pdata->jdata->nports; + int jack_error=0; + pdata->jdata->port_names=pdata->args.jack_port_names; + pdata->jdata->nports=pdata->args.jack_nports; + pdata->jdata->ringbuffer_secs=pdata->args.jack_ringbuffer_secs; + pdata->jdata->snd_buff_ready_mutex=&pdata->snd_buff_ready_mutex; + pdata->jdata->sound_data_read=&pdata->sound_data_read; + pdata->jdata->capture_started=0; + + if ((jack_error=rmdStartJackClient(pdata->jdata))!=0) + return jack_error; + + pdata->args.buffsize=pdata->jdata->buffersize; + pdata->periodsize=pdata->args.buffsize; + pdata->args.frequency=pdata->jdata->frequency; + pdata->args.channels=pdata->jdata->nports; + pdata->periodtime=(1000000*pdata->args.buffsize)/ + pdata->args.frequency; + pdata->sound_framesize=sizeof(jack_default_audio_sample_t)* + pdata->jdata->nports; #else - fprintf(stderr,"Should not be here!\n"); - exit(-1); + fprintf(stderr,"Should not be here!\n"); + exit(-1); #endif - } - } + } + } - if(pdata->args.encOnTheFly) - rmdInitEncoder(pdata,enc_data,0); - else - rmdInitCacheData(pdata,enc_data,cache_data); + if(pdata->args.encOnTheFly) + rmdInitEncoder(pdata, enc_data, 0); + else + rmdInitCacheData(pdata, enc_data, cache_data); - for(i=0;i<(pdata->enc_data->yuv.y_width*pdata->enc_data->yuv.y_height);i++) - pdata->enc_data->yuv.y[i]=0; - for(i=0; - i<(pdata->enc_data->yuv.uv_width*pdata->enc_data->yuv.uv_height); - i++){ - pdata->enc_data->yuv.v[i]=pdata->enc_data->yuv.u[i]=127; - } + for(i=0;i<(pdata->enc_data->yuv.y_width*pdata->enc_data->yuv.y_height);i++) + pdata->enc_data->yuv.y[i]=0; - yblocks=malloc(sizeof(u_int32_t)*(pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH)* - (pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH)); - ublocks=malloc(sizeof(u_int32_t)*(pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH)* - (pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH)); - vblocks=malloc(sizeof(u_int32_t)*(pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH)* - (pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH)); + for(i=0; i<(pdata->enc_data->yuv.uv_width*pdata->enc_data->yuv.uv_height); i++) + pdata->enc_data->yuv.v[i]=pdata->enc_data->yuv.u[i]=127; - pdata->frametime=(1000000)/pdata->args.fps; - return 0; + yblocks=malloc(sizeof(u_int32_t)*(pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH)* + (pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH)); + ublocks=malloc(sizeof(u_int32_t)*(pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH)* + (pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH)); + vblocks=malloc(sizeof(u_int32_t)*(pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH)* + (pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH)); + + pdata->frametime=(1000000)/pdata->args.fps; + return 0; } void rmdSetupDefaultArgs(ProgArgs *args) { - - args->delay = 0; - args->windowid = 0; - args->x = 0; - args->y = 0; - args->width = 0; - args->height = 0; - args->rescue_path = NULL; - args->nosound = 0; - args->full_shots = 0; - args->follow_mouse = 0; - args->encOnTheFly = 0; - args->nowmcheck = 0; - args->overwrite = 0; - args->use_jack = 0; - args->noshared = 0; - args->no_encode = 0; - args->noframe = 0; - args->jack_nports = 0; - args->jack_ringbuffer_secs = 3.0; - args->zerocompression = 1; - args->no_quick_subsample = 1; - args->cursor_color = 1; - args->have_dummy_cursor = 0; - args->xfixes_cursor = 1; - args->fps = 15; - args->channels = 1; - args->frequency = 22050; - args->buffsize = 4096; - args->v_bitrate = 0; - args->v_quality = 63; - args->s_quality = 10; - - if (getenv("DISPLAY") != NULL) { - args->display = (char *) malloc(strlen(getenv("DISPLAY")) + 1); - strcpy(args->display, getenv("DISPLAY")); - } - else { - args->display = NULL; - } - - memset(args->jack_port_names, 0, sizeof(args->jack_port_names)); - - args->device = (char *) malloc(strlen(DEFAULT_AUDIO_DEVICE) + 1); - strcpy(args->device, DEFAULT_AUDIO_DEVICE); - - args->workdir = (char *) malloc(5); - strcpy(args->workdir, "/tmp"); - - args->pause_shortcut = (char *) malloc(15); - strcpy(args->pause_shortcut, "Control+Mod1+p"); - - args->stop_shortcut = (char *) malloc(15); - strcpy(args->stop_shortcut, "Control+Mod1+s"); - - args->filename = (char *) malloc(8); - strcpy(args->filename, "out.ogv"); + args->delay = 0; + args->windowid = 0; + args->x = 0; + args->y = 0; + args->width = 0; + args->height = 0; + args->rescue_path = NULL; + args->nosound = 0; + args->full_shots = 0; + args->follow_mouse = 0; + args->encOnTheFly = 0; + args->nowmcheck = 0; + args->overwrite = 0; + args->use_jack = 0; + args->noshared = 0; + args->no_encode = 0; + args->noframe = 0; + args->jack_nports = 0; + args->jack_ringbuffer_secs = 3.0; + args->zerocompression = 1; + args->no_quick_subsample = 1; + args->cursor_color = 1; + args->have_dummy_cursor = 0; + args->xfixes_cursor = 1; + args->fps = 15; + args->channels = 1; + args->frequency = 22050; + args->buffsize = 4096; + args->v_bitrate = 0; + args->v_quality = 63; + args->s_quality = 10; + + if (getenv("DISPLAY") != NULL) { + args->display = (char *) malloc(strlen(getenv("DISPLAY")) + 1); + strcpy(args->display, getenv("DISPLAY")); + } else { + args->display = NULL; + } + + memset(args->jack_port_names, 0, sizeof(args->jack_port_names)); + + args->device = (char *) malloc(strlen(DEFAULT_AUDIO_DEVICE) + 1); + strcpy(args->device, DEFAULT_AUDIO_DEVICE); + + args->workdir = (char *) malloc(5); + strcpy(args->workdir, "/tmp"); + + args->pause_shortcut = (char *) malloc(15); + strcpy(args->pause_shortcut, "Control+Mod1+p"); + + args->stop_shortcut = (char *) malloc(15); + strcpy(args->stop_shortcut, "Control+Mod1+s"); + + args->filename = (char *) malloc(8); + strcpy(args->filename, "out.ogv"); } -void rmdCleanUp(void){ - - free(yblocks); - free(ublocks); - free(vblocks); - +void rmdCleanUp(void) { + free(yblocks); + free(ublocks); + free(vblocks); } diff --git a/recordmydesktop/src/rmd_jack.c b/recordmydesktop/src/rmd_jack.c index fb7a55e..ada967e 100644 --- a/recordmydesktop/src/rmd_jack.c +++ b/recordmydesktop/src/rmd_jack.c @@ -42,28 +42,28 @@ * \param nframes Number of frames captured * * \param jdata_t Pointer to JackData struct containing port -* and client information +* and client information * * \returns Zero always */ static int rmdJackCapture(jack_nframes_t nframes,void *jdata_t) { - int i=0; - JackData *jdata=(JackData *)jdata_t; + int i=0; + JackData *jdata=(JackData *)jdata_t; - if (!jdata->pdata->running || jdata->pdata->paused || !jdata->capture_started) { - return 0; - } + if (!jdata->pdata->running || jdata->pdata->paused || !jdata->capture_started) + return 0; + + for(i= 0;i<jdata->nports;i++) + jdata->portbuf[i]=jack_port_get_buffer(jdata->ports[i],nframes); - for(i= 0;i<jdata->nports;i++) - jdata->portbuf[i]=jack_port_get_buffer(jdata->ports[i],nframes); //vorbis analysis buffer wants uninterleaved data //so we are simply placing the buffers for every channel //sequentially on the ringbuffer - for(i=0;i<jdata->nports;i++) - (*jack_ringbuffer_write)(jdata->sound_buffer, - (void *)(jdata->portbuf[i]), - nframes* - sizeof(jack_default_audio_sample_t)); + for(i=0;i<jdata->nports;i++) + (*jack_ringbuffer_write)( jdata->sound_buffer, + (void *)(jdata->portbuf[i]), + nframes* + sizeof(jack_default_audio_sample_t)); /*FIXME */ //This is not safe. //cond_var signaling must move away from signal handlers @@ -72,54 +72,55 @@ static int rmdJackCapture(jack_nframes_t nframes,void *jdata_t) { //The callback should write on the pipe and the main thread //should perform a select over the fd's, signaling afterwards the //appropriate cond_var. - pthread_mutex_lock(jdata->snd_buff_ready_mutex); - pthread_cond_signal(jdata->sound_data_read); - pthread_mutex_unlock(jdata->snd_buff_ready_mutex); + pthread_mutex_lock(jdata->snd_buff_ready_mutex); + pthread_cond_signal(jdata->sound_data_read); + pthread_mutex_unlock(jdata->snd_buff_ready_mutex); - return 0; + return 0; } /** * Register and Activate specified ports * * \param jdata_t Pointer to JackData struct containing port -* and client information +* and client information * * \returns 0 on Success, 1 on failure */ static int rmdSetupPorts(JackData *jdata) { - int i=0; - jdata->ports=malloc(sizeof(jack_port_t *)* - jdata->nports); - jdata->portbuf=malloc(sizeof(jack_default_audio_sample_t*)* - jdata->nports); - memset(jdata->portbuf,0,sizeof(jack_default_audio_sample_t*)* - jdata->nports); - - for(i=0;i<jdata->nports;i++){ - char name[64];//recordMyDesktop:input_n<64 is enough for full name - char num[8]; - strcpy(name,"input_"); - snprintf( num, 8, "%d", i+1 ); - strcat(name,num); - if((jdata->ports[i]=jack_port_register(jdata->client, - name, - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsInput, - 0))==0){ - fprintf(stderr,"Cannot register input port \"%s\"!\n",name); - return 1; - } - if(jack_connect(jdata->client, - jdata->port_names[i], - jack_port_name(jdata->ports[i]))){ - fprintf(stderr,"Cannot connect input port %s to %s\n", - jack_port_name(jdata->ports[i]), - jdata->port_names[i]); - return 1; - } - } - return 0; + int i=0; + + jdata->ports=malloc(sizeof(jack_port_t *)* jdata->nports); + jdata->portbuf=malloc(sizeof(jack_default_audio_sample_t*)* jdata->nports); + memset(jdata->portbuf,0,sizeof(jack_default_audio_sample_t*)* jdata->nports); + + for(i=0;i<jdata->nports;i++) { + char name[64];//recordMyDesktop:input_n<64 is enough for full name + char num[8]; + strcpy(name,"input_"); + snprintf( num, 8, "%d", i+1 ); + strcat(name,num); + + jdata->ports[i] = jack_port_register( jdata->client, + name, + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, + 0); + + if (!jdata->ports[i]) { + fprintf(stderr,"Cannot register input port \"%s\"!\n",name); + return 1; + } + + if (jack_connect(jdata->client, jdata->port_names[i], jack_port_name(jdata->ports[i]))) { + + fprintf(stderr,"Cannot connect input port %s to %s\n", + jack_port_name(jdata->ports[i]), + jdata->port_names[i]); + return 1; + } + } + return 0; } //in case the jack server shuts down @@ -127,34 +128,34 @@ static int rmdSetupPorts(JackData *jdata) { //encode the result(if not on the fly) //an exit cleanly. static void rmdJackShutdown(void *jdata_t) { - JackData *jdata = (JackData *)jdata_t; + JackData *jdata = (JackData *)jdata_t; - jdata->pdata->running = FALSE; + jdata->pdata->running = FALSE; - fprintf (stderr, "JACK shutdown\n"); + fprintf (stderr, "JACK shutdown\n"); } -int rmdStartJackClient(JackData *jdata){ - float ring_buffer_size=0.0; - int pid; - char pidbuf[8]; - char rmd_client_name[32]; - - //construct the jack client name - //which is recordMyDesktop-pid - //in order to allow multiple - //instances of recordMyDesktop - //to connetc to a Jack Server - strcpy(rmd_client_name,"recordMyDesktop-"); - pid=getpid(); - snprintf( pidbuf, 8, "%d", pid ); - strcat(rmd_client_name,pidbuf); - - if ((jdata->client=(*jack_client_new)(rmd_client_name))==0){ - fprintf(stderr,"Could not create new client!\n" - "Make sure that Jack server is running!\n"); - return 15; - } +int rmdStartJackClient(JackData *jdata) { + float ring_buffer_size=0.0; + int pid; + char pidbuf[8]; + char rmd_client_name[32]; + + //construct the jack client name + //which is recordMyDesktop-pid + //in order to allow multiple + //instances of recordMyDesktop + //to connetc to a Jack Server + strcpy(rmd_client_name,"recordMyDesktop-"); + pid=getpid(); + snprintf( pidbuf, 8, "%d", pid ); + strcat(rmd_client_name,pidbuf); + + if ((jdata->client=(*jack_client_new)(rmd_client_name))==0) { + fprintf(stderr, "Could not create new client!\n" + "Make sure that Jack server is running!\n"); + return 15; + } //in contrast to ALSA and OSS, Jack dictates frequency //and buffersize to the values it was launched with. //Supposedly jack_set_buffer_size can set the buffersize @@ -168,51 +169,50 @@ int rmdStartJackClient(JackData *jdata){ //(it might be in some cases, but it will certainly be the cause //of unpredicted problems). A clean exit is preferable //and any recording up to that point will be encoded and saved. - jdata->frequency=jack_get_sample_rate(jdata->client); - jdata->buffersize=jack_get_buffer_size(jdata->client); - ring_buffer_size=(jdata->ringbuffer_secs* - jdata->frequency* - sizeof(jack_default_audio_sample_t)* - jdata->nports); - jdata->sound_buffer= - (*jack_ringbuffer_create)((int)(ring_buffer_size+0.5));//round up - jack_set_process_callback(jdata->client,rmdJackCapture,jdata); - jack_on_shutdown(jdata->client,rmdJackShutdown,jdata); - - if (jack_activate(jdata->client)) { - fprintf(stderr,"cannot activate client!\n"); - return 16; - } - if(rmdSetupPorts(jdata)){ - jack_client_close(jdata->client); - return 17; - } - - return 0; + jdata->frequency=jack_get_sample_rate(jdata->client); + jdata->buffersize=jack_get_buffer_size(jdata->client); + ring_buffer_size=( jdata->ringbuffer_secs* + jdata->frequency* + sizeof(jack_default_audio_sample_t)* + jdata->nports); + jdata->sound_buffer= (*jack_ringbuffer_create)((int)(ring_buffer_size+0.5));//round up + jack_set_process_callback(jdata->client,rmdJackCapture,jdata); + jack_on_shutdown(jdata->client,rmdJackShutdown,jdata); + + if (jack_activate(jdata->client)) { + fprintf(stderr,"cannot activate client!\n"); + return 16; + } + + if (rmdSetupPorts(jdata)) { + jack_client_close(jdata->client); + return 17; + } + + return 0; } -int rmdStopJackClient(JackData *jdata){ - int ret=0; +int rmdStopJackClient(JackData *jdata) { + int ret=0; - (*jack_ringbuffer_free)(jdata->sound_buffer); - if(jack_client_close(jdata->client)){ - fprintf(stderr,"Cannot close Jack client!\n"); - ret=1; - } + (*jack_ringbuffer_free)(jdata->sound_buffer); + if (jack_client_close(jdata->client)) { + fprintf(stderr,"Cannot close Jack client!\n"); + ret=1; + } /*TODO*/ //I need to make some kind of program/thread //flow diagram to see where it's safe to dlclose //because here it causes a segfault. -// if(dlclose(jdata->jack_lib_handle)){ -// fprintf(stderr,"Cannot unload Jack library!\n"); -// ret=1; -// } -// else fprintf(stderr,"Unloaded Jack library.\n"); +// if (dlclose(jdata->jack_lib_handle)) { +// fprintf(stderr,"Cannot unload Jack library!\n"); +// ret=1; +// } +// else fprintf(stderr,"Unloaded Jack library.\n"); - return ret; + return ret; } #endif - diff --git a/recordmydesktop/src/rmd_load_cache.c b/recordmydesktop/src/rmd_load_cache.c index e744ce5..089121c 100644 --- a/recordmydesktop/src/rmd_load_cache.c +++ b/recordmydesktop/src/rmd_load_cache.c @@ -48,7 +48,7 @@ //of the widths(specified above), //but the definitions bellow are only //for convenience anyway. -#define Y_UNIT_BYTES 0x0100 +#define Y_UNIT_BYTES 0x0100 #define UV_UNIT_BYTES 0x0040 @@ -56,284 +56,279 @@ //Based on the Header information //we can read the correct amount of bytes. typedef struct _CachedFrame{ - FrameHeader *header; - u_int32_t *YBlocks, //identifying number on the grid, - *UBlocks, //starting at top left - *VBlocks; // >> >> - unsigned char *YData, //pointer to data for the blocks that have changed, - *UData, //which have to be remapped - *VData; //on the buffer when reading + FrameHeader *header; + u_int32_t *YBlocks, //identifying number on the grid, + *UBlocks, //starting at top left + *VBlocks; // >> >> + unsigned char *YData, //pointer to data for the blocks that have changed, + *UData, //which have to be remapped + *VData; //on the buffer when reading }CachedFrame; static void rmdLoadBlock(unsigned char *dest, - unsigned char *source, - int blockno, - int width, - int height, - int blockwidth) { - int j, - block_i=blockno/(width/blockwidth),//place on the grid - block_k=blockno%(width/blockwidth); - for(j=0;j<blockwidth;j++)//we copy rows - memcpy( &dest[(block_i*width+block_k)*blockwidth+j*width], - &source[j*blockwidth], - blockwidth); + unsigned char *source, + int blockno, + int width, + int height, + int blockwidth) { + int j, + block_i=blockno/(width/blockwidth),//place on the grid + block_k=blockno%(width/blockwidth); + + for (j=0;j<blockwidth;j++)//we copy rows + memcpy( &dest[(block_i*width+block_k)*blockwidth+j*width], + &source[j*blockwidth], + blockwidth); } //returns number of bytes static int rmdReadZF(void * buffer, size_t size, size_t nmemb, FILE *ucfp, gzFile *ifp) { - if((ifp!=NULL && ucfp!=NULL)|| - (ifp==NULL && ucfp==NULL)) - return -1; - else if(ucfp!=NULL){ - return (size*fread(buffer,size,nmemb,ucfp)); - } - else - return gzread(ifp,buffer,size*nmemb); + if ((ifp!=NULL && ucfp!=NULL)|| + (ifp==NULL && ucfp==NULL)) + return -1; + else if (ucfp!=NULL) { + return (size*fread(buffer,size,nmemb,ucfp)); + } else + return gzread(ifp,buffer,size*nmemb); } static int rmdReadFrame(CachedFrame *frame, FILE *ucfp, gzFile *ifp) { - int index_entry_size=sizeof(u_int32_t); - if(frame->header->Ynum>0){ - if(rmdReadZF(frame->YBlocks, - index_entry_size, - frame->header->Ynum, - ucfp, - ifp)!=index_entry_size*frame->header->Ynum){ - return -1; - } - } - if(frame->header->Unum>0){ - if(rmdReadZF(frame->UBlocks, - index_entry_size, - frame->header->Unum, - ucfp, - ifp)!=index_entry_size*frame->header->Unum){ - return -1; - } - } - if(frame->header->Vnum>0){ - if(rmdReadZF(frame->VBlocks, - index_entry_size, - frame->header->Vnum, - ucfp, - ifp)!=index_entry_size*frame->header->Vnum){ - return -1; - } - } - if(frame->header->Ynum>0){ - if(rmdReadZF(frame->YData, - Y_UNIT_BYTES, - frame->header->Ynum, - ucfp, - ifp)!=Y_UNIT_BYTES*frame->header->Ynum){ - return -2; - } - } - if(frame->header->Unum>0){ - if(rmdReadZF(frame->UData, - UV_UNIT_BYTES, - frame->header->Unum, - ucfp, - ifp)!=UV_UNIT_BYTES*frame->header->Unum){ - return -2; - } - } - if(frame->header->Vnum>0){ - if(rmdReadZF(frame->VData, - UV_UNIT_BYTES, - frame->header->Vnum, - ucfp, - ifp)!=UV_UNIT_BYTES*frame->header->Vnum){ - return -2; - } - } - return 0; -} + int index_entry_size=sizeof(u_int32_t); + + if (frame->header->Ynum>0) { + if (rmdReadZF( frame->YBlocks, + index_entry_size, + frame->header->Ynum, + ucfp, + ifp)!=index_entry_size*frame->header->Ynum) { + return -1; + } + } + + if (frame->header->Unum>0) { + if (rmdReadZF( frame->UBlocks, + index_entry_size, + frame->header->Unum, + ucfp, + ifp)!=index_entry_size*frame->header->Unum) { + return -1; + } + } + + if (frame->header->Vnum>0) { + if (rmdReadZF( frame->VBlocks, + index_entry_size, + frame->header->Vnum, + ucfp, + ifp)!=index_entry_size*frame->header->Vnum) { + return -1; + } + } -void *rmdLoadCache(ProgData *pdata){ - - yuv_buffer *yuv=&pdata->enc_data->yuv; - gzFile *ifp=NULL; - FILE *ucfp=NULL; - FILE *afp=pdata->cache_data->afp; - FrameHeader fheader; - CachedFrame frame; - int j=0, - nth_cache=1, - audio_end=0, - extra_frames=0,//total number of duplicated frames - missing_frames=0,//if this is found >0 current run will not load - //a frame but it will proccess the previous - thread_exit=0,//0 success, -1 couldn't find files,1 couldn't remove - blocknum_x=pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH, - blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH, - blockszy=Y_UNIT_BYTES,//size of y plane block in bytes - blockszuv=UV_UNIT_BYTES;//size of u,v plane blocks in bytes - signed char *sound_data=(signed char *)malloc(pdata->periodsize* - pdata->sound_framesize); - - u_int32_t YBlocks[(yuv->y_width*yuv->y_height)/Y_UNIT_BYTES], - UBlocks[(yuv->uv_width*yuv->uv_height)/UV_UNIT_BYTES], - VBlocks[(yuv->uv_width*yuv->uv_height)/UV_UNIT_BYTES]; - - // We allocate the frame that we will use - frame.header = &fheader; - frame.YBlocks = YBlocks; - frame.UBlocks = UBlocks; - frame.VBlocks = VBlocks; - frame.YData = malloc(yuv->y_width * yuv->y_height); - frame.UData = malloc(yuv->uv_width * yuv->uv_height); - frame.VData = malloc(yuv->uv_width * yuv->uv_height); - - //and the we open our files - if(!pdata->args.zerocompression){ - ifp=gzopen(pdata->cache_data->imgdata,"rb"); - if(ifp==NULL){ - thread_exit=-1; - pthread_exit(&thread_exit); - } - } - else{ - ucfp=fopen(pdata->cache_data->imgdata,"rb"); - if(ucfp==NULL){ - thread_exit=-1; - pthread_exit(&thread_exit); - } - } - - - if(!pdata->args.nosound){ - afp=fopen(pdata->cache_data->audiodata,"rb"); - if(afp==NULL){ - thread_exit=-1; - pthread_exit(&thread_exit); - } - } - - //this will be used now to define if we proccess audio or video - //on any given loop. - pdata->avd=0; - //If sound finishes first,we go on with the video. - //If video ends we will do one more run to flush audio in the ogg file - while(pdata->running){ - //video load and encoding - if(pdata->avd<=0 || pdata->args.nosound || audio_end){ - if(missing_frames>0){ - extra_frames++; - missing_frames--; - rmdSyncEncodeImageBuffer(pdata); - } - else if(((!pdata->args.zerocompression)&& - (gzread(ifp,frame.header,sizeof(FrameHeader))== - sizeof(FrameHeader) ))|| - ((pdata->args.zerocompression)&& - (fread(frame.header,sizeof(FrameHeader),1,ucfp)==1))){ - //sync - missing_frames+=frame.header->current_total- - (extra_frames+frame.header->frameno); - if (pdata->frames_total) { - fprintf(stdout, - "\r[%d%%] ", - ((frame.header->frameno + extra_frames) * 100) / pdata->frames_total); - } - else - fprintf(stdout,"\r[%d frames rendered] ", - (frame.header->frameno+extra_frames)); - fflush(stdout); - if( (frame.header->Ynum<=blocknum_x*blocknum_y) && - (frame.header->Unum<=blocknum_x*blocknum_y) && - (frame.header->Vnum<=blocknum_x*blocknum_y) && - (!rmdReadFrame(&frame, - ((pdata->args.zerocompression)?ucfp:NULL), - ((pdata->args.zerocompression)?NULL:ifp))) - ){ - //load the blocks for each buffer - if(frame.header->Ynum) - for(j=0;j<frame.header->Ynum;j++) - rmdLoadBlock(yuv->y, - &frame.YData[j*blockszy], - frame.YBlocks[j], - yuv->y_width, - yuv->y_height, - Y_UNIT_WIDTH); - if(frame.header->Unum) - for(j=0;j<frame.header->Unum;j++) - rmdLoadBlock(yuv->u, - &frame.UData[j*blockszuv], - frame.UBlocks[j], - yuv->uv_width, - yuv->uv_height, - UV_UNIT_WIDTH); - if(frame.header->Vnum) - for(j=0;j<frame.header->Vnum;j++) - rmdLoadBlock(yuv->v, - &frame.VData[j*blockszuv], - frame.VBlocks[j], - yuv->uv_width, - yuv->uv_height, - UV_UNIT_WIDTH); - //encode. This is not made in a thread since - //now blocking is not a problem - //and this way sync problems - //can be avoided more easily. - rmdSyncEncodeImageBuffer(pdata); - } - else{ - raise(SIGINT); - continue; - } - } - else{ - if(rmdSwapCacheFilesRead(pdata->cache_data->imgdata, - nth_cache, - &ifp, - &ucfp)){ - raise(SIGINT); - } - else{ - fprintf(stderr,"\t[Cache File %d]",nth_cache); - nth_cache++; - } - continue; - } - } - //audio load and encoding - else{ - if(!audio_end){ - int nbytes=fread(sound_data,1,pdata->periodsize* - pdata->sound_framesize,afp); - if(nbytes<=0) - audio_end=1; - else - rmdSyncEncodeSoundBuffer(pdata,sound_data); - } - } - } - - pdata->v_encoding_clean=pdata->th_encoding_clean=1; - pthread_mutex_lock(&pdata->theora_lib_mutex); - pthread_cond_signal(&pdata->theora_lib_clean); - pthread_mutex_unlock(&pdata->theora_lib_mutex); - pthread_mutex_lock(&pdata->vorbis_lib_mutex); - pthread_cond_signal(&pdata->vorbis_lib_clean); - pthread_mutex_unlock(&pdata->vorbis_lib_mutex); - fprintf(stdout,"\n"); - - // Clear frame - free(frame.YData); - free(frame.UData); - free(frame.VData); - - free(sound_data); - - if(!pdata->args.nosound){ - fclose(afp); - } - - pthread_exit(&thread_exit); + if (frame->header->Ynum>0) { + if (rmdReadZF( frame->YData, + Y_UNIT_BYTES, + frame->header->Ynum, + ucfp, + ifp)!=Y_UNIT_BYTES*frame->header->Ynum) { + return -2; + } + } + if (frame->header->Unum>0) { + if (rmdReadZF( frame->UData, + UV_UNIT_BYTES, + frame->header->Unum, + ucfp, + ifp)!=UV_UNIT_BYTES*frame->header->Unum) { + return -2; + } + } + if (frame->header->Vnum>0) { + if (rmdReadZF( frame->VData, + UV_UNIT_BYTES, + frame->header->Vnum, + ucfp, + ifp)!=UV_UNIT_BYTES*frame->header->Vnum) { + return -2; + } + } + + return 0; } +void *rmdLoadCache(ProgData *pdata) { + + yuv_buffer *yuv=&pdata->enc_data->yuv; + gzFile *ifp=NULL; + FILE *ucfp=NULL; + FILE *afp=pdata->cache_data->afp; + FrameHeader fheader; + CachedFrame frame; + int j=0, nth_cache=1, + audio_end=0, + extra_frames=0,//total number of duplicated frames + missing_frames=0,//if this is found >0 current run will not load + //a frame but it will proccess the previous + thread_exit=0,//0 success, -1 couldn't find files,1 couldn't remove + blocknum_x=pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH, + blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH, + blockszy=Y_UNIT_BYTES,//size of y plane block in bytes + blockszuv=UV_UNIT_BYTES;//size of u,v plane blocks in bytes + signed char *sound_data=(signed char *)malloc(pdata->periodsize* pdata->sound_framesize); + + u_int32_t YBlocks[(yuv->y_width*yuv->y_height)/Y_UNIT_BYTES], + UBlocks[(yuv->uv_width*yuv->uv_height)/UV_UNIT_BYTES], + VBlocks[(yuv->uv_width*yuv->uv_height)/UV_UNIT_BYTES]; + + // We allocate the frame that we will use + frame.header = &fheader; + frame.YBlocks = YBlocks; + frame.UBlocks = UBlocks; + frame.VBlocks = VBlocks; + frame.YData = malloc(yuv->y_width * yuv->y_height); + frame.UData = malloc(yuv->uv_width * yuv->uv_height); + frame.VData = malloc(yuv->uv_width * yuv->uv_height); + + //and the we open our files + if (!pdata->args.zerocompression) { + ifp=gzopen(pdata->cache_data->imgdata,"rb"); + if (ifp==NULL) { + thread_exit=-1; + pthread_exit(&thread_exit); + } + } else { + ucfp=fopen(pdata->cache_data->imgdata,"rb"); + if (ucfp==NULL) { + thread_exit=-1; + pthread_exit(&thread_exit); + } + } + + if (!pdata->args.nosound) { + afp=fopen(pdata->cache_data->audiodata,"rb"); + if (afp==NULL) { + thread_exit=-1; + pthread_exit(&thread_exit); + } + } + + //this will be used now to define if we proccess audio or video + //on any given loop. + pdata->avd=0; + //If sound finishes first,we go on with the video. + //If video ends we will do one more run to flush audio in the ogg file + while (pdata->running) { + //video load and encoding + if (pdata->avd<=0 || pdata->args.nosound || audio_end) { + if (missing_frames>0) { + extra_frames++; + missing_frames--; + rmdSyncEncodeImageBuffer(pdata); + } else if (((!pdata->args.zerocompression)&& + (gzread(ifp,frame.header,sizeof(FrameHeader))== + sizeof(FrameHeader) ))|| + ((pdata->args.zerocompression)&& + (fread(frame.header,sizeof(FrameHeader),1,ucfp)==1))) { + //sync + missing_frames+=frame.header->current_total- + (extra_frames+frame.header->frameno); + if (pdata->frames_total) { + fprintf(stdout, + "\r[%d%%] ", + ((frame.header->frameno + extra_frames) * 100) / pdata->frames_total); + } else + fprintf(stdout,"\r[%d frames rendered] ", + (frame.header->frameno+extra_frames)); + fflush(stdout); + if ( (frame.header->Ynum<=blocknum_x*blocknum_y) && + (frame.header->Unum<=blocknum_x*blocknum_y) && + (frame.header->Vnum<=blocknum_x*blocknum_y) && + (!rmdReadFrame( &frame, + ((pdata->args.zerocompression)?ucfp:NULL), + ((pdata->args.zerocompression)?NULL:ifp))) + ) { + + //load the blocks for each buffer + if (frame.header->Ynum) + for (j=0;j<frame.header->Ynum;j++) + rmdLoadBlock( yuv->y, + &frame.YData[j*blockszy], + frame.YBlocks[j], + yuv->y_width, + yuv->y_height, + Y_UNIT_WIDTH); + if (frame.header->Unum) + for (j=0;j<frame.header->Unum;j++) + rmdLoadBlock( yuv->u, + &frame.UData[j*blockszuv], + frame.UBlocks[j], + yuv->uv_width, + yuv->uv_height, + UV_UNIT_WIDTH); + if (frame.header->Vnum) + for (j=0;j<frame.header->Vnum;j++) + rmdLoadBlock( yuv->v, + &frame.VData[j*blockszuv], + frame.VBlocks[j], + yuv->uv_width, + yuv->uv_height, + UV_UNIT_WIDTH); + + //encode. This is not made in a thread since + //now blocking is not a problem + //and this way sync problems + //can be avoided more easily. + rmdSyncEncodeImageBuffer(pdata); + } else { + raise(SIGINT); + continue; + } + } else { + if (rmdSwapCacheFilesRead( pdata->cache_data->imgdata, + nth_cache, + &ifp, + &ucfp)) { + raise(SIGINT); + } else { + fprintf(stderr,"\t[Cache File %d]",nth_cache); + nth_cache++; + } + continue; + } + //audio load and encoding + } else { + if (!audio_end) { + int nbytes=fread(sound_data,1,pdata->periodsize* + pdata->sound_framesize,afp); + if (nbytes<=0) + audio_end=1; + else + rmdSyncEncodeSoundBuffer(pdata,sound_data); + } + } + } + + pdata->v_encoding_clean=pdata->th_encoding_clean=1; + pthread_mutex_lock(&pdata->theora_lib_mutex); + pthread_cond_signal(&pdata->theora_lib_clean); + pthread_mutex_unlock(&pdata->theora_lib_mutex); + pthread_mutex_lock(&pdata->vorbis_lib_mutex); + pthread_cond_signal(&pdata->vorbis_lib_clean); + pthread_mutex_unlock(&pdata->vorbis_lib_mutex); + fprintf(stdout,"\n"); + + // Clear frame + free(frame.YData); + free(frame.UData); + free(frame.VData); + + free(sound_data); + + if (!pdata->args.nosound) + fclose(afp); + + pthread_exit(&thread_exit); +} diff --git a/recordmydesktop/src/rmd_make_dummy_pointer.c b/recordmydesktop/src/rmd_make_dummy_pointer.c index ef8d164..ba7fb0f 100644 --- a/recordmydesktop/src/rmd_make_dummy_pointer.c +++ b/recordmydesktop/src/rmd_make_dummy_pointer.c @@ -33,62 +33,63 @@ #include <X11/Xlib.h> #include <stdlib.h> -unsigned char *rmdMakeDummyPointer(Display *display, - DisplaySpecs *specs, - int size, - int color, - int type, - unsigned char *npxl){ - unsigned long bpixel = XBlackPixel(display, specs->screen); - unsigned long wpixel = XWhitePixel(display, specs->screen); - int i,k,o='.'; - unsigned long b=(color)?'w':'b', - w=(color)?'b':'w'; - char pmask[1][16][16]={{ - {w,w,o,o,o,o,o,o,o,o,o,o,o,o,o,o}, - {w,b,w,o,o,o,o,o,o,o,o,o,o,o,o,o}, - {w,b,b,w,o,o,o,o,o,o,o,o,o,o,o,o}, - {w,b,b,b,w,o,o,o,o,o,o,o,o,o,o,o}, - {w,b,b,b,b,w,o,o,o,o,o,o,o,o,o,o}, - {w,b,b,b,b,b,w,o,o,o,o,o,o,o,o,o}, - {w,b,b,b,b,b,b,w,o,o,o,o,o,o,o,o}, - {w,b,b,b,b,b,b,b,w,o,o,o,o,o,o,o}, - {w,b,b,b,b,b,b,b,b,w,o,o,o,o,o,o}, - {w,b,b,b,b,b,w,w,w,w,o,o,o,o,o,o}, - {w,b,b,b,b,b,w,o,o,o,o,o,o,o,o,o}, - {w,b,b,w,w,b,b,w,o,o,o,o,o,o,o,o}, - {w,b,w,o,w,b,b,w,o,o,o,o,o,o,o,o}, - {w,w,o,o,o,w,b,b,w,o,o,o,o,o,o,o}, - {o,o,o,o,o,w,b,b,w,o,o,o,o,o,o,o}, - {o,o,o,o,o,o,w,w,o,o,o,o,o,o,o,o}} - }; - unsigned char *ret=malloc(size*sizeof(char[size*4])); - unsigned char wp[4]={ (wpixel ^ 0xff000000) >> 24, - (wpixel ^ 0x00ff0000) >> 16, - (wpixel ^ 0x0000ff00) >> 8, - (wpixel ^ 0x000000ff) }; - unsigned char bp[4]={ (bpixel ^ 0xff000000) >> 24, - (bpixel ^ 0x00ff0000) >> 16, - (bpixel ^ 0x0000ff00) >> 8, - (bpixel ^ 0x000000ff) }; +unsigned char *rmdMakeDummyPointer( Display *display, + DisplaySpecs *specs, + int size, + int color, + int type, + unsigned char *npxl) { - *npxl=((wp[0]-1)!=bp[0])?wp[0]-100:wp[0]-102; - for(i=0;i<size;i++){ - for(k=0;k<size;k++){ - ret[(i*size+k)*4+__ABYTE]=(pmask[type][i][k]=='w')? - wp[0]:(pmask[type][i][k]=='b')? - bp[0]:*npxl; - ret[(i*size+k)*4+__RBYTE]=(pmask[type][i][k]=='w')? - wp[1]:(pmask[type][i][k]=='b')? - bp[1]:*npxl; - ret[(i*size+k)*4+__GBYTE]=(pmask[type][i][k]=='w')? - wp[2]:(pmask[type][i][k]=='b')? - bp[2]:*npxl; - ret[(i*size+k)*4+__BBYTE]=(pmask[type][i][k]=='w')? - wp[3]:(pmask[type][i][k]=='b')? - bp[3]:*npxl; - } - } + unsigned long bpixel = XBlackPixel(display, specs->screen); + unsigned long wpixel = XWhitePixel(display, specs->screen); + int i,k,o='.'; + unsigned long b=(color)?'w':'b', + w=(color)?'b':'w'; + char pmask[1][16][16]={{ + {w,w,o,o,o,o,o,o,o,o,o,o,o,o,o,o}, + {w,b,w,o,o,o,o,o,o,o,o,o,o,o,o,o}, + {w,b,b,w,o,o,o,o,o,o,o,o,o,o,o,o}, + {w,b,b,b,w,o,o,o,o,o,o,o,o,o,o,o}, + {w,b,b,b,b,w,o,o,o,o,o,o,o,o,o,o}, + {w,b,b,b,b,b,w,o,o,o,o,o,o,o,o,o}, + {w,b,b,b,b,b,b,w,o,o,o,o,o,o,o,o}, + {w,b,b,b,b,b,b,b,w,o,o,o,o,o,o,o}, + {w,b,b,b,b,b,b,b,b,w,o,o,o,o,o,o}, + {w,b,b,b,b,b,w,w,w,w,o,o,o,o,o,o}, + {w,b,b,b,b,b,w,o,o,o,o,o,o,o,o,o}, + {w,b,b,w,w,b,b,w,o,o,o,o,o,o,o,o}, + {w,b,w,o,w,b,b,w,o,o,o,o,o,o,o,o}, + {w,w,o,o,o,w,b,b,w,o,o,o,o,o,o,o}, + {o,o,o,o,o,w,b,b,w,o,o,o,o,o,o,o}, + {o,o,o,o,o,o,w,w,o,o,o,o,o,o,o,o}} + }; + unsigned char *ret=malloc(size*sizeof(char[size*4])); + unsigned char wp[4]={ (wpixel ^ 0xff000000) >> 24, + (wpixel ^ 0x00ff0000) >> 16, + (wpixel ^ 0x0000ff00) >> 8, + (wpixel ^ 0x000000ff) }; + unsigned char bp[4]={ (bpixel ^ 0xff000000) >> 24, + (bpixel ^ 0x00ff0000) >> 16, + (bpixel ^ 0x0000ff00) >> 8, + (bpixel ^ 0x000000ff) }; - return ret; + *npxl=((wp[0]-1)!=bp[0])?wp[0]-100:wp[0]-102; + for (i=0;i<size;i++) { + for (k=0;k<size;k++) { + ret[(i*size+k)*4+__ABYTE]=(pmask[type][i][k]=='w')? + wp[0]:(pmask[type][i][k]=='b')? + bp[0]:*npxl; + ret[(i*size+k)*4+__RBYTE]=(pmask[type][i][k]=='w')? + wp[1]:(pmask[type][i][k]=='b')? + bp[1]:*npxl; + ret[(i*size+k)*4+__GBYTE]=(pmask[type][i][k]=='w')? + wp[2]:(pmask[type][i][k]=='b')? + bp[2]:*npxl; + ret[(i*size+k)*4+__BBYTE]=(pmask[type][i][k]=='w')? + wp[3]:(pmask[type][i][k]=='b')? + bp[3]:*npxl; + } + } + + return ret; } diff --git a/recordmydesktop/src/rmd_math.c b/recordmydesktop/src/rmd_math.c index d344c78..5a184e8 100644 --- a/recordmydesktop/src/rmd_math.c +++ b/recordmydesktop/src/rmd_math.c @@ -28,9 +28,6 @@ #include <math.h> -double rmdRoundf(double val){ - - return val < 0.0 ? ceilf( val - 0.5 ) : floorf( val + 0.5 ); - +double rmdRoundf(double val) { + return val < 0.0 ? ceilf( val - 0.5 ) : floorf( val + 0.5 ); } - diff --git a/recordmydesktop/src/rmd_opendev.c b/recordmydesktop/src/rmd_opendev.c index 51783c7..c196c5a 100644 --- a/recordmydesktop/src/rmd_opendev.c +++ b/recordmydesktop/src/rmd_opendev.c @@ -42,135 +42,148 @@ #ifdef HAVE_LIBASOUND -snd_pcm_t *rmdOpenDev(const char *pcm_dev, - unsigned int *channels, - unsigned int *frequency, - snd_pcm_uframes_t *buffsize, - snd_pcm_uframes_t *periodsize, - unsigned int *periodtime, - int *hard_pause){ - - snd_pcm_t *mhandle; - snd_pcm_hw_params_t *hwparams; - unsigned int periods=2; - unsigned int exactrate = *frequency; - - // The compiler might warn us because the expansion starts with - // assert(&hwparams) - snd_pcm_hw_params_alloca(&hwparams); - - if (snd_pcm_open(&mhandle,pcm_dev,SND_PCM_STREAM_CAPTURE,SND_PCM_ASYNC)<0){ - fprintf(stderr, "Couldn't open PCM device %s\n", pcm_dev); - return NULL; - } - else - fprintf(stderr, "Opened PCM device %s\n", pcm_dev); - if (snd_pcm_hw_params_any(mhandle, hwparams)<0){ - fprintf(stderr, "Couldn't configure PCM device.\n"); - return NULL; - } - if (snd_pcm_hw_params_set_access(mhandle, - hwparams, - SND_PCM_ACCESS_RW_INTERLEAVED)<0){ - fprintf(stderr, "Couldn't set access.\n"); - return NULL; - } - if (snd_pcm_hw_params_set_format(mhandle, - hwparams, - SND_PCM_FORMAT_S16_LE)<0){ - fprintf(stderr, "Couldn't set format.\n"); - return NULL; - } - if (snd_pcm_hw_params_set_rate_near(mhandle, hwparams, &exactrate, 0)<0){ - fprintf(stderr, "Couldn't set frequency.\n"); - return NULL; - } - if (*frequency != exactrate){ - fprintf(stderr, "Playback frequency %dHz is not available...\n" - "Using %dHz instead.\n",*frequency,exactrate); - *frequency=exactrate; - } - if (snd_pcm_hw_params_set_channels_near(mhandle, hwparams, channels)<0){ - fprintf(stderr, "Couldn't set channels number.\n"); - return NULL; - } - if(*channels>2){ - fprintf(stderr,"Channels number should be 1(mono) or 2(stereo).\n"); - return NULL; - } - if (snd_pcm_hw_params_set_periods_near(mhandle,hwparams,&periods,0)<0){ - fprintf(stderr, "Couldn't set periods.\n"); - return NULL; - } - - if (snd_pcm_hw_params_set_buffer_size_near(mhandle,hwparams,buffsize)<0){ - fprintf(stderr, "Couldn't set buffer size.\n"); - return NULL; - } - if (snd_pcm_hw_params(mhandle,hwparams)<0){ - fprintf(stderr, "Couldn't set hardware parameters.\n"); - return NULL; - } - if(hard_pause!=NULL) - if(!snd_pcm_hw_params_can_pause(hwparams)){ - *hard_pause=1; - } - if(periodsize!=NULL) - snd_pcm_hw_params_get_period_size(hwparams,periodsize,0); - - if(periodtime!=NULL) - snd_pcm_hw_params_get_period_time(hwparams,periodtime,0); - fprintf(stderr,"Recording on device %s is set to:\n%d channels at %dHz\n", - pcm_dev,*channels,*frequency); - snd_pcm_prepare(mhandle); - - return mhandle; +snd_pcm_t *rmdOpenDev( const char *pcm_dev, + unsigned int *channels, + unsigned int *frequency, + snd_pcm_uframes_t *buffsize, + snd_pcm_uframes_t *periodsize, + unsigned int *periodtime, + int *hard_pause) { + + snd_pcm_t *mhandle; + snd_pcm_hw_params_t *hwparams; + unsigned int periods=2; + unsigned int exactrate = *frequency; + + // The compiler might warn us because the expansion starts with + // assert(&hwparams) + snd_pcm_hw_params_alloca(&hwparams); + + if (snd_pcm_open(&mhandle,pcm_dev,SND_PCM_STREAM_CAPTURE,SND_PCM_ASYNC)<0) { + fprintf(stderr, "Couldn't open PCM device %s\n", pcm_dev); + return NULL; + } else + fprintf(stderr, "Opened PCM device %s\n", pcm_dev); + + if (snd_pcm_hw_params_any(mhandle, hwparams)<0) { + fprintf(stderr, "Couldn't configure PCM device.\n"); + return NULL; + } + + if (snd_pcm_hw_params_set_access(mhandle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)<0) { + fprintf(stderr, "Couldn't set access.\n"); + return NULL; + } + + if (snd_pcm_hw_params_set_format(mhandle, hwparams, SND_PCM_FORMAT_S16_LE)<0) { + fprintf(stderr, "Couldn't set format.\n"); + return NULL; + } + + if (snd_pcm_hw_params_set_rate_near(mhandle, hwparams, &exactrate, 0)<0) { + fprintf(stderr, "Couldn't set frequency.\n"); + return NULL; + } + + if (*frequency != exactrate) { + fprintf(stderr, "Playback frequency %dHz is not available...\n" + "Using %dHz instead.\n", + *frequency, exactrate); + + *frequency=exactrate; + } + + if (snd_pcm_hw_params_set_channels_near(mhandle, hwparams, channels)<0) { + fprintf(stderr, "Couldn't set channels number.\n"); + return NULL; + } + + if (*channels>2) { + fprintf(stderr,"Channels number should be 1(mono) or 2(stereo).\n"); + return NULL; + } + + if (snd_pcm_hw_params_set_periods_near(mhandle,hwparams,&periods,0)<0) { + fprintf(stderr, "Couldn't set periods.\n"); + return NULL; + } + + if (snd_pcm_hw_params_set_buffer_size_near(mhandle,hwparams,buffsize)<0) { + fprintf(stderr, "Couldn't set buffer size.\n"); + return NULL; + } + + if (snd_pcm_hw_params(mhandle,hwparams)<0) { + fprintf(stderr, "Couldn't set hardware parameters.\n"); + return NULL; + } + + if (hard_pause!=NULL) { + if (!snd_pcm_hw_params_can_pause(hwparams)) + *hard_pause=1; + } + + if (periodsize!=NULL) + snd_pcm_hw_params_get_period_size(hwparams,periodsize,0); + + if (periodtime!=NULL) + snd_pcm_hw_params_get_period_time(hwparams,periodtime,0); + + fprintf(stderr, + "Recording on device %s is set to:\n%d channels at %dHz\n", + pcm_dev,*channels,*frequency); + + snd_pcm_prepare(mhandle); + + return mhandle; } #else -int rmdOpenDev(const char *pcm_dev, - unsigned int channels, - unsigned int frequency){ - int fd ; - fd=open(pcm_dev,O_RDONLY); - - if(fd!=-1){ - unsigned int value; - - if(ioctl(fd,SNDCTL_DSP_GETFMTS,&value)<0){ - fprintf(stderr,"Couldn't get audio format list\n"); - return -1; - } - if(value & AFMT_S16_LE){ - value=AFMT_S16_LE; - } - else if(value & AFMT_S16_BE){ - value=AFMT_S16_BE; - } - else{ - fprintf(stderr,"Soundcard doesn't support signed 16-bit-data\n"); - return -1; - } - if(ioctl(fd,SNDCTL_DSP_SETFMT,&value)<0){ - fprintf(stderr,"Couldn't set audio format\n" ); - return -1; - } - value = channels; - if(ioctl(fd,SNDCTL_DSP_CHANNELS,&value)<0){ - fprintf(stderr,"Cannot set the number of channels\n" ); - return -1; - } - value = frequency; - if(ioctl(fd,SNDCTL_DSP_SPEED,&value)<0){ - fprintf(stderr,"Couldn't set audio frequency\n" ); - return -1; - } - if(fcntl(fd,F_SETFL,fcntl(fd,F_GETFL) & ~O_NONBLOCK)<0){ - fprintf(stderr,"Couldn't set audio blocking mode\n" ); - return -1; - } - } - return fd; +int rmdOpenDev(const char *pcm_dev, unsigned int channels, unsigned int frequency) { + int fd ; + unsigned int value; + + fd=open(pcm_dev,O_RDONLY); + if (fd < 0) + return -1; + + if (ioctl(fd,SNDCTL_DSP_GETFMTS,&value)<0) { + fprintf(stderr,"Couldn't get audio format list\n"); + return -1; + } + + if (value & AFMT_S16_LE) { + value=AFMT_S16_LE; + } else if (value & AFMT_S16_BE) { + value=AFMT_S16_BE; + } else { + fprintf(stderr,"Soundcard doesn't support signed 16-bit-data\n"); + return -1; + } + + if (ioctl(fd,SNDCTL_DSP_SETFMT,&value)<0) { + fprintf(stderr,"Couldn't set audio format\n" ); + return -1; + } + + value = channels; + if (ioctl(fd,SNDCTL_DSP_CHANNELS,&value)<0) { + fprintf(stderr,"Cannot set the number of channels\n" ); + return -1; + } + + value = frequency; + if (ioctl(fd,SNDCTL_DSP_SPEED,&value)<0) { + fprintf(stderr,"Couldn't set audio frequency\n" ); + return -1; + } + + if (fcntl(fd,F_SETFL,fcntl(fd,F_GETFL) & ~O_NONBLOCK)<0) { + fprintf(stderr,"Couldn't set audio blocking mode\n" ); + return -1; + } + + return fd; } #endif diff --git a/recordmydesktop/src/rmd_parseargs.c b/recordmydesktop/src/rmd_parseargs.c index e8dcb4b..3ff8d21 100644 --- a/recordmydesktop/src/rmd_parseargs.c +++ b/recordmydesktop/src/rmd_parseargs.c @@ -66,451 +66,446 @@ static boolean rmdValidateArguments(const ProgArgs *args); boolean rmdParseArgs(int argc, char **argv, ProgArgs *arg_return) { - poptContext popt_context = NULL; - boolean no_cursor = FALSE; - boolean quick_subsampling = FALSE; - boolean compress_cache = FALSE; - boolean success = TRUE; - int arg_id = 0; - - // Setup the option tables - struct poptOption generic_options[] = { - { NULL, '\0', - POPT_ARG_CALLBACK, (void *)rmdPrintAndExit, 0, - NULL, NULL }, - - { "help", 'h', - POPT_ARG_NONE, NULL, 0, - "Print this help and exit.", - NULL }, - - { "version", '\0', - POPT_ARG_NONE, NULL, 0, - "Print program version and exit.", - NULL }, - - { "print-config", '\0', - POPT_ARG_NONE, NULL, 0, - "Print info about options selected during compilation and exit.", - NULL }, - - POPT_TABLEEND }; - - struct poptOption image_options[] = { - { "windowid", '\0', - POPT_ARG_INT, &arg_return->windowid, 0, - "id of window to be recorded.", - "id_of_window" }, - - { "display", '\0', - POPT_ARG_STRING, &arg_return->display, 0, - "Display to connect to.", - "DISPLAY" }, - - { "x", 'x', - POPT_ARG_INT, &arg_return->x, 0, - "Offset in x direction.", - "N>=0" }, - - { "x", 'y', - POPT_ARG_INT, &arg_return->y, 0, - "Offset in y direction.", - "N>=0" }, - - { "width", '\0', - POPT_ARG_INT, &arg_return->width, 0, - "Width of recorded window.", - "N>0" }, - - { "height", '\0', - POPT_ARG_INT, &arg_return->height, 0, - "Height of recorded window.", - "N>0" }, - - { "dummy-cursor", '\0', - POPT_ARG_STRING, NULL, RMD_ARG_DUMMY_CURSOR, - "Color of the dummy cursor [black|white]", - "color" }, - - { "no-cursor", '\0', - POPT_ARG_NONE, &no_cursor, 0, - "Disable drawing of the cursor.", - NULL }, - - { "no-shared", '\0', - POPT_ARG_NONE, &arg_return->noshared, 0, - "Disable usage of MIT-shared memory extension(Not Recommended!).", - NULL }, - - { "full-shots", '\0', - POPT_ARG_NONE, &arg_return->full_shots, 0, - "Take full screenshot at every frame(Not recomended!).", - NULL }, - - { "follow-mouse", '\0', - POPT_ARG_NONE, &arg_return->follow_mouse, 0, - "Makes the capture area follow the mouse cursor. Autoenables --full-shots.", - NULL }, - - { "quick-subsampling", '\0', - POPT_ARG_NONE, &quick_subsampling, 0, - "Do subsampling of the chroma planes by discarding, not averaging.", - NULL }, - - { "fps", '\0', - POPT_ARG_FLOAT, &arg_return->fps, 0, - "A positive number denoting desired framerate.", - "N(number>0.0)" }, - - POPT_TABLEEND }; - - struct poptOption sound_options[] = { - { "channels", '\0', - POPT_ARG_INT, &arg_return->channels, 0, - "A positive number denoting desired sound channels in recording.", - "N" }, - - { "freq", '\0', - POPT_ARG_INT, &arg_return->frequency, 0, - "A positive number denoting desired sound frequency.", - "N" }, - - { "buffer-size", '\0', - POPT_ARG_INT, &arg_return->buffsize, 0, - "A positive number denoting the desired sound buffer size (in frames,when using ALSA or OSS)", - "N" }, - - { "ring-buffer-size", '\0', - POPT_ARG_FLOAT, &arg_return->jack_ringbuffer_secs, 0, - "A float number denoting the desired ring buffer size (in seconds,when using JACK only).", - "N" }, - - { "device", '\0', - POPT_ARG_STRING, &arg_return->device, 0, - "Sound device(default " DEFAULT_AUDIO_DEVICE ").", - "SOUND_DEVICE" }, - - { "use-jack", '\0', - POPT_ARG_STRING | RMD_USE_JACK_EXTRA_FLAG, &arg_return->x, RMD_ARG_USE_JACK, - "Record audio from the specified list of space-separated jack ports.", - "port1 port2... portn" }, - - { "no-sound", '\0', - POPT_ARG_NONE, &arg_return->nosound, 0, - "Do not record sound.", - NULL }, - - POPT_TABLEEND }; - - struct poptOption encoding_options[] = { - { "on-the-fly-encoding", '\0', - POPT_ARG_NONE, &arg_return->encOnTheFly, 0, - "Encode the audio-video data, while recording.", - NULL }, - - { "v_quality", '\0', - POPT_ARG_INT, &arg_return->v_quality, 0, - "A number from 0 to 63 for desired encoded video quality(default 63).", - "n" }, - - { "v_bitrate", '\0', - POPT_ARG_INT, &arg_return->v_bitrate, 0, - "A number from 0 to 2000000 for desired encoded video bitrate(default 0).", - "n" }, - - { "s_quality", '\0', - POPT_ARG_INT, &arg_return->s_quality, 0, - "Desired audio quality(-1 to 10).", - "n" }, - - POPT_TABLEEND }; - - struct poptOption misc_options[] = { - { "rescue", '\0', - POPT_ARG_STRING, &arg_return->rescue_path, 0, - "Encode data from a previous, crashed, session.", - "path_to_data" }, - - { "no-encode", '\0', - POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN, &arg_return->no_encode, 0, - "Do not encode any data after recording is complete. This is instead done manually afterwards with --rescue.", - NULL }, - - { "no-wm-check", '\0', - POPT_ARG_NONE, &arg_return->nowmcheck, 0, - "Do not try to detect the window manager(and set options according to it)", - NULL }, - - { "no-frame", '\0', - POPT_ARG_NONE, &arg_return->noframe, 0, - "Don not show the frame that visualizes the recorded area.", - NULL }, - - { "pause-shortcut", '\0', - POPT_ARG_STRING, &arg_return->pause_shortcut, 0, - "Shortcut that will be used for (un)pausing (default Control+Mod1+p).", - "MOD+KEY" }, - - { "stop-shortcut", '\0', - POPT_ARG_STRING, &arg_return->stop_shortcut, 0, - "Shortcut that will be used to stop the recording (default Control+Mod1+s).", - "MOD+KEY" }, - - { "compress-cache", '\0', - POPT_ARG_NONE, &compress_cache, 0, - "Image data are cached with light compression.", - NULL }, - - { "workdir", '\0', - POPT_ARG_STRING, &arg_return->workdir, 0, - "Location where a temporary directory will be created to hold project files(default $HOME).", - "DIR" }, - - { "delay", '\0', - POPT_ARG_STRING, &arg_return->delay, RMD_ARG_DELAY, - "Number of secs(default),minutes or hours before capture starts(number can be float)", - "n[H|h|M|m]" }, - - { "overwrite", '\0', - POPT_ARG_NONE, &arg_return->overwrite, 0, - "If there is already a file with the same name, delete it (default is to add a number postfix to the new one).", - NULL }, - - { "output", 'o', - POPT_ARG_STRING, &arg_return->filename, 0, - "Name of recorded video(default out.ogv).", - "filename" }, - - POPT_TABLEEND }; - - struct poptOption rmd_args[] = { - RMD_OPTION_TABLE("Generic Options", generic_options), - RMD_OPTION_TABLE("Image Options", image_options), - RMD_OPTION_TABLE("Sound Options", sound_options), - RMD_OPTION_TABLE("Encoding Options", encoding_options), - RMD_OPTION_TABLE("Misc Options", misc_options), - POPT_TABLEEND }; - - - // Some trivial setup - popt_context = poptGetContext(NULL, argc, (const char **)argv, rmd_args, 0); - poptSetOtherOptionHelp(popt_context, "[OPTIONS]^filename"); - - - // Parse the arguments - while ((arg_id = poptGetNextOpt(popt_context)) > 0) { - char *arg = poptGetOptArg(popt_context); - - // Most arguments are handled completely by libpopt but we - // handle some by ourself, namely those in this switch case - switch (arg_id) { - case RMD_ARG_DELAY: - { - float num = atof(arg); - - if (num > 0.0) { - int k; - for (k = 0; k < strlen(arg); k++) { - if ((arg[k] == 'M') || (arg[k] == 'm')) { - num *= 60.0; - break; - } - else if ((arg[k] == 'H') || (arg[k] == 'h')) { - num *= 3600.0; - break; - } - } - arg_return->delay = (int) num; - } - else { - fprintf(stderr, - "Argument Usage: --delay n[H|h|M|m]\n" - "where n is a float number\n"); - success = FALSE; - } - } - break; - - case RMD_ARG_DUMMY_CURSOR: - { - if (!strcmp(arg, "white")) - arg_return->cursor_color = 0; - else if (!strcmp(arg, "black")) - arg_return->cursor_color = 1; - else { - fprintf(stderr, - "Argument Usage:\n" - " --dummy-cursor [black|white]\n"); - success = FALSE; - } - arg_return->have_dummy_cursor = TRUE; - arg_return->xfixes_cursor = FALSE; - } - break; - - case RMD_ARG_USE_JACK: - { - arg_return->jack_nports = 0; - - while (arg) { - - arg_return->jack_nports++; - - arg_return->jack_port_names[arg_return->jack_nports - 1] = malloc(strlen(arg) + 1); - strcpy(arg_return->jack_port_names[arg_return->jack_nports - 1], arg); - - arg = poptGetOptArg(popt_context); - } - - if (arg_return->jack_nports > 0) { - arg_return->use_jack = 1; - } - else { - fprintf(stderr, - "Argument Usage: --use-jack port1 port2... portn\n"); - success = FALSE; - } - - if (RMD_USE_JACK_EXTRA_FLAG == POPT_ARGFLAG_DOC_HIDDEN) { - fprintf(stderr, - "Warning, will ignore --use-jack flags, no libjack support in build.\n"); - } - } - - default: - break; - } - } - - if (arg_id == -1) { - // Parsing is complete, perform final adjustments - if (no_cursor) - arg_return->xfixes_cursor = FALSE; - - if (quick_subsampling) - arg_return->no_quick_subsample = FALSE; - - if (compress_cache) - arg_return->zerocompression = FALSE; - - if (arg_return->follow_mouse) - arg_return->full_shots = TRUE; - - if (!arg_return->filename) - arg_return->filename = strdup(poptGetArg(popt_context)); - } - else { - // Parsing error, say what went wrong - const char *str = poptBadOption(popt_context, 0); - - success = FALSE; - - fprintf(stderr, - "Error when parsing `%s': ", str); - - switch (arg_id) { - case POPT_ERROR_NOARG: - fprintf(stderr, "Missing argument\n"); - break; - - case POPT_ERROR_BADNUMBER: - fprintf(stderr, "Bad number\n"); - break; - - default: - fprintf(stderr, "libpopt error: %d\n", arg_id); - break; - } - } - - // Make sure argument ranges are valid - success = success && rmdValidateArguments(arg_return); - - // Clean up - poptFreeContext(popt_context); - - return success; + poptContext popt_context = NULL; + boolean no_cursor = FALSE; + boolean quick_subsampling = FALSE; + boolean compress_cache = FALSE; + boolean success = TRUE; + int arg_id = 0; + + // Setup the option tables + struct poptOption generic_options[] = { + { NULL, '\0', + POPT_ARG_CALLBACK, (void *)rmdPrintAndExit, 0, + NULL, NULL }, + + { "help", 'h', + POPT_ARG_NONE, NULL, 0, + "Print this help and exit.", + NULL }, + + { "version", '\0', + POPT_ARG_NONE, NULL, 0, + "Print program version and exit.", + NULL }, + + { "print-config", '\0', + POPT_ARG_NONE, NULL, 0, + "Print info about options selected during compilation and exit.", + NULL }, + + POPT_TABLEEND }; + + struct poptOption image_options[] = { + { "windowid", '\0', + POPT_ARG_INT, &arg_return->windowid, 0, + "id of window to be recorded.", + "id_of_window" }, + + { "display", '\0', + POPT_ARG_STRING, &arg_return->display, 0, + "Display to connect to.", + "DISPLAY" }, + + { "x", 'x', + POPT_ARG_INT, &arg_return->x, 0, + "Offset in x direction.", + "N>=0" }, + + { "x", 'y', + POPT_ARG_INT, &arg_return->y, 0, + "Offset in y direction.", + "N>=0" }, + + { "width", '\0', + POPT_ARG_INT, &arg_return->width, 0, + "Width of recorded window.", + "N>0" }, + + { "height", '\0', + POPT_ARG_INT, &arg_return->height, 0, + "Height of recorded window.", + "N>0" }, + + { "dummy-cursor", '\0', + POPT_ARG_STRING, NULL, RMD_ARG_DUMMY_CURSOR, + "Color of the dummy cursor [black|white]", + "color" }, + + { "no-cursor", '\0', + POPT_ARG_NONE, &no_cursor, 0, + "Disable drawing of the cursor.", + NULL }, + + { "no-shared", '\0', + POPT_ARG_NONE, &arg_return->noshared, 0, + "Disable usage of MIT-shared memory extension(Not Recommended!).", + NULL }, + + { "full-shots", '\0', + POPT_ARG_NONE, &arg_return->full_shots, 0, + "Take full screenshot at every frame(Not recomended!).", + NULL }, + + { "follow-mouse", '\0', + POPT_ARG_NONE, &arg_return->follow_mouse, 0, + "Makes the capture area follow the mouse cursor. Autoenables --full-shots.", + NULL }, + + { "quick-subsampling", '\0', + POPT_ARG_NONE, &quick_subsampling, 0, + "Do subsampling of the chroma planes by discarding, not averaging.", + NULL }, + + { "fps", '\0', + POPT_ARG_FLOAT, &arg_return->fps, 0, + "A positive number denoting desired framerate.", + "N(number>0.0)" }, + + POPT_TABLEEND }; + + struct poptOption sound_options[] = { + { "channels", '\0', + POPT_ARG_INT, &arg_return->channels, 0, + "A positive number denoting desired sound channels in recording.", + "N" }, + + { "freq", '\0', + POPT_ARG_INT, &arg_return->frequency, 0, + "A positive number denoting desired sound frequency.", + "N" }, + + { "buffer-size", '\0', + POPT_ARG_INT, &arg_return->buffsize, 0, + "A positive number denoting the desired sound buffer size (in frames,when using ALSA or OSS)", + "N" }, + + { "ring-buffer-size", '\0', + POPT_ARG_FLOAT, &arg_return->jack_ringbuffer_secs, 0, + "A float number denoting the desired ring buffer size (in seconds,when using JACK only).", + "N" }, + + { "device", '\0', + POPT_ARG_STRING, &arg_return->device, 0, + "Sound device(default " DEFAULT_AUDIO_DEVICE ").", + "SOUND_DEVICE" }, + + { "use-jack", '\0', + POPT_ARG_STRING | RMD_USE_JACK_EXTRA_FLAG, &arg_return->x, RMD_ARG_USE_JACK, + "Record audio from the specified list of space-separated jack ports.", + "port1 port2... portn" }, + + { "no-sound", '\0', + POPT_ARG_NONE, &arg_return->nosound, 0, + "Do not record sound.", + NULL }, + + POPT_TABLEEND }; + + struct poptOption encoding_options[] = { + { "on-the-fly-encoding", '\0', + POPT_ARG_NONE, &arg_return->encOnTheFly, 0, + "Encode the audio-video data, while recording.", + NULL }, + + { "v_quality", '\0', + POPT_ARG_INT, &arg_return->v_quality, 0, + "A number from 0 to 63 for desired encoded video quality(default 63).", + "n" }, + + { "v_bitrate", '\0', + POPT_ARG_INT, &arg_return->v_bitrate, 0, + "A number from 0 to 2000000 for desired encoded video bitrate(default 0).", + "n" }, + + { "s_quality", '\0', + POPT_ARG_INT, &arg_return->s_quality, 0, + "Desired audio quality(-1 to 10).", + "n" }, + + POPT_TABLEEND }; + + struct poptOption misc_options[] = { + { "rescue", '\0', + POPT_ARG_STRING, &arg_return->rescue_path, 0, + "Encode data from a previous, crashed, session.", + "path_to_data" }, + + { "no-encode", '\0', + POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN, &arg_return->no_encode, 0, + "Do not encode any data after recording is complete. This is instead done manually afterwards with --rescue.", + NULL }, + + { "no-wm-check", '\0', + POPT_ARG_NONE, &arg_return->nowmcheck, 0, + "Do not try to detect the window manager(and set options according to it)", + NULL }, + + { "no-frame", '\0', + POPT_ARG_NONE, &arg_return->noframe, 0, + "Don not show the frame that visualizes the recorded area.", + NULL }, + + { "pause-shortcut", '\0', + POPT_ARG_STRING, &arg_return->pause_shortcut, 0, + "Shortcut that will be used for (un)pausing (default Control+Mod1+p).", + "MOD+KEY" }, + + { "stop-shortcut", '\0', + POPT_ARG_STRING, &arg_return->stop_shortcut, 0, + "Shortcut that will be used to stop the recording (default Control+Mod1+s).", + "MOD+KEY" }, + + { "compress-cache", '\0', + POPT_ARG_NONE, &compress_cache, 0, + "Image data are cached with light compression.", + NULL }, + + { "workdir", '\0', + POPT_ARG_STRING, &arg_return->workdir, 0, + "Location where a temporary directory will be created to hold project files(default $HOME).", + "DIR" }, + + { "delay", '\0', + POPT_ARG_STRING, &arg_return->delay, RMD_ARG_DELAY, + "Number of secs(default),minutes or hours before capture starts(number can be float)", + "n[H|h|M|m]" }, + + { "overwrite", '\0', + POPT_ARG_NONE, &arg_return->overwrite, 0, + "If there is already a file with the same name, delete it (default is to add a number postfix to the new one).", + NULL }, + + { "output", 'o', + POPT_ARG_STRING, &arg_return->filename, 0, + "Name of recorded video(default out.ogv).", + "filename" }, + + POPT_TABLEEND }; + + struct poptOption rmd_args[] = { + RMD_OPTION_TABLE("Generic Options", generic_options), + RMD_OPTION_TABLE("Image Options", image_options), + RMD_OPTION_TABLE("Sound Options", sound_options), + RMD_OPTION_TABLE("Encoding Options", encoding_options), + RMD_OPTION_TABLE("Misc Options", misc_options), + POPT_TABLEEND }; + + + // Some trivial setup + popt_context = poptGetContext(NULL, argc, (const char **)argv, rmd_args, 0); + poptSetOtherOptionHelp(popt_context, "[OPTIONS]^filename"); + + + // Parse the arguments + while ((arg_id = poptGetNextOpt(popt_context)) > 0) { + char *arg = poptGetOptArg(popt_context); + + // Most arguments are handled completely by libpopt but we + // handle some by ourself, namely those in this switch case + switch (arg_id) { + case RMD_ARG_DELAY: + { + float num = atof(arg); + + if (num > 0.0) { + int k; + for (k = 0; k < strlen(arg); k++) { + if ((arg[k] == 'M') || (arg[k] == 'm')) { + num *= 60.0; + break; + } + else if ((arg[k] == 'H') || (arg[k] == 'h')) { + num *= 3600.0; + break; + } + } + arg_return->delay = (int) num; + } else { + fprintf(stderr, + "Argument Usage: --delay n[H|h|M|m]\n" + "where n is a float number\n"); + success = FALSE; + } + } + break; + + case RMD_ARG_DUMMY_CURSOR: + { + if (!strcmp(arg, "white")) + arg_return->cursor_color = 0; + else if (!strcmp(arg, "black")) + arg_return->cursor_color = 1; + else { + fprintf(stderr, + "Argument Usage:\n" + " --dummy-cursor [black|white]\n"); + success = FALSE; + } + arg_return->have_dummy_cursor = TRUE; + arg_return->xfixes_cursor = FALSE; + } + break; + + case RMD_ARG_USE_JACK: + { + arg_return->jack_nports = 0; + + while (arg) { + + arg_return->jack_nports++; + + arg_return->jack_port_names[arg_return->jack_nports - 1] = malloc(strlen(arg) + 1); + strcpy(arg_return->jack_port_names[arg_return->jack_nports - 1], arg); + + arg = poptGetOptArg(popt_context); + } + + if (arg_return->jack_nports > 0) { + arg_return->use_jack = 1; + } else { + fprintf(stderr, + "Argument Usage: --use-jack port1 port2... portn\n"); + success = FALSE; + } + + if (RMD_USE_JACK_EXTRA_FLAG == POPT_ARGFLAG_DOC_HIDDEN) { + fprintf(stderr, + "Warning, will ignore --use-jack flags, no libjack support in build.\n"); + } + } + + default: + break; + } + } + + if (arg_id == -1) { + // Parsing is complete, perform final adjustments + if (no_cursor) + arg_return->xfixes_cursor = FALSE; + + if (quick_subsampling) + arg_return->no_quick_subsample = FALSE; + + if (compress_cache) + arg_return->zerocompression = FALSE; + + if (arg_return->follow_mouse) + arg_return->full_shots = TRUE; + + if (!arg_return->filename) + arg_return->filename = strdup(poptGetArg(popt_context)); + } else { + // Parsing error, say what went wrong + const char *str = poptBadOption(popt_context, 0); + + success = FALSE; + + fprintf(stderr, + "Error when parsing `%s': ", str); + + switch (arg_id) { + case POPT_ERROR_NOARG: + fprintf(stderr, "Missing argument\n"); + break; + + case POPT_ERROR_BADNUMBER: + fprintf(stderr, "Bad number\n"); + break; + + default: + fprintf(stderr, "libpopt error: %d\n", arg_id); + break; + } + } + + // Make sure argument ranges are valid + success = success && rmdValidateArguments(arg_return); + + // Clean up + poptFreeContext(popt_context); + + return success; } static boolean rmdValidateArguments(const ProgArgs *args) { - boolean success = TRUE; - - if (args->x < 0) { - fprintf(stdout, "-x must not be less than 0.\n"); - success = FALSE; - } - if (args->y < 0) { - fprintf(stdout, "-y must not be less than 0.\n"); - success = FALSE; - } - if (args->width < 0) { - fprintf(stdout, "--width must be larger than 0.\n"); - success = FALSE; - } - if (args->height < 0) { - fprintf(stdout, "--height must be larger than 0.\n"); - success = FALSE; - } - if (args->fps <= 0) { - fprintf(stdout, "--fps must be larger than 0.\n"); - success = FALSE; - } - if (args->v_quality < 0 || args->v_quality > 63) { - fprintf(stdout, "--v_quality must be within the inclusive range [0-63].\n"); - success = FALSE; - } - if (args->v_bitrate < 0 || args->v_quality > 2000000) { - fprintf(stdout, "--v_bitrate must be within the inclusive range [0-2000000].\n"); - success = FALSE; - } - if (args->frequency <= 0) { - fprintf(stdout, "--frequency must be larger than 0.\n"); - success = FALSE; - } - if (args->channels <= 0) { - fprintf(stdout, "--channels must be larger than 0.\n"); - success = FALSE; - } - if (args->buffsize <= 0) { - fprintf(stdout, "--buffer-size must be larger than 0.\n"); - success = FALSE; - } - if (args->jack_ringbuffer_secs <= 0) { - fprintf(stdout, "--jack-buffer-size must be larger than 0.\n"); - success = FALSE; - } - - return success; + boolean success = TRUE; + + if (args->x < 0) { + fprintf(stdout, "-x must not be less than 0.\n"); + success = FALSE; + } + if (args->y < 0) { + fprintf(stdout, "-y must not be less than 0.\n"); + success = FALSE; + } + if (args->width < 0) { + fprintf(stdout, "--width must be larger than 0.\n"); + success = FALSE; + } + if (args->height < 0) { + fprintf(stdout, "--height must be larger than 0.\n"); + success = FALSE; + } + if (args->fps <= 0) { + fprintf(stdout, "--fps must be larger than 0.\n"); + success = FALSE; + } + if (args->v_quality < 0 || args->v_quality > 63) { + fprintf(stdout, "--v_quality must be within the inclusive range [0-63].\n"); + success = FALSE; + } + if (args->v_bitrate < 0 || args->v_quality > 2000000) { + fprintf(stdout, "--v_bitrate must be within the inclusive range [0-2000000].\n"); + success = FALSE; + } + if (args->frequency <= 0) { + fprintf(stdout, "--frequency must be larger than 0.\n"); + success = FALSE; + } + if (args->channels <= 0) { + fprintf(stdout, "--channels must be larger than 0.\n"); + success = FALSE; + } + if (args->buffsize <= 0) { + fprintf(stdout, "--buffer-size must be larger than 0.\n"); + success = FALSE; + } + if (args->jack_ringbuffer_secs <= 0) { + fprintf(stdout, "--jack-buffer-size must be larger than 0.\n"); + success = FALSE; + } + + return success; } -static void rmdPrintAndExit(poptContext con, - enum poptCallbackReason reason, - const struct poptOption *opt, - const char *arg, - const void *data) +static void rmdPrintAndExit( poptContext con, + enum poptCallbackReason reason, + const struct poptOption *opt, + const char *arg, + const void *data) { - if (strcmp(opt->longName, "version") == 0) { - fprintf(stderr,"recordMyDesktop v%s\n\n",VERSION); - } - else if (strcmp(opt->longName, "help") == 0) { - poptPrintHelp(con, stdout, 0); - fprintf(stdout, - "\n" - "\tIf no other options are specified, filename can be given without the -o switch.\n" - "\n" - "\n"); - } - else if (strcmp(opt->longName, "print-config") == 0) { - fprintf(stdout, - "\n" - "recordMyDesktop was compiled with the following options:\n" - "\n" - "Jack:\t\t\t" RMD_LIBJACK_STATUS "\n" - "Default Audio Backend:\t" RMD_LIBASOUND_STATUS "\n" - "\n" - "\n"); - } - - exit(0); + if (strcmp(opt->longName, "version") == 0) { + fprintf(stderr,"recordMyDesktop v%s\n\n",VERSION); + } else if (strcmp(opt->longName, "help") == 0) { + poptPrintHelp(con, stdout, 0); + fprintf(stdout, + "\n" + "\tIf no other options are specified, filename can be given without the -o switch.\n" + "\n" + "\n"); + } else if (strcmp(opt->longName, "print-config") == 0) { + fprintf(stdout, + "\n" + "recordMyDesktop was compiled with the following options:\n" + "\n" + "Jack:\t\t\t" RMD_LIBJACK_STATUS "\n" + "Default Audio Backend:\t" RMD_LIBASOUND_STATUS "\n" + "\n" + "\n"); + } + + exit(0); } diff --git a/recordmydesktop/src/rmd_poll_events.c b/recordmydesktop/src/rmd_poll_events.c index db56219..9745889 100644 --- a/recordmydesktop/src/rmd_poll_events.c +++ b/recordmydesktop/src/rmd_poll_events.c @@ -42,10 +42,10 @@ #include <pthread.h> -#define CLIP_EVENT_AREA(e,brwin,xrect){\ - if(((e)->area.x<=(brwin)->rrect.x)&&((e)->area.y<=(brwin)->rrect.y)&&\ +#define CLIP_EVENT_AREA(e,brwin,xrect) {\ + if (((e)->area.x<=(brwin)->rrect.x)&&((e)->area.y<=(brwin)->rrect.y)&&\ ((e)->area.width>=(brwin)->rrect.width)&&\ - ((e)->area.height<(brwin)->rrect.height)){\ + ((e)->area.height<(brwin)->rrect.height)) {\ (xrect)->x=(brwin)->rrect.x;\ (xrect)->y=(brwin)->rrect.y;\ (xrect)->width=(brwin)->rrect.width;\ @@ -74,136 +74,124 @@ (brwin)->rrect.height-(e)->area.y+\ (brwin)->rrect.y:(e)->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;\ }\ } -void rmdInitEventsPolling(ProgData *pdata){ - Window root_return, - parent_return, - *children; - unsigned int i, - nchildren; - - - XSelectInput (pdata->dpy,pdata->specs.root, SubstructureNotifyMask); - - - if(!pdata->args.full_shots){ - XQueryTree (pdata->dpy, - pdata->specs.root, - &root_return, - &parent_return, - &children, - &nchildren); - - for (i = 0; i < nchildren; i++){ - XWindowAttributes attribs; - if (XGetWindowAttributes (pdata->dpy,children[i],&attribs)){ - if(!attribs.override_redirect && - attribs.depth==pdata->specs.depth) - XDamageCreate(pdata->dpy, - children[i], - XDamageReportRawRectangles); - } - } - XFree(children); - XDamageCreate(pdata->dpy, - pdata->specs.root, - XDamageReportRawRectangles); - } - - - +void rmdInitEventsPolling(ProgData *pdata) { + Window root_return, + parent_return, + *children; + unsigned int i, + nchildren; + + XSelectInput (pdata->dpy,pdata->specs.root, SubstructureNotifyMask); + + if (!pdata->args.full_shots) { + XQueryTree ( pdata->dpy, + pdata->specs.root, + &root_return, + &parent_return, + &children, + &nchildren); + + for (i = 0; i < nchildren; i++) { + XWindowAttributes attribs; + if (XGetWindowAttributes (pdata->dpy,children[i],&attribs)) { + if (!attribs.override_redirect && attribs.depth==pdata->specs.depth) + XDamageCreate( pdata->dpy, + children[i], + XDamageReportRawRectangles); + } + } + XFree(children); + XDamageCreate( pdata->dpy, + pdata->specs.root, + XDamageReportRawRectangles); + } } -void rmdEventLoop(ProgData *pdata){ - int inserts=0; - - XEvent event; - - while(XPending(pdata->dpy)){ - XNextEvent(pdata->dpy,&event); - if(event.type == KeyPress){ - XKeyEvent *e=(XKeyEvent *)(&event); - if(e->keycode == pdata->pause_key.key){ - int i=0; - int found=0; - for(i=0;i<pdata->pause_key.modnum;i++){ - if(pdata->pause_key.mask[i]==e->state){ - found=1; - break; - } - } - if(found){ - raise(SIGUSR1); - continue; - } - } - if(e->keycode == pdata->stop_key.key){ - int i=0; - int found=0; - for(i=0;i<pdata->stop_key.modnum;i++){ - if(pdata->stop_key.mask[i]==e->state){ - found=1; - break; - } - } - if(found){ - raise(SIGINT); - continue; - } - } - } - else if(event.type == Expose){ - - if(event.xexpose.count!=0) - continue; - else if(!pdata->args.noframe){ - rmdDrawFrame(pdata->dpy, - pdata->specs.screen, - pdata->shaped_w, - pdata->brwin.rrect.width, - pdata->brwin.rrect.height); - - } - - } - else if(!pdata->args.full_shots){ - if(event.type == MapNotify ){ - XWindowAttributes attribs; - if (!((XMapEvent *)(&event))->override_redirect&& - XGetWindowAttributes(pdata->dpy, - event.xcreatewindow.window, - &attribs)){ - if(!attribs.override_redirect&& - attribs.depth==pdata->specs.depth) - XDamageCreate(pdata->dpy, - event.xcreatewindow.window, - XDamageReportRawRectangles); - } - } - else if(event.type == pdata->damage_event + XDamageNotify ){ - XDamageNotifyEvent *e =(XDamageNotifyEvent *)( &event ); - XRectangle xrect; - CLIP_EVENT_AREA(e,&(pdata->brwin),&xrect); - if((xrect.x>=0)&&(xrect.y>=0)&& - (xrect.width>0)&&(xrect.height>0)){ - - inserts+=rmdRectInsert(&pdata->rect_root,&xrect); - - } - } - } - - } - - +void rmdEventLoop(ProgData *pdata) { + int inserts=0; + + XEvent event; + + while (XPending(pdata->dpy)) { + XNextEvent(pdata->dpy,&event); + if (event.type == KeyPress) { + XKeyEvent *e=(XKeyEvent *)(&event); + if (e->keycode == pdata->pause_key.key) { + int i=0; + int found=0; + for (i=0;i<pdata->pause_key.modnum;i++) { + if (pdata->pause_key.mask[i]==e->state) { + found=1; + break; + } + } + if (found) { + raise(SIGUSR1); + continue; + } + } + if (e->keycode == pdata->stop_key.key) { + int i=0; + int found=0; + for (i=0;i<pdata->stop_key.modnum;i++) { + if (pdata->stop_key.mask[i]==e->state) { + found=1; + break; + } + } + if (found) { + raise(SIGINT); + continue; + } + } + } else if (event.type == Expose) { + + if (event.xexpose.count!=0) + continue; + else if (!pdata->args.noframe) { + rmdDrawFrame( pdata->dpy, + pdata->specs.screen, + pdata->shaped_w, + pdata->brwin.rrect.width, + pdata->brwin.rrect.height); + + } + + } else if (!pdata->args.full_shots) { + if (event.type == MapNotify ) { + XWindowAttributes attribs; + + if (!((XMapEvent *)(&event))->override_redirect&& + XGetWindowAttributes( pdata->dpy, + event.xcreatewindow.window, + &attribs)) { + + if (!attribs.override_redirect&& attribs.depth==pdata->specs.depth) + XDamageCreate( pdata->dpy, + event.xcreatewindow.window, + XDamageReportRawRectangles); + } + } else if (event.type == pdata->damage_event + XDamageNotify ) { + XDamageNotifyEvent *e =(XDamageNotifyEvent *)( &event ); + XRectangle xrect; + CLIP_EVENT_AREA(e,&(pdata->brwin),&xrect); + if ((xrect.x>=0)&&(xrect.y>=0)&& + (xrect.width>0)&&(xrect.height>0)) { + + inserts+=rmdRectInsert(&pdata->rect_root,&xrect); + + } + } + } + + } } - - diff --git a/recordmydesktop/src/rmd_queryextensions.c b/recordmydesktop/src/rmd_queryextensions.c index a7ecab0..087f7d2 100644 --- a/recordmydesktop/src/rmd_queryextensions.c +++ b/recordmydesktop/src/rmd_queryextensions.c @@ -36,49 +36,51 @@ -void rmdQueryExtensions(Display *dpy, - ProgArgs *args, - int *damage_event, - int *damage_error, - int *shm_opcode){ - int xf_event_basep, - xf_error_basep, - shm_event_base, - shm_error_base, - shape_event_base, - shape_error_base; +void rmdQueryExtensions( Display *dpy, + ProgArgs *args, + int *damage_event, + int *damage_error, + int *shm_opcode) { + int xf_event_basep, + xf_error_basep, + shm_event_base, + shm_error_base, + shape_event_base, + shape_error_base; - if((!(args->full_shots))&&(!XDamageQueryExtension( dpy, damage_event, damage_error))){ - fprintf(stderr,"XDamage extension not found!!!\n" - "Try again using the --full-shots option, though\n" - "enabling XDamage is highly recommended,\n" - "for performance reasons.\n"); - exit(4); - } - if((!args->noshared)&&(!XQueryExtension(dpy, - "MIT-SHM", - shm_opcode, - &shm_event_base, - &shm_error_base))){ - args->noshared=1; - fprintf(stderr,"Shared Memory extension not present!\n" - "Try again using the --no-shared option\n"); - exit(5); - } - if((args->xfixes_cursor)&& - (XFixesQueryExtension(dpy,&xf_event_basep,&xf_error_basep)==False)){ - args->xfixes_cursor=0; - fprintf(stderr,"Xfixes extension not present!\n" - "Please run with the -dummy-cursor or" - " --no-cursor option.\n"); - exit(6); - } - if((!args->noframe)&& - (!XShapeQueryExtension(dpy,&shape_event_base,&shape_error_base))){ - fprintf(stderr,"XShape Not Found!!!\n" - "Frame won't be available.\n"); + if ((!(args->full_shots))&&(!XDamageQueryExtension( dpy, damage_event, damage_error))) { + fprintf(stderr, "XDamage extension not found!!!\n" + "Try again using the --full-shots option, though\n" + "enabling XDamage is highly recommended,\n" + "for performance reasons.\n"); + exit(4); + } - args->noframe=1; - } + if ((!args->noshared)&&(!XQueryExtension( dpy, + "MIT-SHM", + shm_opcode, + &shm_event_base, + &shm_error_base))) { + args->noshared=1; + fprintf(stderr,"Shared Memory extension not present!\n" + "Try again using the --no-shared option\n"); + exit(5); + } + if ((args->xfixes_cursor)&& + (XFixesQueryExtension(dpy,&xf_event_basep,&xf_error_basep)==False)) { + args->xfixes_cursor=0; + fprintf(stderr,"Xfixes extension not present!\n" + "Please run with the -dummy-cursor or" + " --no-cursor option.\n"); + exit(6); + } + + if ((!args->noframe)&& + (!XShapeQueryExtension(dpy,&shape_event_base,&shape_error_base))) { + fprintf(stderr,"XShape Not Found!!!\n" + "Frame won't be available.\n"); + + args->noframe=1; + } } diff --git a/recordmydesktop/src/rmd_rectinsert.c b/recordmydesktop/src/rmd_rectinsert.c index 33addea..acb4aae 100644 --- a/recordmydesktop/src/rmd_rectinsert.c +++ b/recordmydesktop/src/rmd_rectinsert.c @@ -57,34 +57,31 @@ * */ static int rmdCollideRects(XRectangle *xrect1, - XRectangle *xrect2, - XRectangle xrect_return[], - int *nrects) { - //1 fits in 2 - if((xrect1->x>=xrect2->x)&& - (xrect1->x+xrect1->width<=xrect2->x+xrect2->width)&& - (xrect1->y>=xrect2->y)&& - (xrect1->y+xrect1->height<=xrect2->y+xrect2->height)){ - *nrects=0; - return 1; - } - //2 fits in 1 - else if((xrect2->x>=xrect1->x)&& - (xrect2->x+xrect2->width<=xrect1->x+xrect1->width)&& - (xrect2->y>=xrect1->y)&& - (xrect2->y+xrect2->height<=xrect1->y+xrect1->height)){ - *nrects=0; - return 2; - } - //no collision - else if((xrect1->x+xrect1->width<xrect2->x)|| - (xrect2->x+xrect2->width<xrect1->x)|| - (xrect1->y+xrect1->height<xrect2->y)|| - (xrect2->y+xrect2->height<xrect1->y)){ - *nrects=0; - return 0; - } - else{ + XRectangle *xrect2, + XRectangle xrect_return[], + int *nrects) { + if ((xrect1->x>=xrect2->x)&& + (xrect1->x+xrect1->width<=xrect2->x+xrect2->width)&& + (xrect1->y>=xrect2->y)&& + (xrect1->y+xrect1->height<=xrect2->y+xrect2->height)) { + //1 fits in 2 + *nrects=0; + return 1; + } else if ((xrect2->x>=xrect1->x)&& + (xrect2->x+xrect2->width<=xrect1->x+xrect1->width)&& + (xrect2->y>=xrect1->y)&& + (xrect2->y+xrect2->height<=xrect1->y+xrect1->height)) { + //2 fits in 1 + *nrects=0; + return 2; + } else if ((xrect1->x+xrect1->width<xrect2->x)|| + (xrect2->x+xrect2->width<xrect1->x)|| + (xrect1->y+xrect1->height<xrect2->y)|| + (xrect2->y+xrect2->height<xrect1->y)) { + //no collision + *nrects=0; + return 0; + } else { //overlapping points are considered enclosed //this happens because libxdamage may generate many events for one change //and some of them may be in the the exact same region @@ -93,438 +90,409 @@ static int rmdCollideRects(XRectangle *xrect1, //function should always start at the next element(which is logical since //if any rect makes it to a points none of it's part collides with previous //nodes on the list, too) - int x1[2]={xrect1->x,xrect1->x+xrect1->width}; - int y1[2]={xrect1->y,xrect1->y+xrect1->height}; - int x2[2]={xrect2->x,xrect2->x+xrect2->width}; - int y2[2]={xrect2->y,xrect2->y+xrect2->height}; - int enclosed[2][4],tot1,tot2; - enclosed[0][0]=(((x1[0]>=x2[0])&&(x1[0]<=x2[1])&& - (y1[0]>=y2[0])&&(y1[0]<=y2[1]))?1:0); - enclosed[0][1]=(((x1[1]>=x2[0])&&(x1[1]<=x2[1])&& - (y1[0]>=y2[0])&&(y1[0]<=y2[1]))?1:0); - enclosed[0][2]=(((x1[0]>=x2[0])&&(x1[0]<=x2[1])&& - (y1[1]>=y2[0])&&(y1[1]<=y2[1]))?1:0); - enclosed[0][3]=(((x1[1]>=x2[0])&&(x1[1]<=x2[1])&& - (y1[1]>=y2[0])&&(y1[1]<=y2[1]))?1:0); - enclosed[1][0]=(((x2[0]>=x1[0])&&(x2[0]<=x1[1])&& - (y2[0]>=y1[0])&&(y2[0]<=y1[1]))?1:0); - enclosed[1][1]=(((x2[1]>=x1[0])&&(x2[1]<=x1[1])&& - (y2[0]>=y1[0])&&(y2[0]<=y1[1]))?1:0); - enclosed[1][2]=(((x2[0]>=x1[0])&&(x2[0]<=x1[1])&& - (y2[1]>=y1[0])&&(y2[1]<=y1[1]))?1:0); - enclosed[1][3]=(((x2[1]>=x1[0])&&(x2[1]<=x1[1])&& - (y2[1]>=y1[0])&&(y2[1]<=y1[1]))?1:0); - tot1=enclosed[0][0]+enclosed[0][1]+enclosed[0][2]+enclosed[0][3]; - tot2=enclosed[1][0]+enclosed[1][1]+enclosed[1][2]+enclosed[1][3]; - if((tot1==2)&&(tot2==2)){//same width or height, which is the best case - //group - if((enclosed[1][0]&&enclosed[1][1])&& - (xrect1->width==xrect2->width)){ - *nrects=1; - xrect_return[0].x = xrect1->x; - xrect_return[0].y = xrect1->y; - xrect_return[0].width = xrect1->width; - xrect_return[0].height = xrect2->height + xrect2->y - xrect1->y; - return -10; - } - else if((enclosed[1][0]&&enclosed[1][2])&& - (xrect1->height==xrect2->height)){ - *nrects=1; - xrect_return[0].x = xrect1->x; - xrect_return[0].y = xrect1->y; - xrect_return[0].width = xrect2->width + xrect2->x - xrect1->x; - xrect_return[0].height = xrect1->height; - return -10; - } - else if((enclosed[1][3]&&enclosed[1][1])&& - (xrect1->height==xrect2->height)){ - *nrects=1; - xrect_return[0].x = xrect2->x; - xrect_return[0].y = xrect2->y; - xrect_return[0].width = xrect1->width + xrect1->x - xrect2->x; - xrect_return[0].height = xrect2->height; - return -10; - } - else if((enclosed[1][3]&&enclosed[1][2])&& - (xrect1->width==xrect2->width)){ - *nrects=1; - xrect_return[0].x = xrect2->x; - xrect_return[0].y = xrect2->y; - xrect_return[0].width = xrect2->width; - xrect_return[0].height = xrect1->height + xrect1->y - xrect2->y; - return -10; - } - //if control reaches here therewasn't a group and we go on - } - if(tot2==2){ - //break rect2 - xrect_return[0].x = xrect2->x; - xrect_return[0].y = xrect2->y; - xrect_return[0].width = xrect2->width; - xrect_return[0].height = xrect2->height; - *nrects=1; - if(enclosed[1][0]&&enclosed[1][1]){ - xrect_return[0].y = y1[1]; - xrect_return[0].height -= y1[1] - y2[0]; - } - else if(enclosed[1][0]&&enclosed[1][2]){ - xrect_return[0].x = x1[1]; - xrect_return[0].width -= x1[1] - x2[0]; - } - else if(enclosed[1][3]&&enclosed[1][1]) - xrect_return[0].width -= x2[1] - x1[0]; - else if(enclosed[1][3]&&enclosed[1][2]) - xrect_return[0].height -= y2[1] - y1[0]; - return -2; - } - else if(tot1==2){ - //if the first one breaks(which is already inserted) - //then we reenter the part that was left and the one - //that was to be inserted - xrect_return[1].x = xrect2->x; - xrect_return[1].y = xrect2->y; - xrect_return[1].width = xrect2->width; - xrect_return[1].height = xrect2->height; - xrect_return[0].x = xrect1->x; - xrect_return[0].y = xrect1->y; - xrect_return[0].width = xrect1->width; - xrect_return[0].height = xrect1->height; - *nrects=1; - if(enclosed[0][0]&&enclosed[0][1]){ - xrect_return[0].y = y2[1]; - xrect_return[0].height -= y2[1] - y1[0]; - } - else if(enclosed[0][0]&&enclosed[0][2]){ - xrect_return[0].x = x2[1]; - xrect_return[0].width -= x2[1] - x1[0]; - } - else if(enclosed[0][3]&&enclosed[0][1]) - xrect_return[0].width -= x1[1] - x2[0]; - else if(enclosed[0][3]&&enclosed[0][2]) - xrect_return[0].height -= y1[1] - y2[0]; - return -1; + int x1[2]={xrect1->x,xrect1->x+xrect1->width}; + int y1[2]={xrect1->y,xrect1->y+xrect1->height}; + int x2[2]={xrect2->x,xrect2->x+xrect2->width}; + int y2[2]={xrect2->y,xrect2->y+xrect2->height}; + int enclosed[2][4],tot1,tot2; + enclosed[0][0]=(((x1[0]>=x2[0])&&(x1[0]<=x2[1])&& + (y1[0]>=y2[0])&&(y1[0]<=y2[1]))?1:0); + enclosed[0][1]=(((x1[1]>=x2[0])&&(x1[1]<=x2[1])&& + (y1[0]>=y2[0])&&(y1[0]<=y2[1]))?1:0); + enclosed[0][2]=(((x1[0]>=x2[0])&&(x1[0]<=x2[1])&& + (y1[1]>=y2[0])&&(y1[1]<=y2[1]))?1:0); + enclosed[0][3]=(((x1[1]>=x2[0])&&(x1[1]<=x2[1])&& + (y1[1]>=y2[0])&&(y1[1]<=y2[1]))?1:0); + enclosed[1][0]=(((x2[0]>=x1[0])&&(x2[0]<=x1[1])&& + (y2[0]>=y1[0])&&(y2[0]<=y1[1]))?1:0); + enclosed[1][1]=(((x2[1]>=x1[0])&&(x2[1]<=x1[1])&& + (y2[0]>=y1[0])&&(y2[0]<=y1[1]))?1:0); + enclosed[1][2]=(((x2[0]>=x1[0])&&(x2[0]<=x1[1])&& + (y2[1]>=y1[0])&&(y2[1]<=y1[1]))?1:0); + enclosed[1][3]=(((x2[1]>=x1[0])&&(x2[1]<=x1[1])&& + (y2[1]>=y1[0])&&(y2[1]<=y1[1]))?1:0); + tot1=enclosed[0][0]+enclosed[0][1]+enclosed[0][2]+enclosed[0][3]; + tot2=enclosed[1][0]+enclosed[1][1]+enclosed[1][2]+enclosed[1][3]; + if ((tot1==2)&&(tot2==2)) {//same width or height, which is the best case + //group + if ((enclosed[1][0]&&enclosed[1][1])&& + (xrect1->width==xrect2->width)) { + *nrects=1; + xrect_return[0].x = xrect1->x; + xrect_return[0].y = xrect1->y; + xrect_return[0].width = xrect1->width; + xrect_return[0].height = xrect2->height + xrect2->y - xrect1->y; + return -10; + } else if ((enclosed[1][0]&&enclosed[1][2])&& + (xrect1->height==xrect2->height)) { + *nrects=1; + xrect_return[0].x = xrect1->x; + xrect_return[0].y = xrect1->y; + xrect_return[0].width = xrect2->width + xrect2->x - xrect1->x; + xrect_return[0].height = xrect1->height; + return -10; + } else if ((enclosed[1][3]&&enclosed[1][1])&& + (xrect1->height==xrect2->height)) { + *nrects=1; + xrect_return[0].x = xrect2->x; + xrect_return[0].y = xrect2->y; + xrect_return[0].width = xrect1->width + xrect1->x - xrect2->x; + xrect_return[0].height = xrect2->height; + return -10; + } else if ((enclosed[1][3]&&enclosed[1][2])&& + (xrect1->width==xrect2->width)) { + *nrects=1; + xrect_return[0].x = xrect2->x; + xrect_return[0].y = xrect2->y; + xrect_return[0].width = xrect2->width; + xrect_return[0].height = xrect1->height + xrect1->y - xrect2->y; + return -10; + } + //if control reaches here therewasn't a group and we go on + } - } - else if(tot2==1){ //in which case there is also tot1==1 - //but we rather not break that - //break rect2 in two - *nrects=2; - if(enclosed[1][0]){ + if (tot2==2) { + //break rect2 + xrect_return[0].x = xrect2->x; + xrect_return[0].y = xrect2->y; + xrect_return[0].width = xrect2->width; + xrect_return[0].height = xrect2->height; + *nrects=1; + if (enclosed[1][0]&&enclosed[1][1]) { + xrect_return[0].y = y1[1]; + xrect_return[0].height -= y1[1] - y2[0]; + } else if (enclosed[1][0]&&enclosed[1][2]) { + xrect_return[0].x = x1[1]; + xrect_return[0].width -= x1[1] - x2[0]; + } else if (enclosed[1][3]&&enclosed[1][1]) + xrect_return[0].width -= x2[1] - x1[0]; + else if (enclosed[1][3]&&enclosed[1][2]) + xrect_return[0].height -= y2[1] - y1[0]; + return -2; + } else if (tot1==2) { + //if the first one breaks(which is already inserted) + //then we reenter the part that was left and the one + //that was to be inserted + xrect_return[1].x = xrect2->x; + xrect_return[1].y = xrect2->y; + xrect_return[1].width = xrect2->width; + xrect_return[1].height = xrect2->height; + xrect_return[0].x = xrect1->x; + xrect_return[0].y = xrect1->y; + xrect_return[0].width = xrect1->width; + xrect_return[0].height = xrect1->height; + *nrects=1; + if (enclosed[0][0]&&enclosed[0][1]) { + xrect_return[0].y = y2[1]; + xrect_return[0].height -= y2[1] - y1[0]; + } else if (enclosed[0][0]&&enclosed[0][2]) { + xrect_return[0].x = x2[1]; + xrect_return[0].width -= x2[1] - x1[0]; + } else if (enclosed[0][3]&&enclosed[0][1]) + xrect_return[0].width -= x1[1] - x2[0]; + else if (enclosed[0][3]&&enclosed[0][2]) + xrect_return[0].height -= y1[1] - y2[0]; + return -1; + + } else if (tot2==1) { //in which case there is also tot1==1 + //but we rather not break that + //break rect2 in two + *nrects=2; + if (enclosed[1][0]) { //first - xrect_return[0].x = x1[1]; - xrect_return[0].y = y2[0]; - xrect_return[0].width = xrect2->width - x1[1] + x2[0]; - xrect_return[0].height = xrect2->height; + xrect_return[0].x = x1[1]; + xrect_return[0].y = y2[0]; + xrect_return[0].width = xrect2->width - x1[1] + x2[0]; + xrect_return[0].height = xrect2->height; //second - xrect_return[1].x = x2[0]; - xrect_return[1].y = y1[1]; - xrect_return[1].width = x1[1] - x2[0]; - xrect_return[1].height = xrect2->height - y1[1] + y2[0]; - } - else if(enclosed[1][1]){ + xrect_return[1].x = x2[0]; + xrect_return[1].y = y1[1]; + xrect_return[1].width = x1[1] - x2[0]; + xrect_return[1].height = xrect2->height - y1[1] + y2[0]; + } else if (enclosed[1][1]) { //first - xrect_return[0].x = x2[0]; - xrect_return[0].y = y2[0]; - xrect_return[0].width = xrect2->width - x2[1] + x1[0]; - xrect_return[0].height = xrect2->height; + xrect_return[0].x = x2[0]; + xrect_return[0].y = y2[0]; + xrect_return[0].width = xrect2->width - x2[1] + x1[0]; + xrect_return[0].height = xrect2->height; //second - xrect_return[1].x = x1[0]; - xrect_return[1].y = y1[1]; - xrect_return[1].width = x2[1] - x1[0]; - xrect_return[1].height = xrect2->height - y1[1] + y2[0]; - } - else if(enclosed[1][2]){ + xrect_return[1].x = x1[0]; + xrect_return[1].y = y1[1]; + xrect_return[1].width = x2[1] - x1[0]; + xrect_return[1].height = xrect2->height - y1[1] + y2[0]; + } else if (enclosed[1][2]) { //first(same as [1][0]) - xrect_return[0].x = x1[1]; - xrect_return[0].y = y2[0]; - xrect_return[0].width = xrect2->width - x1[1] + x2[0]; - xrect_return[0].height = xrect2->height; + xrect_return[0].x = x1[1]; + xrect_return[0].y = y2[0]; + xrect_return[0].width = xrect2->width - x1[1] + x2[0]; + xrect_return[0].height = xrect2->height; //second - xrect_return[1].x = x2[0]; - xrect_return[1].y = y2[0]; - xrect_return[1].width = x1[1] - x2[0]; - xrect_return[1].height = xrect2->height - y2[1] + y1[0]; - } - else if(enclosed[1][3]){ + xrect_return[1].x = x2[0]; + xrect_return[1].y = y2[0]; + xrect_return[1].width = x1[1] - x2[0]; + xrect_return[1].height = xrect2->height - y2[1] + y1[0]; + } else if (enclosed[1][3]) { //first(same as [1][1]) - xrect_return[0].x = x2[0]; - xrect_return[0].y = y2[0]; - xrect_return[0].width = xrect2->width - x2[1] + x1[0]; - xrect_return[0].height = xrect2->height; + xrect_return[0].x = x2[0]; + xrect_return[0].y = y2[0]; + xrect_return[0].width = xrect2->width - x2[1] + x1[0]; + xrect_return[0].height = xrect2->height; //second - xrect_return[1].x = x1[0]; - xrect_return[1].y = y2[0]; - xrect_return[1].width = x2[1] - x1[0]; - xrect_return[1].height = xrect2->height - y2[1] + y1[0]; - } - return -2; - } - else{//polygons collide but no point of one is in the other - //so we just keep the two parts of rect2 that are outside rect1 + xrect_return[1].x = x1[0]; + xrect_return[1].y = y2[0]; + xrect_return[1].width = x2[1] - x1[0]; + xrect_return[1].height = xrect2->height - y2[1] + y1[0]; + } + return -2; + } else {//polygons collide but no point of one is in the other + //so we just keep the two parts of rect2 that are outside rect1 - //break rect2 in two - //two cases: - //rect2 crossing vertically rect1 - //and rect2 crossing horizontally rect1 - //The proper one can be found by simply checking x,y positions - *nrects=2; - if(xrect2->y<xrect1->y){ - //common - xrect_return[0].x = xrect_return[1].x = x2[0]; - xrect_return[0].width = xrect_return[1].width = xrect2->width; + //break rect2 in two + //two cases: + //rect2 crossing vertically rect1 + //and rect2 crossing horizontally rect1 + //The proper one can be found by simply checking x,y positions + *nrects=2; + if (xrect2->y<xrect1->y) { + //common + xrect_return[0].x = xrect_return[1].x = x2[0]; + xrect_return[0].width = xrect_return[1].width = xrect2->width; - xrect_return[0].y = y2[0]; - xrect_return[0].height = xrect2->height - y2[1] + y1[0]; - xrect_return[1].y = y1[1]; - xrect_return[1].height = y2[1] - y1[1]; - } - else{ - //common - xrect_return[0].y = xrect_return[1].y = y2[0]; - xrect_return[0].height = xrect_return[1].height = xrect2->height; + xrect_return[0].y = y2[0]; + xrect_return[0].height = xrect2->height - y2[1] + y1[0]; + xrect_return[1].y = y1[1]; + xrect_return[1].height = y2[1] - y1[1]; + } else { + //common + xrect_return[0].y = xrect_return[1].y = y2[0]; + xrect_return[0].height = xrect_return[1].height = xrect2->height; - xrect_return[0].x = x2[0]; - xrect_return[0].width = xrect2->width - x2[1] + x1[0]; - xrect_return[1].x = x1[1]; - xrect_return[1].width = x2[1] - x1[1]; - } - return -2; - } - } + xrect_return[0].x = x2[0]; + xrect_return[0].width = xrect2->width - x2[1] + x1[0]; + xrect_return[1].x = x1[1]; + xrect_return[1].width = x2[1] - x1[1]; + } + return -2; + } + } } -int rmdRectInsert(RectArea **root,XRectangle *xrect){ +int rmdRectInsert(RectArea **root,XRectangle *xrect) { - int total_insertions=0; - RectArea *temp=NULL,*newnode=(RectArea *)malloc(sizeof(RectArea)); - //align - //we do need to know boundaries - xrect->width+=(xrect->width%2)|(xrect->x%2); - xrect->height+=(xrect->height%2)|(xrect->y%2); - xrect->width+=(xrect->width%2); - xrect->height+=(xrect->height%2); - xrect->x-=xrect->x%2; - xrect->y-=xrect->y%2; -// fprintf(stderr," %d %d %d %d\n",xrect->x, + int total_insertions=0; + RectArea *temp=NULL,*newnode=(RectArea *)malloc(sizeof(RectArea)); + //align + //we do need to know boundaries + xrect->width+=(xrect->width%2)|(xrect->x%2); + xrect->height+=(xrect->height%2)|(xrect->y%2); + xrect->width+=(xrect->width%2); + xrect->height+=(xrect->height%2); + xrect->x-=xrect->x%2; + xrect->y-=xrect->y%2; +// fprintf(stderr," %d %d %d %d\n",xrect->x, - newnode->rect.x=xrect->x; - newnode->rect.y=xrect->y; - newnode->rect.width=xrect->width; - newnode->rect.height=xrect->height; - newnode->prev=newnode->next=NULL; - if(*root==NULL){ - *root=newnode; - total_insertions=1; - } - else{ - XRectangle xrect_return[2]; + newnode->rect.x=xrect->x; + newnode->rect.y=xrect->y; + newnode->rect.width=xrect->width; + newnode->rect.height=xrect->height; + newnode->prev=newnode->next=NULL; + if (*root==NULL) { + *root=newnode; + total_insertions=1; + } else { + XRectangle xrect_return[2]; - int nrects=0,insert_ok=1,i=0; - temp=*root; - while(insert_ok){ //if something is broken list does not procceed - //(except on -1 collres case) - int collres = rmdCollideRects(&temp->rect, xrect, &xrect_return[0], &nrects); - if((!collres)) - insert_ok=1; - else{ - for(i=0;i<nrects;i++){ - xrect_return[i].width += (xrect_return[i].width % 2) | - (xrect_return[i].x % 2); - xrect_return[i].height += (xrect_return[i].height % 2) | - (xrect_return[i].y % 2); - xrect_return[i].width += (xrect_return[i].width % 2); - xrect_return[i].height += (xrect_return[i].height % 2); - xrect_return[i].x -= xrect_return[i].x % 2; - xrect_return[i].y -= xrect_return[i].y % 2; - } - insert_ok=0; - switch(collres){ - case 1://remove current node,reinsert new one - total_insertions--; - if(temp->prev!=NULL){//no root - if(temp->next!=NULL){// - RectArea *temp1=temp->next; - temp->prev->next=temp->next; - temp->next->prev=temp->prev; - free(temp); - if((xrect->width>0)&&(xrect->height>0)) - total_insertions+=rmdRectInsert(&temp1,xrect); - } - else{ - temp->prev->next=newnode; - newnode->prev=temp->prev; - total_insertions++; - free(temp); - } - } - else{//root - if((*root)->next!=NULL){ - (*root)=(*root)->next; - (*root)->prev=NULL; - if((xrect->width>0)&&(xrect->height>0)) - total_insertions+=rmdRectInsert(root,xrect); - } - else if((xrect->width>0)&&(xrect->height>0)){ - *root=newnode; - total_insertions++; - } - else{ - *root=NULL; - total_insertions++; - } - free(temp); - } - break; - case 2://done,area is already covered - free(newnode); - break; - case -1://current node is broken and reinserted - //(in same pos) - //newnode is also reinserted - if (xrect_return[0].width > 0 && - xrect_return[0].height > 0) { - temp->rect.x = xrect_return[0].x; - temp->rect.y = xrect_return[0].y; - temp->rect.width = xrect_return[0].width; - temp->rect.height = xrect_return[0].height; - if(temp->next==NULL){ - temp->next=newnode; - newnode->prev=temp; - total_insertions++; - } - else{ - insert_ok=1; - } - } - else{//it might happen that the old and now broken node - //is of zero width or height - //(so it isn't reinserted) - if((temp->prev==NULL)&&(temp->next!=NULL)){ - *root=(*root)->next; - (*root)->prev=NULL; - } - else if((temp->next==NULL)&&(temp->prev!=NULL)){ - temp->prev->next=newnode; - newnode->prev=temp->prev; - } - else if((temp->next==NULL)&&(temp->prev==NULL)) - (*root)=newnode; - else{ - total_insertions--; - temp->next->prev=temp->prev; - temp->prev->next=temp->next; - total_insertions+=rmdRectInsert(&temp->next, - xrect); - } - free(temp); - } - break; - case -2://new is broken and reinserted - if(temp->next==NULL){ - total_insertions+=nrects; - newnode->rect.x = xrect_return[0].x; - newnode->rect.y = xrect_return[0].y; - newnode->rect.width = xrect_return[0].width; - newnode->rect.height = xrect_return[0].height; - temp->next=newnode; - newnode->prev=temp; - if(nrects>1){ - RectArea *newnode1= - (RectArea *)malloc(sizeof(RectArea)); + int nrects=0,insert_ok=1,i=0; + temp=*root; + while (insert_ok) { //if something is broken list does not procceed + //(except on -1 collres case) + int collres = rmdCollideRects(&temp->rect, xrect, &xrect_return[0], &nrects); + if ((!collres)) + insert_ok=1; + else { + for(i=0;i<nrects;i++) { + xrect_return[i].width += (xrect_return[i].width % 2) | + (xrect_return[i].x % 2); + xrect_return[i].height += (xrect_return[i].height % 2) | + (xrect_return[i].y % 2); + xrect_return[i].width += (xrect_return[i].width % 2); + xrect_return[i].height += (xrect_return[i].height % 2); + xrect_return[i].x -= xrect_return[i].x % 2; + xrect_return[i].y -= xrect_return[i].y % 2; + } + insert_ok=0; + switch (collres) { + case 1://remove current node,reinsert new one + total_insertions--; + if (temp->prev!=NULL) {//no root + if (temp->next!=NULL) {// + RectArea *temp1=temp->next; + temp->prev->next=temp->next; + temp->next->prev=temp->prev; + free(temp); + if ((xrect->width>0)&&(xrect->height>0)) + total_insertions+=rmdRectInsert(&temp1,xrect); + } else { + temp->prev->next=newnode; + newnode->prev=temp->prev; + total_insertions++; + free(temp); + } + } else {//root + if ((*root)->next!=NULL) { + (*root)=(*root)->next; + (*root)->prev=NULL; + if ((xrect->width>0)&&(xrect->height>0)) + total_insertions+=rmdRectInsert(root,xrect); + } else if ((xrect->width>0)&&(xrect->height>0)) { + *root=newnode; + total_insertions++; + } else { + *root=NULL; + total_insertions++; + } + free(temp); + } + break; + case 2://done,area is already covered + free(newnode); + break; + case -1://current node is broken and reinserted + //(in same pos) + //newnode is also reinserted + if (xrect_return[0].width > 0 && + xrect_return[0].height > 0) { + temp->rect.x = xrect_return[0].x; + temp->rect.y = xrect_return[0].y; + temp->rect.width = xrect_return[0].width; + temp->rect.height = xrect_return[0].height; + if (temp->next==NULL) { + temp->next=newnode; + newnode->prev=temp; + total_insertions++; + } else { + insert_ok=1; + } + } else {//it might happen that the old and now broken node + //is of zero width or height + //(so it isn't reinserted) + if ((temp->prev==NULL)&&(temp->next!=NULL)) { + *root=(*root)->next; + (*root)->prev=NULL; + } else if ((temp->next==NULL)&&(temp->prev!=NULL)) { + temp->prev->next=newnode; + newnode->prev=temp->prev; + } else if ((temp->next==NULL)&&(temp->prev==NULL)) + (*root)=newnode; else { + total_insertions--; + temp->next->prev=temp->prev; + temp->prev->next=temp->next; + total_insertions+=rmdRectInsert(&temp->next, + xrect); + } + free(temp); + } + break; + case -2://new is broken and reinserted + if (temp->next==NULL) { + total_insertions+=nrects; + newnode->rect.x = xrect_return[0].x; + newnode->rect.y = xrect_return[0].y; + newnode->rect.width = xrect_return[0].width; + newnode->rect.height = xrect_return[0].height; + temp->next=newnode; + newnode->prev=temp; + if (nrects>1) { + RectArea *newnode1= + (RectArea *)malloc(sizeof(RectArea)); - newnode1->rect.x = xrect_return[1].x; - newnode1->rect.y = xrect_return[1].y; - newnode1->rect.width = xrect_return[1].width; - newnode1->rect.height = xrect_return[1].height; - newnode->next=newnode1; - newnode1->prev=newnode; - newnode1->next=NULL; - } - } - else{ - for(i=0;i<nrects;i++){ - if(xrect_return[i].width > 0 && - xrect_return[i].height > 0) - total_insertions+= - rmdRectInsert(&temp->next, &xrect_return[i]); - } - } - break; - case -10://grouped - if(temp->prev==NULL){ - if(temp->next==NULL){//empty list - newnode->rect.x = xrect_return[0].x; - newnode->rect.y = xrect_return[0].y; - newnode->rect.width = xrect_return[0].width; - newnode->rect.height = xrect_return[0].height; + newnode1->rect.x = xrect_return[1].x; + newnode1->rect.y = xrect_return[1].y; + newnode1->rect.width = xrect_return[1].width; + newnode1->rect.height = xrect_return[1].height; + newnode->next=newnode1; + newnode1->prev=newnode; + newnode1->next=NULL; + } + } else { + for(i=0;i<nrects;i++) { + if (xrect_return[i].width > 0 && + xrect_return[i].height > 0) + total_insertions+= + rmdRectInsert(&temp->next, &xrect_return[i]); + } + } + break; + case -10://grouped + if (temp->prev==NULL) { + if (temp->next==NULL) {//empty list + newnode->rect.x = xrect_return[0].x; + newnode->rect.y = xrect_return[0].y; + newnode->rect.width = xrect_return[0].width; + newnode->rect.height = xrect_return[0].height; - *root=newnode; - free(temp); - } - else{ - total_insertions--; - *root=temp->next; - (*root)->prev=NULL; - free(temp); - if(xrect_return[0].width > 0 && - xrect_return[0].height > 0) - total_insertions+= - rmdRectInsert(root, &xrect_return[0]); - } - } - else if(temp->next==NULL){//last, enter anyway - newnode->rect.x = xrect_return[0].x; - newnode->rect.y = xrect_return[0].y; - newnode->rect.width = xrect_return[0].width; - newnode->rect.height = xrect_return[0].height; - temp->prev->next=newnode; - newnode->prev=temp->prev; - free(temp); - } - else{//remove node and reinsert, starting where we were - total_insertions--; - RectArea *temp1=temp->next; - temp->prev->next=temp->next; - temp->next->prev=temp->prev; - free(temp); - if(xrect_return[0].width > 0 && - xrect_return[0].height > 0) - total_insertions+= - rmdRectInsert(&temp1, &xrect_return[0]); - } - break; - } - } - if(insert_ok){ - if(temp->next==NULL){ - temp->next=newnode; - newnode->prev=temp; - total_insertions++; - break; - } - else{ - temp=temp->next; - } - } - else{ - break; - } - }; - } - return total_insertions; + *root=newnode; + free(temp); + } else { + total_insertions--; + *root=temp->next; + (*root)->prev=NULL; + free(temp); + if (xrect_return[0].width > 0 && + xrect_return[0].height > 0) + total_insertions+= + rmdRectInsert(root, &xrect_return[0]); + } + } else if (temp->next==NULL) {//last, enter anyway + newnode->rect.x = xrect_return[0].x; + newnode->rect.y = xrect_return[0].y; + newnode->rect.width = xrect_return[0].width; + newnode->rect.height = xrect_return[0].height; + temp->prev->next=newnode; + newnode->prev=temp->prev; + free(temp); + } else {//remove node and reinsert, starting where we were + total_insertions--; + RectArea *temp1=temp->next; + temp->prev->next=temp->next; + temp->next->prev=temp->prev; + free(temp); + if (xrect_return[0].width > 0 && + xrect_return[0].height > 0) + total_insertions+= + rmdRectInsert(&temp1, &xrect_return[0]); + } + break; + } + } + if (insert_ok) { + if (temp->next==NULL) { + temp->next=newnode; + newnode->prev=temp; + total_insertions++; + break; + } else { + temp=temp->next; + } + } else { + break; + } + }; + } + return total_insertions; } -void rmdClearList(RectArea **root){ +void rmdClearList(RectArea **root) { - RectArea *temp; - temp=*root; - if(temp!=NULL){ - while(temp->next!=NULL){ - temp=temp->next; - free(temp->prev); + RectArea *temp; + temp=*root; + if (temp!=NULL) { + while (temp->next!=NULL) { + temp=temp->next; + free(temp->prev); - } - free(temp); - *root=NULL; - } + } + free(temp); + *root=NULL; + } } diff --git a/recordmydesktop/src/rmd_register_callbacks.c b/recordmydesktop/src/rmd_register_callbacks.c index 844fece..241f160 100644 --- a/recordmydesktop/src/rmd_register_callbacks.c +++ b/recordmydesktop/src/rmd_register_callbacks.c @@ -34,53 +34,53 @@ // There seem to be no way of passing user data to the signal handler, // so hack around not being able to pass ProgData to them -static int *pdata_running = NULL; -static int *pdata_paused = NULL; -static int *pdata_aborted = NULL; +static int *pdata_running = NULL; +static int *pdata_paused = NULL; +static int *pdata_aborted = NULL; static int *pdata_pause_state_changed = NULL; static void rmdSetPaused(int signum) { - *pdata_pause_state_changed = TRUE; + *pdata_pause_state_changed = TRUE; } static void rmdSetRunning(int signum) { - if (!*pdata_paused) { + if (!*pdata_paused) { - *pdata_running = FALSE; + *pdata_running = FALSE; - if (signum == SIGABRT) { - *pdata_aborted = TRUE; - } - } + if (signum == SIGABRT) { + *pdata_aborted = TRUE; + } + } } void rmdRegisterCallbacks(ProgData *pdata) { - struct sigaction pause_act; - struct sigaction end_act; - - // Is there some way to pass pdata to the signal handlers? - pdata_running = &pdata->running; - pdata_paused = &pdata->paused; - pdata_aborted = &pdata->aborted; - pdata_pause_state_changed = &pdata->pause_state_changed; - - // Setup pause_act - sigfillset(&pause_act.sa_mask); - pause_act.sa_flags = SA_RESTART; - pause_act.sa_handler = rmdSetPaused; - - sigaction(SIGUSR1, &pause_act, NULL); - - // Setup end_act - sigfillset(&end_act.sa_mask); - end_act.sa_flags = SA_RESTART; - end_act.sa_handler = rmdSetRunning; - - sigaction(SIGINT, &end_act, NULL); - sigaction(SIGTERM, &end_act, NULL); - sigaction(SIGABRT, &end_act, NULL); + struct sigaction pause_act; + struct sigaction end_act; + + // Is there some way to pass pdata to the signal handlers? + pdata_running = &pdata->running; + pdata_paused = &pdata->paused; + pdata_aborted = &pdata->aborted; + pdata_pause_state_changed = &pdata->pause_state_changed; + + // Setup pause_act + sigfillset(&pause_act.sa_mask); + pause_act.sa_flags = SA_RESTART; + pause_act.sa_handler = rmdSetPaused; + + sigaction(SIGUSR1, &pause_act, NULL); + + // Setup end_act + sigfillset(&end_act.sa_mask); + end_act.sa_flags = SA_RESTART; + end_act.sa_handler = rmdSetRunning; + + sigaction(SIGINT, &end_act, NULL); + sigaction(SIGTERM, &end_act, NULL); + sigaction(SIGABRT, &end_act, NULL); } diff --git a/recordmydesktop/src/rmd_rescue.c b/recordmydesktop/src/rmd_rescue.c index 8b823a7..ec3130e 100644 --- a/recordmydesktop/src/rmd_rescue.c +++ b/recordmydesktop/src/rmd_rescue.c @@ -40,114 +40,93 @@ #include <stdlib.h> -int rmdRescue(const char *path){ - - int i=0, - offset_x, - offset_y; - - unsigned short width, - height; - - ProgData pdata; - EncData enc_data; - CacheData cache_data; - - rmdSetupDefaultArgs(&pdata.args); - - pdata.enc_data=&enc_data; - pdata.cache_data=&cache_data; - - //projname - cache_data.projname=malloc(strlen(path)+2); - strcpy(cache_data.projname,path); - strcat(cache_data.projname,"/");//having two of these doesn't hurt... - //image data - cache_data.imgdata=malloc(strlen(cache_data.projname)+11); - strcpy(cache_data.imgdata,cache_data.projname); - strcat(cache_data.imgdata,"img.out"); - //audio data - cache_data.audiodata=malloc(strlen(cache_data.projname)+10); - strcpy(cache_data.audiodata,cache_data.projname); - strcat(cache_data.audiodata,"audio.pcm"); - //specsfile - cache_data.specsfile=malloc(strlen(cache_data.projname)+10); - strcpy(cache_data.specsfile,cache_data.projname); - strcat(cache_data.specsfile,"specs.txt"); - - - if(rmdReadSpecsFile(&pdata)) - return 1; - - - width=((pdata.brwin.rrect.width + 15) >>4)<<4; - height=((pdata.brwin.rrect.height + 15) >>4)<<4; - offset_x=((width-pdata.brwin.rrect.width)/2)&~1; - offset_y=((height-pdata.brwin.rrect.height)/2)&~1; - - - enc_data.yuv.y=(unsigned char *)malloc(height*width); - enc_data.yuv.u=(unsigned char *)malloc(height*width/4); - enc_data.yuv.v=(unsigned char *)malloc(height*width/4); - enc_data.yuv.y_width=width; - enc_data.yuv.y_height=height; - enc_data.yuv.y_stride=width; - - enc_data.yuv.uv_width=width/2; - enc_data.yuv.uv_height=height/2; - enc_data.yuv.uv_stride=width/2; - enc_data.x_offset=offset_x; - enc_data.y_offset=offset_y; - - for(i=0;i<(enc_data.yuv.y_width*enc_data.yuv.y_height);i++) - enc_data.yuv.y[i]=0; - for(i=0;i<(enc_data.yuv.uv_width*enc_data.yuv.uv_height);i++){ - enc_data.yuv.v[i]=enc_data.yuv.u[i]=127; - } - - yblocks=malloc(sizeof(u_int32_t)*(enc_data.yuv.y_width/Y_UNIT_WIDTH)* - (enc_data.yuv.y_height/Y_UNIT_WIDTH)); - ublocks=malloc(sizeof(u_int32_t)*(enc_data.yuv.y_width/Y_UNIT_WIDTH)* - (enc_data.yuv.y_height/Y_UNIT_WIDTH)); - vblocks=malloc(sizeof(u_int32_t)*(enc_data.yuv.y_width/Y_UNIT_WIDTH)* - (enc_data.yuv.y_height/Y_UNIT_WIDTH)); - - pdata.frametime=(1000000)/pdata.args.fps; - - pthread_mutex_init(&pdata.theora_lib_mutex,NULL); - pthread_mutex_init(&pdata.vorbis_lib_mutex,NULL); - pthread_mutex_init(&pdata.libogg_mutex,NULL); - pthread_cond_init(&pdata.theora_lib_clean,NULL); - pthread_cond_init(&pdata.vorbis_lib_clean,NULL); - pdata.th_encoding_clean=pdata.v_encoding_clean=1; - pdata.avd=0; - pdata.sound_buffer=NULL; - pdata.running = TRUE; - pdata.aborted = FALSE; - - rmdRegisterCallbacks(&pdata); - fprintf(stderr,"Restoring %s!!!\n",path); - - rmdEncodeCache(&pdata); - - fprintf(stderr,"Done!!!\n"); - fprintf(stderr,"Goodbye!\n"); - rmdCleanUp(); - - return 0; +int rmdRescue(const char *path) { + + int i=0, offset_x, offset_y; + unsigned short width, height; + + ProgData pdata; + EncData enc_data; + CacheData cache_data; + + rmdSetupDefaultArgs(&pdata.args); + + pdata.enc_data=&enc_data; + pdata.cache_data=&cache_data; + + //projname + cache_data.projname=malloc(strlen(path)+2); + strcpy(cache_data.projname,path); + strcat(cache_data.projname,"/");//having two of these doesn't hurt... + //image data + cache_data.imgdata=malloc(strlen(cache_data.projname)+11); + strcpy(cache_data.imgdata,cache_data.projname); + strcat(cache_data.imgdata,"img.out"); + //audio data + cache_data.audiodata=malloc(strlen(cache_data.projname)+10); + strcpy(cache_data.audiodata,cache_data.projname); + strcat(cache_data.audiodata,"audio.pcm"); + //specsfile + cache_data.specsfile=malloc(strlen(cache_data.projname)+10); + strcpy(cache_data.specsfile,cache_data.projname); + strcat(cache_data.specsfile,"specs.txt"); + + + if (rmdReadSpecsFile(&pdata)) + return 1; + + width=((pdata.brwin.rrect.width + 15) >>4)<<4; + height=((pdata.brwin.rrect.height + 15) >>4)<<4; + offset_x=((width-pdata.brwin.rrect.width)/2)&~1; + offset_y=((height-pdata.brwin.rrect.height)/2)&~1; + + enc_data.yuv.y=(unsigned char *)malloc(height*width); + enc_data.yuv.u=(unsigned char *)malloc(height*width/4); + enc_data.yuv.v=(unsigned char *)malloc(height*width/4); + enc_data.yuv.y_width=width; + enc_data.yuv.y_height=height; + enc_data.yuv.y_stride=width; + + enc_data.yuv.uv_width=width/2; + enc_data.yuv.uv_height=height/2; + enc_data.yuv.uv_stride=width/2; + enc_data.x_offset=offset_x; + enc_data.y_offset=offset_y; + + for (i=0;i<(enc_data.yuv.y_width*enc_data.yuv.y_height);i++) + enc_data.yuv.y[i]=0; + + for (i=0;i<(enc_data.yuv.uv_width*enc_data.yuv.uv_height);i++) + enc_data.yuv.v[i]=enc_data.yuv.u[i]=127; + + yblocks=malloc(sizeof(u_int32_t)*(enc_data.yuv.y_width/Y_UNIT_WIDTH)* + (enc_data.yuv.y_height/Y_UNIT_WIDTH)); + ublocks=malloc(sizeof(u_int32_t)*(enc_data.yuv.y_width/Y_UNIT_WIDTH)* + (enc_data.yuv.y_height/Y_UNIT_WIDTH)); + vblocks=malloc(sizeof(u_int32_t)*(enc_data.yuv.y_width/Y_UNIT_WIDTH)* + (enc_data.yuv.y_height/Y_UNIT_WIDTH)); + + pdata.frametime=(1000000)/pdata.args.fps; + + pthread_mutex_init(&pdata.theora_lib_mutex,NULL); + pthread_mutex_init(&pdata.vorbis_lib_mutex,NULL); + pthread_mutex_init(&pdata.libogg_mutex,NULL); + pthread_cond_init(&pdata.theora_lib_clean,NULL); + pthread_cond_init(&pdata.vorbis_lib_clean,NULL); + pdata.th_encoding_clean=pdata.v_encoding_clean=1; + pdata.avd=0; + pdata.sound_buffer=NULL; + pdata.running = TRUE; + pdata.aborted = FALSE; + + rmdRegisterCallbacks(&pdata); + fprintf(stderr,"Restoring %s!!!\n",path); + + rmdEncodeCache(&pdata); + + fprintf(stderr,"Done!!!\n"); + fprintf(stderr,"Goodbye!\n"); + rmdCleanUp(); + + return 0; } - - - - - - - - - - - - - - - diff --git a/recordmydesktop/src/rmd_setbrwindow.c b/recordmydesktop/src/rmd_setbrwindow.c index 8a29b1a..b92eb9b 100644 --- a/recordmydesktop/src/rmd_setbrwindow.c +++ b/recordmydesktop/src/rmd_setbrwindow.c @@ -43,170 +43,155 @@ * \note This is called separately for width and height. */ static void rmdSizePack2_8_16(short *start, unsigned short *size, unsigned short limit) { - int octoffset,hexoffset; - - //align in two - //an odd x can always go down and still be in recording area. - //Resolutions come in even numbers - //so if x is an odd numer, width max is an odd number, too - //thus since x will go down one then width can go up one too and still - //be inbounds - (*size)+=((*size)%2)|((*start)%2); - //but if x goes down 1 and width is already even,it becomes odd so: - (*size)+=((*size)%2); - (*start)-=(*start)%2; - - - //32 bit pack align - //we already have disible by two width,so - //it's 2, 4 or 6 - octoffset=((*size)%8); - if(octoffset==2){ - (*size)-=2; - - } - else if(octoffset==6){ - if((*size)+(*start)+2<=limit) - (*size)+=2; - else if((*start)>=2){ - (*start)-=2; - (*size)+=2; - } - else{ - (*start)+=2; - (*size)-=4; - } - } - - else if(octoffset==4){ - if(((*size)+(*start)+2<=limit)&&((*start)>=2)){ - (*start)-=2; - (*size)+=4; - } - else if((*size)+(*start)+4<=limit){ - (*size)+=4; - } - else if((*start)>=4){ - (*start)-=4; - (*size)+=4; - } - else{ - (*start)+=2; - (*size)-=4; - } - } - - //16 divisble width(needed for shared memory only, - //but applied anyway since theora wants it, too) - //we already have divisibility by 8 so module - //by 16 is euther 8 or 0 - hexoffset=((*size)%16); - if(hexoffset){ - if(((*size)+(*start)+4<=limit)&&((*start)>=4)){ - (*start)-=4; - (*size)+=8; - } - else if((*size)+(*start)+8<=limit){ - (*size)+=8; - } - else if((*start)>=8){ - (*start)-=8; - (*size)+=8; - } - else{ - (*start)+=4; - (*size)-=8; - } - } - + int octoffset,hexoffset; + + //align in two + //an odd x can always go down and still be in recording area. + //Resolutions come in even numbers + //so if x is an odd numer, width max is an odd number, too + //thus since x will go down one then width can go up one too and still + //be inbounds + (*size)+=((*size)%2)|((*start)%2); + //but if x goes down 1 and width is already even,it becomes odd so: + (*size)+=((*size)%2); + (*start)-=(*start)%2; + + //32 bit pack align + //we already have disible by two width,so + //it's 2, 4 or 6 + octoffset=((*size)%8); + if (octoffset==2) { + (*size)-=2; + } else if (octoffset==6) { + if ((*size)+(*start)+2<=limit) + (*size)+=2; + else if ((*start)>=2) { + (*start)-=2; + (*size)+=2; + } else{ + (*start)+=2; + (*size)-=4; + } + } else if (octoffset==4) { + if (((*size)+(*start)+2<=limit)&&((*start)>=2)) { + (*start)-=2; + (*size)+=4; + } else if ((*size)+(*start)+4<=limit) { + (*size)+=4; + } else if ((*start)>=4) { + (*start)-=4; + (*size)+=4; + } else { + (*start)+=2; + (*size)-=4; + } + } + + //16 divisble width(needed for shared memory only, + //but applied anyway since theora wants it, too) + //we already have divisibility by 8 so module + //by 16 is euther 8 or 0 + hexoffset=((*size)%16); + if (hexoffset) { + if (((*size)+(*start)+4<=limit)&&((*start)>=4)) { + (*start)-=4; + (*size)+=8; + } else if ((*size)+(*start)+8<=limit) { + (*size)+=8; + } else if ((*start)>=8) { + (*start)-=8; + (*size)+=8; + } else { + (*start)+=4; + (*size)-=8; + } + } } - - -boolean rmdSetBRWindow(Display *dpy, - BRWindow *brwin, - DisplaySpecs *specs, - ProgArgs *args) { - //before we start recording we have to make sure the ranges are valid - if(args->windowid==0){//root window - //first set it up - brwin->windowid=specs->root; - brwin->rect.x=brwin->rect.y=0; - brwin->rect.width=specs->width; - brwin->rect.height=specs->height; - brwin->rrect.x=args->x; - brwin->rrect.y=args->y; - brwin->rrect.width=((args->width)? - args->width:specs->width-brwin->rrect.x); - brwin->rrect.height=((args->height)? - args->height:specs->height-brwin->rrect.y); - //and then check validity - if((brwin->rrect.x+brwin->rrect.width>specs->width)|| - (brwin->rrect.y+brwin->rrect.height>specs->height)){ - fprintf(stderr,"Window size specification out of bounds!" - "(current resolution:%dx%d)\n", - specs->width,specs->height); - return FALSE; - } - } - else{ - Window wchid; - int transl_x,transl_y; - - XWindowAttributes attribs; - XGetWindowAttributes(dpy,args->windowid,&attribs); - if((attribs.map_state==IsUnviewable)||(attribs.map_state==IsUnmapped)){ - fprintf(stderr,"Window must be mapped and visible!\n"); - return FALSE; - } - XTranslateCoordinates(dpy, - specs->root, - args->windowid, - attribs.x, - attribs.y, - &transl_x, - &transl_y, - &wchid); - - brwin->rect.x=attribs.x-transl_x; - brwin->rect.y=attribs.y-transl_y; - brwin->rect.width=attribs.width; - brwin->rect.height=attribs.height; - if((brwin->rect.x+brwin->rect.width>specs->width)|| - (brwin->rect.y+brwin->rect.height>specs->height)){ - fprintf(stderr,"Window must be on visible screen area!\n"); - return FALSE; - } - - brwin->rrect.x=brwin->rect.x+args->x; - brwin->rrect.y=brwin->rect.y+args->y; - brwin->rrect.width=((args->width)? - args->width:brwin->rect.width-args->x); - brwin->rrect.height=((args->height)? - args->height:brwin->rect.height-args->y); - if((args->x+brwin->rrect.width>brwin->rect.width)|| - (args->y+brwin->rrect.height>brwin->rect.height)){ - fprintf(stderr,"Specified Area is larger than window!\n"); - return FALSE; - } - } - fprintf(stderr, "Initial recording window is set to:\n" - "X:%d Y:%d Width:%d Height:%d\n", - brwin->rrect.x,brwin->rrect.y, - brwin->rrect.width,brwin->rrect.height); - rmdSizePack2_8_16(&brwin->rrect.x,&brwin->rrect.width,specs->width); - rmdSizePack2_8_16(&brwin->rrect.y,&brwin->rrect.height,specs->height); - - fprintf(stderr, "Adjusted recording window is set to:\n" - "X:%d Y:%d Width:%d Height:%d\n", - brwin->rrect.x,brwin->rrect.y, - brwin->rrect.width,brwin->rrect.height); - - - - brwin->nbytes=(((brwin->rrect.width+15)>>4)<<4)* - (((brwin->rrect.height+15)>>4)<<4)* - ((specs->depth==16)?2:4); - - return TRUE; +boolean rmdSetBRWindow( Display *dpy, + BRWindow *brwin, + DisplaySpecs *specs, + ProgArgs *args) { + + //before we start recording we have to make sure the ranges are valid + if (args->windowid==0) {//root window + //first set it up + brwin->windowid=specs->root; + brwin->rect.x=brwin->rect.y=0; + brwin->rect.width=specs->width; + brwin->rect.height=specs->height; + brwin->rrect.x=args->x; + brwin->rrect.y=args->y; + brwin->rrect.width=((args->width)? args->width:specs->width-brwin->rrect.x); + brwin->rrect.height=((args->height)? args->height:specs->height-brwin->rrect.y); + //and then check validity + if ((brwin->rrect.x+brwin->rrect.width>specs->width)|| + (brwin->rrect.y+brwin->rrect.height>specs->height)) { + fprintf(stderr, "Window size specification out of bounds!" + "(current resolution:%dx%d)\n", + specs->width,specs->height); + return FALSE; + } + } else { + Window wchid; + int transl_x,transl_y; + + XWindowAttributes attribs; + XGetWindowAttributes(dpy,args->windowid,&attribs); + + if ((attribs.map_state==IsUnviewable)||(attribs.map_state==IsUnmapped)) { + fprintf(stderr,"Window must be mapped and visible!\n"); + return FALSE; + } + + XTranslateCoordinates( dpy, + specs->root, + args->windowid, + attribs.x, + attribs.y, + &transl_x, + &transl_y, + &wchid); + + brwin->rect.x=attribs.x-transl_x; + brwin->rect.y=attribs.y-transl_y; + brwin->rect.width=attribs.width; + brwin->rect.height=attribs.height; + + if ((brwin->rect.x+brwin->rect.width>specs->width)|| + (brwin->rect.y+brwin->rect.height>specs->height)) { + fprintf(stderr,"Window must be on visible screen area!\n"); + return FALSE; + } + + brwin->rrect.x=brwin->rect.x+args->x; + brwin->rrect.y=brwin->rect.y+args->y; + brwin->rrect.width=((args->width)? args->width:brwin->rect.width-args->x); + brwin->rrect.height=((args->height)? args->height:brwin->rect.height-args->y); + + if ((args->x+brwin->rrect.width>brwin->rect.width)|| + (args->y+brwin->rrect.height>brwin->rect.height)) { + fprintf(stderr,"Specified Area is larger than window!\n"); + return FALSE; + } + } + + fprintf(stderr, "Initial recording window is set to:\n" + "X:%d Y:%d Width:%d Height:%d\n", + brwin->rrect.x,brwin->rrect.y, + brwin->rrect.width,brwin->rrect.height); + + rmdSizePack2_8_16(&brwin->rrect.x,&brwin->rrect.width,specs->width); + rmdSizePack2_8_16(&brwin->rrect.y,&brwin->rrect.height,specs->height); + + fprintf(stderr, "Adjusted recording window is set to:\n" + "X:%d Y:%d Width:%d Height:%d\n", + brwin->rrect.x,brwin->rrect.y, + brwin->rrect.width,brwin->rrect.height); + + brwin->nbytes= (((brwin->rrect.width+15)>>4)<<4)* + (((brwin->rrect.height+15)>>4)<<4)* + ((specs->depth==16)?2:4); + + return TRUE; } diff --git a/recordmydesktop/src/rmd_shortcuts.c b/recordmydesktop/src/rmd_shortcuts.c index 1712b93..bdc8daa 100644 --- a/recordmydesktop/src/rmd_shortcuts.c +++ b/recordmydesktop/src/rmd_shortcuts.c @@ -37,117 +37,107 @@ #include <stdlib.h> #include <string.h> -int rmdRegisterShortcut(Display *dpy, - Window root, - const char *shortcut, - HotKey *hotkey){ - - int keycode=0, - i, j ; - KeySym key=0; - unsigned int modifier_mask=0, - numlock_mask=0; - char *keystr=NULL; - XModifierKeymap *modmap; - - if(strstr(shortcut,"Shift")) - modifier_mask = modifier_mask|ShiftMask; - if(strstr(shortcut,"Control")) - modifier_mask = modifier_mask|ControlMask; - if(strstr(shortcut,"Mod1")) - modifier_mask = modifier_mask|Mod1Mask; - if(strstr(shortcut,"Mod2")) - modifier_mask = modifier_mask|Mod2Mask; - if(strstr(shortcut,"Mod3")) - modifier_mask = modifier_mask|Mod3Mask; - if(strstr(shortcut,"Mod4")) - modifier_mask = modifier_mask|Mod4Mask; - if(strstr(shortcut,"Mod5")) - modifier_mask = modifier_mask|Mod5Mask; - - //we register the shortcut on the root - //window, which means on every keypress event, - //so I think it's neccessary to have at least one - //modifier. - if(modifier_mask == 0) - return 1; - if((keystr=rindex(shortcut,'+'))!=NULL){ - keystr++; - if((key=XStringToKeysym(keystr))==NoSymbol) - return 1; - else - keycode=XKeysymToKeycode(dpy,key); - } - else - return 1; - - - /* Key grabbing stuff taken from tilda who took it from yeahconsole - * who took it from evilwm */ - - modmap = XGetModifierMapping(dpy); - for(i=0;i<8;i++){ - for(j=0;j<modmap->max_keypermod;j++){ - if(modmap->modifiermap[i*modmap->max_keypermod+j]== - XKeysymToKeycode(dpy,XK_Num_Lock)) - numlock_mask=(1<<i); - } - } - XFreeModifiermap(modmap); - - hotkey->modnum=0; - hotkey->key=keycode; - - XGrabKey(dpy, - keycode, - modifier_mask, - root, - True, - GrabModeAsync, - GrabModeAsync); - hotkey->mask[0]=modifier_mask; - hotkey->modnum++; - - XGrabKey(dpy, - keycode, - LockMask | modifier_mask, - root, - True, - GrabModeAsync, - GrabModeAsync); - hotkey->mask[1]=LockMask | modifier_mask; - hotkey->modnum++; - - if(numlock_mask){ - - XGrabKey(dpy, - keycode, - numlock_mask | modifier_mask, - root, - True, - GrabModeAsync, - GrabModeAsync); - hotkey->mask[2]=numlock_mask | modifier_mask; - hotkey->modnum++; - - XGrabKey(dpy, - keycode, - numlock_mask | LockMask | modifier_mask, - root, - True, - GrabModeAsync, - GrabModeAsync); - hotkey->mask[3]=numlock_mask | LockMask | modifier_mask; - hotkey->modnum++; - - } - - return 0; - +int rmdRegisterShortcut( Display *dpy, + Window root, + const char *shortcut, + HotKey *hotkey) { + + int keycode=0, i, j ; + KeySym key=0; + unsigned int modifier_mask=0, numlock_mask=0; + char *keystr=NULL; + XModifierKeymap *modmap; + + if (strstr(shortcut,"Shift")) + modifier_mask = modifier_mask|ShiftMask; + if (strstr(shortcut,"Control")) + modifier_mask = modifier_mask|ControlMask; + if (strstr(shortcut,"Mod1")) + modifier_mask = modifier_mask|Mod1Mask; + if (strstr(shortcut,"Mod2")) + modifier_mask = modifier_mask|Mod2Mask; + if (strstr(shortcut,"Mod3")) + modifier_mask = modifier_mask|Mod3Mask; + if (strstr(shortcut,"Mod4")) + modifier_mask = modifier_mask|Mod4Mask; + if (strstr(shortcut,"Mod5")) + modifier_mask = modifier_mask|Mod5Mask; + + //we register the shortcut on the root + //window, which means on every keypress event, + //so I think it's neccessary to have at least one + //modifier. + if (modifier_mask == 0) + return 1; + if ((keystr=rindex(shortcut,'+'))!=NULL) { + keystr++; + if ((key=XStringToKeysym(keystr))==NoSymbol) + return 1; + else + keycode=XKeysymToKeycode(dpy,key); + } else + return 1; + + + /* Key grabbing stuff taken from tilda who took it from yeahconsole + * who took it from evilwm */ + + modmap = XGetModifierMapping(dpy); + for (i=0;i<8;i++) { + for (j=0;j<modmap->max_keypermod;j++) { + if (modmap->modifiermap[i*modmap->max_keypermod+j]== + XKeysymToKeycode(dpy,XK_Num_Lock)) + numlock_mask=(1<<i); + } + } + XFreeModifiermap(modmap); + + hotkey->modnum=0; + hotkey->key=keycode; + + XGrabKey( dpy, + keycode, + modifier_mask, + root, + True, + GrabModeAsync, + GrabModeAsync); + hotkey->mask[0]=modifier_mask; + hotkey->modnum++; + + XGrabKey( dpy, + keycode, + LockMask | modifier_mask, + root, + True, + GrabModeAsync, + GrabModeAsync); + hotkey->mask[1]=LockMask | modifier_mask; + hotkey->modnum++; + + if (numlock_mask) { + + XGrabKey( dpy, + keycode, + numlock_mask | modifier_mask, + root, + True, + GrabModeAsync, + GrabModeAsync); + hotkey->mask[2]=numlock_mask | modifier_mask; + hotkey->modnum++; + + XGrabKey( dpy, + keycode, + numlock_mask | LockMask | modifier_mask, + root, + True, + GrabModeAsync, + GrabModeAsync); + hotkey->mask[3]=numlock_mask | LockMask | modifier_mask; + hotkey->modnum++; + + } + + return 0; } - - - - - - diff --git a/recordmydesktop/src/rmd_specsfile.c b/recordmydesktop/src/rmd_specsfile.c index 11b55dc..50542a8 100644 --- a/recordmydesktop/src/rmd_specsfile.c +++ b/recordmydesktop/src/rmd_specsfile.c @@ -33,137 +33,119 @@ #include <stdio.h> -int rmdWriteSpecsFile(ProgData *pdata){ - - FILE *fp; - - - fp=fopen(pdata->cache_data->specsfile,"wb"); - if(fp==NULL) - return 1; - else{ - - fprintf(fp,"recordMyDesktop = %s\n",VERSION); - fprintf(fp,"Width = %hu\n",pdata->brwin.rrect.width); - fprintf(fp,"Height = %hu\n",pdata->brwin.rrect.height); - fprintf(fp,"Filename = %s\n",pdata->args.filename); - fprintf(fp,"FPS = %f\n",pdata->args.fps); - fprintf(fp,"NoSound = %d\n",pdata->args.nosound); - fprintf(fp,"Frequency = %d\n",pdata->args.frequency); - fprintf(fp,"Channels = %d\n",pdata->args.channels); - fprintf(fp,"BufferSize = %lu\n",(unsigned long)pdata->args.buffsize); - fprintf(fp,"SoundFrameSize = %d\n",pdata->sound_framesize); - fprintf(fp,"PeriodSize = %lu\n",(unsigned long)pdata->periodsize); - fprintf(fp,"UsedJack = %d\n",pdata->args.use_jack); - fprintf(fp,"v_bitrate = %d\n",pdata->args.v_bitrate); - fprintf(fp,"v_quality = %d\n",pdata->args.v_quality); - fprintf(fp,"s_quality = %d\n",pdata->args.s_quality); - fprintf(fp,"ZeroCompression = %d\n",pdata->args.zerocompression); - - - } - - fclose(fp); - return 0; - +int rmdWriteSpecsFile(ProgData *pdata) { + + FILE *fp; + + fp=fopen(pdata->cache_data->specsfile,"wb"); + if (!fp) + return 1; + + fprintf(fp,"recordMyDesktop = %s\n",VERSION); + fprintf(fp,"Width = %hu\n",pdata->brwin.rrect.width); + fprintf(fp,"Height = %hu\n",pdata->brwin.rrect.height); + fprintf(fp,"Filename = %s\n",pdata->args.filename); + fprintf(fp,"FPS = %f\n",pdata->args.fps); + fprintf(fp,"NoSound = %d\n",pdata->args.nosound); + fprintf(fp,"Frequency = %d\n",pdata->args.frequency); + fprintf(fp,"Channels = %d\n",pdata->args.channels); + fprintf(fp,"BufferSize = %lu\n",(unsigned long)pdata->args.buffsize); + fprintf(fp,"SoundFrameSize = %d\n",pdata->sound_framesize); + fprintf(fp,"PeriodSize = %lu\n",(unsigned long)pdata->periodsize); + fprintf(fp,"UsedJack = %d\n",pdata->args.use_jack); + fprintf(fp,"v_bitrate = %d\n",pdata->args.v_bitrate); + fprintf(fp,"v_quality = %d\n",pdata->args.v_quality); + fprintf(fp,"s_quality = %d\n",pdata->args.s_quality); + fprintf(fp,"ZeroCompression = %d\n",pdata->args.zerocompression); + + fclose(fp); + + return 0; } -int rmdReadSpecsFile(ProgData *pdata){ - - - FILE *fp; - - - fp=fopen(pdata->cache_data->specsfile,"rb"); - if(fp==NULL) - return 1; - else{ - - char Cached_Version[256]; - free(pdata->args.filename); - pdata->args.filename=malloc(512); - - //Take that single-point-of-exit advocates !!! - //15 points of exit, just for your pleasure. - //Also, Vi(m) rules, emacs sucks. - - if(fscanf(fp,"recordMyDesktop = %s\n",Cached_Version)!=1){ - fprintf(stderr,"Error reading VERSION attribute!!!\n"); - return 1; - } - if(fscanf(fp,"Width = %hu\n",&pdata->brwin.rrect.width)!=1){ - fprintf(stderr,"Error reading Width attribute!!!\n"); - return 1; - } - if(fscanf(fp,"Height = %hu\n",&pdata->brwin.rrect.height)!=1){ - fprintf(stderr,"Error reading Height attribute!!!\n"); - return 1; - } - if(fscanf(fp,"Filename = %s\n",pdata->args.filename)!=1){ - fprintf(stderr,"Error reading Filename attribute!!!\n"); - return 1; - } - if(fscanf(fp,"FPS = %f\n",&pdata->args.fps)!=1){ - fprintf(stderr,"Error reading FPS attribute!!!\n"); - return 1; - } - if(fscanf(fp,"NoSound = %d\n",&pdata->args.nosound)!=1){ - fprintf(stderr,"Error reading NoSound attribute!!!\n"); - return 1; - } - if(fscanf(fp,"Frequency = %d\n",&pdata->args.frequency)!=1){ - fprintf(stderr,"Error reading Frequency attribute!!!\n"); - return 1; - } - if(fscanf(fp,"Channels = %d\n",&pdata->args.channels)!=1){ - fprintf(stderr,"Error reading Channels attribute!!!\n"); - return 1; - } - if(fscanf(fp,"BufferSize = %lu\n", - (unsigned long *)&pdata->args.buffsize)!=1){ - fprintf(stderr,"Error reading BufferSize attribute!!!\n"); - return 1; - } - if(fscanf(fp,"SoundFrameSize = %d\n",&pdata->sound_framesize)!=1){ - fprintf(stderr,"Error reading SoundFrameSize attribute!!!\n"); - return 1; - } - if(fscanf(fp,"PeriodSize = %lu\n", - (unsigned long *)&pdata->periodsize)!=1){ - fprintf(stderr,"Error reading PeriodSize attribute!!!\n"); - return 1; - } - if(fscanf(fp,"UsedJack = %u\n",&pdata->args.use_jack)!=1){ - fprintf(stderr,"Error reading UsedJack attribute!!!\n"); - return 1; - } - if(fscanf(fp,"v_bitrate = %d\n",&pdata->args.v_bitrate)!=1){ - fprintf(stderr,"Error reading v_bitrate attribute!!!\n"); - return 1; - } - if(fscanf(fp,"v_quality = %d\n",&pdata->args.v_quality)!=1){ - fprintf(stderr,"Error reading v_quality attribute!!!\n"); - return 1; - } - if(fscanf(fp,"s_quality = %d\n",&pdata->args.s_quality)!=1){ - fprintf(stderr,"Error reading s_quality attribute!!!\n"); - return 1; - } - if(fscanf(fp,"ZeroCompression = %d\n",&pdata->args.zerocompression)!=1){ - fprintf(stderr,"Error reading ZeroCompression attribute!!!\n"); - return 1; - } - - - } - - fclose(fp); - return 0; - +int rmdReadSpecsFile(ProgData *pdata) { + char Cached_Version[256]; + FILE *fp; + + fp=fopen(pdata->cache_data->specsfile,"rb"); + if (!fp) + return 1; + + free(pdata->args.filename); + pdata->args.filename=malloc(512); + + //Take that single-point-of-exit advocates !!! + //15 points of exit, just for your pleasure. + //Also, Vi(m) rules, emacs sucks. + + if (fscanf(fp,"recordMyDesktop = %s\n",Cached_Version)!=1) { + fprintf(stderr,"Error reading VERSION attribute!!!\n"); + return 1; + } + if (fscanf(fp,"Width = %hu\n",&pdata->brwin.rrect.width)!=1) { + fprintf(stderr,"Error reading Width attribute!!!\n"); + return 1; + } + if (fscanf(fp,"Height = %hu\n",&pdata->brwin.rrect.height)!=1) { + fprintf(stderr,"Error reading Height attribute!!!\n"); + return 1; + } + if (fscanf(fp,"Filename = %s\n",pdata->args.filename)!=1) { + fprintf(stderr,"Error reading Filename attribute!!!\n"); + return 1; + } + if (fscanf(fp,"FPS = %f\n",&pdata->args.fps)!=1) { + fprintf(stderr,"Error reading FPS attribute!!!\n"); + return 1; + } + if (fscanf(fp,"NoSound = %d\n",&pdata->args.nosound)!=1) { + fprintf(stderr,"Error reading NoSound attribute!!!\n"); + return 1; + } + if (fscanf(fp,"Frequency = %d\n",&pdata->args.frequency)!=1) { + fprintf(stderr,"Error reading Frequency attribute!!!\n"); + return 1; + } + if (fscanf(fp,"Channels = %d\n",&pdata->args.channels)!=1) { + fprintf(stderr,"Error reading Channels attribute!!!\n"); + return 1; + } + if (fscanf(fp,"BufferSize = %lu\n", + (unsigned long *)&pdata->args.buffsize)!=1) { + fprintf(stderr,"Error reading BufferSize attribute!!!\n"); + return 1; + } + if (fscanf(fp,"SoundFrameSize = %d\n",&pdata->sound_framesize)!=1) { + fprintf(stderr,"Error reading SoundFrameSize attribute!!!\n"); + return 1; + } + if (fscanf(fp,"PeriodSize = %lu\n", + (unsigned long *)&pdata->periodsize)!=1) { + fprintf(stderr,"Error reading PeriodSize attribute!!!\n"); + return 1; + } + if (fscanf(fp,"UsedJack = %u\n",&pdata->args.use_jack)!=1) { + fprintf(stderr,"Error reading UsedJack attribute!!!\n"); + return 1; + } + if (fscanf(fp,"v_bitrate = %d\n",&pdata->args.v_bitrate)!=1) { + fprintf(stderr,"Error reading v_bitrate attribute!!!\n"); + return 1; + } + if (fscanf(fp,"v_quality = %d\n",&pdata->args.v_quality)!=1) { + fprintf(stderr,"Error reading v_quality attribute!!!\n"); + return 1; + } + if (fscanf(fp,"s_quality = %d\n",&pdata->args.s_quality)!=1) { + fprintf(stderr,"Error reading s_quality attribute!!!\n"); + return 1; + } + if (fscanf(fp,"ZeroCompression = %d\n",&pdata->args.zerocompression)!=1) { + fprintf(stderr,"Error reading ZeroCompression attribute!!!\n"); + return 1; + } + + fclose(fp); + + return 0; } - - - - - - diff --git a/recordmydesktop/src/rmd_threads.c b/recordmydesktop/src/rmd_threads.c index 320e8f4..7afe792 100644 --- a/recordmydesktop/src/rmd_threads.c +++ b/recordmydesktop/src/rmd_threads.c @@ -45,122 +45,119 @@ #include <stdlib.h> #include <unistd.h> -void rmdThreads(ProgData *pdata){ - pthread_t image_capture_t, - image_encode_t, - image_cache_t, - sound_capture_t, - sound_encode_t, - sound_cache_t, - flush_to_ogg_t, - timer_t; - - if(pdata->args.delay>0){ - fprintf(stderr,"Will sleep for %d seconds now.\n",pdata->args.delay); - sleep(pdata->args.delay); - } - - /*start threads*/ - pthread_create(&image_capture_t, - NULL, - (void *)rmdGetFrame, - (void *)pdata); - if(pdata->args.encOnTheFly) - pthread_create(&image_encode_t, - NULL, - (void *)rmdEncodeImageBuffer, - (void *)pdata); - else - pthread_create(&image_cache_t, - NULL, - (void *)rmdCacheImageBuffer, - (void *)pdata); - - if(!pdata->args.nosound){ - if(!pdata->args.use_jack) - pthread_create(&sound_capture_t, - NULL, - (void *)rmdCaptureSound, - (void *)pdata); - if(pdata->args.encOnTheFly) - pthread_create(&sound_encode_t, - NULL, - (void *)rmdEncodeSoundBuffer, - (void *)pdata); - else - pthread_create(&sound_cache_t, - NULL, - (void *)rmdCacheSoundBuffer, - (void *)pdata); - } - if(pdata->args.encOnTheFly) - pthread_create(&flush_to_ogg_t, - NULL, - (void *)rmdFlushToOgg, - (void *)pdata); - - rmdRegisterCallbacks(pdata); - pdata->timer_alive=1; - pthread_create(&timer_t, - NULL, - (void *)rmdTimer, - (void *)pdata); - fprintf(stderr,"Capturing!\n"); +void rmdThreads(ProgData *pdata) { + pthread_t image_capture_t, + image_encode_t, + image_cache_t, + sound_capture_t, + sound_encode_t, + sound_cache_t, + flush_to_ogg_t, + timer_t; + + if (pdata->args.delay>0) { + fprintf(stderr, "Will sleep for %d seconds now.\n", pdata->args.delay); + sleep(pdata->args.delay); + } + + /*start threads*/ + pthread_create( &image_capture_t, + NULL, + (void *)rmdGetFrame, + (void *)pdata); + + if (pdata->args.encOnTheFly) + pthread_create( &image_encode_t, + NULL, + (void *)rmdEncodeImageBuffer, + (void *)pdata); + else + pthread_create( &image_cache_t, + NULL, + (void *)rmdCacheImageBuffer, + (void *)pdata); + + if (!pdata->args.nosound) { + if (!pdata->args.use_jack) + pthread_create( &sound_capture_t, + NULL, + (void *)rmdCaptureSound, + (void *)pdata); + + if (pdata->args.encOnTheFly) + pthread_create( &sound_encode_t, + NULL, + (void *)rmdEncodeSoundBuffer, + (void *)pdata); + else + pthread_create( &sound_cache_t, + NULL, + (void *)rmdCacheSoundBuffer, + (void *)pdata); + } + + if(pdata->args.encOnTheFly) + pthread_create( &flush_to_ogg_t, + NULL, + (void *)rmdFlushToOgg, + (void *)pdata); + + rmdRegisterCallbacks(pdata); + pdata->timer_alive=1; + pthread_create( &timer_t, + NULL, + (void *)rmdTimer, + (void *)pdata); + fprintf(stderr,"Capturing!\n"); + #ifdef HAVE_LIBJACK - if(pdata->args.use_jack){ - pdata->jdata->capture_started=1; - } + if (pdata->args.use_jack) + pdata->jdata->capture_started=1; #endif - //wait all threads to finish - - pthread_join(image_capture_t,NULL); - fprintf(stderr,"Shutting down."); - //if no damage events have been received the thread will get stuck - while(!pdata->th_enc_thread_waiting && !pdata->th_encoding_clean){ - usleep(10000); - pthread_mutex_lock(&pdata->img_buff_ready_mutex); - pthread_cond_signal(&pdata->image_buffer_ready); - pthread_mutex_unlock(&pdata->img_buff_ready_mutex); - } - - if(pdata->args.encOnTheFly){ - pthread_join(image_encode_t,NULL); - } - else - pthread_join(image_cache_t,NULL); - fprintf(stderr,"."); - - if(!pdata->args.nosound){ + //wait all threads to finish + + pthread_join(image_capture_t,NULL); + fprintf(stderr,"Shutting down."); + //if no damage events have been received the thread will get stuck + while (!pdata->th_enc_thread_waiting && !pdata->th_encoding_clean) { + usleep(10000); + pthread_mutex_lock(&pdata->img_buff_ready_mutex); + pthread_cond_signal(&pdata->image_buffer_ready); + pthread_mutex_unlock(&pdata->img_buff_ready_mutex); + } + + if (pdata->args.encOnTheFly) + pthread_join(image_encode_t,NULL); + else + pthread_join(image_cache_t,NULL); + fprintf(stderr,"."); + + if (!pdata->args.nosound) { #ifdef HAVE_LIBJACK - if(pdata->args.use_jack) - rmdStopJackClient(pdata->jdata); + if (pdata->args.use_jack) + rmdStopJackClient(pdata->jdata); #endif - if(!pdata->args.use_jack) - pthread_join(sound_capture_t,NULL); - fprintf(stderr,"."); - while(pdata->v_enc_thread_waiting || !pdata->v_encoding_clean){ - usleep(10000); - pthread_mutex_lock(&pdata->snd_buff_ready_mutex); - pthread_cond_signal(&pdata->sound_data_read); - pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); - } - if(pdata->args.encOnTheFly){ - pthread_join(sound_encode_t,NULL); - } - else{ - pthread_join(sound_cache_t,NULL); - } - } - else - fprintf(stderr,".."); - - if(pdata->args.encOnTheFly) - pthread_join(flush_to_ogg_t,NULL); - fprintf(stderr,"."); - - //Now that we are done with recording we cancel the timer - pdata->timer_alive=0; - pthread_join(timer_t,NULL); - - + if (!pdata->args.use_jack) + pthread_join(sound_capture_t,NULL); + + fprintf(stderr,"."); + while (pdata->v_enc_thread_waiting || !pdata->v_encoding_clean) { + usleep(10000); + pthread_mutex_lock(&pdata->snd_buff_ready_mutex); + pthread_cond_signal(&pdata->sound_data_read); + pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); + } + + if (pdata->args.encOnTheFly) + pthread_join(sound_encode_t, NULL); + else + pthread_join(sound_cache_t, NULL); + } else + fprintf(stderr,".."); + + fprintf(stderr,"."); + + //Now that we are done with recording we cancel the timer + pdata->timer_alive=0; + pthread_join(timer_t,NULL); } diff --git a/recordmydesktop/src/rmd_timer.c b/recordmydesktop/src/rmd_timer.c index af6fa75..2548fbe 100644 --- a/recordmydesktop/src/rmd_timer.c +++ b/recordmydesktop/src/rmd_timer.c @@ -38,51 +38,40 @@ void *rmdTimer(ProgData *pdata){ - - long unsigned int secs_tw=1/pdata->args.fps; - long unsigned int usecs_tw=(1000000)/pdata->args.fps- - secs_tw*1000000; - - while(pdata->timer_alive){ - - if (pdata->pause_state_changed) { - pdata->pause_state_changed = FALSE; - - if (!pdata->paused) { - pdata->paused = TRUE; - fprintf(stderr,"STATE:PAUSED\n");fflush(stderr); - } - else{ - pdata->paused = FALSE; - fprintf(stderr,"STATE:RECORDING\n");fflush(stderr); - pthread_mutex_lock(&pdata->pause_mutex); - pthread_cond_broadcast(&pdata->pause_cond); - pthread_mutex_unlock(&pdata->pause_mutex); - } - - } - - if (!pdata->paused) { - pdata->frames_total++; - if (pdata->capture_busy) { - pdata->frames_lost++; - } - } - - pthread_mutex_lock(&pdata->time_mutex); - pthread_cond_broadcast(&pdata->time_cond); - pthread_mutex_unlock(&pdata->time_mutex); - - - if(secs_tw) - sleep(secs_tw); - usleep(usecs_tw); - - } - - - pthread_exit(&errno); + long unsigned int secs_tw=1/pdata->args.fps; + long unsigned int usecs_tw=(1000000)/pdata->args.fps- secs_tw*1000000; + + while (pdata->timer_alive){ + if (pdata->pause_state_changed) { + pdata->pause_state_changed = FALSE; + + if (!pdata->paused) { + pdata->paused = TRUE; + fprintf(stderr,"STATE:PAUSED\n");fflush(stderr); + } else{ + pdata->paused = FALSE; + fprintf(stderr,"STATE:RECORDING\n");fflush(stderr); + pthread_mutex_lock(&pdata->pause_mutex); + pthread_cond_broadcast(&pdata->pause_cond); + pthread_mutex_unlock(&pdata->pause_mutex); + } + } + + if (!pdata->paused) { + pdata->frames_total++; + if (pdata->capture_busy) + pdata->frames_lost++; + } + + pthread_mutex_lock(&pdata->time_mutex); + pthread_cond_broadcast(&pdata->time_cond); + pthread_mutex_unlock(&pdata->time_mutex); + + if (secs_tw) + sleep(secs_tw); + + usleep(usecs_tw); + } + + pthread_exit(&errno); } - - - diff --git a/recordmydesktop/src/rmd_types.h b/recordmydesktop/src/rmd_types.h index e0fe1a1..9e5aa93 100644 --- a/recordmydesktop/src/rmd_types.h +++ b/recordmydesktop/src/rmd_types.h @@ -70,8 +70,8 @@ typedef u_int32_t cmp_int_t; //type of pixel proccessing for the Cb,Cr planes //when converting from full rgb to 4:2:2 Ycbcr enum{ - __PXL_DISCARD, //only select 1 pixel in every block of four - __PXL_AVERAGE //calculate the average of all four pixels + __PXL_DISCARD, //only select 1 pixel in every block of four + __PXL_AVERAGE //calculate the average of all four pixels }; // Boolean type @@ -89,123 +89,123 @@ typedef int boolean; typedef struct _ProgData ProgData; typedef struct _DisplaySpecs{ //this struct holds some basic information - int screen; //about the display,needed mostly for - unsigned int width, height; //validity checks at startup - Window root; - Visual *visual; - GC gc; - int depth; + int screen; //about the display,needed mostly for + unsigned int width, height; //validity checks at startup + Window root; + Visual *visual; + GC gc; + int depth; }DisplaySpecs; typedef struct _RectArea{ //an area that has been damaged gets stored - XRectangle rect; //in a list comprised of structs of this type - struct _RectArea *prev,*next; + XRectangle rect; //in a list comprised of structs of this type + struct _RectArea *prev,*next; }RectArea; typedef struct _BRWindow{ //'basic recorded window' specs - XRectangle rect; //window attributes - XRectangle rrect; //part of window that is recorded - int nbytes; //size of zpixmap when screenshoting - Window windowid; //id + XRectangle rect; //window attributes + XRectangle rrect; //part of window that is recorded (rounded to alignment) + int nbytes; //size of zpixmap when screenshoting + Window windowid; //id }BRWindow; //defaults in the following comment lines may be out of sync with reality //check the SetupDefaultArgs() function further bellow typedef struct _ProgArgs{ - int delay; //start up delay - Window windowid; //window to record(default root) - char *display; //display to connect(default :0) - int x,y; //x,y offset(default 0,0) - int width,height; //defaults to window width and height - char *filename; //output file(default out.[ogg|*]) - int cursor_color; //black or white=>1 or 0 - int have_dummy_cursor; //disable/enable drawing of the dummy cursor - int xfixes_cursor; //disable/enable drawing of a cursor obtained - //through the xfixes extension - float fps; //desired framerate(default 15) - unsigned int frequency; //desired frequency (default 22050) - unsigned int channels; //no of channels(default 2) - char *device; //default sound device + int delay; //start up delay + Window windowid; //window to record(default root) + char *display; //display to connect(default :0) + int x,y; //x,y offset(default 0,0) + int width,height; //defaults to window width and height + char *filename; //output file(default out.[ogg|*]) + int cursor_color; //black or white=>1 or 0 + int have_dummy_cursor; //disable/enable drawing of the dummy cursor + int xfixes_cursor; //disable/enable drawing of a cursor obtained + //through the xfixes extension + float fps; //desired framerate(default 15) + unsigned int frequency; //desired frequency (default 22050) + unsigned int channels; //no of channels(default 2) + char *device; //default sound device #ifdef HAVE_LIBASOUND - snd_pcm_uframes_t buffsize; //buffer size(in frames) for sound capturing + snd_pcm_uframes_t buffsize; //buffer size(in frames) for sound capturing #else - u_int32_t buffsize; + u_int32_t buffsize; #endif - const char* rescue_path; - int nosound; //do not record sound(default 0) - int noshared; //do not use shared memory extension(default 0) - int nowmcheck; //do not check if there's a 3d comp window manager - //(which changes full-shots and with-shared to 1) - int full_shots; //do not poll damage, take full screenshots - int follow_mouse; //capture area follows the mouse(fullshots auto enabled) - int no_encode; //do not encode or delete the temporary files(debug opt) - int no_quick_subsample; //average pixels in chroma planes - int v_bitrate,v_quality,s_quality; //video bitrate,video-sound quality - int encOnTheFly; //encode while recording, no caching(default 0) - char *workdir; //directory to be used for cache files(default $HOME) - char *pause_shortcut; //pause/unpause shortcut sequence(Control+Alt+p) - char *stop_shortcut; //stop shortcut sequence(Control+Alt+s) - int noframe; //don't draw a frame around the recording area - int zerocompression; //image data are always flushed uncompressed - int overwrite; //overwite a previously existing file - //(do not add a .number postfix) - int use_jack; //record audio with jack - unsigned int jack_nports; - char *jack_port_names[RMD_MAX_JACK_PORTS]; - float jack_ringbuffer_secs; + const char* rescue_path; + int nosound; //do not record sound(default 0) + int noshared; //do not use shared memory extension(default 0) + int nowmcheck; //do not check if there's a 3d comp window manager + //(which changes full-shots and with-shared to 1) + int full_shots; //do not poll damage, take full screenshots + int follow_mouse; //capture area follows the mouse(fullshots auto enabled) + int no_encode; //do not encode or delete the temporary files(debug opt) + int no_quick_subsample; //average pixels in chroma planes + int v_bitrate,v_quality,s_quality; //video bitrate,video-sound quality + int encOnTheFly; //encode while recording, no caching(default 0) + char *workdir; //directory to be used for cache files(default $HOME) + char *pause_shortcut; //pause/unpause shortcut sequence(Control+Alt+p) + char *stop_shortcut; //stop shortcut sequence(Control+Alt+s) + int noframe; //don't draw a frame around the recording area + int zerocompression; //image data are always flushed uncompressed + int overwrite; //overwite a previously existing file + //(do not add a .number postfix) + int use_jack; //record audio with jack + unsigned int jack_nports; + char *jack_port_names[RMD_MAX_JACK_PORTS]; + float jack_ringbuffer_secs; }ProgArgs; //this struct holds anything related to encoding AND //writting out to file. typedef struct _EncData{ - ogg_stream_state m_ogg_ts; //theora - ogg_stream_state m_ogg_vs; //vorbis - ogg_page m_ogg_pg; //this could be avoided since - // it is used only while initializing - ogg_packet m_ogg_pckt1; //theora stream - ogg_packet m_ogg_pckt2; //vorbis stream + ogg_stream_state m_ogg_ts; //theora + ogg_stream_state m_ogg_vs; //vorbis + ogg_page m_ogg_pg; //this could be avoided since + // it is used only while initializing + ogg_packet m_ogg_pckt1; //theora stream + ogg_packet m_ogg_pckt2; //vorbis stream //theora data - theora_state m_th_st; - theora_info m_th_inf; - theora_comment m_th_cmmnt; - yuv_buffer yuv; + theora_state m_th_st; + theora_info m_th_inf; + theora_comment m_th_cmmnt; + yuv_buffer yuv; //vorbis data - vorbis_info m_vo_inf; - vorbis_comment m_vo_cmmnt; - vorbis_dsp_state m_vo_dsp; - vorbis_block m_vo_block; + vorbis_info m_vo_inf; + vorbis_comment m_vo_cmmnt; + vorbis_dsp_state m_vo_dsp; + vorbis_block m_vo_block; //these should be 0, since area is quantized //before input - int x_offset, - y_offset; + int x_offset, + y_offset; //our file - FILE *fp; + FILE *fp; }EncData; //this struct will hold a few basic //information, needed for caching the frames. typedef struct _CacheData{ - char *workdir, //The directory were the project - //will be stored, while recording. - //Since this will take a lot of space, the user must be - //able to change the location. - *projname, //This is the name of the folder that - //will hold the project. - //It is rMD-session-%d where %d is the pid - //of the current proccess. - //This way, running two instances - //will not create problems - //and also, a frontend can identify - //leftovers from a possible crash - //and delete them - *specsfile, //workdir+projname+specs.txt - *imgdata, //workdir+projname+img.out.gz - *audiodata; //workdir+projname+audio.pcm - - gzFile *ifp; //image data file pointer - FILE *uncifp; //uncompressed image data file pointer - - FILE *afp; //audio data file pointer + char *workdir, //The directory were the project + //will be stored, while recording. + //Since this will take a lot of space, the user must be + //able to change the location. + *projname, //This is the name of the folder that + //will hold the project. + //It is rMD-session-%d where %d is the pid + //of the current proccess. + //This way, running two instances + //will not create problems + //and also, a frontend can identify + //leftovers from a possible crash + //and delete them + *specsfile, //workdir+projname+specs.txt + *imgdata, //workdir+projname+img.out.gz + *audiodata; //workdir+projname+audio.pcm + + gzFile *ifp; //image data file pointer + FILE *uncifp; //uncompressed image data file pointer + + FILE *afp; //audio data file pointer }CacheData; @@ -213,33 +213,33 @@ typedef struct _CacheData{ //sound keeps coming so we que it in this list //which we then traverse typedef struct _SndBuffer{ - signed char *data; - struct _SndBuffer *next; + signed char *data; + struct _SndBuffer *next; }SndBuffer; #ifdef HAVE_LIBJACK typedef struct _JackData{ - ProgData *pdata; //pointer to prog data - jack_client_t *client; - unsigned int buffersize, //buffer size for every port in frames. - frequency, //samplerate with which jack server was started. - nports; //number of ports. - float ringbuffer_secs; - char **port_names; //names of ports(as specified in args). - jack_port_t **ports; //connections to thes ports. - jack_default_audio_sample_t **portbuf; //retrieval of audio buffers. - pthread_mutex_t *snd_buff_ready_mutex; //mutex and cond_var - pthread_cond_t *sound_data_read; //in the pdata struct - jack_ringbuffer_t *sound_buffer; //data exchange happens through this - int capture_started; //used to hold recording in the beginning + ProgData *pdata; //pointer to prog data + jack_client_t *client; + unsigned int buffersize, //buffer size for every port in frames. + frequency, //samplerate with which jack server was started. + nports; //number of ports. + float ringbuffer_secs; + char **port_names; //names of ports(as specified in args). + jack_port_t **ports; //connections to thes ports. + jack_default_audio_sample_t **portbuf; //retrieval of audio buffers. + pthread_mutex_t *snd_buff_ready_mutex; //mutex and cond_var + pthread_cond_t *sound_data_read; //in the pdata struct + jack_ringbuffer_t *sound_buffer; //data exchange happens through this + int capture_started; //used to hold recording in the beginning }JackData; #endif -typedef struct _HotKey{ //Hold info about the shortcuts - int modnum; //modnum is the number of modifier masks - unsigned int mask[4]; //that should be checked (the initial - int key; //user requested modifier plus it's -}HotKey; //combinations with LockMask and NumLockMask). +typedef struct _HotKey{ //Hold info about the shortcuts + int modnum; //modnum is the number of modifier masks + unsigned int mask[4]; //that should be checked (the initial + int key; //user requested modifier plus it's +}HotKey; //combinations with LockMask and NumLockMask). //this structure holds any data related to the program //It's usage is mostly to be given as an argument to the @@ -247,96 +247,96 @@ typedef struct _HotKey{ //Hold info about the shortcuts //at the same time usage of any globals. struct _ProgData { /**recordMyDesktop specific structs*/ - ProgArgs args; //the program arguments - DisplaySpecs specs; //Display specific information - BRWindow brwin; //recording window - RectArea *rect_root; //the interchanging list roots for storing - //the changed regions - SndBuffer *sound_buffer; - EncData *enc_data; - CacheData *cache_data; - HotKey pause_key, //Shortcuts - stop_key; + ProgArgs args; //the program arguments + DisplaySpecs specs; //Display specific information + BRWindow brwin; //recording window + RectArea *rect_root; //the interchanging list roots for storing + //the changed regions + SndBuffer *sound_buffer; + EncData *enc_data; + CacheData *cache_data; + HotKey pause_key, //Shortcuts + stop_key; #ifdef HAVE_LIBJACK - JackData *jdata; + JackData *jdata; #endif /**X related info*/ - Display *dpy; //curtrent display + Display *dpy; //curtrent display /** Mutexes*/ - pthread_mutex_t sound_buffer_mutex, - snd_buff_ready_mutex, - img_buff_ready_mutex, - theora_lib_mutex, - vorbis_lib_mutex, - libogg_mutex, //libogg is not thread safe, - yuv_mutex; //this might not be needed since we only have - //one read-only and one write-only thread - //also on previous versions, - //y component was looped separately - //and then u and v so this was needed - //to avoid wrong coloring to render - //Currently this mutex only prevents - //the cursor from flickering + pthread_mutex_t sound_buffer_mutex, + snd_buff_ready_mutex, + img_buff_ready_mutex, + theora_lib_mutex, + vorbis_lib_mutex, + libogg_mutex, //libogg is not thread safe, + yuv_mutex; //this might not be needed since we only have + //one read-only and one write-only thread + //also on previous versions, + //y component was looped separately + //and then u and v so this was needed + //to avoid wrong coloring to render + //Currently this mutex only prevents + //the cursor from flickering /**Condition Variables*/ - pthread_cond_t time_cond, //this gets a broadcast by the handler - //whenever it's time to get a screenshot - pause_cond, //this is blocks execution, - //when program is paused - sound_data_read, //a buffer is ready for proccessing - image_buffer_ready, //image encoding finished - theora_lib_clean, //the flush_ogg thread cannot - //procceed to creating last - vorbis_lib_clean; //packages until these two libs - //are no longer used, by other threads + pthread_cond_t time_cond, //this gets a broadcast by the handler + //whenever it's time to get a screenshot + pause_cond, //this is blocks execution, + //when program is paused + sound_data_read, //a buffer is ready for proccessing + image_buffer_ready, //image encoding finished + theora_lib_clean, //the flush_ogg thread cannot + //procceed to creating last + vorbis_lib_clean; //packages until these two libs + //are no longer used, by other threads /**Buffers,Flags and other vars*/ - unsigned char *dummy_pointer, //a dummy pointer to be drawn - //in every frame - //data is casted to unsigned for - //later use in YUV buffer - npxl; //this is the no pixel convention - //when drawing the dummy pointer - unsigned int periodtime,//time that a sound buffer lasts (microsecs) - frametime; //time that a frame lasts (microsecs) - Window shaped_w; //frame - int damage_event, //damage event base code - damage_error, //damage error base code - shm_opcode, //MIT-Shm opcode - dummy_p_size, //dummy pointer size,initially 16x16,always square - th_encoding_clean, //thread exit inidcator - v_encoding_clean, // >> >> - v_enc_thread_waiting, //these indicate a wait - th_enc_thread_waiting, //condition on the cond vars. - timer_alive, //determines loop of timer thread - hard_pause, //if sound device doesn't support pause - //we have to close and reopen - avd, //syncronization among audio and video - sound_framesize; //size of each sound frame - - /** Progam state vars */ - boolean running; //1 while the program is capturing/paused/encoding - boolean paused; //1 while the program is paused - boolean aborted; //1 if we should abort - boolean pause_state_changed; //1 if pause state changed - - //the following values are of no effect - //but they might be usefull later for profiling - unsigned int frames_total, //frames calculated by total time expirations - frames_lost; //the value of shame - - //used to determine frame drop which can - //happen on failure to receive a signal over a condition variable - boolean capture_busy, - encoder_busy; - - pthread_mutex_t pause_mutex; - pthread_mutex_t time_mutex; + unsigned char *dummy_pointer, //a dummy pointer to be drawn + //in every frame + //data is casted to unsigned for + //later use in YUV buffer + npxl; //this is the no pixel convention + //when drawing the dummy pointer + unsigned int periodtime,//time that a sound buffer lasts (microsecs) + frametime; //time that a frame lasts (microsecs) + Window shaped_w; //frame + int damage_event, //damage event base code + damage_error, //damage error base code + shm_opcode, //MIT-Shm opcode + dummy_p_size, //dummy pointer size,initially 16x16,always square + th_encoding_clean, //thread exit inidcator + v_encoding_clean, // >> >> + v_enc_thread_waiting, //these indicate a wait + th_enc_thread_waiting, //condition on the cond vars. + timer_alive, //determines loop of timer thread + hard_pause, //if sound device doesn't support pause + //we have to close and reopen + avd, //syncronization among audio and video + sound_framesize; //size of each sound frame + + /** Progam state vars */ + boolean running; //1 while the program is capturing/paused/encoding + boolean paused; //1 while the program is paused + boolean aborted; //1 if we should abort + boolean pause_state_changed; //1 if pause state changed + + //the following values are of no effect + //but they might be usefull later for profiling + unsigned int frames_total, //frames calculated by total time expirations + frames_lost; //the value of shame + + //used to determine frame drop which can + //happen on failure to receive a signal over a condition variable + boolean capture_busy, + encoder_busy; + + pthread_mutex_t pause_mutex; + pthread_mutex_t time_mutex; #ifdef HAVE_LIBASOUND - snd_pcm_t *sound_handle; - snd_pcm_uframes_t periodsize; + snd_pcm_t *sound_handle; + snd_pcm_uframes_t periodsize; #else - int sound_handle; - u_int32_t periodsize; + int sound_handle; + u_int32_t periodsize; #endif }; @@ -354,13 +354,13 @@ struct _ProgData { typedef struct _FrameHeader{ - char frame_prefix[4]; //always FRAM - u_int32_t frameno, //number of frame(cached frames) - current_total; //number of frames that should have been - //taken at time of caching this one - u_int32_t Ynum, //number of changed blocks in the Y plane - Unum, //number of changed blocks in the U plane - Vnum; //number of changed blocks in the V plane + char frame_prefix[4]; //always FRAM + u_int32_t frameno, //number of frame(cached frames) + current_total; //number of frames that should have been + //taken at time of caching this one + u_int32_t Ynum, //number of changed blocks in the Y plane + Unum, //number of changed blocks in the U plane + Vnum; //number of changed blocks in the V plane }FrameHeader; #endif diff --git a/recordmydesktop/src/rmd_update_image.c b/recordmydesktop/src/rmd_update_image.c index f7ee8d2..657868d 100644 --- a/recordmydesktop/src/rmd_update_image.c +++ b/recordmydesktop/src/rmd_update_image.c @@ -36,50 +36,55 @@ #include <X11/extensions/XShm.h> -void rmdUpdateImage(Display * dpy, - yuv_buffer *yuv, - DisplaySpecs *specs, - RectArea **root, - BRWindow *brwin, - EncData *enc, - char *datatemp, - int noshmem, - XShmSegmentInfo *shminfo, - int shm_opcode, - int no_quick_subsample){ - RectArea *temp; - unsigned char *dtap=(unsigned char*)datatemp; - temp=*root; +void rmdUpdateImage( Display * dpy, + yuv_buffer *yuv, + DisplaySpecs *specs, + RectArea **root, + BRWindow *brwin, + EncData *enc, + char *datatemp, + int noshmem, + XShmSegmentInfo *shminfo, + int shm_opcode, + int no_quick_subsample){ - if(temp!=NULL){ - do{ - if(noshmem){ - rmdGetZPixmap(dpy, - specs->root, - datatemp, - temp->rect.x, - temp->rect.y, - temp->rect.width, - temp->rect.height); - } - else{ - rmdGetZPixmapSHM(dpy, - specs->root, - shminfo, - shm_opcode, - datatemp,temp->rect.x, - temp->rect.y, - temp->rect.width, - 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), - (temp->rect.width),(temp->rect.height), - no_quick_subsample, - specs->depth); - temp=temp->next; - }while(temp!=NULL); - } + RectArea *temp; + unsigned char *dtap=(unsigned char*)datatemp; + temp=*root; + + if (temp!=NULL) { + do { + if (noshmem) { + rmdGetZPixmap( dpy, + specs->root, + datatemp, + temp->rect.x, + temp->rect.y, + temp->rect.width, + temp->rect.height); + } else { + rmdGetZPixmapSHM( dpy, + specs->root, + shminfo, + shm_opcode, + datatemp,temp->rect.x, + temp->rect.y, + temp->rect.width, + 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, + temp->rect.width, + temp->rect.height, + no_quick_subsample, + specs->depth + ); + + temp=temp->next; + } while (temp!=NULL); + } } diff --git a/recordmydesktop/src/rmd_wm_check.c b/recordmydesktop/src/rmd_wm_check.c index 39d86da..4934425 100644 --- a/recordmydesktop/src/rmd_wm_check.c +++ b/recordmydesktop/src/rmd_wm_check.c @@ -32,48 +32,45 @@ #include <X11/Xatom.h> +char *rmdWMCheck(Display *dpy,Window root) { + Window *wm_child=NULL; + Atom nwm_atom, + utf8_string, + wm_name_atom, + rt; + unsigned long nbytes, nitems; -char *rmdWMCheck(Display *dpy,Window root){ + char *wm_name_str=NULL; + int fmt; - Window *wm_child=NULL; - Atom nwm_atom, - utf8_string, - wm_name_atom, - rt; - unsigned long nbytes, - nitems; + utf8_string = XInternAtom(dpy, "UTF8_STRING", False); - char *wm_name_str=NULL; - int fmt; + nwm_atom =XInternAtom(dpy,"_NET_SUPPORTING_WM_CHECK",True); + wm_name_atom =XInternAtom(dpy,"_NET_WM_NAME",True); - utf8_string = XInternAtom(dpy, "UTF8_STRING", False); + if (nwm_atom!=None && wm_name_atom!=None) { - nwm_atom =XInternAtom(dpy,"_NET_SUPPORTING_WM_CHECK",True); - wm_name_atom =XInternAtom(dpy,"_NET_WM_NAME",True); + if (XGetWindowProperty( dpy,root,nwm_atom,0,100, + False,XA_WINDOW, + &rt,&fmt,&nitems, &nbytes, + (unsigned char **)((void*)&wm_child)) + != Success ) { + fprintf(stderr,"Error while trying to get a" + " window to identify the window manager.\n"); + } - if(nwm_atom!=None && wm_name_atom!=None){ - if(XGetWindowProperty( dpy,root,nwm_atom,0,100, - False,XA_WINDOW, - &rt,&fmt,&nitems, &nbytes, - (unsigned char **)((void*)&wm_child)) - != Success ){ - fprintf(stderr,"Error while trying to get a" - " window to identify the window manager.\n"); - } - if((wm_child == NULL)|| - (XGetWindowProperty(dpy,*wm_child,wm_name_atom,0,100, - False,utf8_string,&rt, - &fmt,&nitems, &nbytes, - (unsigned char **)((void*)&wm_name_str)) - !=Success)){ - fprintf(stderr,"Warning!!!\nYour window manager appears" - " to be non-compliant!\n"); - } - } - fprintf(stderr,"Your window manager appears to be %s\n\n", - ((wm_name_str!=NULL)?wm_name_str:"Unknown")); + if ((wm_child == NULL)|| + (XGetWindowProperty(dpy,*wm_child,wm_name_atom,0,100, + False,utf8_string,&rt, + &fmt,&nitems, &nbytes, + (unsigned char **)((void*)&wm_name_str)) + !=Success)) { + fprintf(stderr,"Warning!!!\nYour window manager appears" + " to be non-compliant!\n"); + } + } + fprintf(stderr, "Your window manager appears to be %s\n\n", + ((wm_name_str!=NULL)?wm_name_str:"Unknown")); - - return wm_name_str; + return wm_name_str; } - diff --git a/recordmydesktop/src/rmd_wm_is_compositing.c b/recordmydesktop/src/rmd_wm_is_compositing.c index f893910..bc43282 100644 --- a/recordmydesktop/src/rmd_wm_is_compositing.c +++ b/recordmydesktop/src/rmd_wm_is_compositing.c @@ -36,32 +36,26 @@ boolean rmdWMIsCompositing( Display *dpy, int screen ) { - - Window win; - Atom atom; - char buf[32]; - char *window_manager=rmdWMCheck( dpy, - RootWindow( dpy, screen ) ); - - //If the wm name is queried successfully the wm is compliant (source - //http://standards.freedesktop.org/wm-spec/1.4/ar01s03.html#id2568282 ) - //in which case we will also free() the allcoated string. - - if( window_manager == NULL ) - return FALSE; - else - free( window_manager ); + Window win; + Atom atom; + char buf[32]; + char *window_manager=rmdWMCheck( dpy, RootWindow( dpy, screen ) ); + //If the wm name is queried successfully the wm is compliant (source + //http://standards.freedesktop.org/wm-spec/1.4/ar01s03.html#id2568282 ) + //in which case we will also free() the allcoated string. - snprintf( buf, sizeof(buf), "_NET_WM_CM_S%d", screen); - atom = XInternAtom(dpy, buf, True); - if (atom == None) return FALSE; - - win = XGetSelectionOwner(dpy, atom); - - return win != None; + if (window_manager == NULL) + return FALSE; + else + free(window_manager); + snprintf( buf, sizeof(buf), "_NET_WM_CM_S%d", screen); + atom = XInternAtom(dpy, buf, True); + if (atom == None) + return FALSE; + win = XGetSelectionOwner(dpy, atom); + return win != None; } - diff --git a/recordmydesktop/src/rmd_yuv_utils.c b/recordmydesktop/src/rmd_yuv_utils.c index ff5316e..491d9f1 100644 --- a/recordmydesktop/src/rmd_yuv_utils.c +++ b/recordmydesktop/src/rmd_yuv_utils.c @@ -31,30 +31,29 @@ // Keep these global (for performance reasons I assume). -unsigned char Yr[256], Yg[256], Yb[256], - Ur[256], Ug[256], UbVr[256], - Vg[256], Vb[256]; +unsigned char Yr[256], Yg[256], Yb[256], + Ur[256], Ug[256], UbVr[256], + Vg[256], Vb[256]; // FIXME: These globals are modified in other source files! We keep // thsee here for now. These are the cache blocks. They need to be // accesible in the dbuf macros -u_int32_t *yblocks, - *ublocks, - *vblocks; +u_int32_t *yblocks, + *ublocks, + *vblocks; void rmdMakeMatrices (void) { - - int i; + 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 */ + 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; @@ -75,20 +74,16 @@ void rmdMakeMatrices (void) { vg = ( -0.5 * g / ( 1 - r ) ) * Cscale / RGBscale; vb = ( -0.5 * b / ( 1 - r ) ) * Cscale / RGBscale; - for( i = 0 ; i < 256 ; i++ ) { + for (i = 0; i < 256; i++) { + Yr[i] = (unsigned char) rmdRoundf( Yoffset + yr * i ); + Yg[i] = (unsigned char) rmdRoundf( yg * i ); + Yb[i] = (unsigned char) rmdRoundf( yb * i ); - Yr[i] = (unsigned char) rmdRoundf( Yoffset + yr * i ); - Yg[i] = (unsigned char) rmdRoundf( yg * i ); - Yb[i] = (unsigned char) rmdRoundf( yb * i ); - - Ur[i] = (unsigned char) rmdRoundf( Coffset + ur * i ); - Ug[i] = (unsigned char) rmdRoundf( ug * i ); - UbVr[i] = (unsigned char) rmdRoundf( ub * i ); - - Vg[i] = (unsigned char) rmdRoundf( vg * i ); - Vb[i] = (unsigned char) rmdRoundf( Coffset + vb * i ); - - } + Ur[i] = (unsigned char) rmdRoundf( Coffset + ur * i ); + Ug[i] = (unsigned char) rmdRoundf( ug * i ); + UbVr[i] = (unsigned char) rmdRoundf( ub * i ); + Vg[i] = (unsigned char) rmdRoundf( vg * i ); + Vb[i] = (unsigned char) rmdRoundf( Coffset + vb * i ); + } } - diff --git a/recordmydesktop/src/rmd_yuv_utils.h b/recordmydesktop/src/rmd_yuv_utils.h index d38b1b7..f0c9130 100644 --- a/recordmydesktop/src/rmd_yuv_utils.h +++ b/recordmydesktop/src/rmd_yuv_utils.h @@ -93,7 +93,7 @@ extern u_int32_t *yblocks, __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,\ + 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++){\ @@ -105,7 +105,7 @@ extern u_int32_t *yblocks, datapi++;\ yuv_y++;\ }\ - yuv_y+=yuv->y_width-width_tm;\ + yuv_y+=(yuv)->y_width-width_tm;\ }\ } @@ -142,8 +142,8 @@ extern u_int32_t *yblocks, __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,\ + 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,\ @@ -167,8 +167,8 @@ extern u_int32_t *yblocks, yuv_u++;\ yuv_v++;\ }\ - yuv_u+=(yuv->y_width-width_tm)/2;\ - yuv_v+=(yuv->y_width-width_tm)/2;\ + 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;\ @@ -232,11 +232,11 @@ extern u_int32_t *yblocks, 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]=\ + (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]=\ + (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]] ;\ @@ -256,7 +256,7 @@ extern u_int32_t *yblocks, __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,\ + 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;\ @@ -273,7 +273,7 @@ extern u_int32_t *yblocks, datapi_back++;\ yuv_y++;\ }\ - yuv_y+=yuv->y_width-width_tm;\ + yuv_y+=(yuv)->y_width-width_tm;\ }\ } @@ -288,8 +288,8 @@ extern u_int32_t *yblocks, __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,\ + 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,\ @@ -325,8 +325,8 @@ extern u_int32_t *yblocks, yuv_u++;\ yuv_v++;\ }\ - yuv_u+=(yuv->y_width-width_tm)/2;\ - yuv_v+=(yuv->y_width-width_tm)/2;\ + 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){\ @@ -359,8 +359,8 @@ extern u_int32_t *yblocks, yuv_u++;\ yuv_v++;\ }\ - yuv_u+=(yuv->y_width-width_tm)/2;\ - yuv_v+=(yuv->y_width-width_tm)/2;\ + 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){\ |