Changeset 228603 in webkit


Ignore:
Timestamp:
Feb 18, 2018 2:02:40 AM (6 years ago)
Author:
cturner@igalia.com
Message:

[GStreamer] Push smaller buffers from HTTP source
https://bugs.webkit.org/show_bug.cgi?id=182829

Reviewed by Philippe Normand.

Split the received buffer into smaller buffers of a size consistent
with the basesrc (4KiB). It is important not to push large buffers
into the appsrc (where large is relative to the appsrc's configured
byte size). If large buffers are pushed, then when they are internally
dequeued by the appsrc, the buffering percentage can dramatically
plummet due to a large amount of bytes being removed after a push. This
can in turn trick the media player into thinking it needs to buffer,
and then issuing a spurious set of playing->paused then
paused->playing transitions, which by the time the buffering logic
completes, data are already available.

  • platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:

(CachedResourceStreamingClient::dataReceived):

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r228601 r228603  
     12018-02-18  Charlie Turner  <cturner@igalia.com>
     2
     3        [GStreamer] Push smaller buffers from HTTP source
     4        https://bugs.webkit.org/show_bug.cgi?id=182829
     5
     6        Reviewed by Philippe Normand.
     7
     8        Split the received buffer into smaller buffers of a size consistent
     9        with the basesrc (4KiB). It is important not to push large buffers
     10        into the appsrc (where large is relative to the appsrc's configured
     11        byte size). If large buffers are pushed, then when they are internally
     12        dequeued by the appsrc, the buffering percentage can dramatically
     13        plummet due to a large amount of bytes being removed after a push. This
     14        can in turn trick the media player into thinking it needs to buffer,
     15        and then issuing a spurious set of playing->paused then
     16        paused->playing transitions, which by the time the buffering logic
     17        completes, data are already available.
     18
     19        * platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:
     20        (CachedResourceStreamingClient::dataReceived):
     21
    1222018-02-17  Darin Adler  <darin@apple.com>
    223
  • trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp

    r227061 r228603  
    3333#include "ResourceRequest.h"
    3434#include "ResourceResponse.h"
     35#include <cstdint>
    3536#include <gst/app/gstappsrc.h>
    3637#include <gst/pbutils/missing-plugins.h>
     
    893894        gst_buffer_set_size(priv->buffer.get(), static_cast<gssize>(length));
    894895
    895     GST_BUFFER_OFFSET(priv->buffer.get()) = priv->offset;
     896    uint64_t startingOffset = priv->offset;
     897
    896898    if (priv->requestedOffset == priv->offset)
    897899        priv->requestedOffset += length;
     
    903905        priv->size = priv->offset;
    904906    }
    905     GST_BUFFER_OFFSET_END(priv->buffer.get()) = priv->offset;
    906 
    907     GstFlowReturn ret = gst_app_src_push_buffer(priv->appsrc, priv->buffer.leakRef());
    908     if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
    909         GST_ELEMENT_ERROR(src, CORE, FAILED, (nullptr), (nullptr));
     907
     908    // Now split the recv'd buffer into buffers that are of a size basesrc suggests. It is important not
     909    // to push buffers that are too large, otherwise incorrect buffering messages can be sent from the
     910    // pipeline.
     911    uint64_t bufferSize = gst_buffer_get_size(priv->buffer.get());
     912    uint64_t blockSize = static_cast<uint64_t>(GST_BASE_SRC_CAST(priv->appsrc)->blocksize);
     913    ASSERT(blockSize);
     914    GST_LOG_OBJECT(src, "Splitting the received buffer into %" PRIu64 " blocks", bufferSize / blockSize);
     915    for (uint64_t currentOffset = 0; currentOffset < bufferSize; currentOffset += blockSize) {
     916        uint64_t subBufferOffset = startingOffset + currentOffset;
     917        uint64_t currentOffsetSize = std::min(blockSize, bufferSize - currentOffset);
     918
     919        GST_TRACE_OBJECT(src, "Create sub-buffer from [%" PRIu64 ", %" PRIu64 "]", currentOffset, currentOffset + currentOffsetSize);
     920        GstBuffer* subBuffer = gst_buffer_copy_region(priv->buffer.get(), GST_BUFFER_COPY_ALL, currentOffset, currentOffsetSize);
     921        if (UNLIKELY(!subBuffer)) {
     922            GST_ELEMENT_ERROR(src, CORE, FAILED, ("Failed to allocate sub-buffer"), (nullptr));
     923            break;
     924        }
     925
     926        GST_BUFFER_OFFSET(subBuffer) = subBufferOffset;
     927        GST_BUFFER_OFFSET_END(subBuffer) = subBufferOffset + currentOffsetSize;
     928        GST_TRACE_OBJECT(src, "Set sub-buffer offset bounds [%" PRIu64 ", %" PRIu64 "]", GST_BUFFER_OFFSET(subBuffer), GST_BUFFER_OFFSET_END(subBuffer));
     929
     930        GST_TRACE_OBJECT(src, "Pushing buffer of size %" G_GSIZE_FORMAT " bytes", gst_buffer_get_size(subBuffer));
     931        GstFlowReturn ret = gst_app_src_push_buffer(priv->appsrc, subBuffer);
     932
     933        if (UNLIKELY(ret != GST_FLOW_OK && ret != GST_FLOW_EOS && ret != GST_FLOW_FLUSHING)) {
     934            GST_ELEMENT_ERROR(src, CORE, FAILED, (nullptr), (nullptr));
     935            break;
     936        }
     937    }
     938
     939    priv->buffer.clear();
    910940}
    911941
Note: See TracChangeset for help on using the changeset viewer.