Android 音视频编解码 MediaCodec

MediaCodec 简介

Android中的MediaCodec是一个用于音视频编解码功能的API,使用它可以实现对音视频数据进行压缩、解压缩、编辑和转换。以下是MediaCodec的主要功能:

  1. 支持多种流媒体格式:包括H.264、AAC、VP8等等。

  2. 可以用于实时处理:通过显卡硬解实现低延迟的录制与播放。

  3. 高效:采用底层编码编解码, 能体现高效率和性能,特别适合在高机器配置下处理模式。

  4. 强大的 APIs:支持一系列 API,例如 Android 5.0 以上的 setCallback() 或新的异步方式做双向通信任务,MediaCodec 提供了更多操作控制。

MediaCodec 使用步骤

  1. 配置:创建 MediaCodec 实例并选择所需的输入/输出流格式。

  2. 输入数据:将编码数据送入解码器进行处理。获取输入缓冲区后,您需要填充其数据(例如从文件中读取),然后通过调用 queueInputBuffer() 将缓冲区提交给 MediaCodec 进行处理。

  3. 输出数据:MediaCodec 解码器处理数据后,在输出缓冲区产生所需的 PCM 视频数组或音频信号数组。可以访问输出缓冲区以获取已解码的数据(Ouput buffer)。MediaCodec 回传数据帧描述释放这一信息。

  4. 释放资源:使用完 MediaCodec 后必须销毁它。如果有任何未达到 EOS 并且不再需要的输入或输出缓存区,则必须停止播放并释放所有资源以避免泄漏。

## MediaCodec 常用方法

  1. MediaCodec.createDecoderByType(String mimeType):创建解码器

  2. MediaFormat MediaExtractor.getTrackFormat(int index): 获取媒体文件流的格式。此格式通常包含编解码标准及相关参数等。

  3. ByteBuffer[] MediaCodec.getInputBuffers(): 获取输入缓冲区。

  4. ByteBuffer[] MediaCodec.getOutputBuffers(): 获取输出缓冲区。

  5. int MediaCodec.dequeueInputBuffer(long timeoutUs): 请求一个空闲的解码器输入缓冲区,其中timeoutUs表示请求最大等待时间(微秒)。

  6. void MediaCodec.queueInputBuffer(int index, int offset, int size, long presentationTimeUs, int flags): 添加输入数据到指定的缓冲区及其时间戳信息。

  7. int MediaCodec.dequeueOutputBuffer(BufferInfo info, long timeoutUs): 等待并返回输出缓冲区索引。BufferInfo包含了解码器相关信息和属性,例如已解码数据大小、 PTS、DTS等。

  8. void MediaCodec.releaseOutputBuffer(int index, boolean render): 释放输出缓冲区以便进行下一次解析操作。

  9. void MediaCodec.flush(): 清空所有未处理输入/输出缓冲区,并将解码器重置持状态到初始状态。

  10. void MediaCodec.stop(): 结束并停止正在运行的MediaCodec。

  11. void MediaCodec.release(): 释放资源。

MediaCodec 示例

以下是一个 MediaCodec 实例的简单示例代码,该示例代码从文件 M file 中读取 AAC 音频流并将其解码到 PCM 缓冲区中:

// 创建MediaExtractor来获取已编码的音频数据
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(M_FILE);
int audioTrackIndex = selectTrack(extractor, MIME_TYPE_AUDIO);
extractor.selectTrack(audioTrackIndex);

MediaFormat inputFormat = extractor.getTrackFormat(audioTrackIndex);
String mimeType = inputFormat.getString(MediaFormat.KEY_MIME);
long durationUs = inputFormat.getLong(MediaFormat.KEY_DURATION);

// 创建解码器并配置为解码音频
MediaCodec codec = MediaCodec.createDecoderByType(mimeType);
codec.configure(inputFormat, null, null, 0);
codec.start();

// 获取解码器的输入和输出缓冲区
ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();

// 循环读取音频数据并且解码
try {
    boolean decodeDone = false;
    while (!decodeDone) {
        int inputBufferIndex = codec.dequeueInputBuffer(-1);
        if (inputBufferIndex >= 0) {
            // 将从文件中读取的音频编码数据放入到解码器的输入缓存区中
            ByteBuffer inputBuffer = codecInputBuffers[inputBufferIndex];
            int sampleSize = extractor.readSampleData(inputBuffer, 0);
            if (sampleSize < 0) {
                codec.queueInputBuffer(inputBufferIndex, 0, 0, 0L, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                decodeDone = true;
            } else {
                long presentationTimeUs = extractor.getSampleTime();
                codec.queueInputBuffer(inputBufferIndex, 0, sampleSize, presentationTimeUs, 0);
                extractor.advance();
            }
        }

        //将解码后的PCM音频数据保存在byte数组decodingFrame中。
        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
        int outputBufferIndex = codec.dequeueOutputBuffer(info, TIMEOUT_US);
        if (outputBufferIndex >= 0) {
            ByteBuffer outputBuffer = codecOutputBuffers[outputBufferIndex];
            byte[] decodingFrame = new byte[info.size];
            outputBuffer.get(decodingFrame);
            outputBuffer.clear();
            codec.releaseOutputBuffer(outputBufferIndex, false);
        } 
    }

} finally {

    // 释放一些资源   
    codec.stop();
    codec.release();
    extractor.release();
}

需要注意的是,以上示例代码只能供参考使用,实际使用时需要根据具体情况进行修改和优化。

ffmpeg 和 MediaCodec对比

ffmpeg 和 MediaCodec 都是用于音视频处理的工具,它们有一些共同之处,但也存在很多不同点。

ffmpeg 是一个跨平台的开源集成工具包,可用于解码、编码、转换和播放各种音视频格式。ffmpeg 提供了广泛的功能,可以在命令行中使用,也可以作为库在其他项目中使用,适用于多种操作系统和语言。它支持各种音视频编解码器、滤镜、容器格式等,并且提供了非常灵活的配置选项。

MediaCodec 是 Android 平台上的 API,用于对视频和音频进行硬件加速编解码,以提高性能并减少功耗。MediaCodec 可以与 OpenGL ES 结合使用,使开发者能够通过硬件加速将每个视频帧直接传输到 GPU 上,从而更快地渲染图像。另外,MediaCodec 还提供了基于 Surface 对象的编解码接口,这意味着应用程序可以直接访问硬件,并在屏幕上渲染视频帧。但是,MediaCodec 只是针对 Android 平台的编解码 API,无法在其他平台上使用,而且其功能相对 ffmpeg 较为有限。

总的来说,ffmpeg 提供了比较全面的视频处理功能,并且可以适用于各种操作系统和平台,而 MediaCodec 则主要是针对 Android 平台的硬件加速编解码 API。使用哪个工具取决于你的需求和平台限制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值