问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Android平台音视频编解码技术详解:软解码与硬解码对比

创作时间:
作者:
@小白创作中心

Android平台音视频编解码技术详解:软解码与硬解码对比

引用
CSDN
1.
https://blog.csdn.net/L2010pc_web/article/details/139501565

关键词:Android,音视频编解码,软解码,硬解码,MediaPlayer,MediaCodec

前言

本文主要介绍Android平台上的音视频编解码技术,重点讨论软解码和硬解码的区别,并介绍Android系统中相关的硬解组件MediaPlayer和MediaCodec。本文只做相关概念总体上的介绍和解释,不做深入讨论。

一、概念解释

1. 概念:

硬解,即硬件解码:硬件解码是图形芯片厂商提出的用GPU资源解码视频流的方案;

软解,即软件解码:相对于硬件解码,传统的软件解码是用CPU承担解码工作。

2. 优缺点对比:

对比
优点
缺点
硬解
效率高、功耗低、热功耗低
a)缺乏有力的支持(包括滤镜、字幕)、局限性较大、设置较为复杂;b)需要硬件有硬件解码模块、相关的驱动配合、合适的播放软件以及对播放软件的正确设置,缺一不可。否则无法开启硬件解码功能。
软解
具备普遍适应性
主要靠算法解码,很耗费CPU性能、耗电。

3. 播放器示例:

3.1 硬解播放器

  • 最简单的播放器组件 —— VideoView

VideoView 基于 MediaPlayer 实现,其基本等价于 MediaPalyer + Surface 的组合。通常原生的 Android 系统,其 MediaPlayer 本身对于视频编解码协议支持比较有限。而 MediaPlayer 内部实现主要通过 MediaExtractor + MediaCodec 的组合实现。

  • Google 的 ExoPlayer

ExoPlayer 基于 MediaCodec 实现。而 MediaCodec 则具备很高的拓展性,支持的协议较多,可以根据流媒体的协议和设备硬件本身来自定义硬件解码。

3.2 软解播放器

  • FFmpeg 播放器框架:FFmpeg

FFmpeg 是一个全平台的,非常强大的软解播放器框架。正是因为 MediaPlayer 支持的媒体格式有限。为了能够播放更多的媒体,许多开发人员使用了 FFmpeg 软件解码器来开发播放器。

对应在 Android 平台的移植,可以参考优秀的博客教程:雷霄骅(leixiaohua1020)的专栏

  • Bilibili 播放器:ijkplayer

是Bilibili 公司 基于 FFmpeg 的开发的一款开源的的播放器。

二、Android 硬解组件

通过上面的介绍可知,无论是 MediaPlayer 还是 MediaCodec,都属于 Android 的硬解(Hardware Codec)。下面简单介绍一下相关的示例。

1. MediaPlayer

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;
        }
    }
}

2. MediaCodec

在 Android 的 Jelly Bean 版本,发布了 Android.media.MediaCodec API。该 API 使用与 OpenMAX(媒体行业中的著名标准)相同的原理和架构设计,有效地从纯粹的高级媒体播放器转换到低级编码器/解码器。

由于 MediaCodec 是使用 Java API 编写的,因此它允许接口访问底层系统编解码器,无论是硬件编解码器,还是结合音频编解码器,都是高度优化的软件编解码器。使用MediaCodec能获得合理性能优化并节省电量。

3. 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);  

总结

以上就是今天要讲的内容,本文仅仅简单介绍了Android平台上的音视频编解码技术,包括软解码和硬解码的区别,以及Android系统中相关的硬解组件MediaPlayer和MediaCodec。而Android提供了大量能使我们快速便捷地处理音视频数据的函数和方法,开发者可以根据实际需求选择合适的方案。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号