将 Playbin 状态设置为 NULL 或 READY 后 GStreamer XOverlay 丢失

发布于 2024-12-18 06:25:28 字数 1831 浏览 2 评论 0原文

我正在使用 OSSBuild 和 gstreamersharp 开发 C# WPF 应用程序。我使用 XOverlayAdapter 在我拥有 Windows 句柄的托管 WindowsForms 控件上显示视频。除了我将 playbin2 状态设置为 NULL 或 READY 时的情况外,一切都运行良好。这正是我正在做的事情(我删除了元素是否已正确创建的所有检查):

  1. 创建一个 playbin

    Gst.BasePlugins.PlayBin2 playBin = new Gst.BasePlugins.PlayBin2();
    playBin.PlayFlags &= ~((Gst.BasePlugins.PlayBin2.PlayFlagsType)(1 << 2));
    playBin.Bus.AddSignalWatch();
    playBin.Bus.EnableSyncMessageEmission();
    playBin.Bus.Message += new Gst.MessageHandler(OnPlayBinMessage);
    
  2. 创建一个视频接收器

    Gst.Video.VideoSink videoSink = 
        Gst.ElementFactory.Make("dshowvideosink") as Gst.Video.VideoSink;
    videoSink["力纵横比"] = true;
    
  3. 将视频接收器与 WindowsForms 控件(屏幕)关联,以在 WPF 窗口的矩形区域中显示视频。

    Gst.Interfaces.XOverlayAdapter overrideAdapter =
        新的 Gst.Interfaces.XOverlayAdapter(videoSink.Handle);
    overlayAdapter.XwindowId = (ulong)screen.Handle;
    
  4. 将视频接收器附加到播放箱

    playBin.VideoSink = videoSink;
    
  5. 将 playbin 的 URI 设置为我的硬盘驱动器上的某个视频文件

    playBin.SetState(Gst.State.Ready);
    playBin.Uri = @"file:///" + fileName.Replace('\\', '/');
    playBin.SetState(Gst.State.Paused);
    
  6. 现在我可以通过更改 playbin 的状态来播放和暂停视频

    playBin.SetState(Gst.State.Playing);
    playBin.SetState(Gst.State.Paused);
    

    到目前为止一切顺利,我可以播放、暂停、搜索窗口中矩形区域中显示的视频。当我尝试播放另一个视频文件时,问题开始出现。根据网上找到的所有手册,我应该在更改 URI 之前将管道状态设置为 NULL 或 READY:

  7. 打开另一个视频文件

    playBin.SetState(Gst.State.Ready);
    playBin.Uri = @"file:///" + newFileName.Replace('\\', '/');
    playBin.SetState(Gst.State.Playing);
    

不幸的是,这会导致我的窗口中的矩形区域变黑并由 GStreamer 创建一个单独的窗口。它与更改 URI 无关,它将 playbin 状态设置为 NULL 或 READY,从而断开视频输出与叠加层的连接。我做错了什么?

I'm developing a C# WPF application using OSSBuild and gstreamersharp. I'm using XOverlayAdapter to display video on a hosted WindowsForms control to which I have a Windows handle. Everything is working nicely except the situation when I set the playbin2 state to NULL or READY. This is exactly what I'm doing (I stripped out all checks if the elements have been created correctly):

  1. Create a playbin

    Gst.BasePlugins.PlayBin2 playBin = new Gst.BasePlugins.PlayBin2();
    playBin.PlayFlags &= ~((Gst.BasePlugins.PlayBin2.PlayFlagsType)(1 << 2));
    playBin.Bus.AddSignalWatch();
    playBin.Bus.EnableSyncMessageEmission();
    playBin.Bus.Message += new Gst.MessageHandler(OnPlayBinMessage);
    
  2. Create a videosink

    Gst.Video.VideoSink videoSink = 
        Gst.ElementFactory.Make("dshowvideosink") as Gst.Video.VideoSink;
    videoSink["force-aspect-ratio"] = true;
    
  3. Associate the videosink with a WindowsForms control (screen) to display the video in a rectangular area in my WPF window.

    Gst.Interfaces.XOverlayAdapter overlayAdapter =
        new Gst.Interfaces.XOverlayAdapter(videoSink.Handle);
    overlayAdapter.XwindowId = (ulong)screen.Handle;
    
  4. Attach the videosink to the playbin

    playBin.VideoSink = videoSink;
    
  5. Set playbin's URI to some video file on my hard drive

    playBin.SetState(Gst.State.Ready);
    playBin.Uri = @"file:///" + fileName.Replace('\\', '/');
    playBin.SetState(Gst.State.Paused);
    
  6. Now I can play and pause the video by changing the state of the playbin

    playBin.SetState(Gst.State.Playing);
    playBin.SetState(Gst.State.Paused);
    

    So far so good, everything is working smoothly, I can play, pause, seek the video displayed in a rectangular area in my window. The problems start when I try to play another video file. According to all manuals found on the net, I should set the pipeline state to NULL or READY before changing the URI:

  7. Open another video file

    playBin.SetState(Gst.State.Ready);
    playBin.Uri = @"file:///" + newFileName.Replace('\\', '/');
    playBin.SetState(Gst.State.Playing);
    

Unfortunately this causes the rectangular area in my window to become black and a separate window created by GStreamer. It has nothing to do with changing the URI, it is setting the playbin state to NULL or READY which disconnects the video output from the overlay. What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

愁杀 2024-12-25 06:25:28

解决方案是防止视频接收器改变其状态。
感谢 gstreamer-devel 邮件列表中的 Stefan Sauer。

playBin.VideoSink.SetLockedState(true);
playBin.SetState(Gst.State.Ready);
playBin.Uri = @"file:///" + newFileName.Replace('\\', '/');
playBin.SetState(Gst.State.Paused);
playBin.VideoSink.SetLockedState(false);

The solution is to prevent the videosink from changing its state.
Credit to Stefan Sauer from the gstreamer-devel mailing list.

playBin.VideoSink.SetLockedState(true);
playBin.SetState(Gst.State.Ready);
playBin.Uri = @"file:///" + newFileName.Replace('\\', '/');
playBin.SetState(Gst.State.Paused);
playBin.VideoSink.SetLockedState(false);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文