summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--recordmydesktop/src/encode_image_buffer.c11
-rw-r--r--recordmydesktop/src/encode_sound_buffer.c17
-rw-r--r--recordmydesktop/src/flush_to_ogg.c152
-rw-r--r--recordmydesktop/src/load_cache.c2
-rw-r--r--recordmydesktop/src/opendev.c12
5 files changed, 136 insertions, 58 deletions
diff --git a/recordmydesktop/src/encode_image_buffer.c b/recordmydesktop/src/encode_image_buffer.c
index 979916d..60d87c4 100644
--- a/recordmydesktop/src/encode_image_buffer.c
+++ b/recordmydesktop/src/encode_image_buffer.c
@@ -51,14 +51,8 @@ void *EncodeImageBuffer(ProgData *pdata){
encoder_busy=0;
}
//last packet
- if(theora_encode_YUVin(&pdata->enc_data->m_th_st,&pdata->enc_data->yuv)){
- fprintf(stderr,"Encoder not ready!\n");
- }
-
- theora_encode_packetout(&pdata->enc_data->m_th_st,1,&pdata->enc_data->m_ogg_pckt1);
-
-// ogg_stream_packetin(&pdata->enc_data->m_ogg_ts,&pdata->enc_data->m_ogg_pckt);
+// SyncEncodeImageBuffer(pdata);
pthread_exit(&errno);
}
@@ -70,11 +64,12 @@ void SyncEncodeImageBuffer(ProgData *pdata){
fprintf(stderr,"Encoder not ready!\n");
}
else{
- if(theora_encode_packetout(&pdata->enc_data->m_th_st,0,
+ 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/encode_sound_buffer.c b/recordmydesktop/src/encode_sound_buffer.c
index ee19628..e72884b 100644
--- a/recordmydesktop/src/encode_sound_buffer.c
+++ b/recordmydesktop/src/encode_sound_buffer.c
@@ -79,21 +79,15 @@ void *EncodeSoundBuffer(ProgData *pdata){
free(buff);
}
- vorbis_analysis_wrote(&pdata->enc_data->m_vo_dsp,0);
-// 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);
-// }
+// SyncEncodeSoundBuffer(pdata,NULL);
pthread_exit(&errno);
}
void SyncEncodeSoundBuffer(ProgData *pdata,signed char *buff){
float **vorbis_buffer;
int count=0,i,j;
- int sampread=pdata->periodsize;
+ int sampread=(buff!=NULL)?pdata->periodsize:0;
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++){
@@ -104,18 +98,19 @@ 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){
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);
}
}
+ if(!pdata->running)pdata->enc_data->m_ogg_vs.e_o_s=1;
+ pthread_mutex_unlock(&pdata->libogg_mutex);
+
pdata->avd-=pdata->periodtime;
}
diff --git a/recordmydesktop/src/flush_to_ogg.c b/recordmydesktop/src/flush_to_ogg.c
index 8fa762f..2390810 100644
--- a/recordmydesktop/src/flush_to_ogg.c
+++ b/recordmydesktop/src/flush_to_ogg.c
@@ -26,55 +26,137 @@
#include <recordmydesktop.h>
+//we copy the page because the next call to ogg_stream_pageout
+//will invalidate it. But we must have pages from both streams at every time in
+//order to do correct multiplexing
+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++);
+
+}
+//free our copy
+void ogg_page_cp_free(ogg_page *pg){
+ pg->header_len=pg->body_len=0;
+ free(pg->header);
+ free(pg->body);
+}
+
void *FlushToOgg(ProgData *pdata){
int videoflag=0,audioflag=0;
double video_bytesout=0,audio_bytesout=0;
- ogg_page videopage,audiopage;
- while(pdata->running){
- pthread_mutex_lock(&pdata->libogg_mutex);
- videoflag=ogg_stream_pageout(&pdata->enc_data->m_ogg_ts,&videopage);
- pthread_mutex_unlock(&pdata->libogg_mutex);
- if(videoflag){
- video_bytesout+=fwrite(videopage.header,1,videopage.header_len,pdata->enc_data->fp);
- video_bytesout+=fwrite(videopage.body,1,videopage.body_len,pdata->enc_data->fp);
- videoflag=0;
- if(!pdata->args.nosound){
+ 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);
- audioflag=ogg_stream_pageout(&pdata->enc_data->m_ogg_vs,&audiopage);
+ 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);
- if(audioflag){
- audio_bytesout+=fwrite(audiopage.header,1,audiopage.header_len,pdata->enc_data->fp);
- audio_bytesout+=fwrite(audiopage.body,1,audiopage.body_len,pdata->enc_data->fp);
- audioflag=0;
- }
+ //we need the last page to properly close the stream
+ if(!videoflag)SyncEncodeImageBuffer(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)SyncEncodeSoundBuffer(pdata,NULL);
}
}
- else
+ 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);
}
//last packages
- pdata->enc_data->m_ogg_ts.e_o_s=1;
- videoflag=ogg_stream_flush(&pdata->enc_data->m_ogg_ts,&videopage);
- if(videoflag){
- video_bytesout+=fwrite(videopage.header,1,videopage.header_len,pdata->enc_data->fp);
- video_bytesout+=fwrite(videopage.body,1,videopage.body_len,pdata->enc_data->fp);
- videoflag=0;
- }
- if(!pdata->args.nosound){
- pdata->enc_data->m_ogg_vs.e_o_s=1;
- do{
- audioflag=ogg_stream_flush(&pdata->enc_data->m_ogg_vs,&audiopage);
- if(audioflag){
- audio_bytesout+=fwrite(audiopage.header,1,audiopage.header_len,pdata->enc_data->fp);
- audio_bytesout+=fwrite(audiopage.body,1,audiopage.body_len,pdata->enc_data->fp);
- audioflag=0;
- }
- }while(!ogg_page_eos(&audiopage));
- }
+
+ 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);
diff --git a/recordmydesktop/src/load_cache.c b/recordmydesktop/src/load_cache.c
index eee3fb7..41568c9 100644
--- a/recordmydesktop/src/load_cache.c
+++ b/recordmydesktop/src/load_cache.c
@@ -194,6 +194,8 @@ void *LoadCache(ProgData *pdata){
}
}
}
+ SyncEncodeImageBuffer(pdata);
+ SyncEncodeSoundBuffer(pdata,sound_data);
fprintf(stdout,"\n");
CLEAR_FRAME(&frame)
free(sound_data);
diff --git a/recordmydesktop/src/opendev.c b/recordmydesktop/src/opendev.c
index 9250bab..d5a6af9 100644
--- a/recordmydesktop/src/opendev.c
+++ b/recordmydesktop/src/opendev.c
@@ -36,14 +36,16 @@ snd_pcm_t *OpenDev(const char *pcm_dev,unsigned int *channels,unsigned int *freq
snd_pcm_hw_params_t *hwparams;
unsigned int periods=2;
unsigned int exactrate = *frequency;
-
+ snd_pcm_uframes_t buffsize=1024;
snd_pcm_hw_params_alloca(&hwparams);
- snd_pcm_uframes_t buffsize=4096;
+
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;
@@ -76,7 +78,7 @@ snd_pcm_t *OpenDev(const char *pcm_dev,unsigned int *channels,unsigned int *freq
fprintf(stderr, "Couldn't set periods.\n");
return NULL;
}
- buffsize=(exactrate)>>2;
+
if (snd_pcm_hw_params_set_buffer_size_near(mhandle, hwparams,&buffsize)<0){
fprintf(stderr, "Couldn't set buffer size.\n");
return NULL;
@@ -87,11 +89,13 @@ snd_pcm_t *OpenDev(const char *pcm_dev,unsigned int *channels,unsigned int *freq
}
if(hard_pause!=NULL)
if(!snd_pcm_hw_params_can_pause(hwparams)){
-// fprintf(stderr, "Current sound device doesn't seem to support pausing!\nI will attempt to close/reopen device in case you opt to pause during recording.\n");
*hard_pause=1;
}
if(periodsize!=NULL)
snd_pcm_hw_params_get_period_size(hwparams,periodsize,0);
+ snd_pcm_hw_params_get_buffer_size(hwparams,&buffsize);
+ fprintf(stderr,"buffsize %d,periodsize %d\n",buffsize,*periodsize);
+
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);
© All Rights Reserved