Changeset 206257 in webkit


Ignore:
Timestamp:
Sep 22, 2016 5:43:55 AM (8 years ago)
Author:
commit-queue@webkit.org
Message:

[GStreamer] Support a direct GPU-to-GPU copy of video textures to WebGL
https://bugs.webkit.org/show_bug.cgi?id=159928

Patch by Olivier Blin <Olivier Blin> on 2016-09-22
Reviewed by Carlos Garcia Campos.

Copy of GStreamer video frames to WebGL textures was not accelerated.

WebGLRenderingContextBase::texImage2D(HTMLVideoElement) went
through a slow software paint() wrapping the video frame into
cairo surface (ImageGStreamer), downloading it to draw to the
image cache context, copying it again in software, and uploading
it back to an OpenGL texture.

This patch implements copyVideoTextureToPlatformTexture() for
the GStreamer media player backend, to do GPU-to-GPU copy, by
extracting code from nativeImageForCurrentTime().

Doing this also fixes bug #159621: red and blue colors were
swapped in video rendered through WebGL with GSTREAMER_GL enabled.

  • platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:

(WebCore::MediaPlayerPrivateGStreamerBase::prepareContextForCairoPaint):
(WebCore::MediaPlayerPrivateGStreamerBase::paintToCairoSurface):
(WebCore::MediaPlayerPrivateGStreamerBase::copyVideoTextureToPlatformTexture):
(WebCore::MediaPlayerPrivateGStreamerBase::nativeImageForCurrentTime):

  • platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h:
Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r206256 r206257  
     12016-09-22  Olivier Blin  <olivier.blin@softathome.com>
     2
     3        [GStreamer] Support a direct GPU-to-GPU copy of video textures to WebGL
     4        https://bugs.webkit.org/show_bug.cgi?id=159928
     5
     6        Reviewed by Carlos Garcia Campos.
     7
     8        Copy of GStreamer video frames to WebGL textures was not accelerated.
     9
     10        WebGLRenderingContextBase::texImage2D(HTMLVideoElement) went
     11        through a slow software paint() wrapping the video frame into
     12        cairo surface (ImageGStreamer), downloading it to draw to the
     13        image cache context, copying it again in software, and uploading
     14        it back to an OpenGL texture.
     15
     16        This patch implements copyVideoTextureToPlatformTexture() for
     17        the GStreamer media player backend, to do GPU-to-GPU copy, by
     18        extracting code from nativeImageForCurrentTime().
     19
     20        Doing this also fixes bug #159621: red and blue colors were
     21        swapped in video rendered through WebGL with GSTREAMER_GL enabled.
     22
     23        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
     24        (WebCore::MediaPlayerPrivateGStreamerBase::prepareContextForCairoPaint):
     25        (WebCore::MediaPlayerPrivateGStreamerBase::paintToCairoSurface):
     26        (WebCore::MediaPlayerPrivateGStreamerBase::copyVideoTextureToPlatformTexture):
     27        (WebCore::MediaPlayerPrivateGStreamerBase::nativeImageForCurrentTime):
     28        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h:
     29
    1302016-09-22  Carlos Garcia Campos  <cgarcia@igalia.com>
    231
  • trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp

    r206213 r206257  
    698698
    699699#if USE(GSTREAMER_GL)
    700 NativeImagePtr MediaPlayerPrivateGStreamerBase::nativeImageForCurrentTime()
    701 {
    702 #if USE(CAIRO) && ENABLE(ACCELERATED_2D_CANVAS)
    703     if (m_usingFallbackVideoSink)
    704         return nullptr;
    705 
    706     WTF::GMutexLocker<GMutex> lock(m_sampleMutex);
    707 
    708     GstVideoInfo videoInfo;
     700// This should be called with the sample mutex locked.
     701GLContext* MediaPlayerPrivateGStreamerBase::prepareContextForCairoPaint(GstVideoInfo& videoInfo, IntSize& size, IntSize& rotatedSize)
     702{
    709703    if (!getSampleVideoInfo(m_sample.get(), videoInfo))
    710704        return nullptr;
    711705
     706    GLContext* context = PlatformDisplay::sharedDisplayForCompositing().sharingGLContext();
     707    context->makeContextCurrent();
     708
     709    // Thread-awareness is a huge performance hit on non-Intel drivers.
     710    cairo_gl_device_set_thread_aware(context->cairoDevice(), FALSE);
     711
     712    size = IntSize(GST_VIDEO_INFO_WIDTH(&videoInfo), GST_VIDEO_INFO_HEIGHT(&videoInfo));
     713    rotatedSize = m_videoSourceOrientation.usesWidthAsHeight() ? size.transposedSize() : size;
     714
     715    return context;
     716}
     717
     718// This should be called with the sample mutex locked.
     719bool MediaPlayerPrivateGStreamerBase::paintToCairoSurface(cairo_surface_t* outputSurface, cairo_device_t* device, GstVideoInfo& videoInfo, const IntSize& size, const IntSize& rotatedSize)
     720{
    712721    GstBuffer* buffer = gst_sample_get_buffer(m_sample.get());
    713722    GstVideoFrame videoFrame;
    714723    if (!gst_video_frame_map(&videoFrame, &videoInfo, buffer, static_cast<GstMapFlags>(GST_MAP_READ | GST_MAP_GL)))
    715         return nullptr;
    716 
    717     GLContext* context = PlatformDisplay::sharedDisplayForCompositing().sharingGLContext();
    718     context->makeContextCurrent();
    719     cairo_device_t* device = context->cairoDevice();
    720 
    721     // Thread-awareness is a huge performance hit on non-Intel drivers.
    722     cairo_gl_device_set_thread_aware(device, FALSE);
     724        return false;
    723725
    724726    unsigned textureID = *reinterpret_cast<unsigned*>(videoFrame.data[0]);
    725     IntSize size = IntSize(GST_VIDEO_INFO_WIDTH(&videoInfo), GST_VIDEO_INFO_HEIGHT(&videoInfo));
    726727    RefPtr<cairo_surface_t> surface = adoptRef(cairo_gl_surface_create_for_texture(device, CAIRO_CONTENT_COLOR_ALPHA, textureID, size.width(), size.height()));
    727 
    728     IntSize rotatedSize = m_videoSourceOrientation.usesWidthAsHeight() ? size.transposedSize() : size;
    729     RefPtr<cairo_surface_t> rotatedSurface = adoptRef(cairo_gl_surface_create(device, CAIRO_CONTENT_COLOR_ALPHA, rotatedSize.width(), rotatedSize.height()));
    730     RefPtr<cairo_t> cr = adoptRef(cairo_create(rotatedSurface.get()));
     728    RefPtr<cairo_t> cr = adoptRef(cairo_create(outputSurface));
    731729
    732730    switch (m_videoSourceOrientation) {
     
    758756    gst_video_frame_unmap(&videoFrame);
    759757
     758    return true;
     759}
     760
     761bool MediaPlayerPrivateGStreamerBase::copyVideoTextureToPlatformTexture(GraphicsContext3D* context, Platform3DObject outputTexture, GC3Denum outputTarget, GC3Dint level, GC3Denum internalFormat, GC3Denum format, GC3Denum type, bool premultiplyAlpha, bool flipY)
     762{
     763#if !USE(CAIRO)
     764    return false;
     765#endif
     766
     767    if (m_usingFallbackVideoSink)
     768        return false;
     769
     770    if (flipY || premultiplyAlpha)
     771        return false;
     772
     773    GstVideoInfo videoInfo;
     774    IntSize size, rotatedSize;
     775    WTF::GMutexLocker<GMutex> lock(m_sampleMutex);
     776    GLContext* glContext = prepareContextForCairoPaint(videoInfo, size, rotatedSize);
     777    if (!glContext)
     778        return false;
     779
     780    // Allocate uninitialized memory for the output texture.
     781    context->bindTexture(outputTarget, outputTexture);
     782    context->texImage2DDirect(outputTarget, level, internalFormat, rotatedSize.width(), rotatedSize.height(), 0, format, type, nullptr);
     783
     784    // cairo_gl_surface_create_for_texture sets these parameters to GL_NEAREST, so we need to backup them.
     785    GC3Dint minFilter, magFilter;
     786    context->getTexParameteriv(outputTarget, GL_TEXTURE_MIN_FILTER, &minFilter);
     787    context->getTexParameteriv(outputTarget, GL_TEXTURE_MAG_FILTER, &magFilter);
     788
     789    RefPtr<cairo_surface_t> outputSurface = adoptRef(cairo_gl_surface_create_for_texture(glContext->cairoDevice(), CAIRO_CONTENT_COLOR_ALPHA, outputTexture, rotatedSize.width(), rotatedSize.height()));
     790    if (!paintToCairoSurface(outputSurface.get(), glContext->cairoDevice(), videoInfo, size, rotatedSize))
     791        return false;
     792
     793    context->bindTexture(outputTarget, outputTexture);
     794    context->texParameteri(outputTarget, GraphicsContext3D::TEXTURE_MIN_FILTER, minFilter);
     795    context->texParameteri(outputTarget, GraphicsContext3D::TEXTURE_MAG_FILTER, magFilter);
     796
     797    return true;
     798}
     799
     800NativeImagePtr MediaPlayerPrivateGStreamerBase::nativeImageForCurrentTime()
     801{
     802#if USE(CAIRO) && ENABLE(ACCELERATED_2D_CANVAS)
     803    if (m_usingFallbackVideoSink)
     804        return nullptr;
     805
     806    GstVideoInfo videoInfo;
     807    IntSize size, rotatedSize;
     808    WTF::GMutexLocker<GMutex> lock(m_sampleMutex);
     809    GLContext* context = prepareContextForCairoPaint(videoInfo, size, rotatedSize);
     810    if (!context)
     811        return nullptr;
     812
     813    RefPtr<cairo_surface_t> rotatedSurface = adoptRef(cairo_gl_surface_create(context->cairoDevice(), CAIRO_CONTENT_COLOR_ALPHA, rotatedSize.width(), rotatedSize.height()));
     814    if (!paintToCairoSurface(rotatedSurface.get(), context->cairoDevice(), videoInfo, size, rotatedSize))
     815        return nullptr;
     816
    760817    return rotatedSurface;
    761818#else
  • trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h

    r206202 r206257  
    4848
    4949class BitmapTextureGL;
     50class GLContext;
    5051class GraphicsContext;
    5152class GraphicsContext3D;
     
    117118
    118119#if USE(GSTREAMER_GL)
     120    bool copyVideoTextureToPlatformTexture(GraphicsContext3D*, Platform3DObject, GC3Denum, GC3Dint, GC3Denum, GC3Denum, GC3Denum, bool, bool) override;
    119121    NativeImagePtr nativeImageForCurrentTime() override;
    120122#endif
     
    131133    GstElement* createGLAppSink();
    132134    GstElement* createVideoSinkGL();
     135    GLContext* prepareContextForCairoPaint(GstVideoInfo&, IntSize&, IntSize&);
     136    bool paintToCairoSurface(cairo_surface_t*, cairo_device_t*, GstVideoInfo&, const IntSize&, const IntSize&);
    133137#endif
    134138
Note: See TracChangeset for help on using the changeset viewer.