我正在从Parrot AR.Drone 2.0获得实时视频反馈。我能够从无人机(使用command-ffplay tcp://192.168.1.1:5555)获得传入视频流,并成功地为我输出实时视频。我注意到ffplay将显示自己的帧和直播视频。
那么,在应用程序中有可能"直接"或将框架放入我们自己的Java框架中吗?如果我想在我自己的JCheckBox中实现该功能,我该如何实现呢?例如,如果我点击JCheckBox,它应该自动从无人机获得实时视频流,并在应用程序中显示,而不是使用ffplay帧?
这个问题很老了,但是我刚刚发现它,所以我决定为其他用户写一个可能的解决方案。
有两种方法可以解决这个问题:为Java包装自己的FFmpeg CLI或使用包装的FFmpeg库。前者需要相当长的时间和努力才能实现。而后者更实用。例如,一个很好的库是JavaCV。您只需要使用pom.xml
文件将maven存储库添加到项目中:
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.4.3</version>
</dependency>
然后你可以创建一个SimplePlayer
类,并使用FFmpegFrameGrabber
类解码一个帧,转换成一个图像,并显示在你的Java应用程序。
public class SimplePlayer
{
private static volatile Thread playThread;
private AnimationTimer timer;
private int counter;
public SimplePlayer(String source, GrabberListener grabberListener)
{
if (grabberListener == null) return;
if (source.isEmpty()) return;
counter = 0;
playThread = new Thread(() -> {
try {
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(source);
grabber.start();
grabberListener.onMediaGrabbed(grabber.getImageWidth(), grabber.getImageHeight());
Java2DFrameConverter converter = new Java2DFrameConverter();
while (!Thread.interrupted()) {
Frame frame = grabber.grab();
if (frame == null) {
break;
}
if (frame.image != null) {
Image image = SwingFXUtils.toFXImage(converter.convert(frame), null);
Platform.runLater(() -> {
grabberListener.onImageProcessed(image);
});
}
grabber.stop();
grabber.release();
Platform.exit();
} catch (Exception exception) {
System.exit(1);
}
});
playThread.start();
}
public void stop()
{
playThread.interrupt();
}
}
你可以在这个GitHub仓库中找到完整的实现。
您需要解码AR.Drone使用的几乎但不完全是H264视频格式。要做到这一点,您需要做两件事:
处理AR.Drone的自定义视频帧,它使用标题在他们的PaVE格式。该格式在AR.Drone开发者指南的7.3节中有文档记录,但是几乎所有现有的AR.Drone库都有处理PaVE头文件的代码。
解码剩余的H264视频帧。Xuggler用Java封装了本地库,这可能是解码H264的最好、最快的方法。另一种选择是h264j库,它是纯Java的,但速度较慢,并且有一些解码故障。
有关更多信息,请参阅以下相关问题:
Xuggler and playing from live stream
https://stackoverflow.com/questions/30307003/use-a-xuggler-videostream-in-javacv