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

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

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

解封装:就是将输入的封装格式的数据,分离成为音频流压缩编码数据和视频流压缩编码数据。如上图,将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 -

干货满满!关注一下呗~

  • 20
    点赞
  • 85
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
FFmpeg软解硬解是两种不同的解码方式。软解是指使用CPU计算进行解码的过程,而硬解则是利用GPU进行解码和渲染的过程。 对于FFmpeg软解,可以通过编译的库里面含有videotoolbox模块来实现硬解,例如在iOS平台上。软解的流程一般是先进行解码,然后将解码出来的数据进行格式转换,再通过软件来渲染显示出来。软解的优点是可以在多种平台上运行,但是当需要同时解码多个视频或者处理复杂的视频时,CPU资源的占用会增加,可能导致卡顿现象。 而FFmpeg硬解,则是利用硬件加速进行解码和渲染。例如,可以调用ffmpeg的dxva2硬解H264/H265图像帧,输入为一帧264/265数据帧,输出为YUV数据,264解码输出为YUV420P,265解码输出为NV12格式。硬解的优点是可以减轻CPU的负担,提解码和渲染的效率,特别是在处理大量视频或者分辨率视频时,能够更好地利用GPU的计算能力。 综上所述,FFmpeg软解硬解是两种不同的解码方式,软解使用CPU进行解码和渲染,硬解则利用GPU进行解码和渲染,具体选择哪种方式取决于实际需求和平台支持。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [FFmpeg软解硬解](https://blog.csdn.net/yinshipin007/article/details/131616862)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [ffmpeg+dxva2硬解](https://download.csdn.net/download/lishi_1991/13012092)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [FFmpeg的软、硬解码方式梳理](https://blog.csdn.net/T__zxt/article/details/125008548)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值