Changeset 193836 in webkit
- Timestamp:
- Dec 9, 2015 9:37:29 AM (8 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r193832 r193836 1 2015-12-09 Gwang Yoon Hwang <yoon@igalia.com> 2 3 [ThreadedCompositor] Support HTML5 Video 4 https://bugs.webkit.org/show_bug.cgi?id=143301 5 6 Reviewed by Žan Doberšek. 7 8 This patch implements HTML5 Video supports in Threaded Compositor. 9 10 * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp: 11 (WebCore::GstVideoFrameHolder::GstVideoFrameHolder): 12 Added to support GStreamer GL by ensuring unmapping of the swapped 13 GstVideoFrame performed at GStreamer GL's gl thread. 14 (WebCore::MediaPlayerPrivateGStreamerBase::updateTexture): 15 Modified to upload decoded frame to the given texture instead of 16 creating a texture itself because we should use a texture from the 17 proxy when we are using the threaded compositor. 18 (WebCore::MediaPlayerPrivateGStreamerBase::pushTextureToCompositor): 19 Implements two ways to send a texture from GStreamer to the compositor. 20 1. If we are not using GStreamer GL, we are going to acquire a free texture 21 from a TextureMapperPlatformLayerProxy and upload the decoded frame to the 22 texture. This should be done at the compositing thread because we 23 don't have a Gst's GL thread. 24 2. If we are using GStreamer GL, we map a texture for the given frame 25 and passes it to the compositing thread. The mapped frame will be 26 freed if it is swapped out or the layer is removed. 27 28 (WebCore::MediaPlayerPrivateGStreamerBase::paintToTextureMapper): 29 Modified to aquire a new texture itself. 30 31 * platform/graphics/texmap/TextureMapperPlatformLayerProxy.cpp: 32 Adds a way to pass a function to the compositing thread to allocate / 33 upload textures at the compositing thread. 34 35 1 36 2015-12-09 Xabier Rodriguez Calvar <calvaris@igalia.com> 2 37 -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp
r193621 r193836 56 56 #include "TextureMapperGL.h" 57 57 #endif 58 #if USE(COORDINATED_GRAPHICS_THREADED) 59 #include "TextureMapperPlatformLayerBuffer.h" 60 #endif 58 61 59 62 #if USE(GSTREAMER_GL) … … 103 106 } 104 107 108 #if USE(COORDINATED_GRAPHICS_THREADED) && USE(GSTREAMER_GL) 109 class GstVideoFrameHolder : public TextureMapperPlatformLayerBuffer::UnmanagedBufferDataHolder { 110 public: 111 explicit GstVideoFrameHolder(GstSample* sample) 112 { 113 GstVideoInfo videoInfo; 114 gst_video_info_init(&videoInfo); 115 GstCaps* caps = gst_sample_get_caps(sample); 116 if (UNLIKELY(!gst_video_info_from_caps(&videoInfo, caps))) 117 return; 118 119 m_size = IntSize(GST_VIDEO_INFO_WIDTH(&videoInfo), GST_VIDEO_INFO_HEIGHT(&videoInfo)); 120 m_flags = GST_VIDEO_INFO_HAS_ALPHA(&videoInfo) ? TextureMapperGL::ShouldBlend : 0; 121 122 GstBuffer* buffer = gst_sample_get_buffer(sample); 123 m_videoFrame = new GstVideoFrame(); 124 if (UNLIKELY(!gst_video_frame_map(m_videoFrame, &videoInfo, buffer, static_cast<GstMapFlags>(GST_MAP_READ | GST_MAP_GL)))) { 125 delete m_videoFrame; 126 return; 127 } 128 129 m_textureID = *reinterpret_cast<GLuint*>(m_videoFrame->data[0]); 130 m_isValid = true; 131 } 132 133 virtual ~GstVideoFrameHolder() 134 { 135 if (UNLIKELY(!m_isValid)) 136 return; 137 138 GstMapInfo* info = &m_videoFrame->map[0]; 139 GstGLBaseBuffer* mem = (GstGLBaseBuffer*)info->memory; 140 GstGLWindow* gstWindow = gst_gl_context_get_window(mem->context); 141 142 gst_gl_window_send_message_async(gstWindow, (GstGLWindowCB)unmapVideoFrameCallback, m_videoFrame, (GDestroyNotify)freeVideoFrameCallback); 143 } 144 145 static void unmapVideoFrameCallback(GstVideoFrame* videoFrame) 146 { 147 gst_video_frame_unmap(videoFrame); 148 } 149 150 static void freeVideoFrameCallback(GstVideoFrame* videoFrame) 151 { 152 delete videoFrame; 153 } 154 155 const IntSize& size() const { return m_size; } 156 TextureMapperGL::Flags flags() const { return m_flags; } 157 GLuint textureID() const { return m_textureID; } 158 bool isValid() const { return m_isValid; } 159 160 private: 161 GstVideoFrame* m_videoFrame; 162 IntSize m_size; 163 TextureMapperGL::Flags m_flags; 164 GLuint m_textureID; 165 bool m_isValid { false }; 166 }; 167 #endif 168 105 169 MediaPlayerPrivateGStreamerBase::MediaPlayerPrivateGStreamerBase(MediaPlayer* player) 106 170 : m_player(player) … … 114 178 { 115 179 g_mutex_init(&m_sampleMutex); 180 #if USE(COORDINATED_GRAPHICS_THREADED) 181 m_platformLayerProxy = adoptRef(new TextureMapperPlatformLayerProxy()); 182 #endif 116 183 } 117 184 … … 361 428 } 362 429 363 #if USE(TEXTURE_MAPPER_GL) && !USE(COORDINATED_GRAPHICS) 364 PassRefPtr<BitmapTexture> MediaPlayerPrivateGStreamerBase::updateTexture(TextureMapper* textureMapper) 365 { 366 WTF::GMutexLocker<GMutex> lock(m_sampleMutex); 367 if (!GST_IS_SAMPLE(m_sample.get())) 368 return nullptr; 369 370 GstCaps* caps = gst_sample_get_caps(m_sample.get()); 371 if (!caps) 372 return nullptr; 373 374 GstVideoInfo videoInfo; 375 gst_video_info_init(&videoInfo); 376 if (!gst_video_info_from_caps(&videoInfo, caps)) 377 return nullptr; 378 379 IntSize size = IntSize(GST_VIDEO_INFO_WIDTH(&videoInfo), GST_VIDEO_INFO_HEIGHT(&videoInfo)); 380 RefPtr<BitmapTexture> texture = textureMapper->acquireTextureFromPool(size, GST_VIDEO_INFO_HAS_ALPHA(&videoInfo) ? BitmapTexture::SupportsAlpha : BitmapTexture::NoFlag); 430 #if USE(TEXTURE_MAPPER_GL) && !USE(COORDINATED_GRAPHICS_MULTIPROCESS) 431 void MediaPlayerPrivateGStreamerBase::updateTexture(BitmapTextureGL& texture, GstVideoInfo& videoInfo) 432 { 381 433 GstBuffer* buffer = gst_sample_get_buffer(m_sample.get()); 382 434 … … 385 437 if ((meta = gst_buffer_get_video_gl_texture_upload_meta(buffer))) { 386 438 if (meta->n_textures == 1) { // BRGx & BGRA formats use only one texture. 387 const BitmapTextureGL* textureGL = static_cast<const BitmapTextureGL*>(texture.get()); 388 guint ids[4] = { textureGL->id(), 0, 0, 0 }; 439 guint ids[4] = { texture.id(), 0, 0, 0 }; 389 440 390 441 if (gst_video_gl_texture_upload_meta_upload(meta, ids)) 391 return texture;442 return; 392 443 } 393 444 } … … 399 450 GstVideoFrame videoFrame; 400 451 if (!gst_video_frame_map(&videoFrame, &videoInfo, buffer, GST_MAP_READ)) 401 return nullptr;452 return; 402 453 403 454 int stride = GST_VIDEO_FRAME_PLANE_STRIDE(&videoFrame, 0); 404 455 const void* srcData = GST_VIDEO_FRAME_PLANE_DATA(&videoFrame, 0); 405 texture ->updateContents(srcData, WebCore::IntRect(WebCore::IntPoint(0, 0), size), WebCore::IntPoint(0, 0), stride, BitmapTexture::UpdateCannotModifyOriginalImageData);456 texture.updateContents(srcData, WebCore::IntRect(0, 0, GST_VIDEO_INFO_WIDTH(&videoInfo), GST_VIDEO_INFO_HEIGHT(&videoInfo)), WebCore::IntPoint(0, 0), stride, BitmapTexture::UpdateCannotModifyOriginalImageData); 406 457 gst_video_frame_unmap(&videoFrame); 407 408 return texture; 458 } 459 #endif 460 461 #if USE(COORDINATED_GRAPHICS_THREADED) 462 void MediaPlayerPrivateGStreamerBase::pushTextureToCompositor() 463 { 464 #if !USE(GSTREAMER_GL) 465 class ConditionNotifier { 466 public: 467 ConditionNotifier(Lock& lock, Condition& condition) 468 : m_locker(lock), m_condition(condition) 469 { 470 } 471 ~ConditionNotifier() 472 { 473 m_condition.notifyOne(); 474 } 475 private: 476 LockHolder m_locker; 477 Condition& m_condition; 478 }; 479 ConditionNotifier notifier(m_drawMutex, m_drawCondition); 480 #endif 481 482 WTF::GMutexLocker<GMutex> lock(m_sampleMutex); 483 if (!GST_IS_SAMPLE(m_sample.get())) 484 return; 485 486 LockHolder holder(m_platformLayerProxy->lock()); 487 488 if (!m_platformLayerProxy->isActive()) 489 return; 490 491 #if USE(GSTREAMER_GL) 492 std::unique_ptr<GstVideoFrameHolder> frameHolder = std::make_unique<GstVideoFrameHolder>(m_sample.get()); 493 if (UNLIKELY(!frameHolder->isValid())) 494 return; 495 496 std::unique_ptr<TextureMapperPlatformLayerBuffer> layerBuffer = std::make_unique<TextureMapperPlatformLayerBuffer>(frameHolder->textureID(), frameHolder->size(), frameHolder->flags()); 497 layerBuffer->setUnmanagedBufferDataHolder(WTF::move(frameHolder)); 498 m_platformLayerProxy->pushNextBuffer(WTF::move(layerBuffer)); 499 #else 500 GstCaps* caps = gst_sample_get_caps(m_sample.get()); 501 if (UNLIKELY(!caps)) 502 return; 503 504 GstVideoInfo videoInfo; 505 gst_video_info_init(&videoInfo); 506 if (UNLIKELY(!gst_video_info_from_caps(&videoInfo, caps))) 507 return; 508 509 IntSize size = IntSize(GST_VIDEO_INFO_WIDTH(&videoInfo), GST_VIDEO_INFO_HEIGHT(&videoInfo)); 510 511 std::unique_ptr<TextureMapperPlatformLayerBuffer> buffer = m_platformLayerProxy->getAvailableBuffer(size, GraphicsContext3D::DONT_CARE); 512 if (UNLIKELY(!buffer)) { 513 if (UNLIKELY(!m_context3D)) 514 m_context3D = GraphicsContext3D::create(GraphicsContext3D::Attributes(), nullptr, GraphicsContext3D::RenderToCurrentGLContext); 515 516 RefPtr<BitmapTexture> texture = adoptRef(new BitmapTextureGL(m_context3D)); 517 texture->reset(size, GST_VIDEO_INFO_HAS_ALPHA(&videoInfo) ? BitmapTexture::SupportsAlpha : BitmapTexture::NoFlag); 518 buffer = std::make_unique<TextureMapperPlatformLayerBuffer>(WTF::move(texture)); 519 } 520 updateTexture(buffer->textureGL(), videoInfo); 521 m_platformLayerProxy->pushNextBuffer(WTF::move(buffer)); 522 #endif 409 523 } 410 524 #endif … … 439 553 } 440 554 555 #if USE(COORDINATED_GRAPHICS_THREADED) 556 #if USE(GSTREAMER_GL) 557 pushTextureToCompositor(); 558 #else 559 { 560 LockHolder lock(m_drawMutex); 561 if (!m_platformLayerProxy->scheduleUpdateOnCompositorThread([this] { this->pushTextureToCompositor(); })) 562 return; 563 m_drawCondition.wait(m_drawMutex); 564 } 565 #endif 566 return; 567 #else 441 568 #if USE(GSTREAMER_GL) 442 569 { … … 450 577 repaint(); 451 578 #endif 579 #endif 452 580 } 453 581 … … 472 600 void MediaPlayerPrivateGStreamerBase::paint(GraphicsContext& context, const FloatRect& rect) 473 601 { 474 #if USE(TEXTURE_MAPPER_GL) && !USE(COORDINATED_GRAPHICS) 602 #if USE(COORDINATED_GRAPHICS_THREADED) 603 ASSERT_NOT_REACHED(); 604 return; 605 #elif USE(TEXTURE_MAPPER_GL) && !USE(COORDINATED_GRAPHICS) 475 606 if (client()) 476 607 return; … … 502 633 503 634 if (m_usingFallbackVideoSink) { 504 if (RefPtr<BitmapTexture> texture = updateTexture(textureMapper)) 505 textureMapper->drawTexture(*texture.get(), targetRect, matrix, opacity); 635 RefPtr<BitmapTexture> texture; 636 { 637 WTF::GMutexLocker<GMutex> lock(m_sampleMutex); 638 639 if (!m_sample) 640 return; 641 642 GstCaps* caps = gst_sample_get_caps(m_sample.get()); 643 if (UNLIKELY(!caps)) 644 return; 645 646 GstVideoInfo videoInfo; 647 gst_video_info_init(&videoInfo); 648 if (UNLIKELY(!gst_video_info_from_caps(&videoInfo, caps))) 649 return; 650 651 IntSize size = IntSize(GST_VIDEO_INFO_WIDTH(&videoInfo), GST_VIDEO_INFO_HEIGHT(&videoInfo)); 652 texture = textureMapper->acquireTextureFromPool(size, GST_VIDEO_INFO_HAS_ALPHA(&videoInfo) ? BitmapTexture::SupportsAlpha : BitmapTexture::NoFlag); 653 updateTexture(static_cast<BitmapTextureGL&>(*texture), videoInfo); 654 } 655 textureMapper->drawTexture(*texture, targetRect, matrix, opacity); 506 656 return; 507 657 } -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h
r193651 r193836 36 36 #include "TextureMapperPlatformLayer.h" 37 37 #endif 38 #if USE(COORDINATED_GRAPHICS_THREADED) 39 #include "TextureMapperPlatformLayerProxy.h" 40 #endif 38 41 39 42 typedef struct _GstMessage GstMessage; 40 43 typedef struct _GstStreamVolume GstStreamVolume; 44 typedef struct _GstVideoInfo GstVideoInfo; 41 45 typedef struct _GstGLContext GstGLContext; 42 46 typedef struct _GstGLDisplay GstGLDisplay; … … 44 48 namespace WebCore { 45 49 50 class BitmapTextureGL; 46 51 class GraphicsContext; 52 class GraphicsContext3D; 47 53 class IntSize; 48 54 class IntRect; … … 51 57 #if USE(TEXTURE_MAPPER_GL) && !USE(COORDINATED_GRAPHICS) 52 58 , public TextureMapperPlatformLayer 59 #elif USE(COORDINATED_GRAPHICS_THREADED) 60 , public TextureMapperPlatformLayerProxyProvider 53 61 #endif 54 62 { … … 106 114 #endif 107 115 116 #if USE(COORDINATED_GRAPHICS_THREADED) 117 virtual PlatformLayer* platformLayer() const override { return const_cast<MediaPlayerPrivateGStreamerBase*>(this); } 118 virtual bool supportsAcceleratedRendering() const override { return true; } 119 #endif 120 108 121 protected: 109 122 MediaPlayerPrivateGStreamerBase(MediaPlayer*); … … 156 169 #if USE(GSTREAMER_GL) 157 170 RunLoop::Timer<MediaPlayerPrivateGStreamerBase> m_drawTimer; 158 Condition m_drawCondition;159 Lock m_drawMutex;160 171 #endif 161 172 mutable FloatSize m_videoSize; 162 173 bool m_usingFallbackVideoSink; 163 #if USE(TEXTURE_MAPPER_GL) && !USE(COORDINATED_GRAPHICS )164 PassRefPtr<BitmapTexture> updateTexture(TextureMapper*);174 #if USE(TEXTURE_MAPPER_GL) && !USE(COORDINATED_GRAPHICS_MULTIPROCESS) 175 void updateTexture(BitmapTextureGL&, GstVideoInfo&); 165 176 #endif 166 177 #if USE(GSTREAMER_GL) 167 178 GRefPtr<GstGLContext> m_glContext; 168 179 GRefPtr<GstGLDisplay> m_glDisplay; 180 #endif 181 182 #if USE(COORDINATED_GRAPHICS_THREADED) 183 virtual RefPtr<TextureMapperPlatformLayerProxy> proxy() const override { return m_platformLayerProxy.copyRef(); } 184 virtual void swapBuffersIfNeeded() override { }; 185 void pushTextureToCompositor(); 186 RefPtr<TextureMapperPlatformLayerProxy> m_platformLayerProxy; 187 #endif 188 189 #if USE(GSTREAMER_GL) || USE(COORDINATED_GRAPHICS_THREADED) 190 RefPtr<GraphicsContext3D> m_context3D; 191 Condition m_drawCondition; 192 Lock m_drawMutex; 169 193 #endif 170 194 }; -
trunk/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerProxy.cpp
r193630 r193836 64 64 m_compositor = compositor; 65 65 m_targetLayer = targetLayer; 66 m_compositorThreadUpdateTimer = std::make_unique<RunLoop::Timer<TextureMapperPlatformLayerProxy>>(RunLoop::current(), this, &TextureMapperPlatformLayerProxy::compositorThreadUpdateTimerFired); 66 67 } 67 68 … … 153 154 } 154 155 156 bool TextureMapperPlatformLayerProxy::scheduleUpdateOnCompositorThread(std::function<void()>&& updateFunction) 157 { 158 LockHolder locker(m_lock); 159 if (!m_compositorThreadUpdateTimer) 160 return false; 161 162 m_compositorThreadUpdateFunction = WTF::move(updateFunction); 163 m_compositorThreadUpdateTimer->startOneShot(0); 164 return true; 165 } 166 167 void TextureMapperPlatformLayerProxy::compositorThreadUpdateTimerFired() 168 { 169 std::function<void()> updateFunction; 170 { 171 LockHolder locker(m_lock); 172 if (!m_compositorThreadUpdateFunction) 173 return; 174 updateFunction = WTF::move(m_compositorThreadUpdateFunction); 175 } 176 177 updateFunction(); 178 } 179 155 180 } // namespace WebCore 156 181 -
trunk/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayerProxy.h
r193630 r193836 76 76 void swapBuffer(); 77 77 78 bool scheduleUpdateOnCompositorThread(std::function<void()>&&); 79 78 80 private: 79 81 void scheduleReleaseUnusedBuffers(); … … 94 96 ThreadIdentifier m_compositorThreadID { 0 }; 95 97 #endif 98 99 void compositorThreadUpdateTimerFired(); 100 std::unique_ptr<RunLoop::Timer<TextureMapperPlatformLayerProxy>> m_compositorThreadUpdateTimer; 101 std::function<void()> m_compositorThreadUpdateFunction; 96 102 }; 97 103
Note: See TracChangeset
for help on using the changeset viewer.