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

от автора

Предисловие

Не так давно, возникла необходимость захвата видео с 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
Ссылка на исходник

ссылка на оригинал статьи http://habrahabr.ru/post/177793/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *