Coding Security Camera Monitoring Software – Part 1

Introduction

I’ve got a few CCTV cameras (security cameras for those of your not from these shores) outside my house and never have an eye on them.  I recently got a spare 15” monitor and thought it would be a good idea to monitor them.  I wanted some software that could just show me the four different CCTV feeds, let me click on them toggle between single-camera-maximised and all-four-cameras view and work reliably.  I also didn’t want to spend any money and wanted it to be a completely full-screen interface rather than looking like an ugly, dated Windows application.

Rather than trying to find something off the shelf I thought this would be a fun and quick project for me to tackle myself.

A quick investigation of my cameras shows that they are all capable of providing a HD video stream over the RTSP protocol – as is the case with many cameras.  A quick test and VLC could connect to the cameras and play the video streams back to me.

I wanted to do the development for this using WPF in C# as it would be very quick to do – the only downside is the off-the-shelf video components don’t support RTSP streaming and a quick look at a few free RTSP components didn’t seem to work fantastically (they eventually lagged rather than gracefully handling dropped frames).

The easiest to do this felt like using VLC’s software development kit to interface with C#.  A couple of quick tests and I found a mostly-working library and put it all together.  An hour later and voila a custom piece of security camera monitoring software.

Part 1: The Basics

In this post, I will talk through how to create the basics of the software.  I will assume familiarity with software development and just run through the general concepts and settings.  The video at the top of this post talks through the entire process step-by-step if you want to follow it in more detail.  Please note that this is not following code or architecture best practices – view models are very much absent here, this is a quick-dirty-hack approach to the solution rather than what I’d expect this to be commercially.  It works but there’s a fudge-factor about it – so let us begin.

  1. Create a new WPF project in Visual Studio
  2. Rename MainWindow to VideoStreamWindow in the XAML, code-behind and in App.xaml
  3. Add a NuGet package reference to Vlc.DotNet.Forms
  4. Add a reference to WindowsFormsIntegration system assembly
  5. Add six values in your App.Config for
    1. CctvFeed1 -> CctvFeed4 (containing the URLs for the CCTV feeds)
    2. VlcFolder (which should be the path to your VLC’s installation containing libvlc.dll)
    3. DisplayMonitor (a number indicating which monitor the application should appear on with 0 for the first monitor)
  6. In the VideoStreamWindow XAML file
    1. Set the Title to be “CCTV Monitor”
    2. Set ResizeMode to “CanResize” (we will prevent this being moved later in cod)
    3. Set WindowState to “Normal” (we will set this to maximised later in code)
    4. Set Background to “Black”
    5. Set the content of the window to be a single grid with 2 rows and 2 columns – the width and height for both row and column definitions should be *
    6. Place four WindowsFormsHost controls inside the grid – one in each of the grid sections. These should be named formsHost1 to formsHost4
    7. Set the Focusable property to False on the window, the grid and all the WindowsFormsHost controls
    8. Set the Loaded event and create a new empty event handler called OnLoaded.
  7. If you run it at this point you’ll just have a black window. You’ll notice we haven’t setup the video feeds yet – we need to do this in code.  If we setup the VLC.Net control through XAML then we must hardcode where LibVLC is installed which isn’t great so we have to do some workarounds and do this programmatically.
  8. Open the VideoStream code behind file
    1. Create a class-level private variable of type WindowsFormsHost[] called _formsHost with a size of 4 – we will store our WindowsFormsHost controls in here so that we have a way to access them numerically rather than by name.
    2. Create another private variable of type VlcControl[] called _vlcControls with a size of 4 and add the appropriate namespaces (Vlc.DotNet.Core and Vlc.DotNet.Forms).
    3. In the constructor set _formsHosts[0] equal to formsHost1, _formsHost[1] to formsHost2 and so on
    4. Add the following for loop which sets up each of the VLC video playback controls. They are created, setup with the configuration file value for the LibVLC path, added to the array we just created and then placed into the corresponding WindowsFormHost.  All of the event handlers created should be left empty for now.Edited: 26/Mar/2017 – A reader has commented that VlcLibDirectory is no longer supported and that OnVlcLibDirectoryNeeded() event is used instead.  I have not tested this but please see the VLC.Net documentation for information which will change a single line below.

      // Create VLC controls for our four camera feeds
      for (int i = 1; i <= 4; i++)
      {
      // Get a handle to the forms host to put this video feed in
      WindowsFormsHost host = _formsHosts[i – 1];

      // Create our VLC control along with VLC Folder config and pop it in our array
      VlcControl control = new VlcControl { VlcLibDirectory = new DirectoryInfo(ConfigurationManager.AppSettings[“VlcFolder”]), Tag = i };
      _vlcControls[i – 1] = control;

      // Hookup to VLC control events
      EncounteredError += OnStreamError;
      control.MediaChanged += OnStreamMediaChanged;
      control.Playing += OnStreamPlaying;
      control.Opening += OnStreamOpening;
      control.Stopped += OnStreamStopped;

      // Set this control as a child
      host.Child = control;
      }

  9. Run the application again and this time you should see not a lot different – we have the video controls added but haven’t told them to play yet.
  10. Go back in to the VideoStream code behind file
    1. Setup the OnLoaded method with the code below to instruct each VLC control to finish initialising once the window is loaded and to then have the playback URL set to the one defined in the config (if a value is found). The EndInit() call is required because we setup the controls programmatically rather than directly in the WindowsFormsHost.

      // Setup our VLC controls
      for (int i = 0; i < _vlcControls.Length; i++)
      {
      VlcControl control = _vlcControls[i];
      EndInit();
      string feed = ConfigurationManager.AppSettings[“CctvFeed” + (i + 1)];
      if (string.IsNullOrEmpty(feed))
      continue;
      control.SetMedia(new Uri(feed));
      }

    2. Finally let’s modify the OnMediaChanged event that we have and start playback with this single line of code:SetStatusMessage((int)((VlcControl)sender).Tag, “Media changed…”);
  11. Start your application again and this time you will see four different video feeds showing your CCTV cameras!

So here we have an application showing four cameras.  It has no labels, no controls and not a lot else but you do now have four security camera images!  This feels like a great point to end part 1.

Coming Up Next Time…

The remaining parts of this video will cover adding overlay text on top of the cameras with the feed’s name, having status text to show when a feed is opening or in an error state and to also have a way to retry failed feeds and to toggle whether a feed is maximised or not.  All of this requires working on top of the video feed.

We haven’t encountered it here but there is an issue with the Vlc.Net control used from within WPF in that nothing can be layered on top.  There are a few ways to solve it from directly integrating with LibVLC, working solely within the WinForms domain or capturing individual VLC windows and controlling them remotely – all of that sounds like a lot of hassle though so next time we’ll discover some dirty hacks to work around this which will invalidate all sensible object oriented principles.

I look forward to seeing you then!

Advertisements

2 thoughts on “Coding Security Camera Monitoring Software – Part 1

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s