
Capturing video from a camera and transferring it over the network
Foreword
Not so long ago, there was a need to capture video from a web camera and transmit it over the network using .Net.
Since I faced this problem for the first time, the first thing I started to look for information on this issue.
As it turned out, in a clean .Net there is no support for working with web cameras. After going through several different libraries, I chose Aforge.net.
Aforge.net is a framework for solving a number of problems, from which we will need the AForge.Video library.
Image capture
There is a class for capturing video from a video input device
AForge.Video.DirectShow.VideoCaptureDevice
. He needs to set the moniker of the device from which the capture will occur. It is also necessary to set an event handler NewFrame
. This event occurs every time a new frame is received from the device, which is transmitted to the handler as an object Bitmap
, where it can already be processed: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();
}
}
Video capture is launched by calling the method
Start()
. The list of available cameras installed in the system can be obtained using the class
FilterInfoCollection
, passing it, as a parameter, the necessary category of devices:var videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
This class is a collection of FilterInfo elements that contain two fields:
- Name - device name
- MonikerString - device moniker.
Thus, having received the device moniker, we can pass it to the class
VideoCaptureDevice
.MJPEG video stream generation
MJPEG (Motion JPEG) is the simplest video compression algorithm, so I chose it on it.
The MJPEG video stream consists of sequential frames in JPEG format supplemented by an http header:
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.......
Implementation Example:
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
Link to the source in Google Docs