视频播放原理


***【在线视频教程】***

好文章,来自【福优学苑@音视频+流媒体】

视频播放器简介

  • 视频播放器播放一个互联网上的视频文件(本地文件,需要经过以下几个步骤:

    解协议,解封装,解码视音频,视音频同步

    注意:“文件”本身也是一种“协议”

image.png

解协议

    将流媒体协议的数据,解析为标准的相应的封装格式数据。视音频在网络上传播的时候,常常采用各种流媒体协议,例如HTTP,RTMP,或是MMS等等。这些协议在传输视音频数据的同时,也会传输一些信令数据。这些信令数据包括对播放的控制(播放,暂停,停止),或者对网络状态的描述等。解协议的过程中会去除掉信令数据而只保留视音频数据。例如,采用RTMP协议传输的数据,经过解协议操作后,输出FLV格式的数据。


解封装

    将输入的封装格式的数据,分离成为音频流压缩编码数据和视频流压缩编码数据。封装格式种类很多,例如MP4,MKV,RMVB,TS,FLV,AVI等等,它的作用就是将已经压缩编码的视频数据和音频数据按照一定的格式放到一起。例如,FLV格式的数据,经过解封装操作后,输出H.264编码的视频码流和AAC编码的音频码流。


解码

    将视频/音频压缩编码数据,解码成为非压缩的视频/音频原始数据。音频的压缩编码标准包含AAC,MP3,AC-3等等,视频的压缩编码标准则包含H.264,MPEG2,VC-1等等。解码是整个系统中最重要也是最复杂的一个环节。通过解码,压缩编码的视频数据输出成为非压缩的颜色数据,例如YUV420P,RGB等等;压缩编码的音频数据输出成为非压缩的音频抽样数据,例如PCM数据。


视音频同步

    根据解封装模块处理过程中获取到的参数信息,同步解码出来的视频和音频数据,并将视频音频数据送至系统的显卡和声卡播放出来。

好文章,来自【福优学苑@音视频+流媒体】




FFmpeg播放原理

ffmpeg架构

image.png

ffmpeg解码流程

image.png

  • 1. 注册所有容器格式和CODEC:av_register_all()

  • 2. 打开文件:av_open_input_file()

  • 3. 从文件中提取流信息:av_find_stream_info()

  • 4. 穷举所有的流,查找其中种类为CODEC_TYPE_VIDEO

  • 5. 查找对应的解码器:avcodec_find_decoder()

  • 6. 打开编解码器:avcodec_open()

  • 7. 为解码帧分配内存:avcodec_alloc_frame()

  • 8. 不停地从码流中提取出帧数据:av_read_frame()

  • 9. 判断帧的类型,对于视频帧调用:avcodec_decode_video()

  • 10. 解码完后,释放解码器:avcodec_close()

  • 11. 关闭输入文件:av_close_input_file()

好文章,来自【福优学苑@音视频+流媒体】



VLC视频播放原理

    几乎所有的视频播放器,如VLC、MPlayer、Xine,包括DirectShow,在播放视频的原理和架构上都是非常相似的,理解这个对理解VLC的源码会有事半功倍的效果。

    大致的来说,播放一个视频分为4个步骤:

    1.  acess 访问,或者理解为接收、获取、得到

    2. demux 解复用,就是把通常合在一起的音频和视频分离(还有可能的字幕)   

    3. decode 解码,包括音频和视频的解码

    4. output 输出,也分为音频和视频的输出(aout和vout)

    拿播放一个UDP组播的MPEG TS流来说吧,access部分负责从网络接收组播流,放到VLC的内存缓冲区中,access模块关注IP协议,如是否IPv6、组播地址、组播协议、端口等信息;如果检测出来是RTP协议(RTP协议在UDP头部简单得加上了固定12个字节的信息),还要分析RTP头部信息。这部分可以参看VLC源码 /modules/access/udp.c 。在同目录下还可以看到大量的access模块,如file、http、dvd、ftp、smb、tcp、dshow、mms、v4l…等等


    而demux部分首先要解析TS流的信息。TS格式是MPEG2协议的一部分,概括地说,TS通常是固定188字节的一个packet,一个TS流可以包含多个program(节目),一个program又可以包含多个视频、音频、和文字信息的ES流;每个ES流会有不同的PID标示。而又为了可以分析这些ES流,TS有一些固定的PID用来间隔发送program和es流信息的表格:PAT和PMT表。关于TS格式的详细信息可以去google一下。


    VLC专门做了一个独立的库libdvbpsi来解析和编码TS流,而调用它的代码可以参见VLC源码 /modules/demux/ts.c。

    其实之所以需要demux,是因为音视频在制作的时候实际上都是独立编码的,得到的是分开的数据,为了传输方便必须要用某种方式合起来,这就有了各种封装格式也就有了demux。


    demux分解出来的音频和视频流分别送往音频解码器视频解码器。因为原始的音视频都是占用大量空间,而且冗余度较高的数据,通常在制作的时候就会进行某种压缩。这就是我们熟知的音视频编码格式,包括MPEG1(VCD)、MPEG2(DVD)、MPEG4、H.264、rmvb等等。音视频解码器的作用就是把这些压缩了的数据还原成原始的音视频数据。VLC解码MPEG2使用了一个独立的库libmpeg2,调用它的源文件是 /modules/codec/libmpeg2.c。VLC关于编解码的模块都放在/modules/codec目录下,其中包括著名的庞大的ffmpeg。

    解码器,例如视频解码器输出的是一张一张的类似位图格式的图像,但是要让人从屏幕看得到,还需要一个视频输出的模块。当然可以像一个Win32窗口程序那样直接把图像画到窗口DC上——VLC的一个输出模块WinGDI就是这么干的,但是通常这太慢了,而且消耗大量的CPU。在Windows下比较好的办法是用DirectX的接口,会自动调用显卡的加速功能。

    这样的功能分解使得模块化更容易一点,每个模块住需要专注于自己的事;从整体来说功能强大而且灵活。

好文章,来自【福优学苑@音视频+流媒体】



现代播放器架构

如何构建一个现代播放器,以及构建这样一个播放器需要哪些关键组件。

通常来说,一个典型的播放器可以分解成三部分:UI、 多媒体引擎解码器

image.png


现代播放器架构

  • 用户界面(UI):这是播放器最上层的部分。它通过三部分不同的功能特性定义了终端用户的观看体验:皮肤(播放器的外观设计)、UI(所有可自定义的特性如播放列表和社交分享等)以及业务逻辑部分(特定的业务逻辑特性如广告、设备兼容性逻辑以及认证管理等)。


  • 多媒体引擎:这里处理所有播放控制相关的逻辑,如描述文件的解析,视频片段的拉取,以及自适应码率规则的设定和切换等等,我们将在下文中详细讲解这部分内容。由于这些引擎一般和平台绑定的比较紧,因此可能需要使用多种不同的引擎才能覆盖所有平台。


  • 解码器和 DRM 管理器:播放器最底层的部分是解码器和 DRM 管理器,这层的功能直接调用操作系统暴露出来的 API。解码器的主要功能在于解码并渲染视频内容,而 DRM 管理器则通过解密过程来控制是否有权播放。


接下来我们将使用例子来介绍各层所扮演的不同角色。


一、用户界面(UI)

    UI 层是播放器的最上层,它控制了你用户所能看到和交互的东西,同时也可以使用你自己的品牌来将其定制,为你的用户提供独特的用户体验。这一层最接近于我们说的前端开发部分。在 UI 内部,我们也包含了业务逻辑组件,这些组件构成了你播放体验的独特性,虽然终端用户没法直接和这部分功能进行交互。


UI 部分主要包含三大组件:

1. 皮肤

皮肤是对播放器视觉相关部分的统称:进度控制条、按钮和动画图标等等。和大部分设计类的组件一样,这部分组件也是使用 CSS 来实现的,设计师或者开发者可以很方便的拿来集成(即便你使用的是 JW Player 和 Bitdash 这种整套解决方案)。


2. UI 逻辑

UI 逻辑部分定义了播放过程中和用户交互方面所有可见的交互:播放列表、缩略图、播放频道的选择以及社交媒体分享等。基于你预期达到的播放体验,还可以往这部分中加入很多其它的功能特性,其中有很多以插件的形式存在了,或许可以从中找到一些灵感:Plugins · videojs/video.js Wiki · GitHub 逻辑部分包含的功能较多,我们不一一详细介绍,直接以 Eurosport 播放器的 UI 来作为例子直观感受一下这些功能。


除了传统的 UI 元素之外,还有一个非常有趣的特性,在用户观看 DVR 流媒体的时候,直播以小视窗的形式展示,观众可以通过这个小窗口随时回到直播中。由于布局或者 UI 和多媒体引擎完全独立,这些特性在 HTML5 中使用 dash.js 只需要几行代码就能实现。对于 UI 部分来说,最好的实现方式是让各种特性都以插件/模块的形式添加到 UI 核心模块中。


3. 业务逻辑

除了上面两部分「可见」的功能特性之外,还有一个不可见的部分,这部分构成了你业务的独特性:认证和支付、频道和播放列表的获取,以及广告等。这里也包含一些技术相关的东西,比如用于 A/B 测试模块,以及和设备相关的配置,这些配置用于在多种不同类型的设备之间选择多个不同的媒体引擎。


为了揭开底层隐藏的复杂性,我们在这里更详细的讲解一下这些模块:

设备检测与配置逻辑:这是最重要的特性之一,因为它将播放和渲染剥离开来了。例如,基于你浏览器的不同版本,播放器可能会自动为你选择一个基于 HTML5 MSE 的多媒体引擎 hls.js,或者为你选择一个基于 flash 的播放引擎 FlasHls 来播放 HLS 视频流。这部分的最大特点在于,无论你使用什么样的底层引擎,在上层都可以使用相同的 JavaScript 或者 CSS 来定制你的 UI 或者业务逻辑。


二、多媒体引擎

近年来,多媒体引擎更是以一种全新独立的组件出现在播放器架构中。在 MP4 时代,平台处理了所有播放相关的逻辑,而只将一部分多媒体处理相关的特性(仅仅是播放、暂停、拖拽和全屏模式等功能)开放给开发者。


然而,新的基于 HTTP 的流媒体格式需要一种全新的组件来处理和控制新的复杂性:解析声明文件、下载视频片段、自适应码率监控以及决策指定等等甚至更多。起初,ABR 的复杂性被平台或者设备提供商处理了。然而,随着主播控制和定制播放器需求的递增,一些新的播放器中慢慢也开放了一些更为底层的 API(如 Web 上的 Media Source Extensons,Flash 上的 Netstream 以及 Android 平台的 Media Codec),并迅速吸引来了很多基于这些底层 API 的强大而健壮的多媒体引擎。


三、解码器和 DRM 管理器

出于解码性能(解码器)和安全考虑(DRM),解码器和 DRM 管理器与操作系统平台密切绑定。

image.png

解码器、渲染器和 DRM 工作流程图

1. 解码器

解码器处理最底层播放相关的逻辑。

它将不同封装格式的视频进行解包,并将其内容解码,然后将解码后的视频帧交给操作系统进行渲染,最终让终端用户看到。


由于视频压缩算法变得越来越复杂,解码过程是一个需要密集计算的过程,并且为了保证解码性能和流畅的播放体验,解码过程需要强依赖于操作系统和硬件。现在的大部分解码都依赖于 GPU 加速解码的帮助(这也是为什么免费而更强大的 VP9 解码器没有赢得 H.264 市场地位的原因之一)。如果没有 GPU 的加速,解码一个 1080P 的视频就会占去 70% 左右的 CPU 计算量,并且丢帧率还可能很严重。


在解码和渲染视频帧的基础之上,管理器也提供了一个原生的 buffer,多媒体引擎可以直接与该 buffer 进行交互,实时了解它的大小并在必要的时候刷新它。


我们前面提到,每个平台都有它自己的渲染引擎和相应的 API:Flash 平台有 Netstream,Android 平台有 Media Codec API,而 Web 上则有标准的 Media Sources Extensions。MSE 越来越吸引眼球,将来可能会成为继浏览器之后其它平台上的事实标准。


2. DRM 管理器

今天,在传输工作室生产的付费内容的时候,DRM 是必要的

这些内容必须防止被盗,因此 DRM 的代码和工作过程都向终端用户和开发者屏蔽了。

解密过的内容不会离开解码层,因此也不会被拦截。

好文章,来自【福优学苑@音视频+流媒体】
***【在线视频教程】***