Changeset 201076 in webkit


Ignore:
Timestamp:
May 18, 2016 7:30:41 AM (8 years ago)
Author:
yoon@igalia.com
Message:

[GStreamer] Use FakeSink to get a decoded texture from a pipeline
https://bugs.webkit.org/show_bug.cgi?id=153641

Reviewed by Philippe Normand.

.:

  • Source/cmake/FindGStreamer.cmake: Bump gst-gl version to 1.8.0

Source/WebCore:

Relying on GstGLImageSink to use GStreamerGL brings a lot of overheads such as
window handling, context switching and overlay handling which are not needed in
our case.

This patch replaces GstGLImageSink with a custom GstBin which has a
GstGLUpload, GstGLColorConvert, and GstFakeSink.

GstFakeSink sends decoded frames via handoff signal from the vqueue thread of
GStreamer. Previously, GstGLImageSink passes frames through GStreamer's GL
thread, which adds additional overhead.

  • platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:

(WebCore::GstVideoFrameHolder::~GstVideoFrameHolder): Modified to
unmap GstVideoFrame without async call. GstGLMemory will unmap itself
in gl-thread.
(WebCore::MediaPlayerPrivateGStreamerBase::drawCallback):
(WebCore::MediaPlayerPrivateGStreamerBase::createVideoSinkGL): Split
out creating of the gst-gl video sink into the separte method.
(WebCore::MediaPlayerPrivateGStreamerBase::paint): Remove assertion
for the threaded compositor. It can be called by focusing event.

  • platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h:
Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/ChangeLog

    r201051 r201076  
     12016-05-18  Gwang Yoon Hwang  <yoon@igalia.com>
     2
     3        [GStreamer] Use FakeSink to get a decoded texture from a pipeline
     4        https://bugs.webkit.org/show_bug.cgi?id=153641
     5
     6        Reviewed by Philippe Normand.
     7
     8        * Source/cmake/FindGStreamer.cmake: Bump gst-gl version to 1.8.0
     9
    1102016-05-17  Dean Jackson  <dino@apple.com>
    211
  • trunk/Source/WebCore/ChangeLog

    r201075 r201076  
     12016-05-18  Gwang Yoon Hwang  <yoon@igalia.com>
     2
     3        [GStreamer] Use FakeSink to get a decoded texture from a pipeline
     4        https://bugs.webkit.org/show_bug.cgi?id=153641
     5
     6        Reviewed by Philippe Normand.
     7
     8        Relying on GstGLImageSink to use GStreamerGL brings a lot of overheads such as
     9        window handling, context switching and overlay handling which are not needed in
     10        our case.
     11
     12        This patch replaces GstGLImageSink with a custom GstBin which has a
     13        GstGLUpload, GstGLColorConvert, and GstFakeSink.
     14
     15        GstFakeSink sends decoded frames via handoff signal from the vqueue thread of
     16        GStreamer. Previously,  GstGLImageSink passes frames through GStreamer's GL
     17        thread, which adds additional overhead.
     18
     19        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
     20        (WebCore::GstVideoFrameHolder::~GstVideoFrameHolder): Modified to
     21        unmap GstVideoFrame without async call. GstGLMemory will unmap itself
     22        in gl-thread.
     23        (WebCore::MediaPlayerPrivateGStreamerBase::drawCallback):
     24        (WebCore::MediaPlayerPrivateGStreamerBase::createVideoSinkGL): Split
     25        out creating of the gst-gl video sink into the separte method.
     26        (WebCore::MediaPlayerPrivateGStreamerBase::paint): Remove assertion
     27        for the threaded compositor. It can be called by focusing event.
     28        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h:
     29
    1302016-05-18  Antti Koivisto  <antti@apple.com>
    231
  • trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp

    r199057 r201076  
    116116
    117117        GstBuffer* buffer = gst_sample_get_buffer(sample);
    118         m_videoFrame = new GstVideoFrame();
    119         if (UNLIKELY(!gst_video_frame_map(m_videoFrame, &videoInfo, buffer, static_cast<GstMapFlags>(GST_MAP_READ | GST_MAP_GL)))) {
    120             delete m_videoFrame;
     118        if (UNLIKELY(!gst_video_frame_map(&m_videoFrame, &videoInfo, buffer, static_cast<GstMapFlags>(GST_MAP_READ | GST_MAP_GL))))
    121119            return;
    122         }
    123 
    124         m_textureID = *reinterpret_cast<GLuint*>(m_videoFrame->data[0]);
     120
     121        m_textureID = *reinterpret_cast<GLuint*>(m_videoFrame.data[0]);
    125122        m_isValid = true;
    126123    }
     
    131128            return;
    132129
    133         GstMapInfo* info = &m_videoFrame->map[0];
    134         GstGLBaseBuffer* mem = (GstGLBaseBuffer*)info->memory;
    135         GstGLWindow* gstWindow = gst_gl_context_get_window(mem->context);
    136 
    137         gst_gl_window_send_message_async(gstWindow, (GstGLWindowCB)unmapVideoFrameCallback, m_videoFrame, (GDestroyNotify)freeVideoFrameCallback);
    138     }
    139 
    140     static void unmapVideoFrameCallback(GstVideoFrame* videoFrame)
    141     {
    142         gst_video_frame_unmap(videoFrame);
    143     }
    144 
    145     static void freeVideoFrameCallback(GstVideoFrame* videoFrame)
    146     {
    147         delete videoFrame;
     130        gst_video_frame_unmap(&m_videoFrame);
    148131    }
    149132
     
    154137
    155138private:
    156     GstVideoFrame* m_videoFrame;
     139    GstVideoFrame m_videoFrame;
    157140    IntSize m_size;
    158141    TextureMapperGL::Flags m_flags;
     
    578561
    579562#if USE(GSTREAMER_GL)
    580 gboolean MediaPlayerPrivateGStreamerBase::drawCallback(MediaPlayerPrivateGStreamerBase* player, GstGLContext*, GstSample* sample)
    581 {
    582     player->triggerRepaint(sample);
     563gboolean MediaPlayerPrivateGStreamerBase::drawCallback(MediaPlayerPrivateGStreamerBase* player, GstBuffer* buffer, GstPad* pad, GstBaseSink* sink)
     564{
     565    GST_PAD_STREAM_LOCK(pad);
     566    GRefPtr<GstCaps> caps = adoptGRef(gst_pad_get_current_caps(pad));
     567    GRefPtr<GstSample> sample = adoptGRef(gst_sample_new(buffer, caps.get(), &sink->segment, NULL));
     568    GST_PAD_STREAM_UNLOCK(pad);
     569    player->triggerRepaint(sample.get());
    583570    return TRUE;
    584571}
     
    593580{
    594581#if USE(COORDINATED_GRAPHICS_THREADED)
    595     ASSERT_NOT_REACHED();
    596582    return;
    597583#elif USE(TEXTURE_MAPPER_GL) && !USE(COORDINATED_GRAPHICS)
     
    720706}
    721707
     708#if USE(GSTREAMER_GL)
     709GstElement* MediaPlayerPrivateGStreamerBase::createVideoSinkGL()
     710{
     711    if (!webkitGstCheckVersion(1, 8, 0))
     712        return nullptr;
     713
     714    gboolean result = TRUE;
     715    GstElement* videoSink = gst_bin_new(nullptr);
     716    GstElement* upload = gst_element_factory_make("glupload", nullptr);
     717    GstElement* colorconvert = gst_element_factory_make("glcolorconvert", nullptr);
     718
     719    if (!upload || !colorconvert) {
     720        WARN_MEDIA_MESSAGE("Failed to create GstGL elements");
     721        gst_object_unref(videoSink);
     722
     723        if (upload)
     724            gst_object_unref(upload);
     725        if (colorconvert)
     726            gst_object_unref(colorconvert);
     727
     728        return nullptr;
     729    }
     730
     731    GstElement* fakesink = gst_element_factory_make("fakesink", nullptr);
     732
     733    gst_bin_add_many(GST_BIN(videoSink), upload, colorconvert, fakesink, nullptr);
     734
     735    GRefPtr<GstCaps> caps = adoptGRef(gst_caps_from_string("video/x-raw(" GST_CAPS_FEATURE_MEMORY_GL_MEMORY "), format = (string) { RGBA }"));
     736
     737    result &= gst_element_link_pads(upload, "src", colorconvert, "sink");
     738    result &= gst_element_link_pads_filtered(colorconvert, "src", fakesink, "sink", caps.get());
     739
     740    GRefPtr<GstPad> pad = adoptGRef(gst_element_get_static_pad(upload, "sink"));
     741    gst_element_add_pad(videoSink, gst_ghost_pad_new("sink", pad.get()));
     742
     743    g_object_set(fakesink, "enable-last-sample", FALSE, "signal-handoffs", TRUE, "silent", TRUE, "sync", TRUE, nullptr);
     744
     745    if (result)
     746        g_signal_connect_swapped(fakesink, "handoff", G_CALLBACK(drawCallback), this);
     747    else {
     748        WARN_MEDIA_MESSAGE("Failed to link GstGL elements");
     749        gst_object_unref(videoSink);
     750        videoSink = nullptr;
     751    }
     752    return videoSink;
     753}
     754#endif
     755
    722756GstElement* MediaPlayerPrivateGStreamerBase::createVideoSink()
    723757{
    724     GstElement* videoSink = nullptr;
    725 #if USE(GSTREAMER_GL)
    726     if (webkitGstCheckVersion(1, 5, 0)) {
    727         m_videoSink = gst_element_factory_make("glimagesink", nullptr);
    728         if (m_videoSink) {
    729             g_signal_connect_swapped(m_videoSink.get(), "client-draw", G_CALLBACK(drawCallback), this);
    730             videoSink = m_videoSink.get();
    731         }
    732     }
     758#if USE(GSTREAMER_GL)
     759    m_videoSink = createVideoSinkGL();
    733760#endif
    734761
     
    739766    }
    740767
     768    GstElement* videoSink = nullptr;
    741769    m_fpsSink = gst_element_factory_make("fpsdisplaysink", "sink");
    742770    if (m_fpsSink) {
  • trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h

    r199057 r201076  
    3636#include <wtf/RunLoop.h>
    3737
     38typedef struct _GstBaseSink GstBaseSink;
    3839typedef struct _GstMessage GstMessage;
    3940typedef struct _GstStreamVolume GstStreamVolume;
     
    121122    virtual GstElement* createVideoSink();
    122123
     124#if USE(GSTREAMER_GL)
     125    GstElement* createVideoSinkGL();
     126#endif
     127
    123128    void setStreamVolumeElement(GstStreamVolume*);
    124129    virtual GstElement* createAudioSink() { return 0; }
     
    134139    static void repaintCallback(MediaPlayerPrivateGStreamerBase*, GstSample*);
    135140#if USE(GSTREAMER_GL)
    136     static gboolean drawCallback(MediaPlayerPrivateGStreamerBase*, GstGLContext*, GstSample*);
     141    static gboolean drawCallback(MediaPlayerPrivateGStreamerBase*, GstBuffer*, GstPad*, GstBaseSink*);
    137142#endif
    138143
  • trunk/Source/cmake/FindGStreamer.cmake

    r196804 r201076  
    8686FIND_GSTREAMER_COMPONENT(GSTREAMER_AUDIO gstreamer-audio-1.0 gstaudio-1.0)
    8787FIND_GSTREAMER_COMPONENT(GSTREAMER_FFT gstreamer-fft-1.0 gstfft-1.0)
    88 FIND_GSTREAMER_COMPONENT(GSTREAMER_GL gstreamer-gl-1.0>=1.6.0 gstgl-1.0)
     88FIND_GSTREAMER_COMPONENT(GSTREAMER_GL gstreamer-gl-1.0>=1.8.0 gstgl-1.0)
    8989FIND_GSTREAMER_COMPONENT(GSTREAMER_MPEGTS gstreamer-mpegts-1.0>=1.4.0 gstmpegts-1.0)
    9090FIND_GSTREAMER_COMPONENT(GSTREAMER_PBUTILS gstreamer-pbutils-1.0 gstpbutils-1.0)
Note: See TracChangeset for help on using the changeset viewer.