如何在WPF中预览Windows Media编码器会话?
此代码适用于windows窗体应用程序(它显示预览),但不适用于WPF应用程序如何在WPF中预览Windows Media编码器会话?,wpf,directshow,windows-media-encoder,Wpf,Directshow,Windows Media Encoder,此代码适用于windows窗体应用程序(它显示预览),但不适用于WPF应用程序 WMEncoder _encoder; WMEncDataView _preview; _encoder = new WMEncoder(); IWMEncSourceGroupCollection SrcGrpColl = _encoder.SourceGroupCollection; IWMEncSourceGroup2 sourceGroup = (IWMEncSourceGroup2)SrcGrpColl.
WMEncoder _encoder;
WMEncDataView _preview;
_encoder = new WMEncoder();
IWMEncSourceGroupCollection SrcGrpColl = _encoder.SourceGroupCollection;
IWMEncSourceGroup2 sourceGroup = (IWMEncSourceGroup2)SrcGrpColl.Add("SG_1");
IWMEncVideoSource2 videoDevice = (IWMEncVideoSource2)sourceGroup.AddSource(WMENC_SOURCE_TYPE.WMENC_VIDEO);
videoDevice.SetInput("Default_Video_Device", "Device", "");
IWMEncAudioSource audioDevice = (IWMEncAudioSource)sourceGroup.AddSource(WMENC_SOURCE_TYPE.WMENC_AUDIO);
audioDevice.SetInput("Default_Audio_Device", "Device", "");
IWMEncProfile2 profile = new WMEncProfile2();
profile.LoadFromFile("Recording.prx");
sourceGroup.set_Profile(profile);
_encoder.PrepareToEncode(true);
_preview = new WMEncDataView();
int lpreviewStream = videoDevice.PreviewCollection.Add(_preview);
_encoder.Start();
_preview.SetViewProperties(lpreviewStream, (int)windowsFormsHost1.Handle);
_preview.StartView(lpreviewStream);
我曾尝试使用WindowsFormsHost控件获取要传递的句柄(如示例所示),但仍然没有成功。我最近做了类似的事情,将现有的DirectShow视频组件与新的WPF UI集成在一起。有多种方法可以实现这一点,但最简单的方法可能是从中派生一个新类。然后,您只需覆盖几个方法,为预览流提供窗口句柄,所有这些都应该可以正常工作。根据您的要求,您可能需要在WndProc中处理两条Windows消息,以便在不播放视频时处理显示更改和重画
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace SOQuestion
{
public class VideoHost : HwndHost
{
protected override HandleRef BuildWindowCore(HandleRef hwndParent)
{
IntPtr hwndHost = IntPtr.Zero;
int hostHeight = (int) this.ActualHeight;
int hostWidth = (int) this.ActualWidth;
hwndHost = CreateWindowEx(0, "static", "",
WS_CHILD | WS_VISIBLE,
0, 0,
hostHeight, hostWidth,
hwndParent.Handle,
(IntPtr)HOST_ID,
IntPtr.Zero,
0);
return new HandleRef(this, hwndHost);
}
protected override void DestroyWindowCore(HandleRef hwnd)
{
DestroyWindow(hwnd.Handle);
}
protected override void OnWindowPositionChanged(Rect rcBoundingBox)
{
base.OnWindowPositionChanged(rcBoundingBox);
_preview.SetViewProperties(lpreviewStream, (int)this.Handle);
}
protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// Handle a couple of windows messages if required - see MSDN for details
return base.WndProc(hwnd, msg, wParam, lParam, ref handled);
}
[DllImport("user32.dll", EntryPoint = "CreateWindowEx", CharSet = CharSet.Auto)]
internal static extern IntPtr CreateWindowEx(int dwExStyle,
string lpszClassName,
string lpszWindowName,
int style,
int x, int y,
int width, int height,
IntPtr hwndParent,
IntPtr hMenu,
IntPtr hInst,
[MarshalAs(UnmanagedType.AsAny)] object pvParam);
[DllImport("user32.dll", EntryPoint = "DestroyWindow", CharSet = CharSet.Auto)]
internal static extern bool DestroyWindow(IntPtr hwnd);
internal const int WS_CHILD = 0x40000000;
internal const int WS_VISIBLE = 0x10000000;
internal const int HOST_ID = 0x00000002;
}
}
这个效果很好!无法从控件访问_preview变量。您知道在控件更改大小时启用调整预览大小的方法吗?这正是我的示例在窗口位置或大小更改时重置句柄的原因-这会导致DirectShow渲染器重置。如果在响应控件大小调整时连续调用StopView和StartView会发生什么情况?即使在OnWindowPositionChanged或单独的按钮中调用StopView、SetViewProperties和StartView,它也不起作用。我必须开始/停止编码(可能是windows media encoder的问题)恐怕不知道。我只是看了一下WME文档——它们并没有太多的细节,不是吗?这可能是不可能的-这取决于预览是如何在内部实现的。不,它们不是。。谢谢你的回答,它确实解决了我的主要问题!