硬解码和软解码

  • Post author:
  • Post category:其他



硬解码和软解码



1.硬件解码就是通过显卡的视频加速功能对高清视频进行解码。




因此硬解码能够将CPU从繁重的视频解码运算中释放出来,使播放设备具备流畅播放高清视频的能力。显卡的GPU/VPU要比CPU更适合这类



大数据



量的、低难度的重复工作。视频解码工作从处理器那里分离出来,交给显卡去做,这就叫做“硬解码”。




2.与之对应的,以前纯粹依靠CPU来解码的方式则是“软解码”。




软解码是在显卡本身不支持或者部分不支持硬件解码的前提下,将解压高清编码的任务交给CPU,这是基于硬件配置本身达不到硬解压要求的前提下,属于一个折中的无奈之举

对于一个超级电视而言,观看高清电影无疑是用户最大的诉求,而硬解码的优势就在于可以流畅的支持1080p甚至4K清晰度的电影播放,而不需要占用CPU,CPU就可以如释重负,轻松上阵,承担更多的其他任务。如果通过软解码的方式播放高清电影,CPU的负担较重,往往会出现卡顿、不流畅的现象。



3.视频解码有四个步骤,分别是

VLD(

流处理

)



iDCT(

频率转换

)



MoComp(

运动补偿

)



PostProc(

显示后处理,解码去块滤波

Deblocking)




通常我们所说的

硬件加速或硬件解码

,就是指视频解码的这几个步骤中,用显卡专用的解码引擎替代

CPU

的软件计算,降低

CPU

的计算负荷。


显卡的硬件解码引擎


微软规定的显卡硬件加速标准为

DXVA2.0(DirectX Video Acceleration)

,它将显卡硬件加速级别从高到低划分为四个等级,顺序为:

VLD>iDCT>MoComp>PostProc

。主要包括和以上四个步骤对应的流处理

(BitstreamProcessing CAVLC/CABAC,

前后自适应可变长度编码、前后自适应二进制算数编码

)

、逆变换

(InverseTransform)

、运动补偿

(MotionCompensation)

、解码去块滤波

(Deblocking)

。其中

VLD

加速包含了全部四步,

iDCT

加速包含了

MoComp



PostProc



MoComp

加速包含了

PostProc

。而对

H.264

视频解码则加上了

FGT(FilmGrain Technology

,电影胶片质感技术

)

后分为

A



F

的六个等级,

F

级的硬解级别最高。




解码去块滤波影响画质



其实,无论是硬件解码还是软件解码,所进行的解码过程和解码结果都是完全一样的。他们的区别就是视频解码的工作是由处理器完成,还是由显卡来完成而已。因此,在理论上硬件解码和软件解码的效果应该是完全一样的。但是,也的确有用户在开启和关闭硬解码之后发现明显的画质区别,这个关键在于最后一个解码步骤

PostProc(

显示后处理,解码去块滤波操作

Deblocking)



Deblocking

的意思为解码去块,能够消除

H.264

压缩编码可能产生的马赛克现象,真实地还原视频图像。

Deblocking

对处理器提出了较高的要求,早期的

GeForce6/7



RadeonX1000

显卡在开启显卡硬件加速的状态下就会关闭解码去块滤波操作

Deblocking

,这时播放一些影片会看到较明显的马赛克现象,明显影响画面质量。而在其它编码格式的高清视频中,则没有相关的问题。





硬解码最大的优点就是速度非常快(与软解码相比较而言,在相同条件下),再有就是省电。软解码在解码工过程中要借助软件提供的

算法

来取指,分析,运算解码等工作,相对来讲速度就降下来了,还非常费电。在这里,我再举几个例子吧,比如说电脑中的独立显卡(具有各种的处理,控制芯片,当然还有显存)和集成显示芯片,他们都可以处理图像数据,但是在具有独立显卡的机器中,


CPU


把全部的图形处理工作都交给了专门的显卡去完成(硬件完成,里面也有微指令控制系统,如同


Firmware


),而没有独立显卡的


PC


机中,


CPU


将不可推卸地完成大部分的图形图像的处理任务(软件程序控制


CPU


完成)


,


显示芯片负责少量的处理以及输出。



补充:Android当中的视频编码的4中实现方式分析




在所有的Android平台上进行视频编码都是一件很痛苦的事情,即使到了Android4.3,这种

状况依然没有很大的改变。在Android当中我们很难找到一个效率高同时又免费的将视频编成

AVC/H.264格式。对于Android5.0还没有更细微的研究,所以我们现在暂时先分析

android 4.4以前当中Android各个版本当中的视频编码实现机制。

从Android诞生之日起,MediaRecorder的相关API就没有大的改变过,也就是说从Android1.0到

现在的Android4.3之间一直没有很实用的关于视频编码的API被添加。但是Google自己开发的视频

聊天App–Google Talk对视频编码的处理十分出色。所以如果我们仔细的浏览一下AOSP就会发现那些

用于支持Google Talk实现的关于视频编码的部分的代码(当然Google Talk本身是不开源的。但是

支持Google Talk实现的那部分代码是位于AOSP当中的)。

如果我们想要录制高质量的视频,那么我们就需要深入的了解Android内部提供的关于视频编码的

实现。我们将会分析Android当中提供的MediaRecorder, OMXCodec, MediaCodec, Software encoding

一共4种方式。




(1) MediaRecorder




在很长的一段时间内,我们在Android当中只能使用这个API来录制视频。简单又稳定。但是这个API

只支持对来自Camera preview的frame进行编码。也就说如果你的permission节点当中没有声明

使用camera的权限,你甚至都不能使用MediaRecorder的API。

然后在Android 4.0当中,Google引入了一个隐藏的API,就是GRALLOC_BUFFER.如果我们使用的

是原生的Android系统的话,在ICS版本当中的Camera程序当中一定体验过一个短暂的人脸渐变动画(short-lived

face morphing feature).这个功能的实现是基于一个Hidden API实现的。这个隐藏的API

允许我们可以对来自Surface的frame进行编码。这个API在Android 4.3当中仍然是隐藏的。

关于如何使用Hidden API,网络上又很多教程,其中最简单的办法就是通过reflection。

但是使用隐藏的API本身有点不太稳定,毕竟有的OEM厂商会将AOSP当中的Hidden API删除掉,

例如某粮食品牌手机。




(2) OMXCodec




这种办法的编码过程(encoding)没有解码(decoding)过程稳定,但是比起来MediaRecorder的GRALLOC_BUFFER

来说稳定多了。

使用这种解决办法比使用MediaRecorder要灵活的许多,你可以在stagefright当中同时使用多个

MediaWriter,或者使用自己重新定制的MediaWriter。

如果你想做一些关于视频流(video streaming)的处理或者生成一些特殊的视频容器(video containers),

这个API将会特别好使用。




(3) MediaCodec




这个API是Android 4.1当中才引入的。在Android 4.3当中被优化和改进了一些。

他可以像GRALLOC_BUFFER那样直接提供从surface当中编码视频帧(encode video frame).Google可能会在

以后逐渐的见GRALLOC_BUFFER移除掉,或者deprecate掉。因为Google现在已经发布了具有同样功能的

MediaCodec,但是依然将GRALLOC_BUFFER设置成@hide.

所以如果你的程序的target platform是4.3的话,请优先使用这个api。但是缺点就是文档比较少,教程

也少。在一些特定的设备上甚至都会直接崩掉。

将编码过的帧(frame)封装到一个合适的视频容器(video container)当中是一个很困难的过程,但是直接使用

MediaMutex提供的API功能又十分有限。

在Android 4.1+以上的平台上,MediaCodec需要不同的颜色格式(color formats)作为输入缓冲区(input buffer),

MediaCodec的性能还是很高的,但是没有MediaRecorder稳定,在某些特定的设备上和定制的ROM上会崩掉。




(4) Software encoding




以上提到的三种方法都是基于硬件的编码。软编码的方式相对来说就是更稳定,同时移植性也更好。当然

唯一的缺点就是太难了。还有一个致命的缺点就是跟硬编码相比太慢了,尤其是软编码720P以及以上的视频时,

基本上就挂了。

所以我们在这里也就是提提,当然如果你足够土壕可以购买商业的解决办法,真的是很贵。

所以说还是要多看源代码,即使我们不做系统级的开发,但是我们会将会经常发现SDK当中提供的API并不能

直接解决我们遇到的需求,不是性能达不到,就是干脆解决不了问题。所以我们需要仔细的查看AOSP的代码,

然后查看里面的实现,有一些Hidden API会解决我们的问题。或者查看他们的实现,然后自己单独的移植

出来都可以帮助我们解决问题。

以上只是从理论上进行粗略的分析。并没有提供详细的代码和实现方面的方向。所以我只是提供一个大致的方向。

可以顺着这个方向查看源代码,或者直接Google。

希望以上的文章能对你有所帮助。




版权声明:本文为Jason_Fish原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。