《WebKit 技术内幕》学习之十一(2):多媒体

2 视频

2.1 HTML5视频

        在HTML5规范定义中,Web开发者可以使用“video”元素来播放视频资源。视频中有个重要的问题就是视频编码格式,对此,目前标准中包含了三种编码格式,它们分别是Ogg、MPEG4和WebM。其中Ogg是由Xiph.org组织开发的一个开放标准,不需要任何授权费用,它使用Theora作为视频编码格式和Vorbis作为音频编码格式。MPEG4是MPEG工作组开发的需要授权费用的标准,它使用H.264作为视频编码格式和AAC作为音频编码格式。而WebM是由Google研发的标准,它也是完全免费自由使用的,使用VP8作为视频编码格式和Vorbis作为音频编码格式。表11-1说明4个主流浏览器是否支持这三种标准的情况。

                        表11-1 主流浏览器对HTML5中三个视频格式的支持

        从图中可以看到,除了Chrome浏览器支持所有的三种标准之外,其他浏览器可能只是支持其中的一种或者两种,这对网页的开发者造成了困扰。到底如何编写代码才能让视频在这些浏览器上都能工作呢?示例代码11-1是一种很好的解决方法,前提是前端开发者需要了解三种格式的视频文件。

示例代码11-1 使用“video”元素的HTML5代码片段

    <video width="800" height="600" controls="controls"><source src="video.webm" type="video/webm"><source src="video.mp4" type="video/mp4"><source src="video.ogg" type="video/ogg">Your browser does not support the video tag.</video>

浏览器会根据自身支持情况来决定播放哪一个,对于不支持HTML5视频规范的浏览器来说,它显示的是用户的浏览器不支持它。

HTML5提供了一些属性让开发者来使用JavaScript代码检查和操作视频。HTML5在“video”和“audio”元素之间抽象了一个基类元素,也就是“media”元素,结合它提供的能力,大致有以下几个方面的JavaScript编程接口。

首先是资源加载和信息方面的接口,开发者可以通过特定接口检查浏览器支持什么格式,如Metadata和海报(Poster)等。其次是缓冲(Buffering)处理,包括缓冲区域、进度等信息。然后是播放方面的状态,包括播放、暂停、终止等。再次是搜寻(Seeking)方面的信息,包括设置当前时间、“Timeupdate”事件,以及两个状态“Seeking”和“seeked”。最后是音量方面的设置,包括获取和设置音量、静音和音量变换等事件。

2.2 WebKit基础设施

        WebKit提供了支持多媒体规范的基础框架,如音视频元素、JavaScript接口和视频播放等。根据WebKit的一般设计思想,它主要是提供标准的实现框架,而具体的实现由各个移植来完成,因为音视频需要平台的支持。图11-1是WebKit为了达到这一目标而设计的各个类和它们之间的关系,也包括了Chromium移植的几个基础类,关系比较复杂,下面按功能来分析它们。

                                图11-1 WebKit支持视频的基础类和关系

        首先WebKit是支持规范定义的编程接口,图11-1中左侧的HTMLMediaElement和HTMLVideo-Element类是DOM树中的节点类,分别对应于W3C标准中的定义,包含众多DOM接口,这些接口可以被JavaScript代码访问。

        其次是MediaPlayer和MediaPlayerClient两个类,它们的作用非常明显。MediaPlayer类是一个公共标准类,被HTMLMediaElement类使用来播放音频和视频,它本身只是提供抽象接口,具体实现依赖于不同的WebKit移植。同时,一些播放器中的状态信息需要通知到HTMLMediaElement类,这里使用MediaPlayerClient类来定义这些有关状态信息的接口,HTMLMediaElement类需要继承MediaPlayerClient类并接收这些状态信息。根据前面的描述,规范要求将事件派发到JavaScript代码中,而这一实现就在HTMLMediaElement类完成。

        然后是不同移植对MediaPlayer类的实现,其中包括MediaPlayerPrivateInterface类和WebMediaPlayerClientImpl类。前者是除了Chromium移植之外使用的标准接口,也是一个抽象接口,由不同移植来实现。后者是Chromium移植的实现类。为什么会这样?因为Chromium将WebKit复制出Blink之后就将MediaPlayerPrivateInterface类直接移除了,而在MediaPlayer类中直接调用它。WebMediaPlayerClientImpl类会使用Chromium移植自己定义的WebMediaPlayer接口类来作为实际的播放器,而真正的播放器则是在Chromium项目的代码中来实现的。

        最后是同渲染有关的部分,这里面就是之前介绍的RenderObject树和RenderLayer树,图中的RenderMedia类和RenderVideo类是RenderObject的子类,用于表示Media节点和Video节点。图中并没有关于将MediaPlayer类解码和渲染结合起来这一部分的说明,这在Chromium实现中会介绍到。

        图11-1中关于资源获取的部分也没有绘制出来,本质上来讲,同其他资源一样,这里仍然使用ResourceDispatcher类来请求资源,但是在资源的缓冲上Chromium有特殊之处,这些后面介绍。

        图11-1是采用硬件加速机制的视频播放所使用的类,对于具体过程将在稍后介绍。当然,WebKit也支持使用软件渲染方式来播放视频,实际比硬件加速方式要简单一些。根据之前章节的描述,WebKit采用软件渲染方式不需要使用RenderLayer类、GraphicsLayer类等,当需要绘制的时候,由RenderVideo类使用HTMLMediaElement类获取MediaPlayer对象,调用它的paint方法来让MediaPlayer对象将解码后的图像绘制在当前的2D图形上下文接口中,具体软件渲染过程前面介绍过,比较容易理解,不再赘述。

2.3 Chromium视频机制

2.3.1 资源获取

        因为视频资源相对其他资源而言,一般比较大,当用户播放视频的时候,需要连续性播放以获得较好的体验,但是网络可能并不是一直都稳定和高速,所以资源的获取对用户体验很重要,需要使用缓存机制或者其他机制来预先获取视频资源。

        图11-2是Chromium中的缓存资源类。BufferedDataSource类表示资源数据,它是一个简单的数据表示类,内部包含一个较小的内存空间(32K),实际的缓冲机制由BufferedResourceLoader类完成,前面章节介绍了资源的加载机制,BufferedResourceLoader类也是使用该机制来获取数据,只是它会使用一定的内存空间来保存这些视频数据。在Chromium的设置中,最小的缓存空间是2M内存,最大的缓存空间是20M内存,并没有使用磁盘来缓存视频资源。

                             图11-2 Chromium的视频资源缓存类

        上面这些都是浏览器为视频或者音频所做的工作,看起来一切都与网页开发者无关,真是这样的吗?当然不是,W3C组织提供了Media Source规范,开发者可以使用Media Source接口来进行音视频数据流的缓冲,这样可以按照实际需求来处理数据。还是来看一个JavaScript代码的例子,如示例代码11-2所示。

示例代码11-2 一个使用MediaSource接口的代码片段

    var mediaSource = new MediaSource();var avideo = document.querySelector('avideo');avideo.src = window.URL.createObjectURL(mediaSource);mediaSource.addEventListener('sourceopen', function(e) {var sourceBuffer =mediaSource.addSourceBuffer('video/webm; codecs="vorbis,vp8"');sourceBuffer.append(aChunk);}, false);

这段代码的基本思想是,Web开发者使用“video”元素的“src”属性设置自定义的数据流。不同于传统文件等数据流方式,示例代码11-2使用MediaSource对象来创建一个URL对象,然后往对象中不断地加入音视频数据。结合前面关于播放控制的JavaScript接口和事件,开发者可以将数据流同多媒体播放器播放进度很好地结合起来,从而达到根据实际需求来实现自适应的数据流的目的。

2.3.2 基础设施

        前面介绍了WebKit中支持规范的相关类等基础设施,这里介绍Chromium中支持硬件加速机制的视频播放所需的基础设施。图11-3是一个总体架构图,基于Chromium的多进程结构。

                        图11-3 Chromium多进程结构的媒体播放器设施

        根据多进程架构的设计原则,Chromium的媒体播放器的实现应该在Renderer进程,而对于资源的获取则是在Browser进程。当然,前面介绍的WebKit基础设施需要每个移植的具体实现,所以,WebKit的Chromium移植部分提供了桥接接口,并且实现则是在Chromium代码中来完成的。Chromium支持媒体播放器的具体实现相当复杂,而且涉及到不同的操作系统,目前Chromium在不同操作系统上实现的媒体播放器也不一样。首先看一看Chromium基础类,为了方便理解这些类和图11-1中类之间的关系,图11-4标注了一些WebKit中同Chromium直接相关的类。

                                        图11-4 Chromium支持视频的基础类和关系

        图11-4的上半部分是WebKit和WebKit的Chromium移植中的相关类,它们同样出现在图11-1中,而下半部分是Chromium中使用硬件加速机制来实现视频播放的基础设施类。而从左右分开来看,左边部分是播放器的具体实现类,右边部分则是支持视频在合成器中工作的相关类。

        首先看一看这些类和对象的创建过程。WebMediaPlayerClientImpl类是WebKit在创建HTMLMediaElement对象之后创建MediaPlayer对象的时候,由MediaPlayer对象来创建的。当视频资源开始加载时,WebKit创建一个WebMediaPlayer对象,当然就是Chromium中的具体实现类WebMediaPlayerImpl对象,同时WebMediaPlayerClientImpl类也实现了WebMediaPlayerClient类,所以WebMediaPlayerImpl在播放视频的过程中需要向该WebMediaPlayerClient类更新各种状态,这些状态信息最终会传递到HTMLMediaElement类中,最终可能成为JavaScript事件,如前面介绍播放进度事件等。之后,WebMediaPlayerImpl对象会创建一个WebLayerImpl对象,还会同时创建VideoLayer对象,根据合成器的设计,Chromium还有一个LayerImpl树,在同步的时候,VideoLayer对象对应的VideoLayerImpl对象会被创建。之后Chromium需要创建VideoFrameProviderClientImpl对象,该对象将合成器的Video层同视频播放器联系起来并将合成器绘制一帧的请求转给提供视频内容的VideoFrameProvider类,这实际上是调用Chromium的媒体播放器WebMediaPlayerImpl,因为它就是一个VideoFrameProvider类的实现子类。

        然后是Chromium如何使用这些类来生成和显示每一帧的。当合成器调用每一层来绘制下一帧的时候,VideoFrameProviderClientImpl::AcquireLockAndCurrentFrame()函数会被调用,然后该函数调用WebMediaPlayerImpl类的GetCurrentFrame函数返回当前一帧的数据。VideoLayerImpl类根据需要会将这一帧数据上传(或者是拷贝等)到GPU的纹理对象中。当绘制完这一帧之后,VideoLayerImpl调用VideoFrame-ProviderClientImpl::PutCurrentFrame来通知播放器这一帧已绘制完成,并释放掉相应的资源。同时,媒体播放器也可以通知合成器有一些新帧生成,需要绘制出来,它会首先调用播放器的VideoFrameProvider::DidReceiveFrame()函数,该函数用来检查当前有没有一个VideoLayerImpl对象,如果有对象存在,需要设置它的SetNeedsRedraw标记位,这样,合成器就知道需要重新生成新的一帧。

        最后是上述有关视频播放对象的销毁过程。有多种情况使Chromium需要销毁媒体播放器和相关的资源,如“video”元素被移除或者设置为隐藏等,这样视频元素对应的各种层对象,以及WebKit和Chromium中的这些设施就会被销毁。

        WebMediaPlayerImpl类是多媒体播放器的具体实现类。在Chromium项目中,随着工程师增加了对Android系统(这里不涉及iOS系统话题,那是另外的故事)的支持,Chromium既能支持桌面系统也能支持移动系统,而这两者对视频和音频的支持很不一样,所以在不同系统上WebMediaPlayerImpl是如何实现和工作的,也很不一样。下面,依次了解桌面系统和Android系统中支持视频播放的过程。

2.3.3 桌面系统

        在桌面系统中,Chromium使用了一套多媒体播放框架,而不是直接使用系统或者第三方库的完整解决方案。图11-5是Chromium在桌面系统中采用的多媒体播放引擎的工作模块和过程,来源于网页http://www.chromium.org/developers/design-documents/video,这里稍微做了些修改,这一框架称为多媒体管线化引擎,图中主要的模块是多路分配器(Demuxer)、音视频解码器、音视频渲染器。这些部分主要被WebMediaPlayerImpl类调用。

                                                图11-5 Chromium的多媒体管线化引擎

        在处理音视频的管线化过程中,需要解码器和渲染器来分别处理视频和音频数据。它们均采用一种叫做“拉”而不是“推”的方式进行,也就是说由视频或者音频渲染器根据声卡或者时钟控制器,按需要来请求解码器解码数据,然后解码器和渲染器又向前请求“拉”数据,直到请求从视频资源文件读入数据。根据之前的多进程架构和Chromium的安全机制,整个管线化引擎虽然在Renderer进程中,但是由于Renderer进程不能访问声卡,所以图中渲染器需要通过IPC将数据或者消息同Browser进程通信,由Browser进程来访问声卡。

        虽然FFmpeg多媒体库拥有上述管线化过程的能力,但是其实Chromium并不是将其作为一个黑盒来使用,而是分别使用FFmpeg的不同模块来实现自己的管线化引擎,目的是由自身来控制这一整个过程。

        Chromium使用并行FFmpeg解码技术,也就是说FFmpeg能够在帧这个层面上并行解码,当然这不是针对所有格式的视频文件,目前主要针对H.264这个格式的视频。根据Chromium官方的实验结果,在多核机器上,性能能够得到较大幅度的提升。

        FFmpeg多媒体库只是在桌面系统上被使用,而在Android上则是另外一种情况了。

2.3.4 Android系统

        在Android系统上,情况变得很不一样,因为Chromium使用的是Android系统所提供的android.media.MediaPlayer类,也就是使用系统提供的音视频的渲染框架。在减少了管线化引擎带来复杂性的同时,Chromium却额外引入了一些复杂性,接下来一起来看看。

Android中的Chromium彻底抛弃了FFmpeg,直接使用系统自带的多媒体功能,因而,Android系统支持什么样的视频和音频格式,Chromium就只能支持什么样的相应格式。同时,由于Android多媒体框架的优点,使得视频元素仍然能够同HTML5中的其他技术一起工作,这点很重要。

1.Android媒体播放框架

        Android中使用一个名为“MediaService”的服务进程来为应用程序提供音频和视频的播放功能,图11-6所示的是一个Android的多媒体框架概念图。对于每一个使用多媒体播放功能的应用程序来说,“MediaService”服务是透明的。因为Android系统提供了使用“MediaService”的封装接口,这些接口隐藏了“MediaService”服务内部的细节,应用程序只是使用了简单的播放接口。

                                        图11-6 Android多媒体框架

        MediaService能够为多个播放器提供服务,对于播放器来说,它主要设置两个参数,其一是输入的URL,其二是输出结果的绘制目标。图11-7描述了Android的播放器类和相关类,以及它们之间的关系。

                                        图11-7 Android的MediaPlayer相关类

        所以,当应用程序需要使用播放器的时候,Chromium可以创建MediaPlayer类的对象,调用setDataSource函数来设置待播放视频文件,并调用setSurface来设置视频结果绘制的目标——SurfaceTexture对象,这是一个GL的纹理对象。因为实际的解码和绘制是在MediaService进程中完成的,这需要该纹理对象能够被多个不同的GL上下文对象所访问,支持多个GL上下文对象访问的GL经理对象的类型就是:GL_TEXTURE_EXTERNAL_OES。

        根据上面的描述,读者可以看到Chromium使用Android系统提供的音视频播放功能。这表示Chromium使用Android系统的音视频解码器,所以Chromium是依赖于Android系统支持的音视频编码格式,而不像Chromium的桌面版独立于操作系统支持的音视频编码格式。

2.Chromium的视频解决方案

        在Android系统上,因为Chromium使用系统的多媒体框架,所以它没有自己的管线化引擎,主要的工作还是将Chromium的架构同Android多媒体框架结合起来以完成对网页中视频和音频的播放。

        图11-8是Chromium在Android系统上支持音频和视频播放的播放器主要类,因为Chromium的多进程架构,所以这里面包括两大部分,首先是右侧的Renderer进程中的相关类。根据前面Chromium的桌面版上支持多媒体的相关类,笔者可以看到WebKit::WebMediaPlayer类和WebMediaPlayerClient类来自于WebKit的Chromium移植,这两个类在所有平台上的定义都是一样的。下面介绍Chromium的Android版支持多媒体播放的不同之处。

                                        图11-8 Android系统上的播放器基础设施

        上图中右侧的Renderer进程,从上向下看首先是WebMediaPlayerAndroid类,它同之前的WebMediaPlayerImpl类相似,表示的是Android系统上网页中的播放器,同video元素是一一对应的。与桌面系统上不一样的是,Android系统使用Renderer-MediaPlayerManager类来管理所有的WebMediaPlayerAndroid对象,这是因为一个网页中可能包含多个播放器实例。而WebMediaPlayerProxyAndroid则是同Browser进程来通信的,因为真正的Android播放器是在Browser进程中的,这里主要请求Browser进程创建实际的Android的MediaPlayer类并设置播放文件的信息。

        图11-8中左侧则是实际的播放器,在JNI(Java Native Interface)之上的是Java类,如同前面介绍的,该播放器就是使用Android系统中的android.media.MediaPlayer及其相关类来工作的。从下向上看,首先是BrowserMediaPlayerManager类,该类不仅负责同Renderer进程的播放器类进行通信,而且自身又是一个播放器的管理类,它包含当前全部网页中的所有播放器对象,因为可能会有多个Renderer进程,所以只能通过播放器的唯一标记来区分这些播放器。BrowserMediaPlayerManager类管理称为MediaPlayerAndroid类的多个对象,而MediaPlayerAndroid的子类MediaPlayerBridge则是具体实现类,该子类能够与Java层中相同名字类通过JNI调用来控制Android系统的播放器类,图中已经表明这一关系。请读者记住,这里的所有类都是工作在Browser进程的主线程。

        上面的过程基本上就是如何在网页中创建一个播放器的过程,从右向左,直到图11-8中左侧上面的android.media.MediaPlayer对象被创建完成,与此同时Chromium获取网页中设置的视频文件的URL字符串,然后传递并设置该URL字符串到Android的媒体播放器中。

        输入是有了,那么输出呢?播放器将解码之后的结果输出到什么目标上呢?在Android上,如前面所述,Chrome使用SurfaceTexture对象作为输出目标。创建和使用SurfaceTexture对象的过程是如何进行的呢?当Chromium调用WebMediaPlayerAndroid类的play函数时,该函数发起请求从Renderer进程到Browser进程来创建输出目标,也就是SurfaceTexture对象,图11-9描述了这一过程中使用到的主要类和它们之间的关系。

                                图11-9 媒体播放器的视频结果基础设施

        下面依次了解右侧的Renderer进程部分。从上往下看,最上面的是StreamTexture-FactoryImpl类,顾名思义,该类就是创建目标结果存储空间的类,它被WebMedia-PlayerAndroid类使用来创建所需要的结果存储对象StreamTexture。因为实际的对象是在Browser进程中被创建的,所以Renderer进程中的StreamTextureProxy类就是一个代理类,最后的请求通过GPUChannelHost类来传递给Browser进程。

        在Browser进程中,负责处理上述请求的是GPU线程,该线程由StreamTextureManager-Android类来处理所有创建StreamTexture对象的请求。StreamTexture对象的直接使用者是GPU线程。Renderer进程需要区分和标识这些StreamTexture对象,具体的方法是使用整形标记符来表示Browser进程中的各个StreamTexture对象。StreamTexture和StreamTextureManager是基础抽象类,在Android系统上,StreamTextureAndroid和StreamTextureManagerAndroid是实际的实现类。Stream-TextureAndroid表示的是C++端的桥接类,它包含一个SurfaceTexture对象,该对象会在Java端创建一个android.graphics.SurfaceTexture对象,Chromium设置该对象到MediaPlayer对象作为播放器的输出目标。

        当视频播放器将解码后的结果写入到SurfaceTexture中后,播放器需要告诉Chromium浏览器这一信息,因为Chromium浏览器需要执行合成操作,而合成器在Renderer进程中,同之前创建SurfaceTexture对象的调用过程正好相反,这里需要使用回调机制,这就是Java层SurfaceTextureListener类的作用,该回调类注册Java层的回调对象到创建好的SurfaceTexture对象,当该对象被写入新帧的时候,Chromium首先是从Browser进程中的Java层将这一回调动作通过JNI到C++层的SurfaceTextureListener类的FrameAvailable函数,该函数经过StreamTextureAndroid和StreamTextureManagerAndroid类最后发送到Renderer进程,Renderer进程的调用过程如图11-10所示。

                                                图11-10 视频帧的合成过程

        上面的过程同桌面系统是一致的,在这之后的合成过程相信读者都知道了吧?没错,读者可以回忆一下第8章中对于它们的详细介绍,视频只是众多层中的一层,合成过程仍然是之前所描述的那样。

        网页中的视频播放有两种模式,其一是嵌入式模式,其二是全屏模式,这两种模式在对解码后结果的处理上是不一样的。图11-11描述了全屏模式创建视频结果的绘制目标的相关类和过程。

                                图11-11 全屏模式下的输出目标创建过程

        当某个播放器进入全屏模式的时候,Chromium使用ContentVideoView类来管理,该类会创建一个SurfaceView对象并将对象传递给C++端的ContentVideoView类,因为总是只有一个播放器是全屏模式,而且BrowserMediaPlayerManager管理所有的MediaPlayer对象,所以该管理类能够知道哪个对象是全屏播放模式,并将该SurfaceView对象设置到相应的MediaPlayer对象中去。

        关于多媒体播放器,还有一点非常有趣,那就是播放器的控制器(Controls),它是用来控制播放的开始、停止、快进、声音控制等操作的,网页的开发者在“video”元素中加入属性“controls”就可以调用默认的控制器,浏览器就可以为网页绘制出一个默认的控制器,当然开发者也能够定义自身的控制器,因为浏览器已经提供了相应的JavaScript接口。当使用默认控制器的时候,浏览器是如何绘制控制器的呢?方法就是使用第4章的影子DOM技术,此处介绍的DOM树结构不会出现在网页的DOM树中,这样就可以使用HTML5的CSS技术来绘制所需的控制器,非常方便而且易于维护。

2.4 字幕

        对于视频技术,还有一个重要的组成部分,那就是字幕的支持。庆幸的是,W3C组织已经开始定义支持字幕的“track”元素,而字幕文件采用的格式是WebVTT格式,该格式看起来比较直观,简单的例子就是时间戳区间加上相应的字幕文字,有兴趣的读者可以去W3C官网上查看一下。示例代码11-3是一个使用字幕的视频元素,实际上,因为语言的问题,每个“video”元素可以有多个“track”元素,每个“track”元素可以用来表示一种语言。

示例代码11-3 使用字幕的视频元素代码

    <video controls="controls"><source src="video.mp4" type="video/mp4"><track src="captions.vtt" kind="subtitles" srclang="en"  label="English"></track></video>

        字幕文件的解释工作不依赖各个WebKit移植,WebCore模块完整地支持了“track”元素解析、字幕文件解析等功能。图11-12是WebKit支持字幕功能的主要类,笔者逐次来分析它们。

                                                图11-12 WebKit中支持字幕的基础设施

        “track”本身是一个HTML元素,所以它在DOM中有相应的节点元素,这就是图中的HTMLTrackElement类。根据规范,“track”元素有一个重要的属性,那就是“src”,该属性指定了字幕文件的URL。WebKit使用LoadableTextTrack类来负责解析字幕文件并使用TextTrack类来存储解析后的结果。目前WebKit只支持WebVTT格式的字幕,使用WebVTTParser解析器来解释它们,关系不是很复杂。

        下面一部分是提供接口,这里的接口依然是WebKit的Chromium移植所定义的接口,不同的移植所定义的接口可能不一样。接口依然是两个类,WebInbandTextTrack和WebInbandText-TrackClient类,且是公开接口,WebInbandTextTrack类由Chromium实现,由WebKit调用。而WebInbandTextTrackClient类则由WebKit实现,实现类就是InbandTextTrackPrivateImpl,它实现WebInbandTextTrackClient的接口,然后调用解析后的字幕并返回给Chromium。这一过程由InbandTextTrackPrivateClient类和InbandTextTrack类完成,这里类的关系有些复杂,WebKit/Blink今后最好能简化一下。

        上面这些动作需要将一些消息传递给JavaScript代码,因为规范提供了JavaScript接口,开发者可以让JavaScript代码控制或者获取字幕信息,这些不再介绍。下面是Chromium中的支持框架,图11-13描述了Chromium是如何将WebKit中的字幕信息桥接到多媒体管线化引擎中去的。

                                图11-13 Chromium中支持字幕的基础设施

        在Chromium中,WebMediaPlayerImpl类创建继承类的对象,并设置WebInband-TextTrackClient对象到该对象。根据之前的介绍可知,该对象实际上是InTextTrack,它包含解析后的字幕内容,这样TextTrackImpl就可以获得字幕的内容,而TextTrack对象会被多媒体的管线化引擎所调用并渲染在视频的结果中。

2.5 视频扩展

        在视频领域,还有很多方面在不停地向前发展,包括Media Source接口、音视频资源保护等,这些称为Media的扩展。

        接下来讨论的是对音视频资源的保护,也就是版权保护的问题,通俗一点就是如何避免被非法拷贝和使用。在HTML5中,目前没有成熟方案的原因有两种。一种说法是编码格式应该自行解决该问题,而不是需要HTML5额外提供解决方案。但是,就目前而言,主流的三种方式都没有解决加密等保护问题,所以事实上这的确是一个问题。另外一种就是目前标准组织没有继续坚持之前的想法,开始了其他方面的研究和工作,这就是“Encrypted Media Extensions”,它目前还在草案阶段,主要用来保护播放内容的安全,具体请查看W3C官方网站上的文档。

        而关于Media Source扩展,其主要目的是提供接口来让JavaScript代码能够生成多媒体流,典型的应用场景是自适应流,其主要接口是MediaSource和SourceBuffer。每个MediaSource对象可以包含多个SourceBuffer对象,每个SourceBuffer包含一个数据流,如视频流或音频流,Chromium已经开始提供一些支持。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/648739.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【模拟算法系列】详解5道题

本文讲解模拟算法系列的5道经典题&#xff0c;在讲解题目的同时提供AC代码&#xff0c;点击题目即可打开对应OJ链接 目录 模拟算法的介绍 1、替换所有的问号 2、提莫攻击 3、 Z 字形变换 4、外观数列 5、数青蛙 模拟算法的介绍 题目中明确告诉你要干什么&#xff0c;思路…

ChatGPT 和文心一言 | 两大AI助手哪个更胜一筹

欢迎来到英杰社区&#xff1a; https://bbs.csdn.net/topics/617804998 欢迎来到阿Q社区&#xff1a; https://bbs.csdn.net/topics/617897397 &#x1f4d5;作者简介&#xff1a;热爱跑步的恒川&#xff0c;致力于C/C、Java、Python等多编程语言&#xff0c;热爱跑步&#xff…

Web开发4:单元测试

在Web开发中&#xff0c;单元测试是一种重要的开发实践&#xff0c;它可以帮助我们确保代码的质量和可靠性。通过编写和运行单元测试&#xff0c;我们可以验证代码的正确性&#xff0c;减少错误和缺陷&#xff0c;并提高代码的可维护性。本文将介绍单元测试的概念、好处以及如何…

python写一个彩票中奖小游戏修订版本

先说规则&#xff1a; print("下面介绍双色球颜色规则:")print("一等奖,投注号码与当期开奖号码全部相同&#xff08;顺序不限&#xff0c;下同&#xff09;&#xff0c;即中奖")print("二等奖:投注号码与当期开奖号码中的6个红色球号码相同,即中奖&q…

鸿蒙开发实战-手写文心一言AI对话APP

运行环境 &#xff08;后面附有API9版本&#xff0c;可修改后在HarmonyOS4设备上运行&#xff09; DAYU200:4.0.10.16 SDK&#xff1a;4.0.10.15 IDE&#xff1a;4.0.600 在DAYU200:4.0.10.16上运行 一、创建应用 1.点击File->new File->Create Progect 2.选择模版…

分享7种SQL的进阶用法

分享7种SQL的进阶用法 前言 还只会使用SQL进行简单的insert、update、detele吗&#xff1f;本文给大家带来7种SQL的进阶用法&#xff0c;让大家在平常工作中使用SQL简化复杂的代码逻辑。 1.自定义排序&#xff08;ORDER BY FIELD&#xff09; 在MySQL中ORDER BY排序除了可以…

temu跨境电商怎么样?做temu蓝海项目有哪些优势?

在全球电商市场激烈的竞争中&#xff0c;Temu跨境电商平台以其独特的优势和策略&#xff0c;逐渐崭露头角。对于许多想要拓展海外市场的商家来说&#xff0c;Temu的蓝海项目提供了一个充满机遇的新平台。本文将深入探讨Temu跨境电商的优势以及在蓝海市场中的发展前景。 全球化市…

编程笔记 html5cssjs 056 CSS不透明度

编程笔记 html5&css&js 056 CSS不透明度 一、CSS 不透明度 / 透明度二、使用 RGBA 的透明度三、透明盒中的文本小结 不透明度/透明度。利用透明度可以提高页面的层次效果。 一、CSS 不透明度 / 透明度 opacity 属性指定元素的不透明度/透明度。 opacity 属性通常与 :h…

仅使用 Python 创建的 Web 应用程序(前端版本)第08章_商品详细

在本章中,我们将实现一个产品详细信息页面。 完成后的图像如下。 Model、MockDB、Service都是在产品列表页实现的,所以创建步骤如下。 No分类内容1Page定义PageId并创建继承自BasePage的页面类2Application将页面 ID 和页面类对添加到 MultiPageApp 的页面中Page:定义PageI…

VsCode提高生产力的插件推荐-持续更新中

别名路径跳转 自定义配置// 文件名别名跳转 "alias-skip.mappings": { "~/": "/src", "views": "/src/views", "assets": "/src/assets", "network": "/src/network", "comm…

Android App开发基础(2)—— App的工程结构

本专栏文章 上一篇 Android开发修炼之路——&#xff08;一&#xff09;Android App开发基础-1 2 App的工程结构 本节介绍App工程的基本结构及其常用配置&#xff0c;首先描述项目和模块的区别&#xff0c;以及工程内部各目录与配置文件的用途说明&#xff1b;其次阐述两种级别…

THM学习笔记——OSI模型和TCP/IP模型

全是文字 比较枯燥 建议视频 OSI模型由七个层次组成&#xff1a; 第7层 -- 应用层&#xff1a; OSI模型的应用层主要为在计算机上运行的程序提供网络选项。它几乎专门与应用程序一起工作&#xff0c;为它们提供一个界面以用于传输数据。当数据传递到应用层时&#xff0c;它…

【医学图像隐私保护】联邦学习:密码学 + 机器学习 + 分布式 实现隐私计算,破解医学界数据孤岛的长期难题

联邦学习&#xff1a;密码学 机器学习 分布式 提出背景&#xff1a;数据不出本地&#xff0c;又能合力干大事联邦学习的问题 分布式机器学习&#xff1a;解决大数据量处理的问题横向联邦学习&#xff1a;解决跨多个数据源学习的问题纵向联邦学习&#xff1a;解决数据分散在多…

【grafana】使用教程

【grafana】使用教程 一、简介二、下载及安装及配置三、基本概念3.1 数据源&#xff08;Data Source&#xff09;3.2 仪表盘&#xff08;Dashboard&#xff09;3.3 Panel&#xff08;面板&#xff09;3.4 ROW&#xff08;行&#xff09;3.5 共享及自定义 四、常用可视化示例4.1…

湿法蚀刻酸洗槽—— 应用半导体新能源光伏光电行业

PFA清洗槽又被称为防腐蚀槽、酸洗槽、溢流槽、纯水槽、浸泡槽、水箱、滴流槽&#xff0c;是四氟清洗桶后的升级款&#xff0c;是为半导体光伏光电等行业设计&#xff0c;一体成型&#xff0c;无需担心漏液。主要用于浸泡、清洗带芯片硅片电池片的花篮。 由于PFA的特点它能耐受…

【linux-虚拟化】 SR-IOV技术

文章目录 参考1. 什么是 SR-IOV?1.2. 将 SR-IOV 网络设备附加到虚拟机1.3. SR-IOV 分配支持的设备 参考 管理 SR-IOV 设备 1. 什么是 SR-IOV? 单根 I/O 虚拟化(SR-IOV)是一种规范&#xff0c;它允许单个 PCI Express(PCIe)设备向主机系统呈现多个独立的 PCI 设备&#xff…

QT获取本机网络信息

QT获取本机网络信息 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();void getinform…

视频智能分析:冶炼/冶金工厂视频智能监管方案的设计和应用

一、背景与需求 随着工业4.0的推进&#xff0c;冶金行业正面临着转型升级的压力。为了提高生产效率、降低能耗、保障安全&#xff0c;冶金智能工厂视频监管方案应运而生。该方案通过高清摄像头、智能分析技术、大数据处理等手段&#xff0c;对工厂进行全方位、实时监控&#x…

k8s的安全机制

k8s的安全机制。分布式集群管理工具&#xff0c;就是容器编排 安全机制的核心&#xff1a;APIserver作为整个内部通信的中介&#xff0c;也是外部控制的入口&#xff0c;所有的安全机制都是围绕API server来进行设计 请求API资源&#xff1a; 1、认证 2、鉴权 3、准入机制 …

如何使用WinSCP公网远程访问本地CentOS服务器编辑上传文件

文章目录 1. 简介2. 软件下载安装&#xff1a;3. SSH链接服务器4. WinSCP使用公网TCP地址链接本地服务器5. WinSCP使用固定公网TCP地址访问服务器 1. 简介 ​ Winscp是一个支持SSH(Secure SHell)的可视化SCP(Secure Copy)文件传输软件&#xff0c;它的主要功能是在本地与远程计…