簡體   English   中英

捕獲每個 WPF MediaElement 幀

[英]Capture each WPF MediaElement frame

有沒有辦法捕獲每個 WPF MediaElement 幀? 就像在每個渲染幀上觸發並允許我訪問它的事件。 如果 MediaElement 不提供此類功能,如何實現它或我可以使用哪些其他控件? 附帶說明一下,是否有這樣的控件或方法允許使用幀捕獲對媒體剪輯進行屏幕外快速渲染? (所以我可以盡快處理幀)

試試我的WPF MediaKit項目。 允許您使用媒體在 WPF 中執行幾乎任何操作。 試試 MediaDetector.cs,它允許您從媒體中的任何時間提取幀。 這有點小問題,因為我從來沒有花很多時間在上面,但應該可以滿足您的需要。

沒有內置的 WPF 方式:

  • MediaElement 沒有這種能力。
  • BitmapDecoder 有 API 來請求這個,但是沒有實現使用 BitmapDecoder 從任意媒體中提取幀:它只能從一些動畫位圖格式(如 .gif)中提取幀。

我能夠使用 DirectShow 從 .mpg、.wmv、.mov、.flv、.avi 和其他電影格式獲取幀圖像。 我使用 DirectShow 的 COM 圖形構建器接口構建了一個過濾器圖形。 生成的過濾器圖形解碼電影並將其連接到用 C# 編寫的自定義渲染器過濾器。 我的自定義過濾器接收幀數據並將其轉換為 BitmapSource 對象以使用 BitmapSource.Create 進行顯示。

DirectShow 解決方案表現相當不錯,托管到非托管的轉換沒什么大不了的,但需要一段時間才能弄清楚 DirectShow 圖形構建的細節。

如果你發揮你的想象力,也許這個片段可以給你一些想法:

MediaPlayer player = new MediaPlayer();
player.Open(new Uri(_inputFilename));
player.ScrubbingEnabled = true;
DrawingVisual dv = new DrawingVisual();
for (int i = 0; i < session.FramesList.Count; i++)
{
    Frame f = session.FramesList[i];
    player.Position = new TimeSpan((long)(f.Time * 10000000));
    using (DrawingContext dc = dv.RenderOpen())
    {
        dc.DrawVideo(player, new Rect(0, 0, 1024, 576));
    }
    RenderTargetBitmap bmp = new RenderTargetBitmap(1024, 576, 96, 96, PixelFormats.Pbgra32);
    bmp.Render(dv);
    f.Thumbnail = bmp.GetAsFrozen() as ImageSource;
    framesListView.Dispatcher.Invoke(() => FramesList.Add(f));
}

您可以嘗試使用此方法輸出任何 UI 元素,包括 WPF 中的 MediaElement

 public static void ConvertUiElementToBitmap(UIElement elt, string path)
        {
            double h = elt.RenderSize.Height;
            double w = elt.RenderSize.Width;
            if (h > 0)
            {
                PresentationSource source = PresentationSource.FromVisual(elt);
                RenderTargetBitmap rtb = new RenderTargetBitmap((int)w, (int)h, 96, 96, PixelFormats.Default);

                VisualBrush sourceBrush = new VisualBrush(elt);
                DrawingVisual drawingVisual = new DrawingVisual();
                DrawingContext drawingContext = drawingVisual.RenderOpen();
                using (drawingContext)
                {
                    drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0),
                          new Point(w, h)));
                }
                rtb.Render(drawingVisual);

                // return rtb;
                var encoder = new PngBitmapEncoder();
                var outputFrame = BitmapFrame.Create(rtb);
                encoder.Frames.Add(outputFrame);

                using (var file = System.IO.File.OpenWrite(path))
                {
                    encoder.Save(file);
                }
            }
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM