Click here to Skip to main content
Click here to Skip to main content

Web-Cam SecureChat

, 12 Mar 2010
Rate this:
Please Sign up or sign in to vote.
This article will explain how to create a simple chat program using this remoting technology, which supports web-cam and sending files.

Introduction

This article explains how to create a simple Secure Chat with WebCam support using Pfz.Remoting.

Background

I've already written some articles about communication, in special Pfz.Remoting and Creating an Asymmetric/Symmetric Secure Stream without SSL, which is in fact part of the remoting DLL. This article will explain how to create a simple chat program using this remoting technology, which supports web-cam and sending files.

I then wanted to create an article explaining how to create a simple multi-user chat but, when I saw AForge and its video capture capabilities, I wanted to create a chat program with web-cam support. In the end, I created a very basic chat, almost without exception handling, but the important part is that it supports web-cam and audio capture with multiple clients.

The Principle

The principle is very simple. Data can be lost. This is not a very big problem for video, it can be for audio, but it is not possible to simple avoid it.

For example, the program receiving the web-cam frames can receive 10 frames, but the client which receives it can only be able to receive 5. Intermediate frames must be lost.

Also, in the architecture I made for this sample, everything goes throught the server. So, the web-cam owner receives 10 frames. The server receives only seven frames. And it can distribute the frames it receives among its clients, which one can be able to receive them all (the 7), another can receive only 3 and another can receive only 5. So, how do we distribute the data?

ActualValueEnumerator and EnumeratorDistributor

I created two main classes that help the distribution of data that "can be lost". The ActualValueEnumerator is a class that "enumerates" throught its values, and waits for new values when all values are already read. But, if two or more values appears before the "enumerator" is able to read them, only the last one (the actual) remains. That's why I called the class ActualValueEnumerator.

In the first version of the article I made the WebCamEnumerator class using ManualResetEvent, but it was ugly. Now it is very simple. So, look at the code:

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using AForge.Video;
using AForge.Video.DirectShow;
using Pfz.Collections;
 
namespace SecureChat.Client
{
	public sealed class WebCamEnumerator:
		ActualValueEnumerator<byte[]>
	{
		private volatile VideoCaptureDevice fDevice;
		public WebCamEnumerator(string monikerString)
		{
			var device = new VideoCaptureDevice(monikerString);
			fDevice = device;
			device.DesiredFrameSize = new Size(160, 120);
			device.NewFrame += p_NewFrame;
			device.Start();
		}
		protected override void Dispose(bool disposing)
		{
			var device = fDevice;
			if (device != null)
			{
				fDevice = null;
				device.SignalToStop();
				device.WaitForStop();
			}
 
 			 base.Dispose(disposing);
		}
 
		private void p_NewFrame(object sender, NewFrameEventArgs eventArgs)
		{
			var image = (Bitmap)eventArgs.Frame;
			
			using(var stream = new MemoryStream())
			{
				image.Save(stream, ImageFormat.Jpeg);
				ActualValue = stream.ToArray();
			}
		}
	}
}

The important things here are: In the constructor, it starts the web-cam and sets the NewFrame event. In the dispose it stops the web-cam. And, in the new frame, it generates the byte array of the image and sets the ActualValue to such bytes. I convert the image to bytes so the server does not need to know how to process graphics... it only receives bytes and distribute bytes to the clients. It may not be "visible" in the first moment, but as this class inherits from ActualValueEnumerator, it can be used in a foreach (must use Pfz.Extensions.FastEnumeratorExtensions and the AsEnumerable method) and it already deals with the possibility of loosing frames.

The server is always a bit more complicated, and I must admit I made it hard. I will try to make it easier and re-update the article, but to help the server be less-complicated I created the EnumeratorDistributor class. Similar to the ActualValueEnumerator, it allows values to be lost. But, instead of being an enumerator itself, it must be used over another enumerator, and each client gets its own enumerator which allows the frames to be lost. So, different speed clients will receive different number of values. So, to use it, the server receives the enumerator from one client (for example, the server receives the WebCamEnumerator from one client), and creates an EnumeratorDistributor over it. Each client that is now interested in such web-cam will get a new enumerator (throught the CreateClient method), which will always receive the last frame from such base enumerator. If frames are to be skipped, they will be.

The project As I said earlier, the server is still more complicated than it needs to be, but the basic idea here is: There is the Common library, in which the classes and interfaces used by both client and server are present. Note that any method the client needs to call in the server or that the client must call in the client must be done via interfaces, which are here.

There is the server project, which supports the client connections and implements the server part, so it is responsible for telling all other clients when a new one connects and to find another client, requests its web-cam or sound-capture device and returning the appropriate enumerator when someone asks for the web-cam or sound from another client. And the client project. It is "simpler" than the server as it does not need to deals with many clients, but it must be able to capture video and sound and must be able to play them. Actually, when one client wants the video or sound from another one, it must request the Server for such information, which will be returned as a IFastEnumerator. The IFastEnumerator is faster than a custom enumerator over the TCP/IP, as instead of first calling "MoveNext" (which sends and receives information) and then Current (which agains sends and receives information) it uses only GetNext, which can return null to tell there are no more values. Well, I hope this little explanation and the source-code is enough for anyone trying to create an application which remote web-cam or sound-capture support.

The Samples

If you want to try the samples, you must:

  • Run the server in command prompt with any parameter (I use the parameter DEBUG), or install it with installutil and then start the service.
  • Run a local client normally, if you want.
  • Change the app.config to point to the server host and run a client from another computer. Having more clients is better.
  • Actually the user-name is taken from the user logged in the system, and this user can't log many times in the same server. Someone must start his own web-cam (be it a fake web-cam or a real one). Then, the others can ask to start that clients' web-cam.

The program supports simple chat and file transfer (drag-and-drop a file over a user name). Dragging a file to your own name will do a really wasteful work of sending the file to the server and then sending the file back to the client.

History

  • 17th December, 2009: Initial post
  • 11th January, 2010: New version of webcam source - This version has corrected a bug in the server, where a client with two webcams will only send the first one for the clients, not importing which one the client asked. Also, it has corrected a bug when sending files with more than 2GB.
  • 12th March, 2010: Added very basic support to sound capture.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Paulo Zemek
Architect
Canada Canada
I started to program computers when I was 11 years old, as a hobbist, programming in AMOS Basic and Blitz Basic for Amiga.
At 12 I had my first try with assembler, but it was too difficult at the time. Then, in the same year, I learned C and, after learning C, I was finally able to learn assembler (for Motorola 680x0).
Not sure, but probably between 12 and 13, I started to learn C++. I always programmed "in an object oriented way", but using function pointers instead of virtual methods.
 
At 15 I started to learn Pascal at school and to use Delphi. At 16 I started my first internship (using Delphi). At 18 I started to work professionally using C++ and since then I've developed my programming skills as a professional developer in C++ and C#, generally creating libraries that help other developers do they work easier, faster and with less errors.
 
Want more info or simply want to contact me?
Take a look at: http://paulozemek.azurewebsites.net/
Or e-mail me at: paulozemek@outlook.com
 
Codeproject MVP 2012
Microsoft MVP 2013

Comments and Discussions

 
QuestionEcho Cancellation Pinmemberdaknu0927-Jan-13 12:57 
QuestionAccessing Remote server Webcam From the Local Machine? PinmemberPawan Kiran28-Aug-12 4:57 
AnswerRe: Accessing Remote server Webcam From the Local Machine? PinmvpPaulo Zemek28-Aug-12 6:24 
GeneralRe: Accessing Remote server Webcam From the Local Machine? PinmemberPawan Kiran25-Sep-12 0:09 
GeneralRe: Accessing Remote server Webcam From the Local Machine? PinmvpPaulo Zemek25-Sep-12 4:14 
GeneralMy vote of 5 PinmemberMember 36979113-Jan-12 13:43 
GeneralRe: My vote of 5 PinmemberPaulo Zemek6-Jan-12 7:48 
Questiontwo video session online and message cannot be sent PinmemberSARP CEVİK4-Jul-11 9:54 
AnswerRe: two video session online and message cannot be sent PinmemberPaulo Zemek5-Jul-11 2:31 
GeneralRe: two video session online and message cannot be sent PinmemberSARP CEVİK5-Jul-11 17:13 
GeneralRe: two video session online and message cannot be sent PinmemberPaulo Zemek6-Jul-11 10:56 
GeneralRe: two video session online and message cannot be sent PinmemberSARP CEVİK7-Jul-11 7:42 
GeneralRe: two video session online and message cannot be sent PinmemberPaulo Zemek7-Jul-11 7:54 
GeneralRe: two video session online and message cannot be sent PinmemberSARP CEVİK9-Jul-11 10:25 
Generalmultiple rooms [modified] Pinmemberhamada el3ashe29-Nov-10 13:26 
QuestionSending a Message after Receiving Pinmemberdythim12-Sep-10 14:16 
AnswerRe: Sending a Message after Receiving PinmemberPaulo Zemek13-Sep-10 15:02 
GeneralRe: Sending a Message after Receiving Pinmemberdythim13-Sep-10 17:10 
GeneralServer go out Pinmembercybertronick24-Apr-10 6:25 
GeneralRe: Server go out PinmemberPaulo Zemek26-Apr-10 10:40 
GeneralRe: Server go out Pinmembercybertronick9-May-10 3:41 
Generalthank you Paulo Zemek ! PinmemberMember 408024115-Mar-10 16:25 
QuestionIs a web version of this application possible? Pinmemberxyzhee2-Mar-10 5:56 
AnswerRe: Is a web version of this application possible? PinmemberPaulo Zemek2-Mar-10 12:04 
GeneralRe: Is a web version of this application possible? Pinmemberdefwebserver6-Mar-10 6:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 12 Mar 2010
Article Copyright 2009 by Paulo Zemek
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid