diff options
-rw-r--r-- | rMD-exp/include/recordmydesktop.h | 50 | ||||
-rw-r--r-- | rMD-exp/src/Makefile.am | 3 | ||||
-rw-r--r-- | rMD-exp/src/cache_frame.c | 7 | ||||
-rw-r--r-- | rMD-exp/src/init_encoder.c | 27 | ||||
-rw-r--r-- | rMD-exp/src/parseargs.c | 21 | ||||
-rw-r--r-- | rMD-exp/src/recordmydesktop.c | 12 | ||||
-rw-r--r-- | rMD-exp/src/rmd_cache.c | 90 |
7 files changed, 186 insertions, 24 deletions
diff --git a/rMD-exp/include/recordmydesktop.h b/rMD-exp/include/recordmydesktop.h index b06db1b..1c3ebe0 100644 --- a/rMD-exp/include/recordmydesktop.h +++ b/rMD-exp/include/recordmydesktop.h @@ -49,6 +49,7 @@ #include <sys/ipc.h> #include <sys/shm.h> #include <pthread.h> +#include <zlib.h> #include <X11/Xlib.h> #include <X11/Xlibint.h> #include <X11/extensions/Xfixes.h> @@ -143,6 +144,9 @@ typedef struct _ProgArgs{ int no_quick_subsample;//average pixels in chroma planes int v_bitrate,v_quality,s_quality;//video bitrate,video-sound quality int dropframes; //option for theora encoder + int encOnTheFly; //encode while recording, no caching(default 0) + char *workdir; //directory to be used for cache files(default $HOME) + }ProgArgs; @@ -173,6 +177,25 @@ typedef struct _EncData{ 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 + *imgdata, //workdir+projname+img.out.gz + *audiodata; //workdir+projname+audio.pcm + + gzFile *ifp; //image data file pointer + FILE *afp; //audio data file pointer + +}CacheData; + //sound buffer //sound keeps coming so we que it in this list //which we then traverse @@ -207,6 +230,7 @@ typedef struct _ProgData{ running; SndBuffer *sound_buffer; EncData *enc_data; + CacheData *cache_data; int hard_pause;//if sound device doesn't support pause //we have to close and reopen int avd;//syncronization among audio and video @@ -357,7 +381,7 @@ int capture_busy, (args)->display=NULL;\ (args)->windowid=(args)->x=(args)->y\ =(args)->width=(args)->height=(args)->quietmode\ - =(args)->nosound=(args)->full_shots=0;\ + =(args)->nosound=(args)->full_shots=(args)->encOnTheFly=0;\ (args)->noshared=1;\ (args)->dropframes=(args)->nocondshared=0;\ (args)->no_quick_subsample=1;\ @@ -376,6 +400,8 @@ int capture_busy, (args)->v_bitrate=45000;\ (args)->v_quality=63;\ (args)->s_quality=10;\ + (args)->workdir=(char *)malloc(strlen(getenv("HOME"))+1);\ + strcpy((args)->workdir,getenv("HOME"));\ } #define QUERY_DISPLAY_SPECS(display,specstruct){\ @@ -518,6 +544,24 @@ int capture_busy, } +#define I16TOA(number,buffer){\ + int t_num=(number),k=0,i=0;\ + char *t_buf=malloc(8);\ + t_num=t_num&((2<<15)-1);\ + while(t_num>0){\ + int digit=t_num%10;\ + t_buf[k]=digit+48;\ + t_num-=digit;\ + t_num/=10;\ + k++;\ + }\ + while(k>0)\ + (buffer)[i++]=t_buf[--k];\ + (buffer)[i]='\0';\ + free(t_buf);\ +};\ + + /**Function prototypes*/ void *PollDamage(void *pdata); @@ -539,9 +583,11 @@ unsigned char *MakeDummyPointer(DisplaySpecs *specs,int size,int color,int type, void *CaptureSound(void *pdata); void *EncodeSoundBuffer(void *pdata); snd_pcm_t *OpenDev(const char *pcm_dev,unsigned int *channels,unsigned int *frequency,snd_pcm_uframes_t *periodsize,unsigned int *periodtime,int *hardpause); -void InitEncoder(ProgData *pdata,EncData *enc_data_t); +void InitEncoder(ProgData *pdata,EncData *enc_data_t,int buffer_ready); void MakeMatrices(); void SizePack2_8_16(int *start,int *size,int limit); void *CacheImageBuffer(void *pdata); +void InitCacheData(ProgData *pdata,EncData *enc_data_t,CacheData *cache_data_t); +void InitCacheData(ProgData *pdata,EncData *enc_data_t,CacheData *cache_data_t); #endif diff --git a/rMD-exp/src/Makefile.am b/rMD-exp/src/Makefile.am index 4315ab3..8332134 100644 --- a/rMD-exp/src/Makefile.am +++ b/rMD-exp/src/Makefile.am @@ -20,7 +20,8 @@ recordmydesktop_SOURCES= recordmydesktop.c\ capture_sound.c\ encode_sound_buffer.c\ init_encoder.c\ - cache_frame.c + cache_frame.c\ + rmd_cache.c INCLUDES= $(all_includes) -I../include -I$x_includes diff --git a/rMD-exp/src/cache_frame.c b/rMD-exp/src/cache_frame.c index 6b214e0..6f97723 100644 --- a/rMD-exp/src/cache_frame.c +++ b/rMD-exp/src/cache_frame.c @@ -25,7 +25,8 @@ **********************************************************************************/ #include <recordmydesktop.h> -#include <zlib.h> + + void MakeChecksums(unsigned char *buf,int width,int height,int divisor,unsigned short int *checksums){ int i,k,j,m; @@ -60,8 +61,8 @@ void *CacheImageBuffer(void *pdata){ pthread_mutex_init(&pmut,NULL); pthread_mutex_init(&imut,NULL); yuv_buffer yuv[2]; - gzFile *fp; - fp=gzopen("temp.out","wb1f"); + gzFile *fp=((ProgData *)pdata)->cache_data->ifp; + if(fp==NULL)exit(13); unsigned short int checksums_y[2][256], diff --git a/rMD-exp/src/init_encoder.c b/rMD-exp/src/init_encoder.c index ed1ad53..34db2a7 100644 --- a/rMD-exp/src/init_encoder.c +++ b/rMD-exp/src/init_encoder.c @@ -27,7 +27,7 @@ #include <recordmydesktop.h> -void InitEncoder(ProgData *pdata,EncData *enc_data_t){ +void InitEncoder(ProgData *pdata,EncData *enc_data_t,int buffer_ready){ int y1,y2; (pdata)->enc_data=enc_data_t; srand(time(NULL)); @@ -150,19 +150,20 @@ void InitEncoder(ProgData *pdata,EncData *enc_data_t){ } + 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.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; + (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/rMD-exp/src/parseargs.c b/rMD-exp/src/parseargs.c index a335b59..746df5c 100644 --- a/rMD-exp/src/parseargs.c +++ b/rMD-exp/src/parseargs.c @@ -32,11 +32,11 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){ int i; char *usage="\nUsage:\n" "\trecordmydesktop [-h| --help| --version| -delay n[H|h|M|m]| -windowid id_of_window|\n" - "\t-display DISPLAY| -x X| -y Y|-width N| -height N| -fps N(number>0)|\n" + "\t-display DISPLAY| -x X| -y Y|-width N| -height N| -fps N(number>0)| --on-the-fly-encoding|\n" "\t -v_quality n| -s_quality n| -v_bitrate n| --no-framedrop| -dummy-cursor color|\n" "\t --no-cursor| -freq N(number>0)| -channels N(number>0)| -device SOUND_DEVICE|\n" "\t --nosound| --with-shared| --no-cond-shared| -shared-threshold n| --full-shots|\n" - "\t --quick-subsampling| -o filename]^filename\n\n\n" + "\t --quick-subsampling| -workdir DIR| -o filename]^filename\n\n\n" "General Options:\n" "\t-h or --help\t\tPrint this help and exit.\n" @@ -66,12 +66,14 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){ "\t--nosound\t\tDo not record sound.\n\n" "Encoding Options\n" + "\t--on-the-fly-encoding\tEncode the audio-video data, while recording.\n" "\t-v_quality n\t\tA number from 0 to 63 for desired encoded video quality(default 63).\n" "\t-v_bitrate n\t\tA number from 45000 to 2000000 for desired encoded video bitrate(default 45000).\n" "\t--drop-frames\t\tAllow theora encoder to drop frames.\n" "\t-s_quality n\t\tDesired audio quality(-1 to 10).\n\n" "Misc Options:\n" + "\t-workdir DIR\t\tLocation where a temporary directory will be created to hold project files(default $HOME).\n" "\t-delay n[H|h|M|m]\tNumber of secs(default),minutes or hours before capture starts(number can be float)\n" "\t-o filename\t\tName of recorded video(default out.ogg).\n" "\n\tIf no other options are specified, filename can be given without the -o switch.\n\n\n"; @@ -363,6 +365,18 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){ } i++; } + else if(!strcmp(argv[i],"-workdir")){ + if(i+1<argc){ + free(arg_return->workdir); + arg_return->workdir=malloc(strlen(argv[i+1])+1); + strcpy(arg_return->workdir,argv[i+1]); + } + else{ + fprintf(stderr,"Argument Usage: -workdir DIR\n"); + return 1; + } + i++; + } else if(!strcmp(argv[i],"--nosound")) arg_return->nosound=1; else if(!strcmp(argv[i],"--drop-frames")) @@ -380,6 +394,9 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){ else if(!strcmp(argv[i],"--quick-subsampling")){ arg_return->no_quick_subsample=0; } + else if(!strcmp(argv[i],"--on-the-fly-encoding")){ + arg_return->encOnTheFly=1; + } else if(!strcmp(argv[i],"--help")||!strcmp(argv[i],"-h")){ fprintf(stderr,"%s",usage); return 1; diff --git a/rMD-exp/src/recordmydesktop.c b/rMD-exp/src/recordmydesktop.c index c14f605..df7fbb3 100644 --- a/rMD-exp/src/recordmydesktop.c +++ b/rMD-exp/src/recordmydesktop.c @@ -51,6 +51,7 @@ int main(int argc,char **argv){ } else{ EncData enc_data; + CacheData cache_data; pthread_t poll_damage_t, image_capture_t, image_encode_t, @@ -131,17 +132,22 @@ int main(int argc,char **argv){ if(!pdata.args.nosound){ pdata.sound_handle=OpenDev(pdata.args.device,&pdata.args.channels,&pdata.args.frequency,&pdata.periodsize, &pdata.periodtime,&pdata.hard_pause); if(pdata.sound_handle==NULL){ - fprintf(stderr,"Error while opening/configuring soundcard %s\nTry running with the --no-sound or specify a correct device.\n",pdata.args.device); + fprintf(stderr,"Error while opening/configuring soundcard %s\nTry running with the --nosound or specify a correct device.\n",pdata.args.device); exit(3); } } + + if(pdata.args.encOnTheFly) + InitEncoder(&pdata,&enc_data,0); + else + InitCacheData(&pdata,&enc_data,&cache_data); - InitEncoder(&pdata,&enc_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; } + if((pdata.args.nocondshared)&&(!pdata.args.noshared)){ if(pdata.args.no_quick_subsample){ UPDATE_YUV_BUFFER_IM_AVG((&pdata.enc_data->yuv),((unsigned char*)pdata.shimage->data), @@ -199,7 +205,7 @@ int main(int argc,char **argv){ fprintf(stderr,"."); if(!pdata.args.nosound){ int *snd_exit; - pthread_join(sound_capture_t,(&snd_exit)); + pthread_join(sound_capture_t,(void *)(&snd_exit)); fprintf(stderr,"."); // if(!(*snd_exit)) // pthread_join(sound_encode_t,NULL); diff --git a/rMD-exp/src/rmd_cache.c b/rMD-exp/src/rmd_cache.c new file mode 100644 index 0000000..eb86aad --- /dev/null +++ b/rMD-exp/src/rmd_cache.c @@ -0,0 +1,90 @@ +/********************************************************************************* +* recordMyDesktop * +********************************************************************************** +* * +* Copyright (C) 2006 John Varouhakis * +* * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the Free Software * +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * +* * +* * +* * +* For further information contact me at johnvarouhakis@gmail.com * +**********************************************************************************/ + +#include <recordmydesktop.h> + +void InitCacheData(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.rgeom.width + 15) >>4)<<4; + height=((pdata->brwin.rgeom.height + 15) >>4)<<4; + offset_x=((width-pdata->brwin.rgeom.width)/2)&~1; + offset_y=((height-pdata->brwin.rgeom.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(); + + I16TOA(pid,pidbuf) + //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.gz"); + //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"); + + //now that've got out buffers and our filenames we start + //creating the needed files + + mkdir(cache_data_t->projname,0777); + cache_data_t->ifp=gzopen(cache_data_t->imgdata,"wb1f"); + if(!pdata->args.nosound) + cache_data_t->afp=fopen(cache_data_t->audiodata,"wb"); + +} + + |