Gstreamer Tee / Queue多个流水线

时间:2012-02-14 01:16:04

标签: java multithreading pipe gstreamer tee

所以我正在使用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);
    }
}

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

1 个答案:

答案 0 :(得分:4)

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

基本上,您应该从videosrc接收数据并将其提供给GstTee,现在Tee必须有两个SrcPads。这将允许两个路径分别运行。

第一个src路径应该连接到encmux,这将继续录制,第二条路径将占用显示屏。一切都应该同时工作。

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

这是电路的样子。

Circuit