Android16进阶之MediaRecorder.setVideoEncoder调用流程与实战(二百五十八)

简介: CSDN博客专家、《Android系统多媒体进阶实战》作者

博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列原创干货持续更新中...... 】🚀
Android多媒体专栏地址:多媒体系统工程师系列原创干货持续更新中...... 】🚀
专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀
专题三:Android14 Binder之HIDL与AIDL通信实战课 🚀
专题四:Android15快速自定义与集成音效实战课 🚀
专题五:Android15音频策略实战课 🚀
专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例) 🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
更多原创,欢迎关注:Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉

      • [🌻1. 前言](#🌻1. 前言)
      • [🌻2. 用法与应用场景](#🌻2. 用法与应用场景)
      • [🌻3. 调用流程剖析](#🌻3. 调用流程剖析)
        • [3.1 核心步骤](#3.1 核心步骤)
        • [3.2 涉及核心时序图](#3.2 涉及核心时序图)
      • [🌻4. 实战应用案例](#🌻4. 实战应用案例)
      • [🌻5. 用法总结](#🌻5. 用法总结)

🌻1. 前言

本篇目的:Android16音频深度解析之 MediaRecorder.setVideoEncoder 调用流程与实战。

在 Android 多媒体录制体系中,MediaRecorder 是实现音视频捕获的核心组件。setVideoEncoder 方法决定了视频数据在写入文件前采用何种压缩算法。在 Android 16 中,随着硬件编码器(如 AV1、HEVC)的进一步普及,正确配置视频编码器不仅关乎录制的清晰度,更直接影响到文件的体积、功耗以及在不同设备上的播放兼容性。


🌻2. 用法与应用场景

MediaRecorder.setVideoEncoder 用于设置视频录制的编码格式。

  • 用法说明 :必须在 setOutputFormat() 之后且在 prepare() 之前调用。常见的编码器常量包括 VideoEncoder.H264VideoEncoder.HEVC (H.265) 以及 VideoEncoder.AV1
  • 运行结果 :系统将分配对应的硬编或软编资源。如果设置了硬件不支持的编码器,prepare() 阶段将抛出异常。
  • 应用场景
    1. 高清录制 :优先使用 HEVC 以在保持高画质的同时减小文件体积。
    2. 通用分享 :使用 H264 以确保录制的视频能在绝大多数旧设备或网页浏览器中正常播放。
    3. 流媒体传输 :在低带宽环境下使用 AV1 编码,利用其极高的压缩比优化网络传输效率。

🌻3. 调用流程剖析

3.1 核心步骤
  1. 状态机校验MediaRecorder.java 会检查当前状态。setVideoEncoder 必须在 DataSourceConfigured 状态(即设置完输出格式后)调用,否则会抛出 IllegalStateException
  2. JNI 参数分发 :调用进入 android_media_MediaRecorder.cpp,将 Java 层的编码器常量映射为底层 video_encoder 类型。
  3. Stagefright 录制器配置 :指令通过 Binder 发送到 MediaServer 进程。StagefrightRecorder 接收参数并记录预期的编码器类型。
  4. 编码器组件实例化 :在 prepare() 阶段,系统会根据 setVideoEncoder 指定的类型,通过 MediaCodecList 查找匹配的硬件加速组件(如 OMX.qcom.video.encoder.avc)。
  5. 数据链路打通CameraPersistentSurface 产生的原始帧数据被送往 MediaCodec 编码器,编码后的压缩流随后送入 Muxer 进行容器封装。
3.2 涉及核心时序图

MediaMuxer MediaCodec / OMX StagefrightRecorder MediaRecorder Native MediaRecorder Java 应用代码层 MediaMuxer MediaCodec / OMX StagefrightRecorder MediaRecorder Native MediaRecorder Java 应用代码层 此时仅保存配置,不分配资源 调用 setVideoEncoder(H264) 校验状态 (must be Configured) native_setVideoEncoder 设置录制参数中的编码类型 调用 prepare() 创建并配置对应的编码器组件 编码器初始化完成 调用 start() 开始写入封装数据


🌻4. 实战应用案例

本案例演示了如何正确配置 MediaRecorder 以使用 H.264 编码录制 MP4 视频。

java 复制代码
public class VideoCaptureManager {
    private MediaRecorder recorder;

    public void setupRecorder(Surface previewSurface, String outputPath) {
        recorder = new MediaRecorder();
        try {
            // 1. 设置音频和视频源
            recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            recorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);

            // 2. 设置输出格式(必须先于编码器设置)
            recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);

            // 3. 设置视频编码器(本篇核心)
            // 注意:顺序必须在 setOutputFormat 之后
            recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
            
            // 4. 设置音频编码器
            recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);

            // 5. 配置视频参数(分辨率、比特率、帧率)
            recorder.setVideoSize(1920, 1080);
            recorder.setVideoEncodingBitRate(5000000); // 5Mbps
            recorder.setVideoFrameRate(30);
            
            recorder.setOutputFile(outputPath);
            recorder.setPreviewDisplay(previewSurface);

            // 6. 准备录制
            recorder.prepare();
            System.out.println("MediaRecorder 准备就绪,编码器:H.264");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void start() {
        if (recorder != null) {
            recorder.start();
        }
    }

    public void stop() {
        if (recorder != null) {
            recorder.stop();
            recorder.reset();
            recorder.release();
            recorder = null;
        }
    }
}

🌻5. 用法总结

调用层级 核心职责 关键特性/影响
应用框架层 状态机维护与 API 暴露 严格遵循 OutputFormat -> Encoder 顺序
系统服务层 参数传递与 Stagefright 路由 决定了后续 MediaCodec 的选择策略
媒体引擎层 编码器调度与同步 负责处理视频帧的缓冲区流转
编解码层 原始数据压缩 性能核心,优先使用硬件加速单元
硬件抽象层 硬件资源映射 决定设备是否支持 4K、HDR 或 AV1 编码

最优实战方案落地步骤:

  1. 能力探测 :通过 CamcorderProfile.hasProfile()MediaCodecList 确认当前硬件是否支持目标编码器(如 H.265)。
  2. 严格排序 :确保 setVideoEncodersetOutputFormat 之后调用,否则会触发应用崩溃。
  3. 参数对齐 :设置完编码器后,务必显式设置 setVideoEncodingBitRate,否则系统默认比特率可能过低导致画质模糊。
  4. 异常捕获 :在 prepare() 处增加健壮的异常处理逻辑,以防因硬件资源被占用或不支持特定 Profile 而失败。
相关推荐
Android系统攻城狮4 小时前
Android tinyalsa深度解析之pcm_params_set_max调用流程与实战(一百七十)
android·pcm·tinyalsa·android音频进阶
Android系统攻城狮5 天前
Android16进阶之MediaPlayer.deselectTrack调用流程与实战(二百五十一)
mediaplayer·android16·音频进阶·mediaplyer
loitawu7 天前
Rockchip Android16 系统裁剪指南
android·android16·android裁剪·系统裁剪·rockchip app
Android系统攻城狮17 天前
Android16进阶之MediaPlayer.setAudioSessionId调用流程与实战(二百三十八)
mediaplayer·android16·音频进阶
Android系统攻城狮17 天前
Android16进阶之MediaPlayer.getAudioSessionId调用流程与实战(二百三十七)
多媒体·mediaplayer·android16·android音频进阶
Android系统攻城狮17 天前
Android16进阶之MediaPlayer.setAudioAttributes调用流程与实战(二百三十六)
gitee·android16·音频进阶·android hal
Android系统攻城狮1 个月前
Android16进阶之MediaPlayer.isLooping调用流程与实战(二百三十二)
android16·音频进阶·android hal·audio hal·多媒体进阶
Android系统攻城狮1 个月前
Android16进阶之MediaPlayer.setLooping调用流程与实战(二百三十一)
android16·音频进阶·android hal·audio hal·多媒体进阶
Android系统攻城狮2 个月前
Android16进阶之MediaPlayer.getDuration调用流程与实战(二百二十九)
android16·音频进阶·音频性能实战