现在各种视频软件上都有硬解软解这两个选择,但它们有什么区别呢?用哪个好呢?今天就跟随小编一起了解了解吧。

首先,了解下播放视频的基本流程:

解封装:就是将输入的封装格式的数据,分离成为音频流压缩编码数据和视频流压缩编码数据。如上图,将MP4和FLV格式解封装成视频数据H264、MPEG2和音频数据AAC、MP3格式。

解码:就是将视频/音频压缩编码数据,解码成为非压缩的视频/音频原始数据。如上图,将视频数据解码成YUV格式和音频数据解码成PCM格式。

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

所谓的软解硬解也就是在解码方式上的区别。下面我们说说软件硬解到底是什么,各有什么优缺点。

概述

软件解码:即通过软件让CPU来对视频进行解码处理;

硬件解码:是将原来全部交由CPU来处理的视频数据的部分交由GPU来做。

优缺点

硬解码效率非常高,这样不但能够减轻CPU的负担,还有着低功耗,发热少等特点。但是,由于硬解码起步比较晚,软件和驱动对他的支持度很低,往往会出现兼容性不好的问题。此外,硬解码的滤镜、字幕、画质方面都做的不够理想。

软解码需要对大量的视频信息进行运算,所以对CPU处理性能的要求非常高。巨大的运算量就会造成转换效率低,发热量高等问题。不过,软解码不需要过多的硬件支持,兼容性非常高。而且软解码拥有丰富的滤镜,字幕,画面处理优化等效果,只有你CPU够强悍,就能够实现更加出色的画面效果。

实现方式

软解码

我们最最常见的视频软解码开源库就是FFmpeg。目前基于FFmpeg的开源播放器有B站的ijkplayer。

ijkplayer的开源地址 : https://github.com/bilibili/ijkplayer

从下图中可以看到,ijkplayer内部利用了ffmpeg解码库。

基于ffmpeg实现主要接口

//创建ffmpeg codec,在ffmpeg中是根据codecid(aac,h264等注册的id)寻找合适的decoder,返回AVCodec对象
avcodec_find_decoder/*这函数创建decode的context,返回的codecContext包含解码器所需要的各种配置信息,比如对于aac decode,context可以用来设置sample_rate,channels,profile等对于h264 decode,context可以用来设置width,height等*/
avcodec_alloc_context3//用已经配置好的decoder的context,来configure解码器codec
avcodec_open2//初始化一个pkt用于接收待解码的数据,用demux输出的数据,填充pkt的data,设置pkt的flag(是否包含key frame等)
av_init_packet(AVPacket *pkt)//将填充满的pkt,发送给解码器
avcodec_send_packet//从解码器接收decode后的数据,填充到AVFrame中。
avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)

硬解码

MediaCodec

MediaCodec是安卓自带的视频编解码接口,由于使用的是硬解码,其效率相对FFMPEG高出来不少。而MediaCodec就很好拓展,我们可以根据流媒体的协议和设备硬件本身来自定义硬件解码,代表播放器就是Google的ExoPlayer。

ExoPlayer的开源地址 : https://github.com/google/ExoPlayer

基本流程:

  • 1.创建和配置MediaCodec对象
  • 2.进行以下循环:
  • 如果一个输入缓冲区准备好:
  • 读取部分数据,复制到缓冲区
  • 如果一个输出缓冲区准备好:
  • 复制到缓冲区
  • 3.销毁MediaCodec对象

接口如下:

//根据视频编码创建解码器,这里是解码AVC编码的视频
MediaCodec mediaCodec =MediaCodec.createDecoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
//创建视频格式信息
MediaFormat mediaFormat = MediaFormat.createVideoFormat(mimeType, width, height);
//配置
mediaCodec.configure(mediaFormat, surfaceView.getHolder().getSurface(), null, 0);
mediaCodec.start();
//停止解码,此时可以再次调用configure()方法
mediaCodec.stop();
//释放内存
mediaCodec.release();
//一下是循环解码接口
getInputBuffers:获取需要编码数据的输入流队列,返回的是一个ByteBuffer数组
queueInputBuffer:输入流入队列
dequeueInputBuffer:从输入流队列中取数据进行编码操作
getOutputBuffers:获取编解码之后的数据输出流队列,返回的是一个ByteBuffer数组
dequeueOutputBuffer:从输出队列中取出编码操作之后的数据
releaseOutputBuffer:处理完成,释放ByteBuffer数据 

用MediaCodec来实现的话,代码中主要通过上面的接口实现了媒体的播放过程。

实例可以参考:

https://blog.csdn.net/u014653815/article/details/81084161

下图是MediaCodec调用createDecoderByType创建过程。

由上图可知,MediaCodec并不是真正的codec,真正codec是在openMax。

OpenMax是一个多媒体应用程序的框架标准,通过使媒体加速组件能够在开发、集成和编程环节中实现跨多操作系统和处理器硬件平台,提供全面的流媒体编解码器和应用程序便携化。Android的多媒体引擎OpenCore和StageFright都可以使用OpenMax作为插件,主要用于编解码(Codec)处理。

下面我来看看硬件厂商又是如何将自己硬解码代码加载到OpenMax框架中的?

在加载软解码库的代码中,可以看到有加载libstagefrighthw.so的代码,其是加载硬件解码plugin,每个平台都有自己libstagefrighthw.so的实现,以实现硬编解码。

MediaPlayer

MediaPlayer是Android中的一个多媒体播放类,我们能通过它控制音视频流或本地音视频资源的播放过程。

以下是mediaPlayer接口:

MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();

用MediaPlayer来实现的话,代码中主要通过5个步骤实现了媒体的播放功能。底层是如何实现的呢?下面我们就来看看。

不同的平台,硬件厂商也会实现自己的播放器。下图是MediaPlayer框架图:

MediaPlayer通过Binder通信,最后调用到MediaPlayerService(由于篇幅问题,其过程这里就不展开讲了,可以参考小编的另一篇文章:【android系统】binder通信机制--记一次项目开发中用到的实例)。这里以Hiplayer为例,展开说明下厂商是如何在android 的 mediaplayer中注入自己播放器的。

从上图中可以看到,海思自己实现了一个HiMediaPlayerManage,然后实现了HiMediaPlayerFactory来创建HiMediaPlayerManage,HiMediaPlayerFactory是在MediaPlayerFactory中被注册进去的。这样就完成了厂商自己播放器注入到android框架中去。

MediaPlayerFactory也是使用了android设计模式中经典的工厂模式(如果有兴趣关注我们,回复"android设计模式")。

HiMediaPlayerFactory都实现了IFactory的接口,其中最重要的是ScoreFactory和CreatePlayer。其中ScoreFactory是根据播放类型参数来选择播放方式,CreatePlayer创建播放器。

HiMediaPlayerManage就是播放器的具体实现了,用来对接Android标准的MediaPlayer接口。

结束语

在Android设备硬件支持的情况下优先使用Android设备的硬件解码,减少CPU的占用,更加省电。

在Android设备硬解不支持的情况下选择使用软解码,不管怎么样,视频至少能够播放,具有更好的适应性,但是增加了CPU的占用,更加费电,软硬结合才是王道,根据实际情况合理选择。

读完了这篇文章,是否对视频应用的软解硬解有了了解呢?赶紧去试下软解硬解功能吧,你更喜欢哪一个?欢迎大家扫描关注下方二维码和我分享交流吧!也欢迎大家下方留言评论,谢谢!

- END -

干货满满!关注一下呗~

【干货】关于软解(ffmpeg)和硬解(MediaCodec、MediaPlayer)以及底层(OpenMax)的那点事相关推荐

  1. Ubuntu18使用FFMPEG实现QSV硬解

    前言 由于项目需要,需要在一块I7-8850H上进行H264解码成YUV并显示的功能.由于系统是Ubuntu18,故打算使用QT+FFMPEG来实现.先前的一路软解发现CPU占用率去到了20%以上,我 ...

  2. ffmpeg mediacodec 硬解初探

    http://www.cnblogs.com/elesos/p/6860865.html ffmpeg mediacodec 硬解初探 1编译: ffmpeg自3.1版本加入了android medi ...

  3. android播放器和视频拍摄中的硬解和软解以及硬编和软编的区别

    转载 原文地址:https://blog.csdn.net/ltym2014/article/details/82354606 https://blog.csdn.net/lipengshiwo/ar ...

  4. 播放器解码硬解跟软解有什么区别

    1.什么是硬解?硬解是要机器中的专门的解码芯片来完成,质量因厂家的技术能力而定,部分厂商技术实力强,兼容性和解码效果做的比较好,而有些厂商技术实力稍差,兼容性和解码效果做的就不尽如意. 2.什么是软解 ...

  5. Linux安装jellyfin硬件加速,ESXi7,黑群晖,Jellyfin与NVIDIA硬解的解决方案

    Last updated on 2021年1月25日 这是一片没有人的领地,基本没有现成的文章和教程,参考了网络上几乎所有相关教程,总结如下. 关于实现之后的效果,可以参考:https://www.l ...

  6. Win7codecs设置教程-开启高清的详细步骤--硬解

    下载最新版本Win7codecs(解码器)有了这款解码器你不用安装别的播放器了Windows Media Player通吃! 下载好了为什么要设置硬解呢?一般安装好Win7codecs已经默认硬解了, ...

  7. FFmpeg之硬解码

    导读 前面我们已经使用NDK编译出了FFmpeg并且已经集成到了Android Studio中去,相关文章:NDK21编译ffmpeg5.0.1 众所周知,软解码虽然兼容性一流,但是却非常依赖CPU, ...

  8. 基于ffmpeg与nvidia-video-sdk-8.1.24视频硬解与软解多路rtsp,支持Qt的QOpenglWidget与qml接口显示

    https://blog.csdn.net/wanghualin033/article/details/82050448 为了解决工程上的一个问题,我研究了nvidia较新的video-sdk-8.1 ...

  9. ffmpeg解码的软解及硬解(cuda和qsv)使用方法

    对ffmpeg不是很熟悉,在使用的过程中遇到了很多坑,总结下,避免以后再遇到类似情况 版本兼容问题: 本次使用的ffmpeg版本是4.2,解码的调用方式为: int32_t iRet = -1;// ...

最新文章

  1. uefi怎么添加linux启动项,LINUX下EFIBOOTMGR的使用,删除UEFI主板多余启动项和添加启动项...
  2. android Java BASE64编码和解码一:基础
  3. 解决ueditor jquery javascript 取值问题
  4. java json乱码_Java Http请求传json数据乱码问题的解决
  5. 他:32岁,公司骨干技术,月薪1万,加班猝死
  6. 加密 CryptoJS DES
  7. java解析json字符串详解(两种方法)
  8. 引入高速缓存的目的_计算机中高速缓存的作用?
  9. 盘点安卓手机被吐槽最多的三大奇葩设计
  10. 车轱辘APP提交到各应用市场的心得~
  11. 苹果内购那些事儿(二)
  12. Ant Counting
  13. Unity2D:物体旋转方法
  14. Python中%是什么意思?如何使用?
  15. python二级第七套答案
  16. 使用Nexus搭建Maven私服、私服下载与上传
  17. Android 高级工程师面试(一)
  18. 软件开发README文档书写模板
  19. freebsd 启用网关
  20. python csv 转换 excel

热门文章

  1. Promise介绍和详解
  2. IDEA项目结构出现 0% methods,0% lines covered
  3. 计算机图形学期末作业
  4. Visual Studio+oneAPI搭建fortran环境以及部分oneAPI无法集成到Visual Studio中问题
  5. 描述点云配准的正太分布变换和著名的ICP点云配准原理
  6. agetty --noclear tty1进程不结束导致树莓派ubuntu的cpu占用率高
  7. C 库函数 - perror()
  8. LeetCode 203 移除链表元素 HERODING的LeetCode之路
  9. zotero文献管理软件插件配置终极教程
  10. 一个比较有趣的 Android 动画效果