视频的播放原理

1.视频播放器简介

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

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

  注意:本地文件也是一种协议

在这里插入图片描述

解协议

  将流媒体协议的数据,解析为标准的相应的封装格式数据。音视频在网络上传播的时候,常常采用各种流媒体协议,例如 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 数据。

音视频同步

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

2.FFmpeg播放原理

ffmpeg架构:
在这里插入图片描述
ffmpeg解码流程
在这里插入图片描述

  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()

3.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 的接口,会自动调用显卡的加速功能。这样的功能分解使得模块化更容易一点,每个模块住需要专注于自己的事;从整体来说功能强大而且灵活。

4.现代播放器架构

  如何构建一个现代播放器,以及构建这样一个播放器需要哪些关键组件。
  通常来说,一个典型的播放器可以分成三部分:UI、多媒体引擎和解码器。
现代播放器架构

  • 用户界面(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 管理器与操作系统平台密切绑定。

  下图为解码器、渲染器和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 的代码和工作过程都向终端用户和开发者屏蔽了。解密过的内容不会离开解码层,因此也不会被拦截。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值