You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

小米Note10S调用MediaCodec.configure崩溃,报错0x80001001

解决小米Note10S上H264编码器configure崩溃问题

核心问题分析

崩溃报错MediaCodec$CodecException: Error 0x80001001本质是编码器配置参数与设备硬件能力不兼容,小米Note10S的MediaCodec对H264编码的参数约束比三星机型更严格,尤其是Surface输入模式下的格式参数校验。

具体修复方案

1. 调整编码器查找逻辑,优先匹配支持Surface输入的H264编码器

不再直接用自定义格式查找编码器,而是先筛选出所有支持Surface输入的H264编码器,避免找到的编码器实际不兼容Surface模式:

val codecList = MediaCodecList(MediaCodecList.ALL_CODECS)
// 筛选所有支持H264编码的编码器
val h264Encoders = codecList.codecInfos.filter {
    it.isEncoder && it.supportedTypes.contains("video/avc")
}

var targetEncoder: MediaCodecInfo? = null
for (encoder in h264Encoders) {
    val caps = encoder.getCapabilitiesForType("video/avc")
    // 检查是否支持Surface输入格式
    if (caps.colorFormats.contains(CodecCapabilities.COLOR_FormatSurface)) {
        targetEncoder = encoder
        break
    }
}

val encoderName = targetEncoder?.name ?: error("未找到支持Surface输入的H264编码器")
codec = MediaCodec.createByCodecName(encoderName)

2. 基于编码器能力构建兼容的MediaFormat

避免硬编码参数,而是根据编码器支持的范围调整参数:

val caps = targetEncoder.getCapabilitiesForType("video/avc")
val videoCaps = caps.videoCapabilities

// 确认分辨率在编码器支持范围内
val supportedSize = videoCaps.getSupportedSizesForCodec(videoWidth, videoHeight)
    ?: videoCaps.supportedSizes.first()
val finalWidth = supportedSize.width
val finalHeight = supportedSize.height

// 调整帧率到编码器支持的范围
val fpsRange = videoCaps.supportedFrameRateRanges.first()
val finalFps = videoFrameRate.coerceIn(fpsRange.lower, fpsRange.upper).toInt()

// 调整码率到编码器支持的范围
val bitrateRange = videoCaps.bitrateRange
val finalBitrate = bitrate.coerceIn(bitrateRange.lower, bitrateRange.upper)

// 构建兼容的格式
format = MediaFormat.createVideoFormat("video/avc", finalWidth, finalHeight).apply {
    setInteger(MediaFormat.KEY_BIT_RATE, finalBitrate)
    setInteger(MediaFormat.KEY_FRAME_RATE, finalFps)
    setInteger(MediaFormat.KEY_COLOR_FORMAT, CodecCapabilities.COLOR_FormatSurface)
    // I帧间隔用整数,避免部分设备不支持float类型
    setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1)
    // 移除KEY_MAX_INPUT_SIZE,Surface输入模式下不需要该参数
}

3. 容错处理与配置验证

在configure前添加参数校验,并且捕获异常做降级处理:

try {
    codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
    codec.setInputSurface(surface)
    codec.start()
} catch (e: MediaCodec.CodecException) {
    // 降级处理:尝试使用软件编码器(如果存在)
    val softwareEncoder = codecList.codecInfos.find {
        it.isEncoder && it.name.startsWith("OMX.google") && it.supportedTypes.contains("video/avc")
    }
    if (softwareEncoder != null) {
        codec = MediaCodec.createByCodecName(softwareEncoder.name)
        // 重新配置软件编码器(参数可适当调整)
        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, CodecCapabilities.COLOR_FormatYUV420Flexible)
        codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
        codec.start()
    } else {
        throw e
    }
}

关键注意点

  • 小米部分机型的硬件编码器不支持非标准分辨率,必须确保相机输出的分辨率是编码器支持的标准尺寸(如1080p、720p)
  • Surface输入模式下不需要设置KEY_MAX_INPUT_SIZE,该参数仅针对ByteBuffer输入
  • I帧间隔优先使用整数类型,避免部分设备对float参数的兼容性问题
  • 若硬件编码器始终不兼容,可降级使用谷歌的软件编码器OMX.google.h264.encoder

内容的提问来源于stack exchange,提问作者Mohammad Elsayed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 00:30:44