链接两个textoverlay元素的Java gstreamer不起作用

链接两个textoverlay元素的Java gstreamer不起作用,java,streaming,video-streaming,rtsp,gstreamer-1.0,Java,Streaming,Video Streaming,Rtsp,Gstreamer 1.0,我有一个用java编写的rtsp播放器应用程序,它构建在gstreamer 1之上。当我尝试在播放视频的顶部显示文本时,在管道中只有一个textoverlay元素,它工作正常。但我需要在窗口的所有角落显示不同的文本 我想到的第一个想法是链接覆盖元素,它实际上是从命令行使用gst-launch-1.0运行的,如下所示 gst-launch-1.0 -v rtspsrc location=rtsp://10.0.5.41:8554 ! rtpjitterbuffer ! rtph264depay

我有一个用java编写的rtsp播放器应用程序,它构建在gstreamer 1之上。当我尝试在播放视频的顶部显示文本时,在管道中只有一个textoverlay元素,它工作正常。但我需要在窗口的所有角落显示不同的文本

我想到的第一个想法是链接覆盖元素,它实际上是从命令行使用gst-launch-1.0运行的,如下所示

gst-launch-1.0 -v rtspsrc location=rtsp://10.0.5.41:8554  ! rtpjitterbuffer  ! rtph264depay ! vaapiparse_h264 ! vaapidecodebin !  textoverlay text = "live video" halignment=left ! textoverlay text="action camera 1" ! xvimagesink
this.sourceElement = ElementFactory.make(RTSP_SOURCE, RTSP_SOURCE);
    final Element videoQueue = ElementFactory.make(QUEUE, QUEUE);
    final Element videoDepay = ElementFactory.make(RTP_H264_DEPAY, RTP_H264_DEPAY);
    final Element videoParser = ElementFactory.make(VAAPI_H264_PARSE, VAAPI_H264_PARSE);
    final Element videoDecoder = ElementFactory.make(VAAPI_DECODE, VAAPI_DECODE);
    videoTypeOverlay = ElementFactory.make(TEXT_OVERLAY, TEXT_OVERLAY);
    videoSourceOverlay = ElementFactory.make(TEXT_OVERLAY, TEXT_OVERLAY);
    sinkElement = ElementFactory.make(XV_IMAGE_SINK, XV_IMAGE_SINK);

    pipe.addMany(sourceElement, videoQueue, videoDepay, videoParser, videoDecoder, videoSourceOverlay, videoTypeOverlay, sinkElement);
    Element.linkMany(videoQueue, videoDepay, videoParser, videoDecoder, videoSourceOverlay, videoTypeOverlay, sinkElement);

      sourceElement.connect((Element.PAD_ADDED) (element, pad) -> {
        if (pad.isLinked()) {
            return;
        }
        Caps caps = pad.getCaps();
        if (caps.size() > 0) {
            String mediaType = caps.getStructure(0).getString("media");
            if ("video".equalsIgnoreCase(mediaType)) {
                pad.link(videoQueue.getStaticPad("sink"));
            }
        }
    });

 @Override
        public void play(PlaySettings playSettings) {
            videoTimeOverlay.set("text", text);
            videoTimeOverlay.set("valignment", valign);
            videoTimeOverlay.set("halignment", halign);
            ...
    }
pipe.addMany(sourceElement, videoQueue, videoDepay, videoParser, videoDecoder, videoSourceOverlay,  sinkElement);
Element.linkMany(videoQueue, videoDepay, videoParser, videoDecoder, videoSourceOverlay,  sinkElement);
当我尝试用java构建相同的管道时,如下所示

gst-launch-1.0 -v rtspsrc location=rtsp://10.0.5.41:8554  ! rtpjitterbuffer  ! rtph264depay ! vaapiparse_h264 ! vaapidecodebin !  textoverlay text = "live video" halignment=left ! textoverlay text="action camera 1" ! xvimagesink
this.sourceElement = ElementFactory.make(RTSP_SOURCE, RTSP_SOURCE);
    final Element videoQueue = ElementFactory.make(QUEUE, QUEUE);
    final Element videoDepay = ElementFactory.make(RTP_H264_DEPAY, RTP_H264_DEPAY);
    final Element videoParser = ElementFactory.make(VAAPI_H264_PARSE, VAAPI_H264_PARSE);
    final Element videoDecoder = ElementFactory.make(VAAPI_DECODE, VAAPI_DECODE);
    videoTypeOverlay = ElementFactory.make(TEXT_OVERLAY, TEXT_OVERLAY);
    videoSourceOverlay = ElementFactory.make(TEXT_OVERLAY, TEXT_OVERLAY);
    sinkElement = ElementFactory.make(XV_IMAGE_SINK, XV_IMAGE_SINK);

    pipe.addMany(sourceElement, videoQueue, videoDepay, videoParser, videoDecoder, videoSourceOverlay, videoTypeOverlay, sinkElement);
    Element.linkMany(videoQueue, videoDepay, videoParser, videoDecoder, videoSourceOverlay, videoTypeOverlay, sinkElement);

      sourceElement.connect((Element.PAD_ADDED) (element, pad) -> {
        if (pad.isLinked()) {
            return;
        }
        Caps caps = pad.getCaps();
        if (caps.size() > 0) {
            String mediaType = caps.getStructure(0).getString("media");
            if ("video".equalsIgnoreCase(mediaType)) {
                pad.link(videoQueue.getStaticPad("sink"));
            }
        }
    });

 @Override
        public void play(PlaySettings playSettings) {
            videoTimeOverlay.set("text", text);
            videoTimeOverlay.set("valignment", valign);
            videoTimeOverlay.set("halignment", halign);
            ...
    }
pipe.addMany(sourceElement, videoQueue, videoDepay, videoParser, videoDecoder, videoSourceOverlay,  sinkElement);
Element.linkMany(videoQueue, videoDepay, videoParser, videoDecoder, videoSourceOverlay,  sinkElement);
我得到一张空白画布。 使应用程序至少工作的唯一方法是从linkMany和addMany行中删除一个覆盖,如下所示

gst-launch-1.0 -v rtspsrc location=rtsp://10.0.5.41:8554  ! rtpjitterbuffer  ! rtph264depay ! vaapiparse_h264 ! vaapidecodebin !  textoverlay text = "live video" halignment=left ! textoverlay text="action camera 1" ! xvimagesink
this.sourceElement = ElementFactory.make(RTSP_SOURCE, RTSP_SOURCE);
    final Element videoQueue = ElementFactory.make(QUEUE, QUEUE);
    final Element videoDepay = ElementFactory.make(RTP_H264_DEPAY, RTP_H264_DEPAY);
    final Element videoParser = ElementFactory.make(VAAPI_H264_PARSE, VAAPI_H264_PARSE);
    final Element videoDecoder = ElementFactory.make(VAAPI_DECODE, VAAPI_DECODE);
    videoTypeOverlay = ElementFactory.make(TEXT_OVERLAY, TEXT_OVERLAY);
    videoSourceOverlay = ElementFactory.make(TEXT_OVERLAY, TEXT_OVERLAY);
    sinkElement = ElementFactory.make(XV_IMAGE_SINK, XV_IMAGE_SINK);

    pipe.addMany(sourceElement, videoQueue, videoDepay, videoParser, videoDecoder, videoSourceOverlay, videoTypeOverlay, sinkElement);
    Element.linkMany(videoQueue, videoDepay, videoParser, videoDecoder, videoSourceOverlay, videoTypeOverlay, sinkElement);

      sourceElement.connect((Element.PAD_ADDED) (element, pad) -> {
        if (pad.isLinked()) {
            return;
        }
        Caps caps = pad.getCaps();
        if (caps.size() > 0) {
            String mediaType = caps.getStructure(0).getString("media");
            if ("video".equalsIgnoreCase(mediaType)) {
                pad.link(videoQueue.getStaticPad("sink"));
            }
        }
    });

 @Override
        public void play(PlaySettings playSettings) {
            videoTimeOverlay.set("text", text);
            videoTimeOverlay.set("valignment", valign);
            videoTimeOverlay.set("halignment", halign);
            ...
    }
pipe.addMany(sourceElement, videoQueue, videoDepay, videoParser, videoDecoder, videoSourceOverlay,  sinkElement);
Element.linkMany(videoQueue, videoDepay, videoParser, videoDecoder, videoSourceOverlay,  sinkElement);

那么,如何在视频画布上放置多个静态覆盖字符串呢?

我通过创建一个Bin元素解决了这个问题,两个覆盖元素被包装在其中。 下面的方法是一个工作代码示例,用于创建带有重影焊盘的Bin容器元素

  private Bin createTextOverlayBin() {
    Bin textOverlayBin = new Bin();
    videoTypeOverlay = ElementFactory.make(TEXT_OVERLAY, "video-type-overlay");

    Optional<Pad> textOverlaySinkPad = playIdOverlay.getSinkPads().stream().filter(pad -> pad.getName().equals("video_sink")).findAny();
    Optional<Pad> textOverlaySrcPad = videoTypeOverlay.getSrcPads().stream().filter(pad -> pad.getName().equals("src")).findAny();

    if (textOverlaySinkPad.isPresent() && textOverlaySrcPad.isPresent()) {
        textOverlayBin.add(playIdOverlay);
        textOverlayBin.add(videoTypeOverlay);

        GhostPad ghostSinkPad = new GhostPad("sink", textOverlaySinkPad.get());
        textOverlayBin.addPad(ghostSinkPad);

        GhostPad ghostSrcPad = new GhostPad("src", textOverlaySrcPad.get());
        textOverlayBin.addPad(ghostSrcPad);


        playIdOverlay.link(videoTypeOverlay);
    } else {
        LOGGER.error("Video text overlay element creation is failed!");
    }
    return textOverlayBin;
}