Changeset 139877 in webkit


Ignore:
Timestamp:
Jan 16, 2013 6:15:58 AM (11 years ago)
Author:
kov@webkit.org
Message:

[GStreamer][Soup] Let GStreamer provide the buffer data is downloaded to, to avoid copying
https://bugs.webkit.org/show_bug.cgi?id=105552

Patch by Gustavo Noronha Silva <gustavo.noronha@collabora.com> on 2013-01-15
Reviewed by Philippe Normand.

Makes it possible for the GStreamer media backend to provide the buffer to which
the Soup networking backend will use to download data to. This makes copying
memory unnecessary when ResourceHandle hands data over to the media player's
StreamingClient. Thanks to Dan Winship for help designing the interface.

No behaviour change, covered by existing tests.

  • platform/graphics/gstreamer/GStreamerVersioning.cpp:

(getGstBufferSize): Abstract obtaining the size of the buffer, so the code
is cleaner while still working for both GST 0.10 and 1.0.
(setGstBufferSize): Ditto, but for setting the size.
(getGstBufferDataPointer): Ditto, but for grabbing the data pointer.
(mapGstBuffer): Convenience method to take care of mapping the buffer so that
we can provide the data pointer to ResourceHandle.
(unmapGstBuffer): Convenience method which takes care of unmapping the buffer
and properly freeing the GstMapInfo.

  • platform/graphics/gstreamer/GStreamerVersioning.h:
  • platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:

(StreamingClient): New methods.
(_WebKitWebSrcPrivate): We now store the GstBuffer we provided the data pointer from
so we can later unmap it and push it to the pipeline.
(webKitWebSrcDispose): Deal with the GstBuffer in case it exists when the source is
destroyed.
(webKitWebSrcStop): Also clear the GstBuffer in this case.
(StreamingClient::didReceiveData): Handle the hand-over of the buffer.
(StreamingClient::getBuffer): Provide ResourceHandle with a new GstBuffer's data pointer.

  • platform/network/ResourceHandleClient.h:

(ResourceHandleClient):
(WebCore::ResourceHandleClient::ResourceHandleClient): Constructor to initialize the buffer
member variable to 0.
(WebCore::ResourceHandleClient::~ResourceHandleClient): Destructor to free the buffer if it
has been allocated.
(WebCore::ResourceHandleClient::getBuffer): Default implementation which returns a
newly allocated char pointer.

  • platform/network/ResourceHandleInternal.h:

(WebCore::ResourceHandleInternal::ResourceHandleInternal):
(ResourceHandleInternal): Store actual buffer size, which is no longer a constant.

  • platform/network/soup/ResourceHandleSoup.cpp:

(WebCore::cleanupSoupRequestOperation): Clear the buffer pointer, the life-cycle of the
buffer is handled by the ResourceHandleClient.
(WebCore::nextMultipartResponsePartCallback): Get a new buffer from the client before reading.
(WebCore::sendRequestCallback): Ditto.
(WebCore::readCallback): Ditto.

Location:
trunk/Source/WebCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r139876 r139877  
     12013-01-15  Gustavo Noronha Silva  <gustavo.noronha@collabora.com>
     2
     3        [GStreamer][Soup] Let GStreamer provide the buffer data is downloaded to, to avoid copying
     4        https://bugs.webkit.org/show_bug.cgi?id=105552
     5
     6        Reviewed by Philippe Normand.
     7
     8        Makes it possible for the GStreamer media backend to provide the buffer to which
     9        the Soup networking backend will use to download data to. This makes copying
     10        memory unnecessary when ResourceHandle hands data over to the media player's
     11        StreamingClient. Thanks to Dan Winship for help designing the interface.
     12
     13        No behaviour change, covered by existing tests.
     14
     15        * platform/graphics/gstreamer/GStreamerVersioning.cpp:
     16        (getGstBufferSize): Abstract obtaining the size of the buffer, so the code
     17        is cleaner while still working for both GST 0.10 and 1.0.
     18        (setGstBufferSize): Ditto, but for setting the size.
     19        (getGstBufferDataPointer): Ditto, but for grabbing the data pointer.
     20        (mapGstBuffer): Convenience method to take care of mapping the buffer so that
     21        we can provide the data pointer to ResourceHandle.
     22        (unmapGstBuffer): Convenience method which takes care of unmapping the buffer
     23        and properly freeing the GstMapInfo.
     24        * platform/graphics/gstreamer/GStreamerVersioning.h:
     25        * platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:
     26        (StreamingClient): New methods.
     27        (_WebKitWebSrcPrivate): We now store the GstBuffer we provided the data pointer from
     28        so we can later unmap it and push it to the pipeline.
     29        (webKitWebSrcDispose): Deal with the GstBuffer in case it exists when the source is
     30        destroyed.
     31        (webKitWebSrcStop): Also clear the GstBuffer in this case.
     32        (StreamingClient::didReceiveData): Handle the hand-over of the buffer.
     33        (StreamingClient::getBuffer): Provide ResourceHandle with a new GstBuffer's data pointer.
     34        * platform/network/ResourceHandleClient.h:
     35        (ResourceHandleClient):
     36        (WebCore::ResourceHandleClient::ResourceHandleClient): Constructor to initialize the buffer
     37        member variable to 0.
     38        (WebCore::ResourceHandleClient::~ResourceHandleClient): Destructor to free the buffer if it
     39        has been allocated.
     40        (WebCore::ResourceHandleClient::getBuffer): Default implementation which returns a
     41        newly allocated char pointer.
     42        * platform/network/ResourceHandleInternal.h:
     43        (WebCore::ResourceHandleInternal::ResourceHandleInternal):
     44        (ResourceHandleInternal): Store actual buffer size, which is no longer a constant.
     45        * platform/network/soup/ResourceHandleSoup.cpp:
     46        (WebCore::cleanupSoupRequestOperation): Clear the buffer pointer, the life-cycle of the
     47        buffer is handled by the ResourceHandleClient.
     48        (WebCore::nextMultipartResponsePartCallback): Get a new buffer from the client before reading.
     49        (WebCore::sendRequestCallback): Ditto.
     50        (WebCore::readCallback): Ditto.
     51
    1522013-01-16  Jocelyn Turcotte  <jocelyn.turcotte@digia.com>
    253
  • trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.cpp

    r138919 r139877  
    11/*
    22 * Copyright (C) 2012 Igalia, S.L.
     3 * Copyright (C) 2013 Collabora Ltd.
    34 *
    45 *  This library is free software; you can redistribute it and/or
     
    3233#endif
    3334
     35#ifdef GST_API_VERSION_1
     36const char* webkitGstMapInfoQuarkString = "webkit-gst-map-info";
     37#endif
     38
    3439void webkitGstObjectRefSink(GstObject* gstObject)
    3540{
     
    122127}
    123128
     129int getGstBufferSize(GstBuffer* buffer)
     130{
     131#ifdef GST_API_VERSION_1
     132    return gst_buffer_get_size(buffer);
     133#else
     134    return GST_BUFFER_SIZE(buffer);
     135#endif
     136}
     137
     138void setGstBufferSize(GstBuffer* buffer, int newSize)
     139{
     140#ifdef GST_API_VERSION_1
     141    gst_buffer_set_size(buffer, static_cast<gssize>(newSize));
     142#else
     143    GST_BUFFER_SIZE(buffer) = static_cast<gsize>(newSize);
     144#endif
     145}
     146
     147char* getGstBufferDataPointer(GstBuffer* buffer)
     148{
     149#ifdef GST_API_VERSION_1
     150    static char* webkitGstMapInfoQuarkString = "webkit-gst-map-info";
     151    GstMiniObject* miniObject = reinterpret_cast<GstMiniObject*>(buffer);
     152    GstMapInfo* mapInfo = static_cast<GstMapInfo*>(gst_mini_object_get_qdata(miniObject, g_quark_from_static_string(webkitGstMapInfoQuarkString)));
     153    return reinterpret_cast<char*>(mapInfo->data);
     154#else
     155    return reinterpret_cast<char*>(GST_BUFFER_DATA(buffer));
     156#endif
     157}
     158
     159#ifdef GST_API_VERSION_1
     160void mapGstBuffer(GstBuffer* buffer)
     161{
     162    GstMapInfo* mapInfo = g_slice_new(GstMapInfo);
     163    if (!gst_buffer_map(buffer, mapInfo, GST_MAP_WRITE)) {
     164        g_slice_free(GstMapInfo, mapInfo);
     165        gst_buffer_unref(buffer);
     166        return;
     167    }
     168
     169    GstMiniObject* miniObject = reinterpret_cast<GstMiniObject*>(buffer);
     170    gst_mini_object_set_qdata(miniObject, g_quark_from_static_string("webkit-gst-map-info"), mapInfo, 0);
     171}
     172
     173void unmapGstBuffer(GstBuffer* buffer)
     174{
     175    GstMiniObject* miniObject = reinterpret_cast<GstMiniObject*>(buffer);
     176    GstMapInfo* mapInfo = static_cast<GstMapInfo*>(gst_mini_object_steal_qdata(miniObject, g_quark_from_static_string("webkit-gst-map-info")));
     177
     178    if (!mapInfo)
     179        return;
     180
     181    gst_buffer_unmap(buffer, mapInfo);
     182    g_slice_free(GstMapInfo, mapInfo);
     183}
     184#endif
     185
    124186void setGstElementClassMetadata(GstElementClass* elementClass, const char* name, const char* longName, const char* description, const char* author)
    125187{
  • trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.h

    r138786 r139877  
    3737#endif
    3838GstBuffer* createGstBuffer(GstBuffer*);
     39int getGstBufferSize(GstBuffer*);
     40void setGstBufferSize(GstBuffer*, int newSize);
     41char* getGstBufferDataPointer(GstBuffer*);
     42#ifdef GST_API_VERSION_1
     43void mapGstBuffer(GstBuffer*);
     44void unmapGstBuffer(GstBuffer*);
     45#endif
    3946void setGstElementClassMetadata(GstElementClass*, const char* name, const char* longName, const char* description, const char* author);
    4047bool gstObjectIsFloating(GstObject*);
  • trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp

    r135705 r139877  
    11/*
    22 *  Copyright (C) 2009, 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
     3 *  Copyright (C) 2013 Collabora Ltd.
    34 *
    45 *  This library is free software; you can redistribute it and/or
     
    3334#include "ResourceRequest.h"
    3435#include "ResourceResponse.h"
    35  
    3636#include <gst/app/gstappsrc.h>
     37#include <gst/gst.h>
    3738#include <gst/pbutils/missing-plugins.h>
    38 
    3939#include <wtf/Noncopyable.h>
    4040#include <wtf/gobject/GOwnPtr.h>
     
    5252        virtual void willSendRequest(ResourceHandle*, ResourceRequest&, const ResourceResponse&);
    5353        virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&);
     54
     55        virtual char* getBuffer(int, int*);
     56
    5457        virtual void didReceiveData(ResourceHandle*, const char*, int, int);
    5558        virtual void didFinishLoading(ResourceHandle*, double /*finishTime*/);
     
    8487    guint enoughDataID;
    8588    guint seekID;
     89
     90    GstBuffer* buffer;
    8691
    8792    // icecast stuff
     
    116121static void webKitWebSrcUriHandlerInit(gpointer gIface, gpointer ifaceData);
    117122
     123static void webKitWebSrcDispose(GObject*);
    118124static void webKitWebSrcFinalize(GObject*);
    119125static void webKitWebSrcSetProperty(GObject*, guint propertyID, const GValue*, GParamSpec*);
     
    151157    GstElementClass* eklass = GST_ELEMENT_CLASS(klass);
    152158
     159    oklass->dispose = webKitWebSrcDispose;
    153160    oklass->finalize = webKitWebSrcFinalize;
    154161    oklass->set_property = webKitWebSrcSetProperty;
     
    275282}
    276283
     284static void webKitWebSrcDispose(GObject* object)
     285{
     286    WebKitWebSrc* src = WEBKIT_WEB_SRC(object);
     287    WebKitWebSrcPrivate* priv = src->priv;
     288
     289    if (priv->buffer) {
     290#ifdef GST_API_VERSION_1
     291        unmapGstBuffer(priv->buffer);
     292#endif
     293        gst_object_unref(priv->buffer);
     294        priv->buffer = 0;
     295    }
     296
     297    GST_CALL_PARENT(G_OBJECT_CLASS, dispose, (object));
     298}
     299
    277300static void webKitWebSrcFinalize(GObject* object)
    278301{
     
    284307    g_free(priv->uri);
    285308
    286     GST_CALL_PARENT(G_OBJECT_CLASS, finalize, ((GObject* )(src)));
     309    GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object));
    287310}
    288311
     
    354377
    355378    priv->player = 0;
     379
     380    if (priv->buffer) {
     381#ifdef GST_API_VERSION_1
     382        unmapGstBuffer(priv->buffer);
     383#endif
     384        gst_object_unref(priv->buffer);
     385        priv->buffer = 0;
     386    }
    356387
    357388    GST_OBJECT_LOCK(src);
     
    857888    WebKitWebSrcPrivate* priv = m_src->priv;
    858889
    859     GST_LOG_OBJECT(m_src, "Have %d bytes of data", length);
     890    ASSERT(priv->buffer);
     891    ASSERT(data == getGstBufferDataPointer(priv->buffer));
     892
     893    GST_LOG_OBJECT(m_src, "Have %d bytes of data", getGstBufferSize(priv->buffer));
     894
     895#ifdef GST_API_VERSION_1
     896    unmapGstBuffer(priv->buffer);
     897#endif
    860898
    861899    if (priv->seekID || handle != priv->resourceHandle) {
    862900        GST_DEBUG_OBJECT(m_src, "Seek in progress, ignoring data");
     901        gst_buffer_unref(priv->buffer);
     902        priv->buffer = 0;
    863903        return;
    864904    }
    865905
    866     GstBuffer* buffer = gst_buffer_new_and_alloc(length);
    867 
    868 #ifdef GST_API_VERSION_1
    869     gst_buffer_fill(buffer, 0, data, length);
    870 #else
    871     memcpy(GST_BUFFER_DATA(buffer), data, length);
    872 #endif
    873     GST_BUFFER_OFFSET(buffer) = priv->offset;
     906    // We need to update the buffer's knowledge of how much data it carries.
     907    setGstBufferSize(priv->buffer, length);
     908
     909    GST_BUFFER_OFFSET(priv->buffer) = priv->offset;
    874910    priv->offset += length;
    875     GST_BUFFER_OFFSET_END(buffer) = priv->offset;
    876 
    877     GstFlowReturn ret = gst_app_src_push_buffer(priv->appsrc, buffer);
     911    GST_BUFFER_OFFSET_END(priv->buffer) = priv->offset;
     912
     913    GstFlowReturn ret = gst_app_src_push_buffer(priv->appsrc, priv->buffer);
    878914#ifdef GST_API_VERSION_1
    879915    if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
     
    882918#endif
    883919        GST_ELEMENT_ERROR(m_src, CORE, FAILED, (0), (0));
     920
     921    priv->buffer = 0;
     922}
     923
     924char* StreamingClient::getBuffer(int requestedSize, int* actualSize)
     925{
     926    WebKitWebSrcPrivate* priv = m_src->priv;
     927
     928    ASSERT(!priv->buffer);
     929
     930    GstBuffer* buffer = gst_buffer_new_and_alloc(requestedSize);
     931
     932#ifdef GST_API_VERSION_1
     933    mapGstBuffer(buffer);
     934#endif
     935
     936    priv->buffer = buffer;
     937
     938    *actualSize = getGstBufferSize(buffer);
     939    return getGstBufferDataPointer(buffer);
    884940}
    885941
  • trunk/Source/WebCore/platform/network/ResourceHandleClient.h

    r136998 r139877  
    3636#endif
    3737
     38#if USE(SOUP)
     39#include <glib.h>
     40#endif
     41
    3842#if PLATFORM(WIN) && USE(CFNETWORK)
    3943#include <ConditionalMacros.h>
     
    6468    class ResourceHandleClient {
    6569    public:
     70#if USE(SOUP)
     71        ResourceHandleClient(): m_buffer(0) { }
     72
     73        virtual ~ResourceHandleClient()
     74        {
     75            if (m_buffer) {
     76                g_free(m_buffer);
     77                m_buffer = 0;
     78            }
     79        }
     80#else
    6681        virtual ~ResourceHandleClient() { }
     82#endif
    6783
    6884        // request may be modified
     
    8197        virtual bool supportsDataArray() { return false; }
    8298        virtual void didReceiveDataArray(ResourceHandle*, CFArrayRef) { }
     99#endif
     100
     101#if USE(SOUP)
     102        virtual char* getBuffer(int requestedLength, int* actualLength)
     103        {
     104            *actualLength = requestedLength;
     105
     106            if (!m_buffer)
     107                m_buffer = static_cast<char*>(g_malloc(requestedLength));
     108
     109            return m_buffer;
     110        }
    83111#endif
    84112
     
    108136        virtual AsyncFileStream* createAsyncFileStream(FileStreamClient*) { return 0; }
    109137#endif
     138
     139#if USE(SOUP)
     140private:
     141        char* m_buffer;
     142#endif
    110143    };
    111144
  • trunk/Source/WebCore/platform/network/ResourceHandleInternal.h

    r139239 r139877  
    114114            , m_cancelled(false)
    115115            , m_buffer(0)
     116            , m_bufferSize(0)
    116117            , m_bodySize(0)
    117118            , m_bodyDataSent(0)
     
    201202        GRefPtr<GSource> m_timeoutSource;
    202203        char* m_buffer;
     204        int m_bufferSize;
    203205        unsigned long m_bodySize;
    204206        unsigned long m_bodyDataSent;
  • trunk/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp

    r139239 r139877  
    561561
    562562    if (d->m_buffer) {
    563         g_slice_free1(READ_BUFFER_SIZE, d->m_buffer);
    564563        d->m_buffer = 0;
     564        d->m_bufferSize = 0;
    565565    }
    566566
     
    634634    }
    635635
    636     g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, READ_BUFFER_SIZE,
     636    d->m_buffer = client->getBuffer(READ_BUFFER_SIZE, &d->m_bufferSize);
     637
     638    g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, d->m_bufferSize,
    637639        G_PRIORITY_DEFAULT, d->m_cancellable.get(), readCallback, handle.get());
    638640}
     
    698700    }
    699701
    700     d->m_buffer = static_cast<char*>(g_slice_alloc(READ_BUFFER_SIZE));
    701 
    702702    if (soupMessage && d->m_response.isMultipart()) {
    703703        d->m_multipartInputStream = adoptGRef(soup_multipart_input_stream_new(soupMessage, inputStream.get()));
     
    708708
    709709    d->m_inputStream = inputStream;
    710     g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, READ_BUFFER_SIZE,
     710
     711    ASSERT(!d->m_buffer);
     712
     713    d->m_buffer = client->getBuffer(READ_BUFFER_SIZE, &d->m_bufferSize);
     714
     715    g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, d->m_bufferSize,
    711716                              G_PRIORITY_DEFAULT, d->m_cancellable.get(), readCallback, handle.get());
    712717}
     
    13631368    }
    13641369
    1365     g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, READ_BUFFER_SIZE, G_PRIORITY_DEFAULT,
     1370    d->m_buffer = client->getBuffer(READ_BUFFER_SIZE, &d->m_bufferSize);
     1371
     1372    g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, d->m_bufferSize, G_PRIORITY_DEFAULT,
    13661373                              d->m_cancellable.get(), readCallback, handle.get());
    13671374}
Note: See TracChangeset for help on using the changeset viewer.