【Android 音视频开发打怪升级:音视频硬解码篇】二、音视频硬解码流程:封装基础解码框架

本文深入解析Android音视频硬解码流程,介绍MediaCodec的使用,包括数据流、解码状态和解码流程。通过创建解码基类BaseDecoder,阐述解码器的初始化、数据输入输出、解码状态管理和资源释放,为Android音视频开发提供基础指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文你可以了解到

本文主要简介Android使用硬解码API实现硬解码的流程,包含MediaCodec输入输出缓冲、MediaCodec解码流程、解码代码封装和讲解。

一、简介

MediaCodec 是Android 4.1(api 16)版本引入的编解码接口,同时支持音视频的编码和解码。

一定要好好理解接下来这两幅图,因为后续的代码就是基于这两幅图来编写的。

数据流

首先,来看看MediaCodec的数据流,也是官方Api文档中的,很多文章都会引用。

MediaCodec数据流

仔细看一下,MediaCodec将数据分为两部分,分别为input(左边)和output(右边),即输入和输出两个数据缓冲区。

input:是给客户端输入需要解码的数据(解码时)或者需要编码的数据(编码时)。

output:是输出解码好(解码时)或者编码好(编码时)的数据给客户端。

MediaCodec内部使用异步的方式对input和output数据进行处理。MediaCodec将处理好input的数据,填充到output缓冲区,交给客户端渲染或处理

注:客户端处理完数据后,必须手动释放output缓冲区,否则将会导致MediaCodec输出缓冲被占用,无法继续解码。

状态

依然是一副来自官方的状态图

MediaCodec状态

再仔细看看这幅图,整体上分为三个大的状态:Sotpped、Executing、Released。

  • Stoped:包含了3个小状态:Error、Uninitialized、Configured。

首先,新建MediaCodec后,会进入Uninitialized状态;

其次,调用configure方法配置参数后,会进入Configured;

  • Executing:同样包含3个小状态:Flushed、Running、End of Stream。

再次,调用start方法后,MediaCodec进入Flushed状态;
接着,调用dequeueInputBuffer方法后,进入Running状态;
最后,当解码/编码结束时,进入End of Stream(EOF)状态。

这时,一个视频就处理完成了。

  • Released:最后,如果想结束整个数据处理过程,可以调用release方法,释放所有的资源。

那么,Flushed是什么状态呢?

从图中我们可以看到,在Running或者End of Stream状态时,都可以调用flush方法,重新进入Flushed状态。

当我们在解码过程中,进入了End of Stream后,解码器就不再接收输入了,这时候,需要调用flush方法,重新进入接收数据状态。

或者,我们在播放视频过程中,想进行跳播,这时候,我们需要Seek到指定的时间点,这时候,也需要调用flush方法,清除缓冲,否则解码时间戳会混乱。

再次强调一下,一定要好好理解这两幅图,因为后续的代码就是基于这两幅图来编写的。

二、解码流程

MediaCodec有两种工作模式,分别为异步模式和同步模式,这里我们使用同步模式,异步模式可以参考官网例子

根据官方的数据流图和状态图,画出一个最基础的解码流程如下:

解码流程图

经过初始化和配置以后,进入循环解码流程,不断的输入数据,然后获取解码完数据,最后渲染出来,直到所有数据解码完成(End of Stream)。

三、开始解码

根据上面的流程图,可以发现,无论音频还是视频,解码流程基本是一致的,不同的地方只在于【配置】、【渲染】两个部分。

定义解码器

因此,我们将整个解码流程抽象为一个解码基类:BaseDecoder,为了规范代码和更好的拓展性,我们先定义一个解码器:IDecoder,继承Runnable。

interface IDecoder: Runnable {

    /**
     * 暂停解码
     */
    fun pause()

    /**
     * 继续解码
     */
    fun goOn()

    /**
     * 停止解码
     */
    fun stop()

    /**
     * 是否正在解码
     */
    fun isDecoding(): Boolean

    /**
     * 是否正在快进
     */
    fun isSeeking(): Boolean

    /**
     * 是否停止解码
     */
    fun isStop(): Boolean

    /**
     * 设置状态监听器
     */
    fun setStateListener(l: IDecoderStateListener?)

    /**
     * 获取视频宽
     */
    fun getWidth(): Int

    /**
     * 获取视频高
     */
    fun getHeight(): Int

    /**
     * 获取视频长度
     */
    fun getDuration(): Long

    /**
     * 获取视频旋转角度
     */
    fun getRotationAngle(): Int

    /**
     * 获取音视频对应的格式参数
     */
    fun getMediaFormat(): MediaFormat?

    /**
     * 获取音视频对应的媒体轨道
     */
    fun getTrack(): Int

    /**
     * 获取解码的文件路径
     */
    fun getFilePath(): String
} 

定义了解码器的一些基础操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值