小米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
相关产品推荐
相关产品推荐

