WebRtc如何使用网络摄像头


#1

大牛们好:

有一个问题已经困扰我很久了。我使用android 平台连接海康的网络摄像头 从海康摄像头拿到的数据是RTP 协议(内部是PS封装的H264数据)。通过解协议我将RTP 数据解码为H264 数据我需要将这个数据发送到rtc 服务器。 但是我发现apprtc 源码是直接拿的NV21格式的原始数据。 我现在搞不明白该如何改造才能使用采集到的H264 的 数据。


#2

我将RTP 数据解码为H264 数据

OK, 这里你做了depayload处理, 得到了 H264.

根据你使用的不同解码器以及解码配置, 你解码H264能得到不同格式的Raw图像, 一般来说其格式为I420. 这时候你的apprtc需要NV12, 这是一种不同格式的Raw图像, 用libyuv或ffmpeg以及其它格式做下转换即可, 当然手动写这个转换算法也不难, 就是移动一下色度值.

总结

海康摄像头 --> H264 -(dec)-> I420 -(colorspace trans)-> NV12 --> apprtc


#3

非常感谢您的回复

我还是有疑问 如果这么做流程是这样的 rtp 转 h264 转 nv21 然后再转为 vp8 或h264 再转为 rtp 发送 这样不太浪费了吗 。同时也会造成cpu 占用太高。

如果能够使用 rtp 是不是更好。

或者 rtp -->h264 -->rtp 这种方式是不是更好点。


#4

如果你不需要做任何前处理, 可以的


#5

请教下h264 硬解码能够直接转换为NV21 格式的数据吗? 为什么您之前说需要
H264 -(dec)-> I420 -(colorspace trans)-> NV12 这样进行转换 而不是 h264 直接转换为NV21 格式的数据?

我这么转换 转换不了

MediaFormat format = MediaFormat.createVideoFormat(“video/avc”, videoW, videoH);
format.setInteger(MediaFormat.KEY_BIT_RATE, videoBitrate);
format.setInteger(MediaFormat.KEY_FRAME_RATE, videoFrameRate);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 50);
codec.configure(format, null, null, 0);


#6

h264 硬解码能够直接转换为NV21 格式的数据吗?

我上面有提到, 这和你的H264解码器有关, 一般默认是I420.

请先查询此Codec支持的格式类型KEY_COLOR_FORMAT


#7

多谢 我现在实现I420 转化为 NV21 但是我还希望能够优化,我发现能够直接获取到YUV420SP的帧格式而这个数据是NV12 不是NV21 所以我需要在apprtc 中直接使用NV12数据 ,但是我不清楚 这个构造函数里的参数的意思
NV12Buffer(int width, int height, int stride, int sliceHeight, ByteBuffer buffer,

其中这两个参数不知道怎么填充 int stride, int sliceHeight,


#8

stride, int sliceHeight, 这两个值我分别填充了 width height 一样的值能够正在显示了

我在android 6.0 系统 上能够正常显示 cpu 占用也大幅度降低。 但是在android 4.4 上发现显示不正常。

4.4上颜色格式是支持 19 和 21 的 即 I420和 YUV420SP 但是我发现实际解码出来数据依然是I420的数据。

我目标也是需要在4.4设备上运行的。 请问大牛有什么好的思路吗?


#9

NV12和NV21只是交换了U和V: stride跨度和width相等

https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/pixfmt-nv12.html


#10

我不是专门做Android的, 建议先查询一下 MediaCodecInfo, 如果没有YUV420SP, 手动做一下clolorspace作为备用方案.

兼容性确实很麻烦.