关于大疆无人机的Webrtc
阐述问题
在做webrtc期间,都是获取本地的摄像头,那么问题来了,如果没有本地摄像头怎么办?就像大疆无人机,摄像头在飞机上,遥控器根本没有摄像头,你总不能在遥控上插一个摄像头吧?那还叫无人机吗?
流程说明
自创建一个捕获器来捕获飞机的视频流设置为自己的本地流(项目是基于大疆V5.20,获取YUV数据)
实现VideoCapturer接口
- 初始化捕捉器
dji_yuv_data_callback_ = new YuvDataListener() {
@Override
public void onReceive(MediaFormat mediaFormat, byte[] data, int width, int height) {
if (is_rate_time) {
JavaI420Buffer buffer = JavaI420Buffer.allocate(width, height);
ByteBuffer dataY = buffer.getDataY();
ByteBuffer dataU = buffer.getDataU();
ByteBuffer dataV = buffer.getDataV();
final byte[] bytes = data;
int yLen = width * height;
int uLen = (width + 1) / 2 * ((height + 1) / 2);
int vLen = uLen;
int color_format = mediaFormat.getInteger(MediaFormat.KEY_COLOR_FORMAT);
switch (color_format) {
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
byte[] ubytes = new byte[uLen];
byte[] vbytes = new byte[vLen];
for (int i = 0; i < uLen; i++) {
ubytes[i] = bytes[yLen + 2 * i];
vbytes[i] = bytes[yLen + 2 * i + 1];
}
dataY.put(bytes, 0, yLen);
dataU.put(ubytes, 0, uLen);
dataV.put(vbytes, 0, vLen);
break;
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
int yPos = 0;
int uPos = yPos + yLen;
int vPos = uPos + uLen;
dataY.put(bytes, yPos, yLen);
dataU.put(bytes, uPos, uLen);
dataV.put(bytes, vPos, vLen);
break;
default:
break;
}
long captureTimeNs = TimeUnit.MILLISECONDS.toNanos(SystemClock.elapsedRealtime());
VideoFrame videoFrame = new VideoFrame(buffer, 0, captureTimeNs);
capturer_observer_.onFrameCaptured(videoFrame);
videoFrame.release();
}
}
};
capturer_observer_ = capturerObserver;
- 开始捕捉
frame_width_ = width;
frame_height_ = height;
frame_rate_ = framerate;
timer.schedule(tickTask, 0L, (long) (1000 / frame_rate_));
//获取可用的渲染页
surfaceViewRenderer = new SurfaceViewRenderer(_context);
surfaceViewRenderer.init(_rootEglBase.getEglBaseContext(), null);
surfaceViewRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
surfaceViewRenderer.setMirror(true);
//创建解码器
iVideoDecoder = new CapturerDefault.Decodec(_context, videoChannel.getVideoChannelType(), DecoderOutputMode.YUV_MODE,
surfaceViewRenderer.getHandler(), frame_width_, frame_height_, true);
iVideoDecoder.addDecoderStateChangeListener(new DecoderStateChangeListener() {
@Override
public void onUpdate(DecoderState from, DecoderState to) {
System.out.println("解码器状态" + from + "----------" + to);
}
});
//设置数据监听
iVideoDecoder.addYuvDataListener(dji_yuv_data_callback_);
- 继承大疆解码器
//因为获取YUV数据需要在解码器上绑定监听器,在初始化的时候做了这一步
private static class Decodec extends VideoDecoder {
public Decodec(Context context, VideoChannelType channelType, DecoderOutputMode outputMode, Object outputSurface, int width, int height, boolean isForLiveStream) {
super(context, channelType, outputMode, outputSurface, width, height, isForLiveStream);
}
}