How to stream the image of an MJPEG camera to a website in C#?

Timo.Walker
Posted by in C# category on for Intermediate level | Points: 250 | Views : 4999 red flag
Rating: 5 out of 5  
 1 vote(s)

This tutorial will be useful for you if you want to stream you MJPEG camera’s image to a website. After a short review of the technical background full source code is provided for this solution.


 Download source code for How to stream the image of an MJPEG camera to a website in C#?


Introduction


As you may have seen in my previous articles, my interest is in the world of cameras and ONVIF. In this tutorial we will focus another topic that belongs to the field of camera technology.
Lately, I’ve been looking for a good solution that enables me to stream my MJPEG camera’s image to my webpage. Once found a good way to do so , thought it might be useful for you, too, to see how it is achieved. This solution is effective and easy to understand. So, wishing you good reading, have fun and do not hesitate to share your ideas!

Technical background - Glossary

 
Before we get down to coding, let's take a look at some important definitions, you should consider before working on this field.

IP camera: An IP camera can be described as a camera and computer combined in one unit. It is also called ’network camera’. IP camera is a type of digital video cameras. ’IP’ refers to the IP cameras’ characteristics that they can send and receive data over the Internet Protocol.  The main components of an IP camera are the followings:  a lens, an image sensor, one or several processors, and memory. The processors are used for image processing, compression, video analysis and networking functionalities. Like a computer, an IP camera also has its own IP address that is used to connect the device directly to a network (Source [1]).

USB Camera: USB cameras are imaging cameras that use USB 2.0 or USB 3.0 technology to transfer image data. USB Cameras are designed to easily interface with dedicated computer systems by using the same USB technology that is found on most computers (Sourca [2]). 

ONVIF: ONVIF is an open industry forum that is intended to facilitate the development and use of a global open standard for the interface of physical IP-based security products. ONVIF has been established in 2008 by Axis Communications, Bosch Security Systems and Sony with the goal to achieve interoperability between network video products regardless of manufacturer. The keystones of ONVIF are the following: standardization of communication between IP-based video devices; interoperability between IP-based security devices regardless of manufacturer; open to all companies and organizations (Source [3], [4]).

Video streaming: The video streaming functionality makes it possible to stream videos to a webpage by using a server.

RTSP: RTSP is the acronym for Real-Time Streaming Protocol that is a network control protocol designed for use in entertainment and communications systems to control streaming media servers. The protocol is used for establishing and controlling media sessions between end points. The transmission of streaming data itself is not a task of the RTSP protocol. Most RTSP servers use the RTP (Real-time Transport Protocol) in conjunction with RTCP (Real-time Control Protocol) for media stream delivery (Source [5]).

MJPEG: In multimedia, Motion JPEG (M-JPEG or MJPEG) is a video compression format in which each video frame or interlaced field of a digital video sequence is compressed separately as a JPEG image. Originally developed for multimedia PC applications, M-JPEG is now used by video-capture devices such as digital cameras, IP cameras, and webcams; and by non-linear video editing systems (Source [6]).
 

What you need


Now, that the theoretical background is clear, let’s see which hardware and software you need to stream your camera image to your webpage:

Hardware requirements: You will need a PC of course and at least one IP or USB camera as well. (Before programming, make sure that the computer and the IP/USB camera are connected to the same network.)

Software requirements: To implement this solution, Visual Studio (Download link [7]) and .NET Framework 4 (Download link [8]) should be installed on your PC. You also need an SDK that is compatible with the ONVIF standardization. I used Ozeki Camera SDK (Download link [9]) that provides instant ONVIF components for IP/USB camera developments. (Do not forget to add the DLL file offered by the SDK to your references in Visual Studio, and you also need to change your target framework to ’.NET Framework 4.0’.)

Others: In order to connect to a server, broadband Internet connection is also needed.


Code explanation


After you created a new WPF Application in Visual Studio, we can start the actual work. (This is the point where you should add the DLL file to the references.)

Let’s start the work by creating the graphical user interface (GUI) of the application. You can find this part under the .xaml file.

As this application will be able to display and stream the image of both USB webcams and IP (network) cameras, the GUI should contain the following two separate sections: ’Connect to USB camera’ and ’Connect to IP camera’. In both sections there we need 2-2 buttons: ’Connect’ and ’Disconnect’. Thus, a total of 4 buttons are needed.
In the case of USB cameras we only need to have a ’Connect’ button as your PC will look for an available camera when the button is pressed and no additional information is necessary here:
<GroupBox Header="Connect to USB camera" Height="100" Width="150"
HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid>
<Button Name="ConnectUsbButton" Content="Connect" Width="75" Margin="32,19,0,0"
HorizontalAlignment="Left" VerticalAlignment="Top"
 Click="ConnectUSBCamera_Click"/>
 <Button Name="DisconnectUsbButton" Content="Disconnect" Width="75" Margin="32,46,0,0"
HorizontalAlignment="Left" VerticalAlignment="Top"
Click="DisconnectUSBCamera_Click" IsEnabled="False"/>
</Grid>
</GroupBox>
However, in the case of IP cameras, we need to provide the connection data of the camera. We need the IP address of the camera, a username and a password. To provide this information, we need to create three textboxes in this section for the data:
<GroupBox Header="Connect to IP camera" Height="100" Width="387"
HorizontalAlignment="Left" VerticalAlignment="Top" Margin="155,0,0,0">
   <Grid>
<Label Height="25" Width="70" Content="Host"
HorizontalAlignment="Left" VerticalAlignment="Top"/>
<TextBox Name="HostTextBox" HorizontalAlignment="Left" VerticalAlignment="Top"
Height="23" Width="169" Margin="68,2,0,0" TextWrapping="Wrap" />
<Label Height="25" Width="70" Content="Username"
HorizontalAlignment="Left" Margin="0,26,0,0" VerticalAlignment="Top"/>
 <TextBox Name="UserTextBox" HorizontalAlignment="Left" VerticalAlignment="Top"
Height="23" Width="169" Margin="68,29,0,0" TextWrapping="Wrap"/>
<Label Height="25" Width="70" Content="Password"
HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,52,0,0" />
<PasswordBox Name="Password" HorizontalAlignment="Left" VerticalAlignment="Top"
 Height="25" Width="169" Margin="68,56,0,0"/>
<Button Name="ConnectIpCamButton" Content="Connect" HorizontalAlignment="Left"VerticalAlignment="Top"
Margin="267,16,0,0"  Width="75" Click="ConnectIPCamera_Click"/>
 <Button Name="DisconnectIpCamButton" Content="Disconnect" HorizontalAlignment="Left" VerticalAlignment="Top"
Margin="267,43,0,0"  Width="75" Click="DisconnectIPCamera_Click" IsEnabled="False" />
</Grid>
</GroupBox>
Now, we need to create the camera box where the image will be displayed:
<Grid Name="CameraBox" Margin="10,105,10,166"/>
Now we can move on to create the camera box where the image will be displayed. We can do so by employing the .cs file.

Here, we need to add some extra lines: the essential namespaces. Then we add the objects we need to display the image of the IP and USB camera and instantiate them:
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows;
using System.Windows.Media;
using Ozeki.Media.IPCamera;
using Ozeki.Media.MediaHandlers;
using Ozeki.Media.MediaHandlers.Video;
using Ozeki.Media.MJPEGStreaming;
using Ozeki.Media.Video.Controls;

namespace Basic_CameraViewer
  {
public partial class MainWindow : Window
 {
private VideoViewerWPF _videoViewerWpf;

private BitmapSourceProvider _provider;

private IIPCamera _ipCamera;

private WebCamera _webCamera;

private MediaConnector _connector;

private MJPEGStreamer _streamer;

private IVideoSender _videoSender;

public MainWindow()
{
InitializeComponent();

_connector = new MediaConnector();

 _provider = new BitmapSourceProvider();

SetVideoViewer();
After this step we create a helpfunction, which create and set the videoviewer object and add it to the user interface:
private void SetVideoViewer()
        {
            _videoViewerWpf = new VideoViewerWPF
            {
                HorizontalAlignment = HorizontalAlignment.Stretch,
                VerticalAlignment = VerticalAlignment.Stretch,
                Background = Brushes.Black
            };
            CameraBox.Children.Add(_videoViewerWpf);
 
            _videoViewerWpf.SetImageProvider(_provider);
        }  
Now we establish the USB camera connection event handler. Here we create a webcamera object and connect it to the BitmapSourceprovider and then start the camera. Then we implement USB camera disconnection, where we stop the videoviewer and webcamera. In case of an IP camera for the connection we add the camera address, the username and the password, then we can start the camera. The Disconnection happens like at the USB camera:
#region USB Camera Connect/Disconnect
 
        private void ConnectUSBCamera_Click(object sender, RoutedEventArgs e)
        {
            _webCamera = WebCamera.GetDefaultDevice();
            if (_webCamera == null) return;
            _connector.Connect(_webCamera, _provider);
_videoSender = _webCamera;
 
 
            _webCamera.Start();
            _videoViewerWpf.Start();
 
            OnConnectEnabled();
        }
 
        private void DisconnectUSBCamera_Click(object sender, RoutedEventArgs e)
        {
            _videoViewerWpf.Stop();
 
            _webCamera.Stop();
            _webCamera.Dispose();
 
            _connector.Disconnect(_webCamera, _provider);
 
            OnDisconnectEnabled();
        }
        #endregion
 
        #region IP Camera Connect/Disconnect
 
        private void ConnectIPCamera_Click(object sender, RoutedEventArgs e)
        {
            var host = HostTextBox.Text;
            var user = UserTextBox.Text;
            var pass = Password.Password;
 
            _ipCamera = IPCameraFactory.GetCamera(host, user, pass);
            if (_ipCamera == null) return;
            _connector.Connect(_ipCamera.VideoChannel, _provider);
_videoSender = _ipCamera.VideoChannel;
 
            _ipCamera.Start();
            _videoViewerWpf.Start();
 
            OnConnectEnabled();
        }
 
        private void DisconnectIPCamera_Click(object sender, RoutedEventArgs e)
        {
            _videoViewerWpf.Stop();
 
            _ipCamera.Disconnect();
            _ipCamera.Dispose();
 
            _connector.Disconnect(_ipCamera.VideoChannel, _provider);
 
            OnDisconnectEnabled();
        }
        #endregion
Now we get back to user interface to add two textboxes and three buttons that will handle streaming. In the textboxes we add the server data: an IP address and a port number. In this case it will be our IP address and a port number. With the ‘Start’ button we start the server, and with the ‘Stop’ button we stop the server. With the ‘Open in browser’ button we can see our camera image in a browser. For the three buttons we generate three eventhandlers:
<Grid>

<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" Content="IP"/>
<TextBox Grid.Column="1" Name="ipAddressText" HorizontalAlignment="Stretch" Height="30"TextWrapping="Wrap" />
</Grid>

<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" Content="Port"/>
<TextBox Text="554" Grid.Column="1" Name="PortText" HorizontalAlignment="Stretch"Height="30" TextWrapping="Wrap" />
</Grid>

<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Name="StartServerButton" Grid.Column="0" Content="Start"HorizontalAlignment="Center" VerticalAlignment="Center" Width="75" Click="Start_Streaming_Click"IsEnabled="False"/>
<Button Name="StopServerButton" Grid.Column="1" Content="Stop"HorizontalAlignment="Center" VerticalAlignment="Center" Width="75" Click="Stop_Streaming_Click"IsEnabled="False"/>
</Grid>
<Grid>
 <Button Name="OpenInBrowserButton" IsEnabled="False" Click="OpenInBrowserClick" Content="Open in browser" Grid.Column="1" HorizontalAlignment="Left" Margin="77,58,0,0" VerticalAlignment="Top" Width="106"/>
</Grid> 

Now we can deal with the Start button eventhandler. We instantiate the MJPEGStreamer with the IP address and Port number, then connect it to the _videoSender to VideoChannel of the _streamer. Furthermore we subscribe for two streamer events. For ClientConnected and for ClientDisconnected. Now we are to start the server.
In the two eventhandler our only job is two start and stop the streaming.
Finally in the eventhandler of the Stop button we stop the stream and disconnect the _videosender and the VideoChannel of the streamer.
private void Start_Streaming_Click(object sender, RoutedEventArgs e)
        {
            var ip = ipAddressText.Text;
            var port = PortText.Text;
 
            _streamer = new MJPEGStreamer(ip, int.Parse(port));
 
            _connector.Connect(_videoSender, _streamer.VideoChannel);
 
            _streamer.ClientConnected += streamer_ClientConnected;
            _streamer.ClientDisconnected += streamer_ClientDisconnected;
 
            _streamer.Start();
 
            OpenInBrowserButton.IsEnabled = true;
            StartServerButton.IsEnabled = false;
            StopServerButton.IsEnabled = true;
 
        }
 
        void streamer_ClientConnected(object sender, Ozeki.VoIP.VoIPEventArgs e)
        {
            e.Item.StartStreaming();
        }
 
        void streamer_ClientDisconnected(object sender, Ozeki.VoIP.VoIPEventArgs e)
        {
            e.Item.StopStreaming();
        }
 
 
        private void Stop_Streaming_Click(object sender, RoutedEventArgs e)
        {
            _streamer.Stop();
            _connector.Disconnect(_videoSender, _streamer.VideoChannel);
       
After this code is employed, you will see this user interface on your monitor: 


 
The ’Connect’ button on the left can be used to create a connection between your USB camera and your application. The right ‘Connect’ button creates the connection between the IP camera and your application, after providing the necessary data (IP address, username and password) in the textboxes.
Let’s try the application with a USB camera:



After pressing ‘Click’, the USB camera view will be displayed. Under MJPEG Stream Listener Service you can provide the IP address and the port number of the server where you would like to stream the image.
You can get the IP number by running a command prompt and an ipconfig command:


 
After you entered these data, you can connect to the server by clicking on ‘Start’:



After doing so, the service will be started and you can check the result of your work by clicking on ‘Open in browser’:




Conclusion


This article is aimed to provide you with an efficient solution for streaming the image of your MJPEG camera to a website. After a brief theoretical explanation and description you can see the full source code for implementing such a function. On the following websites you can read more about the technologies connected to this topic and you can also find the download links for the necessary software:


References


 

Software requirements


Page copy protected against web site content infringement by Copyscape

About the Author

Timo.Walker
Full Name: Timothy Walker
Member Level: Starter
Member Status: Member
Member Since: 9/11/2014 4:18:57 AM
Country: United Kingdom



Login to vote for this post.

Comments or Responses

Posted by: Skraghava on: 2/22/2015 | Points: 25
This is helpful.

Login to post response

Comment using Facebook(Author doesn't get notification)