3

我创建了一个 C# 应用程序,它在输入中接收 RGB 流,然后压缩流并将其保存在磁盘上。对于我的测试,我正在运行一个充当服务器(在同一台电脑上)的应用程序,它可以输出视频。

我的客户端应用程序的核心是:

void client_ColorFrameReady(object sender, ColorFrameReadyEventArgs e)
{
    if (writer != null)
    {
        count++;
        if (count % 2 == 0)
            writer.WriteVideoFrame(ResizeBitmap(BitmapImage2Bitmap(e.ColorFrame.BitmapImage), 320, 240));
        }
        else
        {
            writer.Close();
        }
    }
}

writer的类型VideoFileWriter来自aforge.net图书馆。

我的应用程序运行良好,但我遇到了与使用的 RAM 量有关的问题。

当我的应用程序获取帧时,服务器应用程序(输出视频的应用程序)使用的 RAM 会随时间线性增加。writer.Close()只有在执行时才释放 RAM 。

方法BitmapImage2Bitmap和 ResieBitmap 如下所示:

private Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage)
{
    // BitmapImage bitmapImage = new BitmapImage(new Uri("../Images/test.png", UriKind.Relative));

    using (MemoryStream outStream = new MemoryStream())
    {
         BitmapEncoder enc = new BmpBitmapEncoder();
         enc.Frames.Add(BitmapFrame.Create(bitmapImage));
         enc.Save(outStream);
         System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);

         // return bitmap; <-- leads to problems, stream is closed/closing ...
         return new Bitmap(bitmap);
    }
}

private static Bitmap ResizeBitmap(Bitmap sourceBMP, int width, int height)
{
    Bitmap result = new Bitmap(width, height);
    using (Graphics g = Graphics.FromImage(result))
    g.DrawImage(sourceBMP, 0, 0, width, height);
    return result;
}

我可以在我的应用程序中限制 RAM 的使用吗?

4

1 回答 1

4

我总是使用

你不是。不幸的是,当你不应该使用它时,你也会使用它。对于每一帧,这里有三个位图对象被“泄漏”。

在 MemoryStream 上使用using时遇到了麻烦。并通过复制位图来修复问题,但位图对象没有被释放。以正确的方式修复此问题,不要处理MemoryStream。不处理 MemoryStream 很好,当您不使用 MemoryStream(Stream) 构造函数时,它只使用内存并且没有一次性成员。现在您也不再需要使用 Bitmap(image) 构造函数制作的副本了。那是一个。

BitmapImage2Bitmap() 返回的位图没有被释放。那是两个。

ResizeBitmap() 返回的位图没有被释放。那是三个。

它应该如下所示:

using (var frame = BitmapImage2Bitmap(e.ColorFrame.BitmapImage))                   
using (var thumb = ResizeBitmap(frame, 320, 240)) {
    writer.WriteVideoFrame(thumb);
}

和:

private Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage)
{
    var outStream = new MemoryStream();  
    var enc = new BmpBitmapEncoder();
    enc.Frames.Add(BitmapFrame.Create(bitmapImage));
    enc.Save(outStream);
    return new System.Drawing.Bitmap(outStream);
}

正如我在评论中提到的那样,您很可能仍然遇到消防软管问题,通过避免位图复制,这段代码肯定比原始代码更快,但仍然不会燃烧橡胶。

于 2013-06-04T09:53:16.853 回答