Pixel 3设备Bitmap转MP4出现绿条纹问题求助
Bitmap列表转MP4在部分Pixel设备出现绿条纹问题(禁用FFmpeg)
我开发的一款将Bitmap图片列表转为MP4视频的应用,采用MediaMuxer和MediaCodec实现核心功能,该功能在绝大多数设备上运行正常,但在部分Pixel设备(如Pixel 3)导出的视频存在绿条纹问题,Pixel 6则无异常。老板要求禁止使用FFmpeg,恳请提供解决思路。
现有配置代码
MediaCodec videoCodec = MediaCodec.createEncoderByType(MIMETYPE_VIDEO_AVC); MediaFormat videoFormat = MediaFormat.createVideoFormat(MIMETYPE_VIDEO_AVC, width, height); videoFormat.setInteger(KEY_BIT_RATE, BIT_RATE); videoFormat.setInteger(KEY_FRAME_RATE, FRAME_RATE); videoFormat.setInteger(KEY_I_FRAME_INTERVAL, I_FRAME_INTERVAL); videoFormat.setInteger(KEY_COLOR_FORMAT, COLOR_FormatYUV420Flexible); videoFormat.setInteger(KEY_MAX_INPUT_SIZE, MAX_INPUT_SIZE); videoCodec.configure(videoFormat, null, null, CONFIGURE_FLAG_ENCODE); videoCodec.start(); mediaMuxer = new MediaMuxer(outputFilePath, MUXER_OUTPUT_MPEG_4);
配置参数值
BIT_RATE = 1000000; FRAME_RATE = 20; I_FRAME_INTERVAL = 5; MAX_INPUT_SIZE = 10485760; // 10 MB
问题现象
Pixel 3导出的视频存在横向绿条纹,画面局部颜色显示异常。
解决思路
- 强制使用设备支持的具体YUV420格式
COLOR_FormatYUV420Flexible是兼容格式,但部分老设备的编码器对其处理存在bug。优先选择设备支持的非Flexible YUV420格式(如Planar或SemiPlanar):
MediaCodecInfo.CodecCapabilities capabilities = videoCodec.getCodecInfo().getCapabilitiesForType(MIMETYPE_VIDEO_AVC); int preferredColorFormat = -1; for (int format : capabilities.colorFormats) { if (format == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar || format == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar) { preferredColorFormat = format; break; } } if (preferredColorFormat != -1) { videoFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, preferredColorFormat); } else { videoFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible); }
检查Bitmap转YUV的转换逻辑
绿条纹多由YUV数据格式错误导致:- 确保输入编码器的YUV数据宽高为偶数(部分编码器强制要求分辨率为2的倍数),若原Bitmap宽高为奇数,先缩放至偶数尺寸再转换;
- 验证Y、U、V分量的顺序、步长(stride)是否与所选颜色格式匹配,比如Planar格式要求Y、U、V分量连续存储,SemiPlanar格式要求Y连续、UV交替存储。
调整编码器缓冲区配置
尝试移除KEY_MAX_INPUT_SIZE的手动设置,让编码器自动分配缓冲区;或计算单帧YUV数据的实际大小(width*height*3/2)作为该参数值,避免缓冲区大小不匹配导致的数据截断。完善编码器收尾逻辑
所有帧数据送入编码器后,调用videoCodec.signalEndOfInputStream(),并循环读取输出缓冲区直到编码器返回INFO_TRY_AGAIN_LATER,确保所有帧都完成编码,避免因数据未完全处理导致画面异常。调整编码参数组合
- 降低帧率至15fps,减少老设备编码器的处理压力;
- 调整I帧间隔为1或0,简化帧间压缩逻辑;
- 适当降低比特率,测试是否能缓解编码异常。
内容的提问来源于stack exchange,提问作者Jackson Daniel
相关产品推荐
相关产品推荐

