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

Java gstreamer linking two textoverlay elements is not working

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

我的第一个想法是链接覆盖元素,这些元素实际上是从命令行使用 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

当我尝试使用 java 构建相同的管道时,如下所示;

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

我得到一个空白 canvas。 使应用程序至少工作的唯一方法是从 linkMany 和 addMany 行中删除其中一个叠加层,如下所示;

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

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

我通过创建一个 Bin 元素并将两个叠加元素包裹在其中解决了这个问题。 下面的方法是使用 ghost pads 创建 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;
}