C#:是否可以在服务中生成或伪造可视树?

时间:2017-08-28 08:58:57

标签: c# media-player video-capture mediaelement

我有一个应该生成视频缩略图的Windows服务。 为此,我尝试使用MediaElement类(https://msdn.microsoft.com/en-us/library/system.windows.controls.mediaelement(v=vs.110).aspx)。要在打开媒体时触发事件,此元素必须位于visualtree中。是否可以模拟或伪造可视树?

编辑:我现在使用MediaPlayer而不是MediaElements,但不能依赖这些事件,因为它们不会被抛出。

更新了代码

        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 个答案:

答案 0 :(得分:1)

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

  

表示包含音频和/或视频的控件

您需要无UI的MediaPlayer。不要忘记拨打Open方法或MediaOpened不要开火。

相关问题