Как сохранить данные потока камеры в массиве в C # - PullRequest
2 голосов
/ 15 октября 2019

Мне нужно хранить пять минут потоковой передачи данных в RAM (или альтернативу, если таковая имеется. Теперь я знаю только RAM ). Я знаю, как преобразовать данные в изображения bmp и сохранить их в списке, используя байты, используя Marshal.copy

Но размер каждого кадра составляет около 3 МБ, что слишком много для ОЗУ для хранения.

Я считаю, что размер данных мог бы быть намного меньше, если бы я просто хранил байты в массиве, но я не знаю как. В настоящий момент мне все не совсем понятно, и дни поиска методов для копирования значения указателя в управляемый массив были напрасны. Мне нужна помощь.

Что мне не хватает? Почему я не могу скопировать кусок, который могу использовать для хранения в виде BMP, в виде простого массива байтов? Как я могу преобразовать следующую функцию в функцию, которая возвращает массив?

Вот код, который я использую для преобразования данных в BMP, и мне нужно иметь возможность внести необходимые изменения, чтобы преобразовать их в функцию, которая собираетвсе данные в списке или массиве.

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;
    }

1 Ответ

0 голосов
/ 15 октября 2019

3 мегабайта на кадр, 300 секунд и N кадров в секунду, скорее всего, сделают его слишком большим для оперативной памяти. Вы должны что-то делать с данными во время захвата видео.

Несколько идей для вас:

  1. Сжатие - если вы можете сжимать данные в режиме реального времени, ваши требования к хранилищу будутзначительно уменьшено, включая 300-секундное хранение в ОЗУ, возможно даже с кодированием без потерь

1.1. Аппаратное сжатие (требуется графический процессор, в некоторых случаях может быть без потерь);вывод будет хорошо для оперативной памяти и для записи на диск

1.2. Программное сжатие с хорошо известным форматом (высокая загрузка процессора);данные будут соответствовать оперативной памяти

1.3. Некоторое легкое сжатие, использующее простой хорошо известный алгоритм, может быть без потерь;в зависимости от содержимого вполне вероятно, что даже простая постобработка сокращает объем данных для сохранения

Асинхронная запись на диск - если вы записываете во время записи, объем данных может быть слишком большим для записи на временное место на диске в режиме реального времени, но асинхронная запись без блокировки записи может привести к тому, что вы сбросите достаточно данных на диска оставшаяся часть данных соответствует доступной оперативной памяти к пятой минуте захвата видео.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...