2012-02-14 36 views
3

所以我使用gstreamer为java,我试图播放实时视频流并在同一时间录制它。现在,我可以一次做一个,但我不知道如何在同一时间做到这一点。我尝试过对它进行线程化,但是由于两个线程都试图访问相同的资源,所以发生冲突。那么,我告诉我,我需要使用T恤和队列,基本上,所有不同的路径共享相同的资源,而不是试图控制它(这就是我的想法),我不知道如何做到这一点虽然在java中,现在互联网没有一个关于tees的java的好教程...(看了一下,所有的代码都没有在我的机器上编译)继承了我在做什么的想法Gstreamer三通/排队多流水线

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); 
    } 
} 

有点长,但很容易看到我正在尝试做什么。如果有人能告诉我如何实施T恤(我尝试过?),那会很棒。谢谢!

回答

4

你不应该像你那样创建两个视频源。 videosrc & videosrcB

基本上,您应该接收来自videosrc的数据并将其提供给GstTee现在Tee必须有两个SrcPads。这将允许两条路径分开工作。

第一个src路径应该连接到您的encmux这将继续录制第二条路径将显示在屏幕上。所有应该同时工作。

Tee可以在每个路径中被Queue缓冲。从电路的角度来看,这不是必需的,但它是好的,所以#2路径不会等到路径#1在阻塞呼叫下完成。

这里是电路的样子。

Circuit

+0

我在哪里放队列? – 2012-02-14 13:04:25