From 9ed6f5963df909cb4710b7dac1ca27d9e6147f90 Mon Sep 17 00:00:00 2001 From: iovar Date: Sun, 10 Dec 2006 14:56:00 +0000 Subject: Many changes, mostly focusing around proper interleaving of theora and vorbis streams (which should now be correct). Also missing eos has been taken care. New condition variables have been added to signal end of encoding threads and avoid lockups, caused by the new configuration for eos. Also the main thread handles better the joins now, making sure that the encoding threads do not get stuck waiting. git-svn-id: https://recordmydesktop.svn.sourceforge.net/svnroot/recordmydesktop/trunk@230 f606c939-3180-4ac9-a4b8-4b8779d57d0a --- recordmydesktop/include/recordmydesktop.h | 12 +++++++++-- recordmydesktop/src/cache_audio.c | 8 +++++-- recordmydesktop/src/cache_frame.c | 3 +++ recordmydesktop/src/encode_image_buffer.c | 10 ++++++++- recordmydesktop/src/encode_sound_buffer.c | 25 +++++++++++++++------ recordmydesktop/src/flush_to_ogg.c | 20 ++++++++++++----- recordmydesktop/src/load_cache.c | 7 ++++-- recordmydesktop/src/recordmydesktop.c | 36 ++++++++++++++++--------------- 8 files changed, 86 insertions(+), 35 deletions(-) (limited to 'recordmydesktop') diff --git a/recordmydesktop/include/recordmydesktop.h b/recordmydesktop/include/recordmydesktop.h index 585a3d1..59ac109 100644 --- a/recordmydesktop/include/recordmydesktop.h +++ b/recordmydesktop/include/recordmydesktop.h @@ -255,7 +255,9 @@ typedef struct _ProgData{ frametime; pthread_mutex_t list_mutex[2],//mutexes for concurrency protection of the lists sound_buffer_mutex, - libogg_mutex,//libogg is not thread safe + libogg_mutex,//libogg is not thread safe, +// libtheora_mutex,//same for libtheora +// libvorbis_mutex,//and libvorbis. 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 @@ -265,7 +267,13 @@ typedef struct _ProgData{ pause_cond,//this is blocks execution, when program is paused sound_buffer_ready,//sound encoding finished sound_data_read,//a buffer is ready for proccessing - image_buffer_ready;//image encoding finished + 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 + int th_encoding_clean,//these indicate a wait condition on the above cond vars + v_encoding_clean; + int v_enc_thread_waiting, + th_enc_thread_waiting; snd_pcm_t *sound_handle; snd_pcm_uframes_t periodsize; }ProgData; diff --git a/recordmydesktop/src/cache_audio.c b/recordmydesktop/src/cache_audio.c index 99465de..afd08cf 100644 --- a/recordmydesktop/src/cache_audio.c +++ b/recordmydesktop/src/cache_audio.c @@ -41,9 +41,13 @@ void *CacheSoundBuffer(ProgData *pdata){ pthread_mutex_init(&tmut,NULL); pthread_cond_wait(&pdata->pause_cond,&tmut); } - - if(pdata->sound_buffer==NULL) + if(pdata->sound_buffer==NULL){ + pdata->v_enc_thread_waiting=1; pthread_cond_wait(&pdata->sound_data_read,&smut); + 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; diff --git a/recordmydesktop/src/cache_frame.c b/recordmydesktop/src/cache_frame.c index 813b9e0..d77308a 100644 --- a/recordmydesktop/src/cache_frame.c +++ b/recordmydesktop/src/cache_frame.c @@ -111,7 +111,10 @@ void *CacheImageBuffer(ProgData *pdata){ FrameHeader fheader; ynum=unum=vnum=0; + pdata->th_enc_thread_waiting=1; pthread_cond_wait(&pdata->image_buffer_ready,&imut); + pdata->th_enc_thread_waiting=0; + if(Paused) pthread_cond_wait(&pdata->pause_cond,&pmut); pthread_mutex_lock(&pdata->yuv_mutex); diff --git a/recordmydesktop/src/encode_image_buffer.c b/recordmydesktop/src/encode_image_buffer.c index 60d87c4..3c50a6f 100644 --- a/recordmydesktop/src/encode_image_buffer.c +++ b/recordmydesktop/src/encode_image_buffer.c @@ -29,12 +29,16 @@ void *EncodeImageBuffer(ProgData *pdata){ pthread_mutex_t pmut,imut; pthread_mutex_init(&pmut,NULL); pthread_mutex_init(&imut,NULL); + pdata->th_encoding_clean=0; while(pdata->running){ + pdata->th_enc_thread_waiting=1; pthread_cond_wait(&pdata->image_buffer_ready,&imut); + pdata->th_enc_thread_waiting=0; encoder_busy=1; if(Paused) pthread_cond_wait(&pdata->pause_cond,&pmut);//this may not be needed pthread_mutex_lock(&pdata->yuv_mutex); +// pthread_mutex_lock(&pdata->libtheora_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); @@ -48,10 +52,12 @@ void *EncodeImageBuffer(ProgData *pdata){ pdata->avd+=pdata->frametime; } } +// pthread_mutex_unlock(&pdata->libtheora_mutex); encoder_busy=0; } //last packet - + pdata->th_encoding_clean=1; + pthread_cond_signal(&pdata->theora_lib_clean); // SyncEncodeImageBuffer(pdata); pthread_exit(&errno); } @@ -59,6 +65,7 @@ void *EncodeImageBuffer(ProgData *pdata){ //this function is meant to be called normally //not through a thread of it's own void SyncEncodeImageBuffer(ProgData *pdata){ +// pthread_mutex_lock(&pdata->libtheora_mutex); if(theora_encode_YUVin(&pdata->enc_data->m_th_st, &pdata->enc_data->yuv)){ fprintf(stderr,"Encoder not ready!\n"); @@ -74,5 +81,6 @@ void SyncEncodeImageBuffer(ProgData *pdata){ pdata->avd+=pdata->frametime; } } +// pthread_mutex_unlock(&pdata->libtheora_mutex); } diff --git a/recordmydesktop/src/encode_sound_buffer.c b/recordmydesktop/src/encode_sound_buffer.c index e72884b..d4c673b 100644 --- a/recordmydesktop/src/encode_sound_buffer.c +++ b/recordmydesktop/src/encode_sound_buffer.c @@ -32,6 +32,7 @@ void *EncodeSoundBuffer(ProgData *pdata){ int sampread=pdata->periodsize; pthread_mutex_t smut; pthread_mutex_init(&smut,NULL); + pdata->v_encoding_clean=0; while((pdata->running)){ float **vorbis_buffer; int count=0,i,j; @@ -43,15 +44,20 @@ void *EncodeSoundBuffer(ProgData *pdata){ pthread_cond_wait(&pdata->pause_cond,&tmut); } - if(pdata->sound_buffer==NULL) + if(pdata->sound_buffer==NULL){ + pdata->v_enc_thread_waiting=1; pthread_cond_wait(&pdata->sound_data_read,&smut); - + 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); +// pthread_mutex_lock(&pdata->libvorbis_mutex); vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,sampread); for(i=0;iargs.channels;j++){ @@ -62,24 +68,27 @@ void *EncodeSoundBuffer(ProgData *pdata){ } 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)){ - 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); } } + pthread_mutex_unlock(&pdata->libogg_mutex); + +// pthread_mutex_unlock(&pdata->libvorbis_mutex); pdata->avd-=pdata->periodtime; free(buff->data); free(buff); } - + pdata->v_encoding_clean=1; + pthread_cond_signal(&pdata->vorbis_lib_clean); // SyncEncodeSoundBuffer(pdata,NULL); pthread_exit(&errno); } @@ -88,6 +97,7 @@ void SyncEncodeSoundBuffer(ProgData *pdata,signed char *buff){ float **vorbis_buffer; int count=0,i,j; int sampread=(buff!=NULL)?pdata->periodsize:0; +// pthread_mutex_lock(&pdata->libvorbis_mutex); vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,sampread); for(i=0;iargs.channels;j++){ @@ -98,6 +108,7 @@ void SyncEncodeSoundBuffer(ProgData *pdata,signed char *buff){ } 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){ @@ -108,9 +119,11 @@ void SyncEncodeSoundBuffer(ProgData *pdata,signed char *buff){ ogg_stream_packetin(&pdata->enc_data->m_ogg_vs,&pdata->enc_data->m_ogg_pckt2); } } - if(!pdata->running)pdata->enc_data->m_ogg_vs.e_o_s=1; pthread_mutex_unlock(&pdata->libogg_mutex); + if(!pdata->running)pdata->enc_data->m_ogg_vs.e_o_s=1; +// pthread_mutex_unlock(&pdata->libvorbis_mutex); + pdata->avd-=pdata->periodtime; } diff --git a/recordmydesktop/src/flush_to_ogg.c b/recordmydesktop/src/flush_to_ogg.c index 2390810..10d9553 100644 --- a/recordmydesktop/src/flush_to_ogg.c +++ b/recordmydesktop/src/flush_to_ogg.c @@ -65,6 +65,9 @@ void *FlushToOgg(ProgData *pdata){ double audiotime=0; double videotime=0; + pthread_mutex_t imut,vmut; + pthread_mutex_init(&imut,NULL); + pthread_mutex_init(&vmut,NULL); int working=1, th_st_fin=0, v_st_fin=(pdata->args.nosound); @@ -93,7 +96,12 @@ void *FlushToOgg(ProgData *pdata){ 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)SyncEncodeImageBuffer(pdata); + if(!videoflag){ + if(!pdata->th_encoding_clean){ + pthread_cond_wait(&pdata->theora_lib_clean,&imut); + } + SyncEncodeImageBuffer(pdata); + } } if(!pdata->args.nosound && !v_st_fin &&!audioflag){ pthread_mutex_lock(&pdata->libogg_mutex); @@ -102,7 +110,12 @@ void *FlushToOgg(ProgData *pdata){ 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)SyncEncodeSoundBuffer(pdata,NULL); + if(!audioflag){ + if(!pdata->v_encoding_clean){ + pthread_cond_wait(&pdata->vorbis_lib_clean,&vmut); + } + SyncEncodeSoundBuffer(pdata,NULL); + } } } if(th_st_fin)videoflag=0; @@ -150,8 +163,6 @@ void *FlushToOgg(ProgData *pdata){ working=(!th_st_fin || !v_st_fin); } - //last packages - pthread_mutex_lock(&pdata->libogg_mutex); ogg_stream_clear(&pdata->enc_data->m_ogg_ts); if(!pdata->args.nosound) @@ -161,7 +172,6 @@ void *FlushToOgg(ProgData *pdata){ // 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/load_cache.c b/recordmydesktop/src/load_cache.c index 41568c9..7693774 100644 --- a/recordmydesktop/src/load_cache.c +++ b/recordmydesktop/src/load_cache.c @@ -194,8 +194,11 @@ void *LoadCache(ProgData *pdata){ } } } - SyncEncodeImageBuffer(pdata); - SyncEncodeSoundBuffer(pdata,sound_data); +// SyncEncodeImageBuffer(pdata); +// SyncEncodeSoundBuffer(pdata,sound_data); + pdata->v_encoding_clean=pdata->th_encoding_clean=1; + pthread_cond_signal(&pdata->theora_lib_clean); + pthread_cond_signal(&pdata->vorbis_lib_clean); fprintf(stdout,"\n"); CLEAR_FRAME(&frame) free(sound_data); diff --git a/recordmydesktop/src/recordmydesktop.c b/recordmydesktop/src/recordmydesktop.c index f15bdc9..0a9aa79 100644 --- a/recordmydesktop/src/recordmydesktop.c +++ b/recordmydesktop/src/recordmydesktop.c @@ -119,6 +119,8 @@ int main(int argc,char **argv){ pthread_mutex_init(&pdata.list_mutex[1],NULL); pthread_mutex_init(&pdata.sound_buffer_mutex,NULL); pthread_mutex_init(&pdata.libogg_mutex,NULL); +// pthread_mutex_init(&pdata.libtheora_mutex,NULL); +// pthread_mutex_init(&pdata.libvorbis_mutex,NULL); pthread_mutex_init(&pdata.yuv_mutex,NULL); pthread_cond_init(&pdata.time_cond,NULL); @@ -126,6 +128,9 @@ int main(int argc,char **argv){ pthread_cond_init(&pdata.image_buffer_ready,NULL); pthread_cond_init(&pdata.sound_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.list_selector=Paused=Aborted=pdata.avd=0; pdata.sound_buffer=NULL; pdata.running=1; @@ -233,34 +238,31 @@ int main(int argc,char **argv){ pthread_join(image_capture_t,NULL); fprintf(stderr,"Shutting down."); //if no damage events have been received the thread will get stuck - pthread_cond_broadcast(&pdata.image_buffer_ready); - if(pdata.args.encOnTheFly) + while(!pdata.th_enc_thread_waiting && !pdata.th_encoding_clean){ + usleep(10000); + pthread_cond_signal(&pdata.image_buffer_ready); + } +// pthread_cond_broadcast(&pdata.image_buffer_ready); + if(pdata.args.encOnTheFly){ pthread_join(image_encode_t,NULL); + } else pthread_join(image_cache_t,NULL); fprintf(stderr,"."); if(!pdata.args.nosound){ - int *snd_exit; - pthread_join(sound_capture_t,(void *)(&snd_exit)); + pthread_join(sound_capture_t,NULL); fprintf(stderr,"."); - + while(!pdata.v_enc_thread_waiting && !pdata.v_encoding_clean){ + usleep(10000); + pthread_cond_signal(&pdata.sound_data_read); + } if(pdata.args.encOnTheFly){ - if(!(*snd_exit)) - pthread_join(sound_encode_t,NULL); - else{ - pthread_cancel(sound_encode_t); - exit_status=*snd_exit; - } + pthread_join(sound_encode_t,NULL); } else{ - if(!(*snd_exit)) - pthread_join(sound_cache_t,NULL); - else{ - pthread_cancel(sound_cache_t); - exit_status=*snd_exit; - } + pthread_join(sound_cache_t,NULL); } } else -- cgit v1.2.3