前言
一、概念解释
1. 概念:
2. 优缺点对比:
3. 播放器示例:
二、Android 硬解组件
1. MediaPlayer
2. MediaCodec
3. MediaCodec 的函数调用流程
总结
提示:本文只做相关概念总体上的介绍和解释,不做深入讨论
。
硬解,即硬件解码:硬件解码是图形芯片厂商提出的用 GPU 资源解码视频流的方案;
软解,即软件解码:相对于硬件解码,传统的软件解码是用 CPU 承担解码工作。
对比 | 优点 | 缺点 |
硬解 | 效率高、 功耗低、 热功耗低 | a)缺乏有力的支持(包括滤镜、字幕)、局限性较大、设置较为复杂; b)需要硬件有硬件解码模块、相关的驱动配合、合适的播放软件以及对播放软件的正确设置,缺一不可。否则无法开启硬件解码功能。 |
软解 | 具备普遍适应性 | 主要靠算法解码,很耗费CPU性能、耗电。 |
3.1 硬解播放器
VideoView 基于 MediaPlayer 实现,其基本等价于 MediaPalyer + Surface 的组合。通常原生的 Android 系统,其 MediaPlayer 本身对于视频编解码协议支持比较有限。而 MediaPlayer 内部实现主要通过 MediaExtractor + MediaCodec 的组合实现。
ExoPlayer 基于 MediaCodec 实现。而 MediaCodec 则具备很高的拓展性,支持的协议较多,可以根据流媒体的协议和设备硬件本身来自定义硬件解码。
3.2 软解播放器
FFmpeg 是一个全平台的,非常强大的软解播放器框架。正是因为 MediaPlayer 支持的媒体格式有限。为了能够播放更多的媒体,许多开发人员使用了 FFmpeg 软件解码器来开发播放器。
对应在 Android 平台的移植,可以参考优秀的博客教程:雷霄骅(leixiaohua1020)的专栏
是Bilibili 公司 基于 FFmpeg 的开发的一款开源的的播放器。
通过上面的介绍可知,无论是 MediaPlayer 还是 MediaCodec,都属于 Android 的硬解(Hardware Codec)。下面简单介绍一下相关的示例。
Android 自 API level 1 以来都包含的播放器是 MediaPlayer。开发者能够简单、方便的上手使用它播放音频和视频。播放器如果只是播放音频,可以直接使用 MediaPlayer,如果播放视频,通常使用 MediaPlayer + Surface的组合( 当然,也可以直接使用 VideoView )。
Android平台,实现一个最简单的,使用 VideoView (内部实现基本等价于 MediaPalyer + Surface 的组合)开发的播放器,代码示例:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private VideoView videoView;
private Button btn_start;
private Button btn_pause;
private Button btn_stop;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindViews();
}
private void bindViews() {
videoView = (VideoView) findViewById(R.id.videoView);
btn_start = (Button) findViewById(R.id.btn_start);
btn_pause = (Button) findViewById(R.id.btn_pause);
btn_stop = (Button) findViewById(R.id.btn_stop);
btn_start.setOnClickListener(this);
btn_pause.setOnClickListener(this);
btn_stop.setOnClickListener(this);
// 方式一:根据设备上的视频文件路径播放
if (Environment.getExternalStorageState().
equals(Environment.MEDIA_MOUNTED)) {
videoView.setVideoPath(Environment.
getExternalStorageDirectory() + "/lesson.mp4");
}
// 方式二:读取放在 app 安装文件的 raw 目录的视频文件
//videoView.setVideoURI(Uri.parse(
// "android.resource://com.jay.videoviewdemo/" + R.raw.lesson));
videoView.setMediaController(new MediaController(this));
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start:
videoView.start();
break;
case R.id.btn_pause:
videoView.pause();
break;
case R.id.btn_stop:
videoView.stopPlayback();
break;
}
}
}
在 Android 的 Jelly Bean 版本,发布了 Android.media.MediaCodec API。该 API 使用与 OpenMAX(媒体行业中的著名标准)相同的原理和架构设计,有效地从纯粹的高级媒体播放器转换到低级编码器/解码器。
由于 MediaCodec 是使用 Java API 编写的,因此它允许接口访问底层系统编解码器,无论是硬件编解码器,还是结合音频编解码器,都是高度优化的软件编解码器。使用MediaCodec能获得合理性能优化并节省电量。
调用流程设计的非常简单,参照下图。
配置完成后,开发人员使用 dequeueInputBuffer 获取硬件缓冲区ID。
将解码原始缓冲区复制到输入队列后,使用 queueInputBuffer 使硬件编解码器执行解码功能。
开发人员使用 dequeueOutputBuffer 获取解码缓冲区,然后使用 releaseOutputBuffer 释放硬件缓冲区,输出渲染到屏幕。
有关详细代码,请参阅 Android 源码
https://cs.android.com/android/platform/superproject/main
cts/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
此示例代码使用 MediaExtractor 作为媒体格式解析器。
开发人员需要使用 MediaFormat.createVideoFormat 来创建视频格式(如果使用 MediaExtractor,则使用 getTrackFormat 来获取格式)。
一些解码器(例如:H.264)需要额外的配置信息。可以使用 MediaFormat 或者 刷新帧 添加此信息。例如: H.264刷新帧是IDR帧,在该帧的报头中包括附加配置信息。创建 H.264视频格式示例代码:
videoformat = MediaFormat.createVideoFormat(“video/avc”, width,height);
videoformat.setByteBuffer("csd-0", extra configure data);
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。