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

news2024/11/15 4:17:55

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.coloradmin.cn/o/1404388.html

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

相关文章

分布式一致性算法---Raft初探

读Raft论文也有一段时间了&#xff0c;但是自己总是以目前并没有完全掌握为由拖着这篇博客。今天先以目前的理解程度&#xff08;做了6.824的lab2A和lab2B&#xff09;对这篇论文做一个初步总结&#xff0c;之后有了更深入的理解之后再进行迭代&#xff0c;关于本文有任何疑问欢…

20240122在WIN10+GTX1080下使用字幕小工具V1.2的使用总结(whisper)

20240122在WIN10GTX1080下使用字幕小工具V1.2的使用总结 2024/1/22 19:52 结论&#xff1a;这个软件如果是习作&#xff0c;可以打101分&#xff0c;功能都实现了。 如果作为商业软件/共享软件&#xff0c;在易用性等方面&#xff0c;可能就只能有70分了。 【百分制】 可选的改…

推荐IDEA一个小插件,实用性很高!!

插件&#xff1a; Convert YAML and Properties File 由于每个人的开发习惯不同&#xff0c;在开发过程中会遇到各种小细节的问题。今天给大家介绍一个小插件&#xff0c;作用不大&#xff0c;细节很足。 就是properties类型文件和yml文件互相自由转换 解决&#xff1a;…

[晓理紫]每日论文分享(有中文摘要,源码或项目地址)--机器人、强化学习

专属领域论文订阅 VX 扫吗关注{晓理紫|小李子}&#xff0c;每日更新论文&#xff0c;如感兴趣&#xff0c;请转发给有需要的同学&#xff0c;谢谢支持 如果你感觉对你有帮助可以扫吗关注&#xff0c;每日准时为你推送最新论文 分类: 大语言模型LLM视觉模型VLM扩散模型视觉导航…

Maven 打包时,依赖配置正确,但是类引入出现错误,一般是快照(Snapshot)依赖拉取策略问题

问题描述&#xff1a; 项目打包时&#xff0c;类缺少依赖&#xff0c;操作 pom.xml -> Maven -> Reload project &#xff0c;还是不生效&#xff0c;但是同事&#xff08;别人&#xff09;那里正常。 问题出现的环境&#xff1a; 可能项目是多模块项目&#xff0c;结构…

快速上手MyBatis Plus:简化CRUD操作,提高开发效率!

MyBatisPlus 1&#xff0c;MyBatisPlus入门案例与简介1.1 入门案例步骤1:创建数据库及表步骤2:创建SpringBoot工程步骤3:勾选配置使用技术步骤4:pom.xml补全依赖步骤5:添加MP的相关配置信息步骤6:根据数据库表创建实体类步骤7:创建Dao接口步骤8:编写引导类步骤9:编写测试类 1.2…

使用Go进行HTTP客户端认证

在Go语言中&#xff0c;HTTP客户端认证可以通过net/http包来实现。下面是一个简单的示例&#xff0c;展示如何使用Go进行HTTP客户端认证。 首先&#xff0c;确保你已经安装了Go语言环境&#xff0c;并设置好了相关的环境变量。 Go语言中的HTTP客户端认证主要涉及到设置请求头…

MB6S-ASEMI小功率家用电源MB6S

编辑&#xff1a;ll MB6S-ASEMI小功率家用电源MB6S 型号&#xff1a;MB6S 品牌&#xff1a;ASEMI 正向电流&#xff08;Id&#xff09;&#xff1a;1A 反向耐压&#xff08;VRRM&#xff09;&#xff1a;600V 正向浪涌电流&#xff1a;30A 正向电压&#xff08;VF&…

基于 Spring Boot+MySQL实现的在线考试系统源码+数据库,基于不同类型的客观题,进行自动组卷、批卷等功能的考试系统

1. 部署相关 1.1. 介绍 一个 JAVA 实现的在线考试系统,主要实现一套基于不同类型的客观题,进行自动组卷、批卷等功能的考试系统&#xff08;没有主观题&#xff09; 1.2. 系统架构 后端技术栈基于 Spring Boot数据库MySQLORMMyBatis & MyBatis-plus缓存Redis、guava的L…

2024年安全员-C证证考试题库及安全员-C证试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年安全员-C证证考试题库及安全员-C证试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人员上岗证考试大纲随机出的…

PG14.2异构迁移_数据目录拷贝方式

本文源库和目标库都是采用二进制tar包进行的安装&#xff0c;非rpm和源码编译方式安装。 采用的办法是编译安装数据库软件 拷贝数据目录的方式 迁移要求 由于Centos即将停止维护&#xff0c;客户强烈要求操作系统更改成Ubuntu18.04&#xff0c;需将Centos的PG14迁移至Ubuntu…

opencv#29 图像噪声的产生

在上一节的图像卷积我们了解到图像卷积可以用于去除图像中的噪声&#xff0c;那么对于现实生活中每一张采集到的图像都会包含噪声&#xff0c;也就是我们通过相机无法得到不包含噪声的图像&#xff0c;如果我想衡量噪声去除能力的强弱&#xff0c;就必须在一张不含噪声的图像中…

架构篇11:架构设计流程-设计备选方案

文章目录 架构设计第 2 步&#xff1a;设计备选方案设计备选方案实战小结 上一期我讲了架构设计流程第 1 步识别复杂度&#xff0c;确定了系统面临的主要复杂度问题后&#xff0c;方案设计就有了明确的目标&#xff0c;我们就可以开始真正进行架构方案设计了。今天我来讲讲架构…

【Go面试向】Go程序的执行顺序

【Go】Go程序的执行顺序 大家好 我是寸铁&#x1f44a; 总结了一篇Go程序的执行顺序的文章✨ 喜欢的小伙伴可以点点关注 &#x1f49d; Go程序内容 go程序通常包含: 包、常量、变量、init()、main()等元素 下面从这几个方面分别去梳理&#xff01; 包的执行顺序 程序中的包 …

【数据结构】链表(单链表与双链表实现+原理+源码)

博主介绍&#xff1a;✌全网粉丝喜爱、前后端领域优质创作者、本质互联网精神、坚持优质作品共享、掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战✌有需要可以联系作者我哦&#xff01; &#x1f345;附上相关C语言版源码讲解&#x1f345; &#x1f44…

【GoLang入门教程】Go语言工程结构详述

程序员裁员潮&#xff1a;技术变革下的职业危机 文章目录 程序员裁员潮&#xff1a;技术变革下的职业危机前言总结:专栏集锦强烈推荐写在最后 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网…

瑞金市城北社区开展新时代文明实践文艺汇演

为发扬中华民族优秀传统文化&#xff0c;促进社区居民邻里交流&#xff0c;丰富居民业余文化生活&#xff0c;1月18日&#xff0c;瑞金市城市社区城北社区新时代文明实践站在金盛小区开展新时代文明实践文艺汇演活动。 社区文艺爱好者们自编自演的节目丰富多彩&#xff0c;现场…

基于open3d的半径滤波

概念原理 半径滤波器比较简单粗暴。以某点为中心画一个圆计算落在该圆中点的数量&#xff0c;当数量大于给定值时&#xff0c;则保留该点&#xff0c;数量小于给定值则剔除该点。此算法运行速度快&#xff0c;依序迭代留下的点一定是最密集的&#xff0c;但是圆的半径和圆内点…

5.命令源码文件及命令行参数

目录 概述命令源码文件接收参数查看参数的使用说明结束 概述 命令源码文件接收参数 命令源码文件是程序的运行入口&#xff0c;是每个可独立运行的程序必须拥有的 无论是 Linux 还是 Windows&#xff0c;如果用过命令行&#xff08;command line&#xff09;的话&#xff0c;肯…

泥石流监测识别摄像机

泥石流监测识别摄像机是一种基于图像识别技术的监测设备&#xff0c;主要用于实时监测和识别泥石流的发生和演变过程&#xff0c;以预警和减灾为目的。这种摄像机通常采用高清晰度摄像头和图像处理系统&#xff0c;能够实时拍摄泥石流事件&#xff0c;并对图像进行处理和分析&a…