Video Playback and Compositor

Authors: jamesr@chromium.org, danakj@chromium.org

The Chromium compositor has support for video playback to support offloading work to the GPU and displaying video frames while the main thread is blocked.  There are a few different media engine implementations in Chromium, but they interact with the compositor in similar ways.  Here’s a diagram of the different classes and how they interact:

Things in dotted square boxes are interfaces, things in ovals are concrete classes.  Arrows represent pointers between objects.

Objects by thread (note that a few span multiple threads):

Before video playback:

1.) WebMediaPlayerClientImpl constructed by WebCore

At start of video load:

2.) WebMediaPlayerClientImpl constructs WebMediaPlayer

In SetReadyState, if the video has loaded enough to know we want composited playback:

3.) WebMediaPlayerImpl constructs a WebLayerImpl wrapping a cc::VideoLayer with the provider pointer set to the WebMediaPlayerImpl

4.) WebMediaPlayerImpl provides WebLayer* to WebMediaPlayerClientImpl to register in WebCore’s compositing tree

On the next compositor commit during tree sync (on compositor thread with main thread blocked):

5.) cc::VideoLayer creates a cc::VideoLayerImpl and passes the cc::VideoFrameProvider*

6.) cc::VideoLayerImpl creates a cc::VideoFrameProviderClientImpl with the provider pointer

7.) cc::VideoFrameProviderClientImpl calls SetVideoFrameProviderClient(this) on the cc::VideoFrameProvider*, which is the WebMediaPlayerImpl

On tree activation (immediately after tree sync when not in impl-side painting, at some point later on in impl-side painting)

8.) Active tree cc::VideoLayerImpl sets itself as the cc::VideoFrameProviderClientImpl’s active layer

If we fully initialize without anything shutting down, then the pathway for the video layer to grab a new frame is:

On the compositor thread when preparing to draw a frame:

1.) cc::VideoLayerImpl::WillDraw calls VideoFrameProviderClientImpl::AcquireLockAndCurrentFrame()

2.) VFPCI::ALACF takes its provider_lock_ and calls GetCurrentFrame() on its provider

3.) WebMediaPlayerImpl takes its internal lock_ and returns its current_frame_

4.) cc::VideoLayerImpl uploads data into textures (if needed)

On the compositor thread when drawing a frame:

5.) cc::VideoLayerImpl::AppendQuads adds quads into the draw list referencing the video texture(s)

On the compositor thread after drawing a frame:

6.) cc::VideoLayerImpl::DidDraw calls VideoFrameProviderClientImpl::PutCurrentFrame

7.) VFPCI::PCF calls PutCurrentFrame() on its provider

8.) cc::VideoLayerImpl::DidDraw calls VFPCI::ReleaseLock which releases provider_lock_

The way the media system can notify the compositor of new video frames on the compositor thread is (currently implemented only on android):

On the compositor thread when the media system has a new frame available

1.) Something in the media playback system (content::StreamTextureProxyImpl for android) calls cc::VideoFrameProvider::DidReceiveFrame()

2.) cc::VideoFrameProviderClientImpl checks if it has an active cc::VideoLayerImpl and calls SetNeedsRedraw() on it if so

3.) cc::VideoLayerImpl::SetNeedsRedraw tells the compositor to schedule a new frame

Shutdown

There are a few ways this system can shut down.  All shutdown paths start on the main thread, but they can propagate out to other threads in different ways depending on the type of shutdown.

Video layer removed from compositing tree while playing

This can happen if a <video> element is detached from the DOM tree or display:none is set on an ancestor of the element.

There are two cases to consider here - impl-side painting off and impl-side painting on.  With impl-side painting off, there is only one cc::VideoLayerImpl associated with a given cc::VideoLayer.  The cc::VideoLayerImpl is always created or destroyed during the tree sync part of commit which happens on the compositor thread with the main thread blocked.

With impl-side painting on, there are potentially two cc::VideoLayerImpls associated with a given cc::VideoLayer.  One is in the pending/recycle tree and is always created/destroyed during the commit tree sync on the compositor thread with the main thread blocked.  The other is in the active tree and is created/destroyed during tree activation, which happens on the compositor thread while the main thread is not blocked.  In impl-side painting mode both cc::VideoLayerImpls hold a reference to the same cc::VideoFrameProviderClientImpl.

Preconditions:

1.) WebMediaPlayerClientImpl owns a WebMediaPlayer (which is a WebMediaPlayerImpl)

2.) WebMediaPlayerImpl owns a WebLayerImpl, which has a ref to a cc::VideoLayer

3.) cc::VideoLayer has an associated cc::VideoLayerImpl (two in impl-side painting mode) which reference a cc::VideoFrameProviderClientImpl

4.) WebMediaPlayerImpl’s provider_client_ pointer points to the cc::VideoFrameProviderClientImpl

5.) cc::VideoFrameProviderClientImpl’s provider_ pointer points to the WebMediaPlayerImpl

Sequence:

On the main thread at any point in time

1.) cc::VideoLayer removed from the compositing tree and/or destroyed

In the next compositor commit on the compositor thread with the main thread blocked:

2.) Tree sync starts destruction of the cc::VideoLayerImpl (only cc::VideoLayerImpl when not in impl-side painting, pending/recycle layer in impl-side painting)

3.) ~cc::VideoLayerImpl() calls cc::VideoFrameProviderClientImpl::Stop()

4.) cc::VFPCI::Stop() calls SetVideoFrameProviderClientImpl(NULL) on its cc::VideoFrameProvider*, which is a WebMediaPlayerImpl

5.) cc::VFPCI::StopUsingProvider() takes its provider_lock_ and nulls out its provider_

6.) WebMediaPlayerImpl nulls out its provider_client_ pointer

7.) cc::VFPCI::Stop() nulls out its provider_ pointer (again)

If in impl-side painting mode, on tree activation in the compositor thread:

8.) cc::VideoLayerImpl in active tree destroyed, dropping last reference to cc::VideoFrameProviderClientImpl

Ordering:

Steps 2-7 happen on the compositor thread with the main thread blocked.  This means that the compositor cannot be in a frame for any of these steps and nothing on the main thread can advance (i.e. we can’t start shutting down the WebMediaPlayerImpl).

Postconditions:

1.) WebMediaPlayerImpl’s provider_client_ pointer is NULL (as of step 7)

2.) cc::VideoFrameProviderClientImpl’s provider_ pointer is NULL (as of step 6)

When impl-side painting is not enabled, then

3.) cc::VideoLayerImpl and cc::VideoFrameProviderClientImpl destroyed (as of step 9)

Media engine shut down while video layer is in compositing tree

Preconditions:

1.) WebMediaPlayerClientImpl owns a WebMediaPlayer (which is a WebMediaPlayerImpl)

2.) WebMediaPlayerImpl owns a WebLayerImpl, which has a ref to a cc::VideoLayer

3.) cc::VideoLayer has an associated cc::VideoLayerImpl (two in impl-side painting mode) which reference a cc::VideoFrameProviderClientImpl

4.) WebMediaPlayerImpl’s provider_client_ pointer points to the cc::VideoFrameProviderClientImpl

5.) cc::VideoFrameProviderClientImpl’s provider_ pointer points to the WebMediaPlayerImpl

6.) We’re outside a compositor commit on the main thread

7.) The compositor thread may be in any state, including activation or drawing a frame.

Sequence:

On the main thread at any point in time:

1.) WebMediaPlayerClientImpl destroys its WebMediaPlayer (which is a WebMediaPlayerImpl)

2.) ~WebMediaPlayerImpl() calls SetVideoFrameProviderClient(NULL) on its provider_client_, which is a cc::VideoFrameProvierClientImpl

3.) cc::VideoFrameProviderClientImpl::SetVideoFrameProviderClient() takes its provider_lock_

4.) cc::VideoFrameProviderClientImpl::SetVideoFrameProviderClient() nulls out its provider_ pointer, which pointed to the WebMediaPlayerImpl

5.) cc:VFPCI::SetVideoFrameProviderClient() releases its provider_lock_

6.) ~WebMediaPlayerImpl() completes and the object is destroyed

Ordering:

1.) In step (3) the cc::VFPCI takes its provider_lock_.  If the compositor thread is in the middle of drawing a frame (specifically between WillDraw() and DidDraw()), this call will block until the frame is complete

Postconditions:

1.) WebMediaPlayerImpl’s provider_client_ pointer is NULL (as of step 4)

2.) cc::VideoFrameProviderClientImpl’s provider_ pointer is NULL (as of step 5)

Chromium Graphics: Video Playback and Compositor的更多相关文章

  1. Audio / Video Playback

    For Developers‎ > ‎Design Documents‎ > ‎ Audio / Video Playback Interested in helping out?  Ch ...

  2. Chrome/Chromium HTML5 video 视频播放硬件加速

    Chromium站点上有个大致的框图.描写叙述了Chromium的video在各个平台 - 包含Android - 上是怎样使用硬件资源来做视频编解码加速的: 而依据Android Kitkat上的C ...

  3. stagefright框架(一)Video Playback的流程

    在Android上,預設的多媒體框架(multimedia framework)是OpenCORE. OpenCORE的優點是兼顧了跨平台的移植性,而且已經過多方驗證,所以相對來說較為穩定:但是其缺點 ...

  4. Chromium Graphics: Compositor Thread Architecture

    Compositor Thread Architecture <jamesr, enne, vangelis, nduca> @chromium.org Goals The main re ...

  5. Chromium Graphics: HW Video Acceleration in Chrom{e,ium}{,OS}

    HW Video Acceleration in Chrom{e,ium}{,OS} Ami Fischman <fischman@chromium.org> Status as of 2 ...

  6. Chromium Graphics : GPU Accelerated Compositing in Chrome

    GPU Accelerated Compositing in Chrome Tom Wiltzius, Vangelis Kokkevis & the Chrome Graphics team ...

  7. HW Video Acceleration in Chrome/Chromium HTML5 video 视频播放硬件加速

    Introduction Video decode (e.g. YouTube playback) and encode (e.g. video chat applications) are some ...

  8. Chromium Graphics: Android L平台上WebView的变化及其对浏览器厂商的影响分析

    原创文章.转载请以链接形式注明原始出处为http://blog.csdn.net/hongbomin/article/details/40799167. 摘要:Google近期公布的Android L ...

  9. Chromium Graphics: GPUclient的原理和实现分析之间的同步机制-Part I

    摘要:Chromium于GPU多个流程架构的同意GPUclient这将是这次访问的同时GPU维修,和GPUclient这之间可能存在数据依赖性.因此必须提供一个同步机制,以确保GPU订购业务.本文讨论 ...

随机推荐

  1. html表格设计

    html部分,biaoge.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...

  2. Git 跟 GitHub 是什么关系?

    Git 跟 GitHub 是什么关系? 大概就是「魔兽争霸」与「对战平台」的关系吧. git是一个版本控制工具github是一个用git做版本控制的项目托管平台. git是一个版本管理工具,githu ...

  3. POJ 2190 模拟

    按照题意模拟就好- 注意"X"只能出现在最后一位... // by SiriusRen #include <cstdio> using namespace std; c ...

  4. chrome的全局搜索快捷键

    常用 文件内搜索 ctrl+f 使用快捷键 ctrl+shift+f, 就会进入到全局搜索模式 打开文件:ctrl+o 打开DevTools 你可以通过以下任何一种方式来访问DevTools: 打开浏 ...

  5. jqGrid冻结列

    jqgrid冻结列 冻结列:就是横向移动表格时,让某一列保持不动 做法: 1.colModel的行要加上属性: frozen:true.注意:冻结列必须从第一列开始,包括隐藏列 2.加载jqgrid后 ...

  6. 【记录】Linux安装JDK详细步骤

    Linux安装JDK步骤1. 先从网上下载jdk(jdk-1_5_0_02-linux-i586.rpm) ,推荐SUN的官方网站www.sun.com,下载后放在/home目录中,当然其它地方也行. ...

  7. *hiho 1475 - 数组拆分,dp,由N^2降到NlogN

    题目链接 描述 小Ho得到了一个数组作为他的新年礼物,他非常喜欢这个数组! 在仔细研究了几天之后,小Ho成功的将这个数组拆成了若干段,并且每段的和都不为0! 现在小Ho希望知道,这样的拆分方法一共有多 ...

  8. ZBrush功能特性之变形

    使用ZBrush内置的变形功能可以让用户对三维网格轻松应用扭曲.拉伸.弯曲及其他各种变化.在ZBrush当中,有超过20种的强大变形类型,可以应用于任何轴向.用户只需单击几次即可创造出高级形状,如图所 ...

  9. FCC高级编程篇之Symmetric Difference

    Symmetric Difference Create a function that takes two or more arrays and returns an array of the sym ...

  10. ES6学习笔记(二十)Module 的加载实现

    上一章介绍了模块的语法,本章介绍如何在浏览器和 Node 之中加载 ES6 模块,以及实际开发中经常遇到的一些问题(比如循环加载). 1.浏览器加载 传统方法 HTML 网页中,浏览器通过<sc ...