Android端推流至Ant Media Server出现绿屏问题求助
解决Android隐藏摄像头推流至Ant Media Server的绿屏问题
我之前也碰到过类似的隐藏摄像头推流绿屏的坑,结合你给出的代码细节,大概率是NV21数据处理或格式匹配环节出了问题,咱们一步步来排查解决:
1. 先砍掉多余的中间转换环节
你当前把NV21数据转成YuvImage再提取YuvData,接着又转成IntBuffer塞到GL缓冲区里,这中间每一步都可能引入数据错位。其实Yasea的编码器本身是支持直接接收NV21原始数据的,完全可以跳过这些冗余步骤,直接在onPreviewFrame里把摄像头输出的原始数据传给回调:
@Override public void onPreviewFrame(byte[] data, Camera camera) { Camera.Size previewSize = camera.getParameters().getPreviewSize(); // 直接传摄像头输出的原始NV21数据,跳过YuvImage和GLBuffer转换 mPrevCb.onGetNV21Frame(data, previewSize.width, previewSize.height); }
很多时候绿屏就是中间转换时颜色空间或数据格式被破坏导致的,先简化流程试试。
2. 确认摄像头预览格式与编码器输入格式匹配
一定要确保摄像头输出的格式确实是NV21,有些设备默认可能输出YV12(和NV21的U/V分量顺序相反),这会直接导致编码器解析出异常颜色:
// 在初始化摄像头时检查并强制设置预览格式 Camera.Parameters params = camera.getParameters(); // 先确认设备是否支持NV21 List<Integer> supportedFormats = params.getSupportedPreviewFormats(); if (supportedFormats.contains(ImageFormat.NV21)) { params.setPreviewFormat(ImageFormat.NV21); } camera.setParameters(params);
同时检查Yasea编码器的配置,确保它的视频输入格式也是NV21,避免格式不兼容。
3. 检查分辨率是否完全匹配
如果编码器期望的分辨率和摄像头实际输出的预览分辨率不一致,也会出现绿屏、拉伸或花屏的情况。初始化编码器时,强制绑定摄像头的预览尺寸:
Camera.Size previewSize = camera.getParameters().getPreviewSize(); // 设置编码器的视频尺寸与摄像头预览尺寸一致 mEncoder.setVideoSize(previewSize.width, previewSize.height);
4. 手动计算YuvImage的Strides参数(如果必须用YuvImage的话)
如果你确实需要保留YuvImage的处理逻辑,千万不要给strides参数传null。很多摄像头的实际数据 stride 会对齐到16字节(比如宽度是1080的话,stride可能是1088),默认按宽度计算会导致数据错位:
int previewWidth = camera.getParameters().getPreviewSize().width; int previewHeight = camera.getParameters().getPreviewSize().height; // NV21的strides规则:Y分量stride为宽度,U/V分量各为宽度的一半(或实际对齐后的值) int[] strides = new int[]{previewWidth, previewWidth / 2, previewWidth / 2}; YuvImage yuv = new YuvImage(data, ImageFormat.NV21, previewWidth, previewHeight, strides);
5. 测试U/V分量顺序是否颠倒
如果以上步骤都没用,可能是你的设备输出的是YV12格式(和NV21的U/V顺序相反),可以尝试交换U/V分量再传给编码器测试:
public void onGetNV21Frame(byte[] data, int width, int height) { calcSamplingFps(); if (!sendAudioOnly) { int ySize = width * height; byte[] convertedData = new byte[data.length]; // 复制Y分量 System.arraycopy(data, 0, convertedData, 0, ySize); // 交换U和V分量(把NV21转成YV12) System.arraycopy(data, ySize + ySize/4, convertedData, ySize, ySize/4); System.arraycopy(data, ySize, convertedData, ySize + ySize/4, ySize/4); mEncoder.onGetYuvNV21Frame(convertedData, width, height, new Rect(0, 0, width, height)); } }
如果这样绿屏消失了,说明设备实际输出的是YV12,需要调整摄像头预览格式或编码器的输入格式。
内容的提问来源于stack exchange,提问作者Mir Saman
相关产品推荐
相关产品推荐

