From e7511ddba8ad0346152ef5bc1b6aad6edd816b50 Mon Sep 17 00:00:00 2001 From: jasonchenwork Date: Tue, 12 Aug 2025 09:46:50 +0800 Subject: [PATCH] =?UTF-8?q?202508120940=20video=20=E7=95=AB=E9=9D=A2?= =?UTF-8?q?=E6=94=B9=E5=9B=9E=E5=8E=BB=E7=89=A9=E4=BB=B6=E8=A3=A1=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Program.cs | 2 +- Services/MediaService.cs | 33 +++++++++++++++++---- Services/MediaServicePrimary.cs | 25 +++++++++++++++- VideoPlayerForm.cs | 52 +++++---------------------------- 4 files changed, 60 insertions(+), 52 deletions(-) diff --git a/Program.cs b/Program.cs index 3388131..1756239 100644 --- a/Program.cs +++ b/Program.cs @@ -13,7 +13,7 @@ namespace DualScreenDemo private static PrimaryForm primaryForm; // 儲存實例的參考 public static Room room = new Room(); - public static string verSion = "Server V2.8 202508111757"; + public static string verSion = "Server V2.8 202508120940"; [STAThread] static void Main() diff --git a/Services/MediaService.cs b/Services/MediaService.cs index cc30384..f41fced 100644 --- a/Services/MediaService.cs +++ b/Services/MediaService.cs @@ -11,10 +11,22 @@ namespace DualScreenDemo.Services public IBaseFilter renderer; //private IBaseFilter audioRenderer; private IBaseFilter lavSplitter; + private IVideoWindow videoWindow; public int Run() => (mediaControl != null) ? mediaControl.Run() : 0; public int Stop() => (mediaControl != null) ? mediaControl.Stop() : 0; public int Pause() => (mediaControl != null) ? mediaControl.Pause() : 0; - public bool isAtEnd() + + public void VideoPlayerForm_FormClosing() + { + if (videoWindow != null) + { + videoWindow.put_Visible(OABool.False); + videoWindow.put_Owner(IntPtr.Zero); + Marshal.ReleaseComObject(videoWindow); + videoWindow = null; + } + } + public bool IsAtEnd() { bool isAtEnd = false; if (mediaControl == null) { return false; } @@ -34,20 +46,22 @@ namespace DualScreenDemo.Services Math.Abs(currentSeconds - durationSeconds) < 0.1; // 确保真的到了结尾 //Console.WriteLine($"檢測到歌曲 - 當前位置: {currentSeconds:F2}秒, 總時長: {durationSeconds:F2}秒"); if (isAtEnd) - { + { Console.WriteLine($"檢測到歌曲 -結束: {currentSeconds:F2}秒, 總時長: {durationSeconds:F2}秒"); } } } return isAtEnd; } - public void RenderMediaFile(string filePath) + public void RenderMediaFile(string filePath, nint Handle, int Width, int Height) { + if (videoWindow != null) videoWindow.put_Visible(OABool.False); Stop(); SafeRelease(ref renderer); SafeRelease(ref lavSplitter); SafeRelease(ref graphBuilder); - + + int hr = 0; graphBuilder = (IGraphBuilder)new FilterGraph(); try @@ -67,7 +81,16 @@ namespace DualScreenDemo.Services SetAudioTrackTo(1); else Console.WriteLine("Failed to render secondary file."); - + // 绑定视频窗口到副屏幕 + videoWindow = renderer as IVideoWindow; + if (videoWindow != null) + { + videoWindow.put_Owner(Handle); + videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings); + videoWindow.SetWindowPosition(0, 0, Width, Height); + videoWindow.put_Visible(OABool.True); + } + mediaControl.Run(); } public void SetVolume(int volume) { diff --git a/Services/MediaServicePrimary.cs b/Services/MediaServicePrimary.cs index 12081ad..1fd02a0 100644 --- a/Services/MediaServicePrimary.cs +++ b/Services/MediaServicePrimary.cs @@ -12,12 +12,24 @@ namespace DualScreenDemo.Services public IBaseFilter videoRenderer; IMediaControl mediaControl; IBaseFilter sourceFilter; + private IVideoWindow videoWindow; public MediaServicePrimary() { } public int Run() => (mediaControl != null) ? mediaControl.Run() : 0; public int Stop() => (mediaControl != null)? mediaControl.Stop() : 0; public int Pause() => (mediaControl != null) ? mediaControl.Pause() : 0; + public void VideoPlayerForm_FormClosing() { + if (videoWindow != null) + { + videoWindow.put_Visible(OABool.False); + videoWindow.put_Owner(IntPtr.Zero); + Marshal.ReleaseComObject(videoWindow); + videoWindow = null; + } + } + + public void StopAndReleaseResources() { if (mediaControl != null) @@ -32,8 +44,9 @@ namespace DualScreenDemo.Services SafeRelease(ref graphBuilder); } - public void RenderMediaFile(string filePath) + public void RenderMediaFile(string filePath, nint Handle, int Width, int Height) { + if (videoWindow != null) videoWindow.put_Visible(OABool.False); StopAndReleaseResources(); @@ -58,6 +71,16 @@ namespace DualScreenDemo.Services DsError.ThrowExceptionForHR(hr); hr = ConnectFilters(graphBuilder, lavVideoDecoder, "Output", videoRenderer, "VMR Input0"); DsError.ThrowExceptionForHR(hr); + + videoWindow = videoRenderer as IVideoWindow; + if (videoWindow != null) + { + videoWindow.put_Owner(Handle); + videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren); + videoWindow.SetWindowPosition(0, 0, Width, Height); + videoWindow.put_Visible(OABool.True); + } + mediaControl.Run(); } catch (Exception ex) { diff --git a/VideoPlayerForm.cs b/VideoPlayerForm.cs index 7c51b42..27dc21e 100644 --- a/VideoPlayerForm.cs +++ b/VideoPlayerForm.cs @@ -71,8 +71,8 @@ namespace DualScreenDemo private const uint SWP_NOZORDER = 0x0004; private MediaServicePrimary primary = new MediaServicePrimary(); private MediaService secondary = new MediaService(); - private IVideoWindow videoWindowPrimary; - private IVideoWindow videoWindowSecondary; + + public static OverlayForm overlayForm; public bool isMuted = false; @@ -160,20 +160,8 @@ namespace DualScreenDemo private void VideoPlayerForm_FormClosing(object sender, FormClosingEventArgs e) { - if (videoWindowPrimary != null) - { - videoWindowPrimary.put_Visible(OABool.False); - videoWindowPrimary.put_Owner(IntPtr.Zero); - Marshal.ReleaseComObject(videoWindowPrimary); - videoWindowPrimary = null; - } - if (videoWindowSecondary != null) - { - videoWindowSecondary.put_Visible(OABool.False); - videoWindowSecondary.put_Owner(IntPtr.Zero); - Marshal.ReleaseComObject(videoWindowSecondary); - videoWindowSecondary = null; - } + primary.VideoPlayerForm_FormClosing(); + secondary.VideoPlayerForm_FormClosing(); // 清理COM CoUninitialize(); } @@ -364,39 +352,13 @@ namespace DualScreenDemo private Task InitializeAndPlayMedia(SongData song) { string pathToPlay = song.getFile(); - if (videoWindowPrimary != null) videoWindowPrimary.put_Visible(OABool.False); - if (videoWindowSecondary != null) videoWindowSecondary.put_Visible(OABool.False); - // 渲染媒體文件 - primary.RenderMediaFile(pathToPlay); - secondary.RenderMediaFile(pathToPlay); + primary.RenderMediaFile(pathToPlay,PrimaryForm.Instance.primaryScreenPanel.Handle,newWidth,newHeight); + secondary.RenderMediaFile(pathToPlay,this.Handle,secondMonitor.Bounds.Width,secondMonitor.Bounds.Height); - - videoWindowPrimary = primary.videoRenderer as IVideoWindow; - if (videoWindowPrimary != null) - { - videoWindowPrimary.put_Owner(PrimaryForm.Instance.primaryScreenPanel.Handle); - videoWindowPrimary.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren); - videoWindowPrimary.SetWindowPosition(0, 0, newWidth, newHeight); - videoWindowPrimary.put_Visible(OABool.True); - } - // 绑定视频窗口到副屏幕 - videoWindowSecondary = secondary.renderer as IVideoWindow; - if (videoWindowSecondary != null) - { - videoWindowSecondary.put_Owner(this.Handle); - videoWindowSecondary.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings); - videoWindowSecondary.SetWindowPosition(0, 0, secondMonitor.Bounds.Width, secondMonitor.Bounds.Height); - videoWindowSecondary.put_Visible(OABool.True); - } - - // 音量處理 SetVolume(isMuted ? -10000 : previousVolume); - // 開始播放 - primary.Run(); - secondary.Run(); if (isSyncToPrimaryMonitor) SyncToPrimaryMonitor(); return Task.CompletedTask; } @@ -427,7 +389,7 @@ namespace DualScreenDemo { try { - bool isAtEnd = secondary.isAtEnd() ; + bool isAtEnd = secondary.IsAtEnd() ; if (isAtEnd && !isPaused) { BeginInvoke(new Action(async () =>