[Thoggen-cvs] SF.net SVN: thoggen: [210] branches/thoggen-gstreamer-0.8
Status: Beta
Brought to you by:
tp-m
From: <tp...@us...> - 2006-04-14 19:09:20
|
Revision: 210 Author: tp-m Date: 2006-04-14 12:09:08 -0700 (Fri, 14 Apr 2006) ViewCVS: http://svn.sourceforge.net/thoggen/?rev=210&view=rev Log Message: ----------- * src/th-job.c: (job_check_eos_watches): (job_eos_probe_cb): (job_create_pipeline_setup_eos_watch): (job_create_pipeline): (th_job_run): Add hack to force EOS at the end of a title if for some reason it doesn't work the normal way. Modified Paths: -------------- branches/thoggen-gstreamer-0.8/ChangeLog branches/thoggen-gstreamer-0.8/src/th-job.c Modified: branches/thoggen-gstreamer-0.8/ChangeLog =================================================================== --- branches/thoggen-gstreamer-0.8/ChangeLog 2006-04-14 18:22:27 UTC (rev 209) +++ branches/thoggen-gstreamer-0.8/ChangeLog 2006-04-14 19:09:08 UTC (rev 210) @@ -1,3 +1,14 @@ +2006-04-14 Tim-Philipp Müller <tim at centricular dot net> + + * src/th-job.c: + (job_check_eos_watches): + (job_eos_probe_cb): + (job_create_pipeline_setup_eos_watch): + (job_create_pipeline): + (th_job_run): + Add hack to force EOS at the end of a title if + for some reason it doesn't work the normal way. + 2006-04-11 Tim-Philipp Müller <tim at centricular dot net> * .cvsignore: Modified: branches/thoggen-gstreamer-0.8/src/th-job.c =================================================================== --- branches/thoggen-gstreamer-0.8/src/th-job.c 2006-04-14 18:22:27 UTC (rev 209) +++ branches/thoggen-gstreamer-0.8/src/th-job.c 2006-04-14 19:09:08 UTC (rev 210) @@ -84,6 +84,13 @@ LAST_SIGNAL }; + +typedef struct _ThJobEOSWatchHelper +{ + GstClockTime duration; + gint sent_eos; /* access atomically */ +} ThJobEOSWatchHelper; + struct _ThJobPrivate { gchar *device; /* device */ @@ -141,6 +148,9 @@ /* tag */ gchar *title_tag; gchar *comment_tag; + + ThJobEOSWatchHelper audio_watch; + ThJobEOSWatchHelper video_watch; }; typedef struct _ThJobAudioStream ThJobAudioStream; @@ -1655,6 +1665,27 @@ /*************************************************************************** * + * job_check_eos_watches + * + ***************************************************************************/ + +static gboolean +job_check_eos_watches (ThJob *j) +{ + if (g_atomic_int_get (&j->priv->audio_watch.sent_eos) && + g_atomic_int_get (&j->priv->video_watch.sent_eos)) { + th_log ("Both EOS watches sent EOS!"); + job_eos_cb (j, j->priv->pipeline); + /* wait for a second to give elements a chance + * to process the EOS and the remaining data */ + g_usleep (G_USEC_PER_SEC); + } + + return TRUE; +} + +/*************************************************************************** + * * job_check_free_disk_space * ***************************************************************************/ @@ -1838,6 +1869,110 @@ /*************************************************************************** * + * job_eos_probe_cb + * + * Called whenever data (a buffer or an event) leaves the decoder. When + * we find it pushes buffers beyond the end of the file, we suppress them + * and send an EOS event instead, hoping that will hack around the problem + * with ripping sometimes not stopping at the end of a title. + * + ***************************************************************************/ + +static gboolean +job_eos_probe_cb (GstProbe *p, GstData **p_data, ThJobEOSWatchHelper *helper) +{ + GstClockTime ts; + + if (g_atomic_int_get (&helper->sent_eos) != 0) + return FALSE; /* remove data from stream */ + + if (GST_IS_BUFFER (*p_data)) { + ts = GST_BUFFER_TIMESTAMP (*p_data); + goto check_timestamp; + } + + if (GST_IS_EVENT (*p_data)) { + switch (GST_EVENT_TYPE (*p_data)) + { + case GST_EVENT_FILLER: + { + guint64 dur; + + ts = GST_EVENT_TIMESTAMP (*p_data); + if (ts == (guint64) -1) + break; + dur = gst_event_filler_get_duration (GST_EVENT (*p_data)); + if (dur == (guint64) -1) + break; + ts += dur; + goto check_timestamp; + } + case GST_EVENT_EOS: + { + g_atomic_int_inc (&helper->sent_eos); + break; + } + default: + break; + } + } + + return TRUE; /* do not remove data from stream */ + + +check_timestamp: + { + if (ts == (GstClockTime) -1) + return TRUE; /* do not remove data from stream */ + + if (ts <= helper->duration) + return TRUE; /* do not remove data from stream */ + + /* remove data if timestamp is beyond duration */ + th_log ("Injecting artificial EOS"); + g_atomic_int_inc (&helper->sent_eos); + gst_data_unref (*p_data); + *p_data = GST_DATA (gst_event_new (GST_EVENT_EOS)); + return TRUE; /* send EOS event downstream */ + } +} + +/*************************************************************************** + * + * job_create_pipeline_setup_eos_watch + * + ***************************************************************************/ + +static void +job_create_pipeline_setup_eos_watch (ThJob *j, const gchar *decoder_name, + ThJobEOSWatchHelper * helper) +{ + GstElement *decoder; + GstProbe *decoder_probe; + GstPad *src_pad; + + decoder = gst_bin_get_by_name (GST_BIN (j->priv->pipeline), decoder_name); + g_return_if_fail (decoder != NULL); + + src_pad = gst_element_get_pad (decoder, "src"); + g_return_if_fail (GST_IS_PAD (src_pad)); + + decoder_probe = gst_probe_new (FALSE, + (GstProbeCallback) job_eos_probe_cb, + helper); + + gst_pad_add_probe (src_pad, decoder_probe); + + g_object_weak_ref (G_OBJECT (src_pad), + (GWeakNotify) gst_probe_destroy, + decoder_probe); + + helper->duration = GST_SECOND * j->priv->title_length; + helper->sent_eos = FALSE; +} + +/*************************************************************************** + * * job_create_pipeline * ***************************************************************************/ @@ -1868,7 +2003,7 @@ " .%s " " ! { " " queue name=q-a-in " - " ! %s " + " ! %s name=audio-decoder " " ! audioconvert " " ! audioscale " " ! audio/x-raw-int,rate=44100,channels=2 " @@ -1880,7 +2015,7 @@ " { " " demux.%s " " ! queue name=q-v-in " - " ! mpeg2dec " + " ! mpeg2dec name=video-decoder " " ! videorate " " ! video/x-raw-yuv,framerate=(double)%u.0 " " ! videocrop left=%u right=%u top=%u bottom=%u " @@ -1955,6 +2090,12 @@ "handoff", G_CALLBACK (job_output_identity_handoff_cb), j); + + /* set up EOS watches */ + job_create_pipeline_setup_eos_watch (j, "audio-decoder", + &j->priv->audio_watch); + job_create_pipeline_setup_eos_watch (j, "video-decoder", + &j->priv->video_watch); gst_element_set_state (j->priv->pipeline, GST_STATE_PLAYING); @@ -1975,7 +2116,7 @@ gboolean th_job_run (ThJob *j, GError **err) { - gulong checkid; + gulong checkid, eos_checkid; g_return_val_if_fail (TH_IS_JOB (j), FALSE); g_return_val_if_fail (j->priv->pipeline == NULL, FALSE); @@ -2008,10 +2149,15 @@ checkid = g_timeout_add (DISK_SPACE_CHECK_INTERVAL*1000, (GSourceFunc) job_check_free_disk_space, j); + + eos_checkid = g_timeout_add (5*1000, + (GSourceFunc) job_check_eos_watches, + j); g_main_loop_run (j->priv->loop); g_source_remove (checkid); + g_source_remove (eos_checkid); if (j->priv->pipeline) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |