Захват видео с камеры и передача его по сети

Предисловие


Не так давно, возникла необходимость захвата видео с web камеры и передавать его по сети используя .Net.
Так как с подобной задачей я столкнулся впервые, то первым делом начал искать информацию по этому вопросу.
Как выяснилось, что в чистом .Net нет поддержки работы с web камерами. Перебрав несколько различных библиотек, свой выбор остановил на Aforge.net.

Aforge.net — это фреймворк для решения целого ряда задач, из которого нам понадобится библиотеки AForge.Video.

Захват изображения


Для захвата видео с устройства видео ввода существует класс AForge.Video.DirectShow.VideoCaptureDevice. Ему необходимо задать моникер устройства с которого будет происходить захват. Так же необходимо задать обработчик события NewFrame. Это событие возникает каждый раз, когда с устройства будет получен новый кадр, который и передается в обработчик в виде объекта Bitmap, где его уже можно обработать:
private void VideoSourceNewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
{
    var img = (Image) eventArgs.Frame;
    using (var ms=new MemoryStream())
    {
        img.Save(ms,ImageFormat.Jpeg);
       //Сохраняем изображение в массив байт, для последующего формирования mjpeg
        _bufImage = ms.ToArray();
    }
}


Запуск видеозахвата осуществляется вызовом метода Start().

Список доступных видеокамер, установленных в системе, можно получить с помощью класса FilterInfoCollection, передав ему, в качестве параметра, необходимую категорию устройств:
var videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);

Это класс представляет из себя коллекцию элементов FilterInfo, которые содержат в себе два поля:
  • Name — название устройства
  • MonikerString — моникер устройства.

Таким образом, получив моникер устройства мы можем передать его в класс VideoCaptureDevice.

Формирование видео-потока MJPEG


MJPEG (Motion JPEG) является простейшим алгоритмом видеосжатия, поэтому свой выбор я остановил именно на нем.
Поток видео MJPEG представляет из себя последовательно идущие кадры в JPEG формате дополненные http заголовком:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: multipart/x-mixed-replace; boundary=--myboundary
Expires: -1
--myboundary
Content-Type: image/jpeg
Content-Length:96719
.....image.......
--myboundary
Content-Type: image/jpeg
Content-Length:96720
.....next image.......

Пример реализации:
public ActionResult Video()
{
    Response.Clear();
    //Устанавливает тип передаваемых данных и разделитель кадров
    Response.ContentType = "multipart/x-mixed-replace; boundary=--myboundary";
    //Отключаем кеширование
    Response.Expires = 0;
    Response.Cache.SetCacheability(HttpCacheability.NoCache);

    var ae = new ASCIIEncoding();
    //Передаем поток пока клиент не отключится
    while (Response.IsClientConnected)
    {
        try
        {
            //_bufImage - переменная, в которой хранится новый кадр в формате jpeg
            var buf = _bufImage;
            //Формируем заголовок разделителя
            var boundary = ae.GetBytes("\r\n--myboundary\r\nContent-Type: image/jpeg\r\nContent-Length:"
                                        + buf.Length + "\r\n\r\n");
            Response.OutputStream.Write(boundary, 0, boundary.Length);
            Response.OutputStream.Write(buf, 0, buf.Length);
            Response.Flush();
            //Усыпляем поток, для поддержки частоты кадров 20 кадров/с
            Thread.Sleep(50);

        }
        catch (Exception)
        {

        }

    }
    Response.End();



    return null;
}

Aforge.net
MJPEG
Ссылка на исходник в Google Docs
  • +14
  • 38k
  • 8
Поделиться публикацией

Похожие публикации

Комментарии 8

    0
    А не могли бы написать пример только с использованием потока h264?
      0
      С h264 пока сам не разобрался. Как только с ним разберусь — обязательно напишу.
        0
        Интересная тема, обязательно пишите!
          0
          Эту задачу я решал в рамках проекта удаленного управления роботами через интернет, о чем в ближайшее время и напишу.
      0
      Открыв ссылку ожидал увидеть развернутую статью о захвате видео, о построении графов в directshow, о передаче через службы видеопотока. А ничего этого нет. Один элементарный пример, и все.
      О чем статья?
        0
        Статья больше нацелена на начинающих, на тех, кто только решил передавать видео с камеры по сети, но не знает с какой стороны к этой задаче подступится. Я сам через это прошел и решил поделится опытом, так сказать инструкция для чайников.
          0
          Я думаю начинающему надо начинать с DirectShow(.NET), графов, пинов и фильтров, узнать как это выглядит в фундаменте, и лишь потом использовать фрэйворки. Хотя, если надо простое решение «в лоб», может и пойдет.
            0
            Я думаю начинающему надо начинать с DirectShow(.NET)), графов, пинов и фильтров, узнать как это выглядит в фундаменте, и лишь потом использовать фрэйворки

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

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое