diff options
author | LRN <lrn1986@gmail.com> | 2012-09-14 11:50:02 +0000 |
---|---|---|
committer | LRN <lrn1986@gmail.com> | 2012-09-14 11:50:02 +0000 |
commit | 2445d2186e33a00d5c766219f8187fa81782b40c (patch) | |
tree | 00c2c1d2e693877a7cc47259a55a4a014fc40f84 | |
parent | 75823e00518eaaab9855f99908eed9cfcad92229 (diff) | |
download | libextractor-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.c | 41 |
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 @@ | |||
33 | GST_DEBUG_CATEGORY_STATIC (gstreamer_extractor); | 33 | GST_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 | ||
1738 | static void | 1760 | static 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 | ||
1769 | static 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); |