7

我正在使用 FFmpeg 库通过 UDP 以最小的延迟接收和解码 H.264/MPEG-TS(这是 MediaElement 无法处理的)。

在一个专用的 FFmpeg 线程上,我正在拉取 PixelFormats.Bgr32 视频帧进行显示。我已经尝试过 InteropBitmap:

_section = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, PAGE_READWRITE, 0, size, null);
_buffer = MapViewOfFile(_section, FILE_MAP_ALL_ACCESS, 0, 0, size);
Dispatcher.Invoke((Action)delegate()
{
    _interopBitmap = (InteropBitmap)Imaging.CreateBitmapSourceFromMemorySection(_section, width, height, PixelFormats.Bgr32, (int)size / height, 0);
    this.Source = _interopBitmap;
});

然后每帧更新:

Dispatcher.Invoke((Action)delegate()
{
    _interopBitmap.Invalidate();
});

但是性能很差(跳帧、高 CPU 使用率等)。

我也尝试过 WriteableBitmap: FFmpeg 将帧放入 _writeableBitmap.BackBuffer 并按帧更新:

Dispatcher.Invoke((Action)delegate()
{
    _writeableBitmap.Lock();
});
try
{
    ret = FFmpegInvoke.sws_scale(...);
}
finally
{
    Dispatcher.Invoke((Action)delegate()
    {
        _writeableBitmap.AddDirtyRect(_rect);
        _writeableBitmap.Unlock();
    });
}

遇到几乎相同的性能问题(使用各种 DispatcherPriority 进行测试)。

任何帮助将不胜感激。

4

1 回答 1

1

我知道为时已晚,但我为那些正在努力解决这个问题的人写下这个答案。最近,我使用 InteropBitmap 完成了一个渲染项目,其中我能够以 25fps 的速度在 i7 1.6 Ghz CPU +8Gb RAM 笔记本电脑上同时在 WPF 窗口中运行大约 16 个媒体播放器组件。以下是我为性能调整所采取的技巧:

首先,我没有让 GC 处理我的视频数据包。我在需要实例化视频帧的任何地方使用 Marshal.AllocateHGlobal 分配内存,并在完成渲染后立即使用 Marshal.FreeHGlobal 进行处置。

其次,我为每个单独的媒体播放器创建了一个调度线程。有关详细信息,请阅读“ https://blogs.msdn.microsoft.com/dwayneneed/2007/04/26/multithreaded-ui-hostvisual/ ”。

第三,对于纵横比,通常是调整大小的目的,我使用了原生 EmguCV 库。这个库在性能方面帮助了我很多,而不是使用位图和覆盖等。

我认为这些步骤可以帮助需要使用 InteropBitmap 等手动渲染的每个人。

于 2017-04-18T07:25:53.157 回答