aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLRN <lrn1986@gmail.com>2012-09-14 11:50:02 +0000
committerLRN <lrn1986@gmail.com>2012-09-14 11:50:02 +0000
commit2445d2186e33a00d5c766219f8187fa81782b40c (patch)
tree00c2c1d2e693877a7cc47259a55a4a014fc40f84
parent75823e00518eaaab9855f99908eed9cfcad92229 (diff)
downloadlibextractor-2445d2186e33a00d5c766219f8187fa81782b40c.tar.gz
libextractor-2445d2186e33a00d5c766219f8187fa81782b40c.zip
Add timeouts for GstDiscoverer interaction
If discoverer goes more than 80ms without asking us for something, or giving us data, assume it hanged up, and leave the processing loop. Will hang up for 90ms at most (checks for timeout condition every 45ms).
-rw-r--r--src/plugins/gstreamer_extractor.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/plugins/gstreamer_extractor.c b/src/plugins/gstreamer_extractor.c
index 86a5896..0e005b4 100644
--- a/src/plugins/gstreamer_extractor.c
+++ b/src/plugins/gstreamer_extractor.c
@@ -33,6 +33,19 @@
33GST_DEBUG_CATEGORY_STATIC (gstreamer_extractor); 33GST_DEBUG_CATEGORY_STATIC (gstreamer_extractor);
34#define GST_CAT_DEFAULT gstreamer_extractor 34#define GST_CAT_DEFAULT gstreamer_extractor
35 35
36/**
37 * How often should we check for data timeout.
38 * In milliseconds.
39 */
40#define DATA_TIMEOUT_FREQUENCY 45 /* 45ms, hang up for 90ms at most */
41
42/**
43 * Once discoverer has gone for that long without asking for data or
44 * asking to seek, or giving us discovered info, assume it hanged up
45 * and kill it.
46 * In microseconds.
47 */
48#define DATA_TIMEOUT 80000 /* 80ms */
36 49
37/** 50/**
38 * Struct mapping GSTREAMER tags to LE tags. 51 * Struct mapping GSTREAMER tags to LE tags.
@@ -770,6 +783,8 @@ struct PrivStruct
770 enum CurrentStreamType st; 783 enum CurrentStreamType st;
771 GMainLoop *loop; 784 GMainLoop *loop;
772 GstDiscoverer *dc; 785 GstDiscoverer *dc;
786 guint timeout_id;
787 gint64 last_data_request_time;
773}; 788};
774 789
775 790
@@ -793,6 +808,9 @@ feed_data (GstElement * appsrc, guint size, struct PrivStruct * ps)
793 808
794 GST_DEBUG ("Request %u bytes", size); 809 GST_DEBUG ("Request %u bytes", size);
795 810
811 /* Update it now, in case we bail out due to error */
812 ps->last_data_request_time = g_get_monotonic_time ();
813
796 if (ps->length > 0 && ps->offset >= ps->length) { 814 if (ps->length > 0 && ps->offset >= ps->length) {
797 /* we are at the EOS, send end-of-stream */ 815 /* we are at the EOS, send end-of-stream */
798 gst_app_src_end_of_stream (GST_APP_SRC (ps->source)); 816 gst_app_src_end_of_stream (GST_APP_SRC (ps->source));
@@ -844,6 +862,8 @@ feed_data (GstElement * appsrc, guint size, struct PrivStruct * ps)
844 gst_app_src_end_of_stream (GST_APP_SRC (ps->source)); 862 gst_app_src_end_of_stream (GST_APP_SRC (ps->source));
845 } 863 }
846 864
865 /* Update it again to account for time we spent fulfilling the request */
866 ps->last_data_request_time = g_get_monotonic_time ();
847 return; 867 return;
848} 868}
849 869
@@ -854,6 +874,7 @@ seek_data (GstElement * appsrc, guint64 position, struct PrivStruct * ps)
854 GST_DEBUG ("seek to offset %" G_GUINT64_FORMAT, position); 874 GST_DEBUG ("seek to offset %" G_GUINT64_FORMAT, position);
855 ps->offset = ps->ec->seek (ps->ec->cls, position, SEEK_SET); 875 ps->offset = ps->ec->seek (ps->ec->cls, position, SEEK_SET);
856 876
877 ps->last_data_request_time = g_get_monotonic_time ();
857 return ps->offset >= 0; 878 return ps->offset >= 0;
858} 879}
859 880
@@ -1732,15 +1753,31 @@ _new_discovered_uri (GstDiscoverer * dc,
1732 struct PrivStruct *ps) 1753 struct PrivStruct *ps)
1733{ 1754{
1734 send_discovered_info (info, ps); 1755 send_discovered_info (info, ps);
1756 ps->last_data_request_time = g_get_monotonic_time ();
1735} 1757}
1736 1758
1737 1759
1738static void 1760static void
1739_discoverer_finished (GstDiscoverer * dc, struct PrivStruct *ps) 1761_discoverer_finished (GstDiscoverer * dc, struct PrivStruct *ps)
1740{ 1762{
1763 if (ps->timeout_id > 0)
1764 g_source_remove (ps->timeout_id);
1765 ps->timeout_id = 0;
1741 g_main_loop_quit (ps->loop); 1766 g_main_loop_quit (ps->loop);
1742} 1767}
1743 1768
1769static gboolean
1770_data_timeout (struct PrivStruct *ps)
1771{
1772 gint64 now = g_get_monotonic_time ();
1773 if (now - ps->last_data_request_time > DATA_TIMEOUT)
1774 {
1775 ps->timeout_id = 0;
1776 g_main_loop_quit (ps->loop);
1777 return FALSE;
1778 }
1779 return TRUE;
1780}
1744 1781
1745/** 1782/**
1746 * This callback is called when discoverer has constructed a source object to 1783 * This callback is called when discoverer has constructed a source object to
@@ -1772,6 +1809,8 @@ _source_setup (GstDiscoverer * dc,
1772 * data */ 1809 * data */
1773 g_signal_connect (ps->source, "need-data", G_CALLBACK (feed_data), ps); 1810 g_signal_connect (ps->source, "need-data", G_CALLBACK (feed_data), ps);
1774 g_signal_connect (ps->source, "seek-data", G_CALLBACK (seek_data), ps); 1811 g_signal_connect (ps->source, "seek-data", G_CALLBACK (seek_data), ps);
1812 ps->timeout_id = g_timeout_add (DATA_TIMEOUT_FREQUENCY, _data_timeout, ps);
1813 ps->last_data_request_time = g_get_monotonic_time ();
1775} 1814}
1776 1815
1777 1816
@@ -1812,6 +1851,8 @@ EXTRACTOR_gstreamer_extract_method (struct EXTRACTOR_ExtractContext *ec)
1812 gst_discoverer_start (ps.dc); 1851 gst_discoverer_start (ps.dc);
1813 g_idle_add ((GSourceFunc) &_run_async, &ps); 1852 g_idle_add ((GSourceFunc) &_run_async, &ps);
1814 g_main_loop_run (ps.loop); 1853 g_main_loop_run (ps.loop);
1854 if (ps.timeout_id > 0)
1855 g_source_remove (ps.timeout_id);
1815 gst_discoverer_stop (ps.dc); 1856 gst_discoverer_stop (ps.dc);
1816 g_object_unref (ps.dc); 1857 g_object_unref (ps.dc);
1817 g_main_loop_unref (ps.loop); 1858 g_main_loop_unref (ps.loop);