所以我正在使用gstreamer for java,我正在尝试播放实时视频流并同时录制它。现在,我可以一次做一个,但我不知道如何同时做两个。我尝试过线程,但由于两个线程都试图访问相同的资源,因此存在冲突。然后,我的ta告诉我,我需要使用T恤和队列,基本上,让所有不同的路径共享相同的资源,而不是试图控制它(这就是我的想法),我不知道如何做到这一点虽然在java中,现在互联网没有一个关于tees的java的好教程...(看了一下,所有这些都是我的机器上没有编译的代码)继承人对我正在做什么的想法
public class Main {
private static Pipeline pipe;
private static Pipeline pipeB;
public static void main(String[] args) {
args = Gst.init("SwingVideoTest", args);
pipe = new Pipeline("pipeline");
pipeB = new Pipeline("pipeline");
final Element tee = ElementFactory.make("queue", null);
Element queue0 = ElementFactory.make("queue", null);
Element queue1 = ElementFactory.make("queue", null);
AppSink appsink = (AppSink)ElementFactory.make("appsink", null);
tee.set("silent", "false");
appsink.set("emit-signals", "true");
final Element videosrc = ElementFactory.make("v4l2src", "source");
videosrc.set("device" , "/dev/video1");
final Element colorspace = ElementFactory.make("ffmpegcolorspace", "colorspace");
final Element videofilter = ElementFactory.make("capsfilter", "flt");
videofilter.setCaps(Caps.fromString("video/x-raw-yuv, width=640, height=480, framerate=10/1"));
final Element enc = ElementFactory.make("ffenc_mpeg4", "Encoder");
final Element mux = ElementFactory.make("avimux", "muxer");
final Element sink = ElementFactory.make("filesink", "File sink");
sink.set("location", "./test.avi");
final Element videosrcB = ElementFactory.make("v4l2src", "source");
videosrcB.set("device" , "/dev/video0");
final Element videofilterB = ElementFactory.make("capsfilter", "flt");
videofilterB.setCaps(Caps.fromString("video/x-raw-yuv, width=640, height=480"));
VideoPlayer threadA = new VideoPlayer("screen", videosrcB, null, videofilterB, null, null, null, pipe);
VideoPlayer threadB = new VideoPlayer("recorder", videosrc, colorspace, videofilter, enc, mux, sink, pipeB);
threadA.run();
threadB.run();
}
public class VideoPlayer implements Runnable{
private String playerType;
private Element videosrc, colorspace, videofilter, enc, mux, sink;
private Pipeline pipe;
VideoPlayer(final String playerType, final Element videosrc, final Element colorspace, final Element videofilter, final Element enc, final Element mux, final Element sink, final Pipeline pipe){
this.playerType = playerType;
this.videosrc = videosrc;
this.colorspace = colorspace;
this.videofilter = videofilter;
this.enc = enc;
this.mux = mux;
this.sink = sink;
this.pipe = pipe;
}
public void run(){
VideoComponent videoComponent = new VideoComponent();
Element videosink = videoComponent.getElement();
if(playerType.equals("screen")){
System.out.println(playerType);
pipe.addMany(videosrc, videofilter, videosink);
Element.linkMany(videosrc, videofilter, videosink);
JFrame frame = new JFrame("Swing Video Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(videoComponent, BorderLayout.CENTER);
videoComponent.setPreferredSize(new Dimension(640, 480));
frame.pack();
frame.setVisible(true);
// Start the pipeline processing
pipe.setState(State.PLAYING);
}
else if(playerType.equals("recorder")){
System.out.println(playerType);
pipe.addMany(videosrc, colorspace, videofilter, enc, mux, sink);
Element.linkMany(videosrc, colorspace, videofilter, enc, mux, sink);
JFrame frame = new JFrame("Swing Video Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(videoComponent, BorderLayout.CENTER);
videoComponent.setPreferredSize(new Dimension(640, 480));
frame.pack();
//frame.setVisible(true);
pipe.setState(State.PLAYING);
}
}
有点冗长但很容易看到我在尝试做什么。如果有人能告诉我如何实施发球台(我试过?)那会很棒。谢谢!
答案 0 :(得分:4)
您不应该像以前那样创建两个视频源。 videosrc & videosrcB
。
基本上,您应该从videosrc
接收数据并将其提供给GstTee
,现在Tee必须有两个SrcPads。这将允许两个路径分别运行。
第一个src路径应该连接到enc
和mux
,这将继续录制,第二条路径将占用显示屏。一切都应该同时工作。
Tee
可以在每条路径中由Queue
进行缓冲。从电路的角度来看,这不是必需的,但它是好的,所以路径#2不会等到路径#1在阻塞呼叫下完成。
这是电路的样子。