3

所以我使用gstreamer for java,我正在尝试播放实时视频流并同时记录它。现在,我可以一次做一个,但我不知道如何同时做这两个。我尝试对其进行线程化,但由于两个线程都试图访问相同的资源,因此发生了冲突。然后,我的 ta 告诉我,我需要使用 tee 和队列,基本上,让所有不同的路径共享相同的资源而不是试图控制它(这就是我的想法),我不知道该怎么做虽然在 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);
    }
}

有点长,但很容易看出我在做什么。如果有人能告诉我如何实现发球台(我试过了?)那就太好了。谢谢!

4

1 回答 1

4

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

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

第一个 src 路径应该连接到您的enc并且mux将继续录制第二个路径将占用显示器。所有这些都应该同时工作。

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

这是电路的样子。

电路

于 2012-02-14T11:18:17.350 回答