2017-04-18 20 views
0

Java에서 작성된 rtsp 플레이어 응용 프로그램이 있고 gstreamer 위에 작성되었습니다. 1. 파이프 라인의 textoverlay 요소 하나만 사용하여 재생중인 비디오 위에 텍스트를 표시하려고 시도했습니다. 그것은 잘 작동합니다.하지만 창문의 모든 구석에 다른 텍스트를 표시해야합니다.두 개의 textoverlay 요소를 연결하는 Java gstreamer가 작동하지 않습니다.

처음에는 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); 
      ... 
    } 

빈 캔버스가 있습니다. 최소한 애플리케이션을 작동시키는 유일한 방법은 다음과 같이 linkMany 및 addMany 행에서 오버레이 중 하나를 제거하는 것입니다.

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

어떻게 비디오 캔버스에 둘 이상의 정적 오버레이 문자열을 넣을 수 있습니까?

답변

1

이 문제는 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; 
}