From 58e5ec09e0feb7b6ebe2fc89ba32731b20a1ce39 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Sat, 20 Jun 2020 01:11:56 -0700 Subject: *: more code and synchronization cleanups Not going to bother with granular commit messages yet, not til things get reasonably sane --- recordmydesktop/src/rmd_encode_image_buffer.c | 2 +- recordmydesktop/src/rmd_flush_to_ogg.c | 201 +++++++++++++------------- recordmydesktop/src/rmd_init_encoder.c | 5 +- recordmydesktop/src/rmd_types.h | 46 +++--- 4 files changed, 129 insertions(+), 125 deletions(-) diff --git a/recordmydesktop/src/rmd_encode_image_buffer.c b/recordmydesktop/src/rmd_encode_image_buffer.c index c96412e..f7bd5a8 100644 --- a/recordmydesktop/src/rmd_encode_image_buffer.c +++ b/recordmydesktop/src/rmd_encode_image_buffer.c @@ -57,8 +57,8 @@ void *rmdEncodeImageBuffer(ProgData *pdata) { pthread_mutex_unlock(&pdata->yuv_mutex); } else { pthread_mutex_unlock(&pdata->yuv_mutex); - if (theora_encode_packetout(&enc_data->m_th_st, 0, &enc_data->m_ogg_pckt1) == 1) { + if (theora_encode_packetout(&enc_data->m_th_st, 0, &enc_data->m_ogg_pckt1) == 1) { pthread_mutex_lock(&pdata->libogg_mutex); ogg_stream_packetin(&enc_data->m_ogg_ts, &enc_data->m_ogg_pckt1); pdata->avd += pdata->frametime; diff --git a/recordmydesktop/src/rmd_flush_to_ogg.c b/recordmydesktop/src/rmd_flush_to_ogg.c index fa6b42e..6cd79fe 100644 --- a/recordmydesktop/src/rmd_flush_to_ogg.c +++ b/recordmydesktop/src/rmd_flush_to_ogg.c @@ -44,115 +44,120 @@ //will invalidate it. But we must have pages from //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;iheader_len;i++) - *(newp++)=*(oldp++); - newp=new->body; - oldp=old->body; - for(i=0;ibody_len;i++) - *(newp++)=*(oldp++); +static void page_copy(ogg_page *new, ogg_page *old) { + new->header_len = old->header_len; + new->header = malloc(new->header_len); + new->body_len = old->body_len; + new->body = malloc(new->body_len); + + memcpy(new->header, old->header, new->header_len); + memcpy(new->body, old->body, new->body_len); } + //free our copy -static void ogg_page_cp_free(ogg_page *pg) { - pg->header_len=pg->body_len=0; +static void page_free(ogg_page *pg) { + 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 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 th_st_fin = 0, + v_st_fin = (pdata->args.nosound); + + while (!(th_st_fin && v_st_fin)) { 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); + 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) + page_copy(&videopage_copy, &videopage); + } + + if (!pdata->args.nosound && !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) + page_copy(&audiopage_copy, &audiopage); } - 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); + 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) + page_copy(&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); - } + pthread_mutex_lock(&pdata->theora_lib_mutex); + while (!pdata->th_encoding_clean) + 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) { + + 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); + 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) + page_copy(&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); - } + pthread_mutex_lock(&pdata->vorbis_lib_mutex); + while (!pdata->v_encoding_clean) + pthread_cond_wait(&pdata->vorbis_lib_clean, &pdata->vorbis_lib_mutex); + pthread_mutex_unlock(&pdata->vorbis_lib_mutex); rmdSyncEncodeSoundBuffer(pdata,NULL); } } } + +#if 0 + /* I don't understand what this is about, if these are finished we want to lose + * their pages? + */ if (th_st_fin) videoflag=0; if (v_st_fin) audioflag=0; - +#endif if ((!audioflag && !v_st_fin && !pdata->args.nosound) || (!videoflag && !th_st_fin)) { usleep(10000); continue; @@ -163,50 +168,51 @@ void *rmdFlushToOgg(ProgData *pdata) { } else if (!videoflag) { audio_or_video=0; } else { - if (audiotimeenc_data->fp); + 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; + 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; + th_st_fin = 1; pthread_mutex_unlock(&pdata->libogg_mutex); } - ogg_page_cp_free(&videopage_copy); + + page_free(&videopage_copy); } else { - audio_bytesout+=fwrite( audiopage_copy.header,1, - audiopage_copy.header_len, - pdata->enc_data->fp); + 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; + 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; + v_st_fin = 1; pthread_mutex_unlock(&pdata->libogg_mutex); } - ogg_page_cp_free(&audiopage_copy); - } - working=(!th_st_fin || !v_st_fin); + page_free(&audiopage_copy); + } } + pthread_mutex_lock(&pdata->libogg_mutex); ogg_stream_clear(&pdata->enc_data->m_ogg_ts); @@ -214,8 +220,8 @@ void *rmdFlushToOgg(ProgData *pdata) { 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); + + theora_clear(&pdata->enc_data->m_th_st); if (pdata->enc_data->fp) fclose(pdata->enc_data->fp); @@ -224,5 +230,6 @@ void *rmdFlushToOgg(ProgData *pdata) { "(%.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_init_encoder.c b/recordmydesktop/src/rmd_init_encoder.c index dee0ba3..da442f2 100644 --- a/recordmydesktop/src/rmd_init_encoder.c +++ b/recordmydesktop/src/rmd_init_encoder.c @@ -126,7 +126,7 @@ void rmdInitEncoder(ProgData *pdata,EncData *enc_data_t,int buffer_ready) { //init ogg streams //skeleton first - ogg_stream_init(&m_ogg_skel,y0); + 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"); @@ -134,8 +134,6 @@ void rmdInitEncoder(ProgData *pdata,EncData *enc_data_t,int buffer_ready) { } 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) @@ -326,7 +324,6 @@ void rmdInitEncoder(ProgData *pdata,EncData *enc_data_t,int buffer_ready) { } 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* diff --git a/recordmydesktop/src/rmd_types.h b/recordmydesktop/src/rmd_types.h index cd2cca4..d80f835 100644 --- a/recordmydesktop/src/rmd_types.h +++ b/recordmydesktop/src/rmd_types.h @@ -263,30 +263,30 @@ struct _ProgData { 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 + snd_buff_ready_mutex, + img_buff_ready_mutex, + theora_lib_mutex, //serializes access to th_encoding_clean w/theora_lib_clean + vorbis_lib_mutex, //serializes acces to v_encoding_clean w/vorbis_lib_clean + 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 signal 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 -- cgit v1.2.3