我需要使用Android 将DJI无人机的实时视频数据传输到本地服务器。来自服务器的视频数据将由其他软件(人工识别)处理。什么是证明最佳流媒体质量的推荐方法?我们使用Mavic 2进行开发,Matrice 210 v2 RTK用于生产目的。因此,答案应该主要集中在马特里斯210 v2 RTK的可能性上。
目前,我们使用这样的DJIs Livestreammanager
DJISDKManager.getInstance().getLiveStreamManager().setLiveUrl( rtmpURL );
DJISDKManager.getInstance().getLiveStreamManager().startStream();
我们使用带有rtmp模块的nginx Webserver作为流端点,将流推送到网络,同时将流记录到磁盘。这是可行的,但我们看到这种流的质量很差。这股气流经常会滞后,它会加速无人机的移动。
由于我不熟悉视频处理,我需要建议如何解决这一需求。我的问题是:-Do,我需要使用ffmpeg库对流进行某种方式的预处理?对于后端服务器,-Is有比nginx+rtmp模块更好的解决方案吗?-Would是否有可能利用matrice遥控器的输出来提供更高的质量?
发布于 2019-11-11 14:03:21
-Do我需要使用ffmpeg库以某种方式对流进行预处理?
如果您想自己处理流,则需要使用ffmpeg将原始的livestream解码为实际的帧。见我对问题3的答复。
-Is有比nginx+rtmp模块更好的后端服务器解决方案吗?
这在很大程度上取决于用例。如果你对视频质量不满意,用ffmpeg解码流会更可靠。实际上,我不知道nginx+rtmp自动完成了多少任务,因为我从未使用过它。
-Would是否可以利用矩阵遥控器的输出来提供更高的质量?
可以使用SDK访问的原始livestream是一个原始的h264或h265流(NAL ),这取决于所使用的无人机模型。
在我的应用程序中,我将VideoDataCallback在onComponentChange
方法中注册到相机componentKey中,并通过LocalBroadcastManager发送出去。然后,只要订阅广播,就可以在应用程序中的任何地方访问livestream。
private VideoFeeder.VideoDataListener videoDataCallback = (videoBuffer, size) -> {
Intent intent = new Intent("videoStream");
intent.putExtra("content", videoBuffer);
intent.putExtra("size", size);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
};
通过网络发送livestream的一个简单方法是使用TCP-套接字:启动线程并使用IP和端口打开套接字:
this.s = new Socket(this.ipAddress, this.port);
this.s.setKeepAlive(true);
this.s.setTcpNoDelay(true);
this.dos = new DataOutputStream(this.s.getOutputStream());
如果连接/发送失败,设置一个循环来重新连接它。在BroadcastReceiver中,通过分析大小来累积字节(bos是一个简单的ByteArrayOutputStream):
private BroadcastReceiver frameReceiverNAL = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
try {
int frameSize = intent.getIntExtra("size", 0);
if(frameSize == 2032) {
bos.write(intent.getByteArrayExtra("content"), 0, frameSize);
} else {
bos.write(intent.getByteArrayExtra("content"), 0, frameSize);
final byte[] sendUnit = bos.toByteArray();
bos.reset();
if(numAsyncTasks < MAX_NUMBER_ASYNCTASKS) {
numAsyncTasks++;
AsyncTask.execute(() -> sendNAL(sendUnit));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
private void sendNAL(byte[] sendUnit){
try {
if(dos != null) {
dos.write(sendUnit);
dos.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
numAsyncTasks--;
}
如果MAX_NUMBER_ASYNCTASKS不能足够快地发送NAL(导致500+在崩溃前未完成AsyncTasks ),则它被用作上限,以防止应用程序崩溃。在我的例子中,我将数字设置为128。
在服务器端,您需要创建一个ServerSocket来接收byteStream。根据编程语言的不同,您可以直接使用ffmpeg,也可以使用本机接口,例如bytedeco从流创建框架。
另一种方法是将智能手机上的流解码为YUV图像(每个图像为2.8MB),并可选择地将它们转换为jpeg,以缩小单个帧的大小(每个帧约100 of )。然后,可以使用TCP套接字将YUV或jpeg映像发送到服务器。SDK提供了在类DJICodecManager中创建YUV图像的方法,教程中包含将它们转换为JPEG的示例。
https://stackoverflow.com/questions/57378706
复制相似问题