From 5076dbf5c8974316119d6bad42c413a3e3bf5ec9 Mon Sep 17 00:00:00 2001 From: iovar Date: Sat, 28 Oct 2006 15:14:57 +0000 Subject: mostly changes on cache writting/loading/encoding,which is now functional.Also var other minor changes git-svn-id: https://recordmydesktop.svn.sourceforge.net/svnroot/recordmydesktop/trunk@124 f606c939-3180-4ac9-a4b8-4b8779d57d0a --- rMD-exp/include/recordmydesktop.h | 3 ++ rMD-exp/src/cache_frame.c | 101 +++++++++++++++++++++----------------- rMD-exp/src/encode_image_buffer.c | 19 ++++++- rMD-exp/src/encode_sound_buffer.c | 30 ++++++++++- rMD-exp/src/load_cache.c | 89 ++++++++++++++++----------------- rMD-exp/src/poll_damage.c | 1 - rMD-exp/src/recordmydesktop.c | 35 +++---------- rMD-exp/src/register_callbacks.c | 10 ++++ 8 files changed, 166 insertions(+), 122 deletions(-) diff --git a/rMD-exp/include/recordmydesktop.h b/rMD-exp/include/recordmydesktop.h index 0eafa01..e78b11a 100644 --- a/rMD-exp/include/recordmydesktop.h +++ b/rMD-exp/include/recordmydesktop.h @@ -610,5 +610,8 @@ void *CacheImageBuffer(void *pdata); void InitCacheData(ProgData *pdata,EncData *enc_data_t,CacheData *cache_data_t); void *CacheSoundBuffer(void *pdata); void *LoadCache(void *pdata); +void SyncEncodeImageBuffer(ProgData *pdata); +void CancelTimer(void); +void SyncEncodeSoundBuffer(ProgData *pdata,signed char *buff); #endif diff --git a/rMD-exp/src/cache_frame.c b/rMD-exp/src/cache_frame.c index c83b54b..45fb660 100644 --- a/rMD-exp/src/cache_frame.c +++ b/rMD-exp/src/cache_frame.c @@ -96,12 +96,20 @@ void *CacheImageBuffer(void *pdata){ while(((ProgData *)pdata)->running){ + int prev; + int j; + unsigned short ynum,unum,vnum; + unsigned char yblocks[256],ublocks[64],vblocks[64]; + FrameHeader fheader; + ynum=unum=vnum=0; + pthread_cond_wait(&((ProgData *)pdata)->image_buffer_ready,&imut); if(Paused) pthread_cond_wait(&((ProgData *)pdata)->pause_cond,&pmut); pthread_mutex_lock(&((ProgData *)pdata)->yuv_mutex); //rotate buffers + prev=current; current=(current)?0:1; //copy incoming memcpy(yuv[current].y,((ProgData *)pdata)->enc_data->yuv.y,yuv[current].y_width*yuv[current].y_height); @@ -117,16 +125,21 @@ void *CacheImageBuffer(void *pdata){ //find and flush different blocks if(firstrun){ firstrun=0; - continue; + for(j=0;j(pow(divisor,2)+pow(divisor/2,2)*2)/10) - gzsetparams (fp,1,Z_FILTERED); - else - gzsetparams (fp,0,Z_FILTERED); - strncpy(fheader.frame_prefix,"FRAM",4); - fheader.frameno=++frameno; - fheader.current_total=frames_total; - fheader.Ynum=ynum; - fheader.Unum=unum; - fheader.Vnum=vnum; - fheader.pad=0; - gzwrite(fp,(void*)&fheader,sizeof(FrameHeader)); - //flush indexes - if(ynum)gzwrite(fp,yblocks,ynum); - if(unum)gzwrite(fp,ublocks,unum); - if(vnum)gzwrite(fp,vblocks,vnum); - - - //flush the blocks for each buffer - if(ynum) - for(j=0;javd+=((ProgData *)pdata)->frametime*2*((ProgData *)pdata)->args.channels; - - - } + /**WRITE FRAME TO DISK*/ + if(ynum+unum+vnum>(pow(divisor,2)+pow(divisor/2,2)*2)/10) + gzsetparams (fp,1,Z_FILTERED); + else + gzsetparams (fp,0,Z_FILTERED); + strncpy(fheader.frame_prefix,"FRAM",4); + fheader.frameno=++frameno; + fheader.current_total=frames_total; + fheader.Ynum=ynum; + fheader.Unum=unum; + fheader.Vnum=vnum; + fheader.pad=0; + gzwrite(fp,(void*)&fheader,sizeof(FrameHeader)); + //flush indexes + if(ynum)gzwrite(fp,yblocks,ynum); + if(unum)gzwrite(fp,ublocks,unum); + if(vnum)gzwrite(fp,vblocks,vnum); + + + //flush the blocks for each buffer + if(ynum) + for(j=0;javd+=((ProgData *)pdata)->frametime*2*((ProgData *)pdata)->args.channels; + } //clean up since we're not finished @@ -190,7 +201,7 @@ void *CacheImageBuffer(void *pdata){ free(yuv[i].u); free(yuv[i].v); } - fprintf(stderr,"Saved %d frames in a total of %d requests",frameno,frames_total); + fprintf(stderr,"Saved %d frames in a total of %d requests\n",frameno,frames_total); gzclose(fp); pthread_exit(&errno); } diff --git a/rMD-exp/src/encode_image_buffer.c b/rMD-exp/src/encode_image_buffer.c index 2718d0e..0eb5bfb 100644 --- a/rMD-exp/src/encode_image_buffer.c +++ b/rMD-exp/src/encode_image_buffer.c @@ -62,4 +62,21 @@ void *EncodeImageBuffer(void *pdata){ pthread_exit(&errno); } - +//this function is meant to be called normally +//not through a thread of it's own +void SyncEncodeImageBuffer(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,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*2*pdata->args.channels; + } + } +} \ No newline at end of file diff --git a/rMD-exp/src/encode_sound_buffer.c b/rMD-exp/src/encode_sound_buffer.c index 85e277d..73f6d48 100644 --- a/rMD-exp/src/encode_sound_buffer.c +++ b/rMD-exp/src/encode_sound_buffer.c @@ -90,4 +90,32 @@ void *EncodeSoundBuffer(void *pdata){ pthread_exit(&errno); } - +void SyncEncodeSoundBuffer(ProgData *pdata,signed char *buff){ + float **vorbis_buffer; + int count=0,i,j; + int sampread=pdata->periodsize/(2*pdata->args.channels); + vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,sampread); + for(i=0;iargs.channels;j++){ + vorbis_buffer[j][i]=((buff[count+1]<<8)| + (0x00ff&(int)buff[count]))/32768.f; + count+=2; + } + } + + vorbis_analysis_wrote(&pdata->enc_data->m_vo_dsp,sampread); + + 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)){ + pthread_mutex_lock(&pdata->libogg_mutex); + 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; +} + diff --git a/rMD-exp/src/load_cache.c b/rMD-exp/src/load_cache.c index 246b14e..1c5b29a 100644 --- a/rMD-exp/src/load_cache.c +++ b/rMD-exp/src/load_cache.c @@ -36,11 +36,10 @@ void LoadBlock(unsigned char *dest,unsigned char *source,int blockno,int width, memcpy( &dest[block_i*(width*height/divisor)+j*width+block_k*width/divisor], &source[j*width/divisor], width/divisor); -// gzread(fp,(void *)&dest[block_i*(width*height/divisor)+j*width+block_k*width/divisor],width/divisor); -// ; } + void *LoadCache(void *pdata){ yuv_buffer *yuv=&((ProgData *)pdata)->enc_data->yuv; @@ -48,7 +47,13 @@ void *LoadCache(void *pdata){ FILE *afp=((ProgData *)pdata)->cache_data->afp; FrameHeader fheader; CachedFrame frame; + signed char *sound_data=(signed char *)malloc(((ProgData *)pdata)->periodsize); + int j=0, + 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 divisor=16, blockszy=0,//size of y plane block in bytes @@ -69,8 +74,6 @@ void *LoadCache(void *pdata){ pthread_exit(&thread_exit); } } -// int first=10; - //recalculate the divisor since it is not saved while(((((ProgData *)pdata)->brwin.rgeom.width* ((ProgData *)pdata)->brwin.rgeom.width ) @@ -85,16 +88,26 @@ void *LoadCache(void *pdata){ blockszy=(yuv->y_width*yuv->y_height )/pow(divisor,2); blockszuv=(yuv->uv_width*yuv->uv_height)/pow(divisor/2,2); - + //this will be used now to define if we proccess audio or video + //on any given loop. + ((ProgData *)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(((ProgData *)pdata)->running){ - int framesize=0; -// if(first){ - if(gzread(ifp,frame.header,sizeof(FrameHeader))==sizeof(FrameHeader)){ -// fprintf(stderr,"1:%c%c%c%c \n1: %d \n1: %d \n1: %d \n1: %d \n1: %d \n1: %d\n", -// frame.header->frame_prefix[0],frame.header->frame_prefix[1],frame.header->frame_prefix[2],frame.header->frame_prefix[3], -// frame.header->frameno,frame.header->current_total -// ,frame.header->Ynum,frame.header->Unum,frame.header->Vnum,frame.header->pad);fflush(stderr); - fprintf(stderr,"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b %d of %d",frame.header->frameno,frame.header->current_total); + //video load and encoding + if(((ProgData *)pdata)->avd<=0 || ((ProgData *)pdata)->args.nosound || audio_end){ + if(missing_frames>0){ + extra_frames++; + missing_frames--; + SyncEncodeImageBuffer((ProgData *)pdata); + } + else if(gzread(ifp,frame.header,sizeof(FrameHeader))==sizeof(FrameHeader)){ + //sync + missing_frames+=frame.header->current_total-(extra_frames+frame.header->frameno); + + fprintf(stdout,"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" + "%d of %d",frame.header->frameno+extra_frames,frames_total);fflush(stdout); if( (frame.header->Ynum<=pow(divisor,2)) && (frame.header->Unum<=pow(divisor/2,2)) && (frame.header->Vnum<=pow(divisor/2,2)) && @@ -104,14 +117,6 @@ void *LoadCache(void *pdata){ (gzread(ifp,frame.YData,blockszy*frame.header->Ynum)==blockszy*frame.header->Ynum) && (gzread(ifp,frame.UData,(blockszuv*frame.header->Unum))==(blockszuv*frame.header->Unum)) && (gzread(ifp,frame.VData,(blockszuv*frame.header->Vnum))==(blockszuv*frame.header->Vnum))){ - framesize+=sizeof(FrameHeader) - +frame.header->Ynum+frame.header->Unum+frame.header->Vnum - +blockszy*frame.header->Ynum+(blockszuv*frame.header->Unum) - +(blockszuv*frame.header->Vnum); -// fprintf(stderr,"OK! %d \n%d %d %d\n",framesize,blockszy,blockszuv,sizeof(FrameHeader));fflush(stderr); - - pthread_mutex_lock(&((ProgData *)pdata)->yuv_mutex); - //load the blocks for each buffer if(frame.header->Ynum) for(j=0;jYnum;j++) @@ -137,44 +142,34 @@ void *LoadCache(void *pdata){ yuv->uv_width, yuv->uv_height, divisor/2); - pthread_mutex_unlock(&((ProgData *)pdata)->yuv_mutex); - - while(encoder_busy){ - usleep(100); - } - pthread_cond_broadcast(&((ProgData *)pdata)->image_buffer_ready); - while(encoder_busy){ - usleep(100); - } - } + //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. + SyncEncodeImageBuffer((ProgData *)pdata); + } else{ -// first=0; raise(SIGINT); continue; } } else{ -// first=0; raise(SIGINT); continue; } - -// } - - - //call loading func{ - //if avd>=0 - //load image from cache - //signal buffer - ////if avd<0 - //load sound from cache - //signal buffer - //} - -// sleep(1); + } + //audio load and encoding + else{ + if(!audio_end){ + int nbytes=fread(sound_data,((ProgData *)pdata)->periodsize,1,afp); + if(nbytes<=0) + audio_end=1; + else + SyncEncodeSoundBuffer((ProgData *)pdata,sound_data); + } + } } CLEAR_FRAME(&frame) + free(sound_data); gzclose(ifp); if(remove(((ProgData *)pdata)->cache_data->imgdata)){ diff --git a/rMD-exp/src/poll_damage.c b/rMD-exp/src/poll_damage.c index 1878439..7ac4e52 100644 --- a/rMD-exp/src/poll_damage.c +++ b/rMD-exp/src/poll_damage.c @@ -36,7 +36,6 @@ void *PollDamage(void *pdata){ damage= XDamageCreate( ((ProgData *)pdata)->dpy, ((ProgData *)pdata)->brwin.windowid, XDamageReportRawRectangles); while(((ProgData *)pdata)->running){ -// if(Paused)pthread_cond_wait(&((ProgData *)pdata)->pause_cond,&((ProgData *)pdata)->pause_cond_mutex); //damage polling doesn't stop,eventually full image may be needed XNextEvent(((ProgData *)pdata)->dpy,&event); if(event.type == ((ProgData *)pdata)->damage_event + XDamageNotify ){ diff --git a/rMD-exp/src/recordmydesktop.c b/rMD-exp/src/recordmydesktop.c index a90a953..8bb86f8 100644 --- a/rMD-exp/src/recordmydesktop.c +++ b/rMD-exp/src/recordmydesktop.c @@ -247,11 +247,9 @@ int main(int argc,char **argv){ pthread_join(flush_to_ogg_t,NULL); fprintf(stderr,"."); - //this thread will get cancelled instead of joined - //this is neccessary to terminate the application, if for some reason - //damage events are not delivered(i.e comp windopw managers) if(!pdata.args.full_shots) - pthread_cancel(poll_damage_t); + pthread_join(poll_damage_t,NULL); + fprintf(stderr,"."); if((!pdata.args.noshared)||(!pdata.args.nocondshared)){ @@ -262,16 +260,16 @@ int main(int argc,char **argv){ fprintf(stderr,"\n"); - + //Now that we are done with recording we cancel the timer + CancelTimer(); /** Encoding */ if(!pdata.args.encOnTheFly){ if(!Aborted){ - + fprintf(stderr,"Encoding started!\nPlease wait...\n"); pdata.running=1; InitEncoder(&pdata,&enc_data,1); //load encoding and flushing threads - pthread_create(&image_encode_t,NULL,EncodeImageBuffer,(void *)&pdata); if(!pdata.args.nosound){ //before we start loading again //we need to free any left-overs @@ -279,8 +277,6 @@ int main(int argc,char **argv){ free(pdata.sound_buffer->data); pdata.sound_buffer=pdata.sound_buffer->next; } - pthread_create(&sound_encode_t,NULL,EncodeSoundBuffer,(void *)&pdata); - } pthread_create(&flush_to_ogg_t,NULL,FlushToOgg,(void *)&pdata); @@ -288,32 +284,17 @@ int main(int argc,char **argv){ //start loading image and audio pthread_create(&load_cache_t,NULL,LoadCache,(void *)&pdata); - - //call loading func{ - //if avd>=0 - //load image from cache - //signal buffer - ////if avd<0 - //load sound from cache - //signal buffer - //} - //join and finish - pthread_join(load_cache_t,NULL); - pthread_cond_broadcast(&pdata.image_buffer_ready); - pthread_join(image_encode_t,NULL); - if(!pdata.args.nosound) - pthread_join(sound_encode_t,NULL); - + fprintf(stderr,"Encoding finished!\nWait a moment please...\n"); + pthread_join(flush_to_ogg_t,NULL); + fprintf(stderr,"Done!!!\n"); } - //clean-up data } /**@_______________________________________________@*/ //This can happen earlier, but in some cases it might get stuck. //So we must make sure the recording is not wasted. - XFlush(pdata.dpy); XCloseDisplay(pdata.dpy); if(Aborted){ diff --git a/rMD-exp/src/register_callbacks.c b/rMD-exp/src/register_callbacks.c index 677fc75..08c528f 100644 --- a/rMD-exp/src/register_callbacks.c +++ b/rMD-exp/src/register_callbacks.c @@ -56,6 +56,16 @@ void SetRunning(int signum){ Aborted=1; } +void CancelTimer(void){ + struct itimerval value; + value.it_interval.tv_sec= + value.it_value.tv_sec= + value.it_interval.tv_usec= + value.it_value.tv_usec=0; + + setitimer(ITIMER_REAL,&value,NULL); +} + void RegisterCallbacks(ProgArgs *args){ struct itimerval value; -- cgit v1.2.3