summaryrefslogtreecommitdiff
path: root/src/rmd_flush_to_ogg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rmd_flush_to_ogg.c')
-rw-r--r--src/rmd_flush_to_ogg.c235
1 files changed, 235 insertions, 0 deletions
diff --git a/src/rmd_flush_to_ogg.c b/src/rmd_flush_to_ogg.c
new file mode 100644
index 0000000..87308a6
--- /dev/null
+++ b/src/rmd_flush_to_ogg.c
@@ -0,0 +1,235 @@
+/******************************************************************************
+* recordMyDesktop *
+*******************************************************************************
+* *
+* Copyright (C) 2006,2007,2008 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 "config.h"
+#include "rmd_flush_to_ogg.h"
+
+#include "rmd_encode_image_buffer.h"
+#include "rmd_encode_sound_buffer.h"
+#include "rmd_types.h"
+
+#include <pthread.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.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
+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 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 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)
+ 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);
+ }
+ 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)
+ page_copy(&videopage_copy, &videopage);
+ pthread_mutex_unlock(&pdata->libogg_mutex);
+
+ //we need the last page to properly close the stream
+ if (!videoflag) {
+ 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) {
+ 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)
+ page_copy(&audiopage_copy, &audiopage);
+ pthread_mutex_unlock(&pdata->libogg_mutex);
+
+ //we need the last page to properly close the stream
+ if (!audioflag) {
+ 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;
+ }
+
+ 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);
+ }
+
+ 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.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);
+ }
+
+ page_free(&audiopage_copy);
+ }
+ }
+
+ 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);
+
+ 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);
+}
© All Rights Reserved