简体   繁体   中英

How to store camera stream data in an array in C#

I need to store five minutes of streaming data in RAM (or an alternative, if such available. Now I only know of RAM ). I know how to convert the data into bmp images and store them in an list using the bytes, using Marshal.copy

But the size of each frame is about 3Mb, which is too big for RAM to store.

I believe, the size of the data could be much smaller, if I simply stored the bytes in an array, but I dont know how. The whole Marshal thing is not very clear to me at this moment and days of searching for methods to copy pointer value to managed array was in vain. I need help.

What am I missing? Why I can not copy the chunk I can use to store as BMP, as simple array of bytes? How can I convert the following function to one that returns array?

Here is the code I am using to convert the data into BMP, and I need be able to make necessary changes to convert it to a function that collects all data as it is in a list or array.

private Bitmap GetBitmap(ISampleGrabber i_grabber, int width, int height, int stride)
    {
        int sz = 0;
        i_grabber.GetCurrentBuffer(ref sz, IntPtr.Zero); 
        if (sz == 0) return null;
        var ptr = Marshal.AllocCoTaskMem(sz);
        i_grabber.GetCurrentBuffer(ref sz, ptr);
        var data = new byte[sz];
        Marshal.Copy(ptr, data, 0, sz);
        Bitmap result = null;
        try
        {
            result = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            var bmp_data = result.LockBits(new Rectangle(Point.Empty, result.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
for (int y = 0; y < height; y++)
            {
                var src_idx = sz - (stride * (y + 1));
                //Console.WriteLine(src_idx);
                var dst = new IntPtr(bmp_data.Scan0.ToInt32() + (stride * y));
                Marshal.Copy(data, src_idx, dst, stride);
            }

            result.UnlockBits(bmp_data);
            Marshal.FreeCoTaskMem(ptr);
        }
        catch (ArgumentException ax)
        {
            //System.Windows.Forms.MessageBox.Show(ax.Message);
            Console.WriteLine(ax.Message);
        }

        return result;
    }

3 megabytes per frame, 300 seconds and N frames per second are likely to make it too big for RAM anyway. You have to do something with the data as video capture goes.

Some ideas for you:

  1. Compression - if you can compress the data in real time, your storage requirements will be significantly reduced, including affording storage of 300 seconds in RAM, maybe even with lossless encoding

1.1. Hardware assisted compression (requires GPU, in some cases can be lossless); the output will be fine for RAM and for disk writing

1.2. Software compression with well known format (high CPU load); the data will fit RAM

1.3. Some lightweight compression using simple well known algorithm, may be lossless; depending on content it is quite likely that even simple post-processing reduces amount of data to keep

  1. Asynchronous disk writing - if you write as you capture, the amount of data can be too large to write to temporary disk location in real time but writing asynchronously without blocking capture can take you to the point where you flush enough data to disk and the remainder of the data fits available RAM by the fifth minute of video capture.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM