Title: [248257] releases/WebKitGTK/webkit-2.24/Source/WebCore
Revision
248257
Author
[email protected]
Date
2019-08-03 20:24:16 -0700 (Sat, 03 Aug 2019)

Log Message

Merge r247903 - REGRESSION(r243058): [GStreamer] WebKitWebSrc's internal queue can exhaust the WebProcess memory
https://bugs.webkit.org/show_bug.cgi?id=199998

Reviewed by Xabier Rodriguez-Calvar.

With the webkitwebsrc rewrite the element lost its ability to tell
the resource loader when to pause and resume downloading because
we don't use appsrc and its enough-data/need-data signals anymore.
So new heuristics are introduced with this patch. Downloading of
resources bigger than 2MiB might pause when the internal adapter
has enough data (2% of the full resource) and resume when the
adapter size goes below 20% of those 2%.

No new tests, the media element spec doesn't clearly mandate how
the resource loading should behave when the element is paused or
how aggressively the resource should be downloaded during
playback.

This patch was functionally tested with a 1.3GiB resource loaded
over the local network, the resource was downloaded in ~30MiB
chunks, stopping and resuming every 20 seconds, approximately.

* platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:
(webkit_web_src_class_init):
(webKitWebSrcCreate):
(CachedResourceStreamingClient::responseReceived):
(CachedResourceStreamingClient::dataReceived):

Modified Paths

Diff

Modified: releases/WebKitGTK/webkit-2.24/Source/WebCore/ChangeLog (248256 => 248257)


--- releases/WebKitGTK/webkit-2.24/Source/WebCore/ChangeLog	2019-08-04 03:24:14 UTC (rev 248256)
+++ releases/WebKitGTK/webkit-2.24/Source/WebCore/ChangeLog	2019-08-04 03:24:16 UTC (rev 248257)
@@ -1,3 +1,33 @@
+2019-07-29  Philippe Normand  <[email protected]>
+
+        REGRESSION(r243058): [GStreamer] WebKitWebSrc's internal queue can exhaust the WebProcess memory
+        https://bugs.webkit.org/show_bug.cgi?id=199998
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        With the webkitwebsrc rewrite the element lost its ability to tell
+        the resource loader when to pause and resume downloading because
+        we don't use appsrc and its enough-data/need-data signals anymore.
+        So new heuristics are introduced with this patch. Downloading of
+        resources bigger than 2MiB might pause when the internal adapter
+        has enough data (2% of the full resource) and resume when the
+        adapter size goes below 20% of those 2%.
+
+        No new tests, the media element spec doesn't clearly mandate how
+        the resource loading should behave when the element is paused or
+        how aggressively the resource should be downloaded during
+        playback.
+
+        This patch was functionally tested with a 1.3GiB resource loaded
+        over the local network, the resource was downloaded in ~30MiB
+        chunks, stopping and resuming every 20 seconds, approximately.
+
+        * platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:
+        (webkit_web_src_class_init):
+        (webKitWebSrcCreate):
+        (CachedResourceStreamingClient::responseReceived):
+        (CachedResourceStreamingClient::dataReceived):
+
 2019-07-24  Alicia Boya GarcĂ­a  <[email protected]>
 
         [GStreamer] Don't crash with empty video src

Modified: releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp (248256 => 248257)


--- releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp	2019-08-04 03:24:14 UTC (rev 248256)
+++ releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp	2019-08-04 03:24:16 UTC (rev 248257)
@@ -38,6 +38,17 @@
 
 using namespace WebCore;
 
+// Never pause download of media resources smaller than 2MiB.
+#define SMALL_MEDIA_RESOURCE_MAX_SIZE 2 * 1024 * 1024
+
+// Keep at most 2% of the full, non-small, media resource buffered. When this
+// threshold is reached, the download task is paused.
+#define HIGH_QUEUE_FACTOR_THRESHOLD 0.02
+
+// Keep at least 20% of maximum queue size buffered. When this threshold is
+// reached, the download task resumes.
+#define LOW_QUEUE_FACTOR_THRESHOLD 0.2
+
 class CachedResourceStreamingClient final : public PlatformMediaResourceClient {
     WTF_MAKE_NONCOPYABLE(CachedResourceStreamingClient);
 public:
@@ -129,6 +140,7 @@
     Lock adapterLock;
     Condition adapterCondition;
     uint64_t queueSize { 0 };
+    bool isDownloadSuspended { false };
     GRefPtr<GstAdapter> adapter;
     GRefPtr<GstEvent> httpHeadersEvent;
     GUniquePtr<GstStructure> httpHeaders;
@@ -185,7 +197,7 @@
     GstElementClass* eklass = GST_ELEMENT_CLASS(klass);
     gst_element_class_add_static_pad_template(eklass, &srcTemplate);
 
-    gst_element_class_set_metadata(eklass, "WebKit Web source element", "Source", "Handles HTTP/HTTPS uris",
+    gst_element_class_set_metadata(eklass, "WebKit Web source element", "Source/Network", "Handles HTTP/HTTPS uris",
         "Philippe Normand <[email protected]>");
 
     /* Allows setting the uri using the 'location' property, which is used
@@ -378,7 +390,9 @@
         });
     }
 
-    GST_TRACE_OBJECT(src, "flushing: %s, doesHaveEOS: %s, queueSize: %" G_GSIZE_FORMAT, boolForPrinting(priv->isFlushing), boolForPrinting(priv->doesHaveEOS), priv->queueSize);
+    GST_TRACE_OBJECT(src, "flushing: %s, doesHaveEOS: %s, queueSize: %" G_GSIZE_FORMAT ", isDownloadSuspended: %s",
+        boolForPrinting(priv->isFlushing), boolForPrinting(priv->doesHaveEOS), priv->queueSize,
+        boolForPrinting(priv->isDownloadSuspended));
 
     if (priv->isFlushing) {
         GST_DEBUG_OBJECT(src, "Flushing");
@@ -410,7 +424,7 @@
     }
 
     if (isAdapterDrained) {
-        GST_DEBUG_OBJECT(src, "Adapter still empty after 3 seconds of waiting, assuming EOS");
+        GST_DEBUG_OBJECT(src, "Adapter still empty after 800 milli-seconds of waiting, assuming EOS");
         return GST_FLOW_EOS;
     }
 
@@ -444,6 +458,17 @@
                     priv->doesHaveEOS = true;
             } else if (priv->wasSeeking)
                 priv->wasSeeking = false;
+
+            if (!priv->doesHaveEOS && priv->haveSize && priv->isSeekable
+                && (priv->size > SMALL_MEDIA_RESOURCE_MAX_SIZE) && priv->readPosition
+                && (priv->readPosition != priv->size)
+                && (priv->queueSize < (priv->size * HIGH_QUEUE_FACTOR_THRESHOLD * LOW_QUEUE_FACTOR_THRESHOLD))
+                && (GST_STATE(src) == GST_STATE_PLAYING) && priv->isDownloadSuspended) {
+                GST_DEBUG_OBJECT(src, "[Buffering] Adapter running out of data, restarting download");
+                priv->isDownloadSuspended = false;
+                webKitWebSrcMakeRequest(baseSrc, false);
+            }
+
         } else
             GST_ERROR_OBJECT(src, "Empty adapter?");
     }
@@ -1016,7 +1041,8 @@
             priv->size = length;
             priv->isDurationSet = false;
         }
-    }
+    } else
+        priv->haveSize = false;
 
     // Signal to downstream if this is an Icecast stream.
     GRefPtr<GstCaps> caps;
@@ -1090,6 +1116,16 @@
         GstBuffer* buffer = gst_buffer_new_wrapped(g_memdup(data, length), length);
         priv->queueSize += length;
         gst_adapter_push(priv->adapter.get(), buffer);
+        GST_TRACE_OBJECT(src, "[Buffering] isDownloadSuspended: %s", boolForPrinting(priv->isDownloadSuspended));
+        if (priv->haveSize && (priv->size > SMALL_MEDIA_RESOURCE_MAX_SIZE) && (priv->queueSize > (priv->size * HIGH_QUEUE_FACTOR_THRESHOLD))
+            && !priv->isDownloadSuspended && priv->isSeekable) {
+            GST_TRACE_OBJECT(src, "[Buffering] queueSize: %" G_GUINT64_FORMAT ", threshold: %f", priv->queueSize,
+                priv->size * HIGH_QUEUE_FACTOR_THRESHOLD);
+            GST_DEBUG_OBJECT(src, "[Buffering] Stopping resource loader");
+            priv->isDownloadSuspended = true;
+            priv->resource->stop();
+            return;
+        }
         priv->adapterCondition.notifyOne();
     }
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to