Title: [206257] trunk/Source/WebCore
Revision
206257
Author
commit-qu...@webkit.org
Date
2016-09-22 05:43:55 -0700 (Thu, 22 Sep 2016)

Log 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.b...@softathome.com> 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:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (206256 => 206257)


--- trunk/Source/WebCore/ChangeLog	2016-09-22 12:14:39 UTC (rev 206256)
+++ trunk/Source/WebCore/ChangeLog	2016-09-22 12:43:55 UTC (rev 206257)
@@ -1,3 +1,32 @@
+2016-09-22  Olivier Blin  <olivier.b...@softathome.com>
+
+        [GStreamer] Support a direct GPU-to-GPU copy of video textures to WebGL
+        https://bugs.webkit.org/show_bug.cgi?id=159928
+
+        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:
+
 2016-09-22  Carlos Garcia Campos  <cgar...@igalia.com>
 
         [GTK] Rename DataObjectGtk as SelectionData

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp (206256 => 206257)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp	2016-09-22 12:14:39 UTC (rev 206256)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp	2016-09-22 12:43:55 UTC (rev 206257)
@@ -697,38 +697,36 @@
 #endif
 
 #if USE(GSTREAMER_GL)
-NativeImagePtr MediaPlayerPrivateGStreamerBase::nativeImageForCurrentTime()
+// This should be called with the sample mutex locked.
+GLContext* MediaPlayerPrivateGStreamerBase::prepareContextForCairoPaint(GstVideoInfo& videoInfo, IntSize& size, IntSize& rotatedSize)
 {
-#if USE(CAIRO) && ENABLE(ACCELERATED_2D_CANVAS)
-    if (m_usingFallbackVideoSink)
+    if (!getSampleVideoInfo(m_sample.get(), videoInfo))
         return nullptr;
 
-    WTF::GMutexLocker<GMutex> lock(m_sampleMutex);
+    GLContext* context = PlatformDisplay::sharedDisplayForCompositing().sharingGLContext();
+    context->makeContextCurrent();
 
-    GstVideoInfo videoInfo;
-    if (!getSampleVideoInfo(m_sample.get(), videoInfo))
-        return nullptr;
+    // Thread-awareness is a huge performance hit on non-Intel drivers.
+    cairo_gl_device_set_thread_aware(context->cairoDevice(), FALSE);
 
+    size = IntSize(GST_VIDEO_INFO_WIDTH(&videoInfo), GST_VIDEO_INFO_HEIGHT(&videoInfo));
+    rotatedSize = m_videoSourceOrientation.usesWidthAsHeight() ? size.transposedSize() : size;
+
+    return context;
+}
+
+// This should be called with the sample mutex locked.
+bool MediaPlayerPrivateGStreamerBase::paintToCairoSurface(cairo_surface_t* outputSurface, cairo_device_t* device, GstVideoInfo& videoInfo, const IntSize& size, const IntSize& rotatedSize)
+{
     GstBuffer* buffer = gst_sample_get_buffer(m_sample.get());
     GstVideoFrame videoFrame;
     if (!gst_video_frame_map(&videoFrame, &videoInfo, buffer, static_cast<GstMapFlags>(GST_MAP_READ | GST_MAP_GL)))
-        return nullptr;
+        return false;
 
-    GLContext* context = PlatformDisplay::sharedDisplayForCompositing().sharingGLContext();
-    context->makeContextCurrent();
-    cairo_device_t* device = context->cairoDevice();
-
-    // Thread-awareness is a huge performance hit on non-Intel drivers.
-    cairo_gl_device_set_thread_aware(device, FALSE);
-
     unsigned textureID = *reinterpret_cast<unsigned*>(videoFrame.data[0]);
-    IntSize size = IntSize(GST_VIDEO_INFO_WIDTH(&videoInfo), GST_VIDEO_INFO_HEIGHT(&videoInfo));
     RefPtr<cairo_surface_t> surface = adoptRef(cairo_gl_surface_create_for_texture(device, CAIRO_CONTENT_COLOR_ALPHA, textureID, size.width(), size.height()));
+    RefPtr<cairo_t> cr = adoptRef(cairo_create(outputSurface));
 
-    IntSize rotatedSize = m_videoSourceOrientation.usesWidthAsHeight() ? size.transposedSize() : size;
-    RefPtr<cairo_surface_t> rotatedSurface = adoptRef(cairo_gl_surface_create(device, CAIRO_CONTENT_COLOR_ALPHA, rotatedSize.width(), rotatedSize.height()));
-    RefPtr<cairo_t> cr = adoptRef(cairo_create(rotatedSurface.get()));
-
     switch (m_videoSourceOrientation) {
     case DefaultImageOrientation:
         break;
@@ -757,6 +755,65 @@
 
     gst_video_frame_unmap(&videoFrame);
 
+    return true;
+}
+
+bool MediaPlayerPrivateGStreamerBase::copyVideoTextureToPlatformTexture(GraphicsContext3D* context, Platform3DObject outputTexture, GC3Denum outputTarget, GC3Dint level, GC3Denum internalFormat, GC3Denum format, GC3Denum type, bool premultiplyAlpha, bool flipY)
+{
+#if !USE(CAIRO)
+    return false;
+#endif
+
+    if (m_usingFallbackVideoSink)
+        return false;
+
+    if (flipY || premultiplyAlpha)
+        return false;
+
+    GstVideoInfo videoInfo;
+    IntSize size, rotatedSize;
+    WTF::GMutexLocker<GMutex> lock(m_sampleMutex);
+    GLContext* glContext = prepareContextForCairoPaint(videoInfo, size, rotatedSize);
+    if (!glContext)
+        return false;
+
+    // Allocate uninitialized memory for the output texture.
+    context->bindTexture(outputTarget, outputTexture);
+    context->texImage2DDirect(outputTarget, level, internalFormat, rotatedSize.width(), rotatedSize.height(), 0, format, type, nullptr);
+
+    // cairo_gl_surface_create_for_texture sets these parameters to GL_NEAREST, so we need to backup them.
+    GC3Dint minFilter, magFilter;
+    context->getTexParameteriv(outputTarget, GL_TEXTURE_MIN_FILTER, &minFilter);
+    context->getTexParameteriv(outputTarget, GL_TEXTURE_MAG_FILTER, &magFilter);
+
+    RefPtr<cairo_surface_t> outputSurface = adoptRef(cairo_gl_surface_create_for_texture(glContext->cairoDevice(), CAIRO_CONTENT_COLOR_ALPHA, outputTexture, rotatedSize.width(), rotatedSize.height()));
+    if (!paintToCairoSurface(outputSurface.get(), glContext->cairoDevice(), videoInfo, size, rotatedSize))
+        return false;
+
+    context->bindTexture(outputTarget, outputTexture);
+    context->texParameteri(outputTarget, GraphicsContext3D::TEXTURE_MIN_FILTER, minFilter);
+    context->texParameteri(outputTarget, GraphicsContext3D::TEXTURE_MAG_FILTER, magFilter);
+
+    return true;
+}
+
+NativeImagePtr MediaPlayerPrivateGStreamerBase::nativeImageForCurrentTime()
+{
+#if USE(CAIRO) && ENABLE(ACCELERATED_2D_CANVAS)
+    if (m_usingFallbackVideoSink)
+        return nullptr;
+
+    GstVideoInfo videoInfo;
+    IntSize size, rotatedSize;
+    WTF::GMutexLocker<GMutex> lock(m_sampleMutex);
+    GLContext* context = prepareContextForCairoPaint(videoInfo, size, rotatedSize);
+    if (!context)
+        return nullptr;
+
+    RefPtr<cairo_surface_t> rotatedSurface = adoptRef(cairo_gl_surface_create(context->cairoDevice(), CAIRO_CONTENT_COLOR_ALPHA, rotatedSize.width(), rotatedSize.height()));
+    if (!paintToCairoSurface(rotatedSurface.get(), context->cairoDevice(), videoInfo, size, rotatedSize))
+        return nullptr;
+
     return rotatedSurface;
 #else
     return nullptr;

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h (206256 => 206257)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h	2016-09-22 12:14:39 UTC (rev 206256)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h	2016-09-22 12:43:55 UTC (rev 206257)
@@ -47,6 +47,7 @@
 namespace WebCore {
 
 class BitmapTextureGL;
+class GLContext;
 class GraphicsContext;
 class GraphicsContext3D;
 class IntSize;
@@ -116,6 +117,7 @@
 #endif
 
 #if USE(GSTREAMER_GL)
+    bool copyVideoTextureToPlatformTexture(GraphicsContext3D*, Platform3DObject, GC3Denum, GC3Dint, GC3Denum, GC3Denum, GC3Denum, bool, bool) override;
     NativeImagePtr nativeImageForCurrentTime() override;
 #endif
 
@@ -130,6 +132,8 @@
     static GstFlowReturn newPrerollCallback(GstElement*, MediaPlayerPrivateGStreamerBase*);
     GstElement* createGLAppSink();
     GstElement* createVideoSinkGL();
+    GLContext* prepareContextForCairoPaint(GstVideoInfo&, IntSize&, IntSize&);
+    bool paintToCairoSurface(cairo_surface_t*, cairo_device_t*, GstVideoInfo&, const IntSize&, const IntSize&);
 #endif
 
     void setStreamVolumeElement(GstStreamVolume*);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to