C#:有可能在服务中生成或伪造可视化树吗?
问题描述:
我有一个应该生成视频指纹的windowsservice。 为了实现这一点,我试图使用MediaElement类(https://msdn.microsoft.com/en-us/library/system.windows.controls.mediaelement(v=vs.110).aspx)。要在打开媒体时触发事件,该元素必须位于可视树中。是否有可能模拟或伪造视觉树?C#:有可能在服务中生成或伪造可视化树吗?
编辑:我现在使用MediaPlayer而不是MediaElement,但不能依赖事件,因为它们不会被引发。
更新代码
public class Mp4ThumbnailExtractor : IDisposable
{
private ManualResetEvent waitHandle;
private TimeSpan mediaOpenTimeout;
public TimeSpan Time { get; set; }
= TimeSpan.Parse("00:00:30");
public TimeSpan FallbackTime { get; set; }
= TimeSpan.Parse("00:00:10");
public int Height { get; set; }
= 400;
public int Width { get; set; }
= 400;
public int Dpi { get; set; }
= 96;
public Mp4ThumbnailExtractor()
{
waitHandle = new ManualResetEvent(false);
mediaOpenTimeout = TimeSpan.Parse("00:00:15");
}
public MemoryStream CreateThumbnail(string videoPath)
{
MemoryStream memory = new MemoryStream();
Uri sourceUri = new Uri(videoPath);
MediaPlayer media = new MediaPlayer();
media.MediaOpened += Media_MediaOpened;
media.ScrubbingEnabled = true;
try
{
media.Open(new Uri(videoPath));
//TODO: media.opened event will not get fired
Thread.Sleep(mediaOpenTimeout);
waitHandle.Set();
//15sec timeout for loading the media
if (waitHandle.WaitOne(mediaOpenTimeout))
{
SetPosition(media);
//TODO: this is bad...
Thread.Sleep(2000);
DrawingVisual dv = new DrawingVisual();
DrawingContext dc = dv.RenderOpen();
dc.DrawVideo(media, new Rect(0, 0, Width, Height));
dc.Close();
RenderTargetBitmap bmp = new RenderTargetBitmap(Width, Height, Dpi, Dpi, PixelFormats.Pbgra32);
bmp.Render(dv);
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmp));
encoder.Save(memory);
memory.Seek(0, SeekOrigin.Begin);
}
else
{
throw new Exception($"Unable to open media '{videoPath}' in '{mediaOpenTimeout}'");
}
}
finally
{
media.Close();
}
return memory;
}
private void SetPosition(MediaPlayer player)
{
if (player.NaturalDuration.HasTimeSpan)
{
TimeSpan naturalTime = player.NaturalDuration.TimeSpan;
if (naturalTime < Time)
{
if (naturalTime > FallbackTime)
{
player.Position = FallbackTime;
}
}
else
{
player.Position = Time;
}
}
}
private void Media_MediaOpened(object sender, EventArgs e)
{
waitHandle.Set();
}
public void Dispose()
{
waitHandle.Dispose();
}
}
答
+0
我现在能够捕捉屏幕,但事件不起作用。我现在有2个编码延迟让代码运行(对于大多数情况,但不可靠,位置设置也有点不可靠) –
MediaElement是一个视觉元素。为什么不使用[MediaPlayer](https://msdn.microsoft.com/en-us/library/system.windows.media.mediaplayer(v = vs.110).aspx)呢? – icebat
MediaPlayer能够完成截图,但MediaOpened事件没有被触发,设置位置正在工作2次中的2次。我添加了一个硬编码的Thread.Sleep(150000); waitHandle.Set(); waitHandle.Wait之前。这不是一个可靠的解决方案 –