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(); 
    } 
} 
+1

MediaElement是一个视觉元素。为什么不使用[MediaPlayer](https://msdn.microsoft.com/en-us/library/system.windows.media.mediaplayer(v = vs.110).aspx)呢? – icebat

+0

MediaPlayer能够完成截图,但MediaOpened事件没有被触发,设置位置正在工作2次中的2次。我添加了一个硬编码的Thread.Sleep(150000); waitHandle.Set(); waitHandle.Wait之前。这不是一个可靠的解决方案 –

MediaElement基本上是托管媒体内容的可视化控制:

表示包含一个控制音频和/或视频

你需要一个UI无MediaPlayer。只是不要忘记调用Open方法或MediaOpened不会触发。

+0

我现在能够捕捉屏幕,但事件不起作用。我现在有2个编码延迟让代码运行(对于大多数情况,但不可靠,位置设置也有点不可靠) –