Real Time Stereoscopic Streaming

Appendix

A custom file type: .rml

The first appendix we made on this project was the definition of a custom file type for the media player. Rml, or remote media location is a type of file referencing a stream server.
The file cannot be easier: it is a mere text file containing the following information:

– Simple header
– Hostname or IP address
– Remote port, or which TCP port the client is supposed to connect
– The local RTP port which will receive the raw data transmitted by the server.

Here below is an instance of rml file:

FRML=1.0 header
host=192.168.11.3 hostname or ip
remote_port=1200 remote port
local_port=1201 local port

Then, to register this custom type, we needed to add the following entry in the registry base:
{HKEY_CLASSES_ROOT\Media Type\Extensions\.rml\Source Filter}
Containing {CF5604E6-7126-462a-BE47-E432383B9243}.

This big string is actually the GUID of the RTP receiver filter.
So if a user tries to open a “.rml” file, the windows media subsystem will automatically use this filter. Then it was really easy to do a “media player like” software which could play every file the media player can play, including “.rml” files.

Web Server & Web notification

Another improvement of the original project was the web publication of streams. Basically, it started from the idea to make a little tutorial about how to use a TWTCPSERVERSOCKET, which is a class of the TeapotWare SDK.
A web server is nothing more than a TCP server that can send files over the network. So we made this little server using TeapotWare, in about one hour and half. Then, we started thinking about the dynamic part: since it was not so hard to build a C++ web server, what about improving it to allow dynamic pages? Since we had a lot of time at this moment of the project, we decided to start digging the idea. 2 hours later, we had a basic support of a C++ equivalent of Java servlets.

The advantages of this kind of server are simple: rapidity and security. With a normal application server, or even a servlet engine like Tomcat, if a hacker can access the hard disk of the server, then he can un-compile every java class, and understand clearly, for instance, how the database is structured. In addition, he could create himself a little security backdoor to allow him… more than a normal user could do.
To sum up, a hacker who could access the hard disk of the server can feel at home.
With our approach, the equivalent to the servlet are kind of C++ compiled DLL. Even if someone could access to this kind of file, it would take quite a lot before he could understand what is doing this file, and indeed how the database is accessed.
In addition, java is much slower than C++, particularly in the case of system calls, so the difference of speed is appreciable. The main reason web developers use java instead of C++ is that they need a code running on any kind of OS, which is also true with TeapotWare, and because java provides much more helper functions than C++, but TeapotWare also provides helpers…
It may sound like this is an idea solution, but this SDK is still in development, and the model I proposed is not as complete as real servlet. However, since it worked well enough to handle this part, we used it for the web notification system of the project.

Servlet-like modules

A TW module is quite easy to create. The programmer merely needs to create a dynamic library, and to write a class inheriting from TWSRVMOD.

class PubStream : public TWSERVMOD
{
private:
void MakeRML(STREAM *strm);
int fref;
TWREFCOLLECTION streams;

public:
PubStream();
~PubStream();

void OnGet(TWSOCKET *s,TWPROPERTYBAG *pb);
};

DECL_TWMODULE(PubStream);

The only method to be overloaded is OnGet. Is directly receive the connected socket, and the property bag contains all the data passed as parameter. For instance, for
www.myserver.com/testservmod?x=15&y=hello, the property bag will contain 2 entries, x and y, having for value respectively 15 and hello.

Another important thing to do is to provide a default constructor, and to specify the URL that has to be mapped on the servlet-like module. In the case of the example,

PubStream::PubStream()
{
fref=0;
targeturl="pubstream.htm";
}

Web server

We won’t talk a lot about the server here, because it is quite easy to understand. Globally, it opens a TCP connection as server, and creates a new thread for every incoming connection. Then once this process is done, it will merely process incoming requests, as illustrated below.

The web server procedural diagram

How to use the server with our application

Now knowing that we could use a dynamic web server, it was quite easy to add the notion of public streams to the main sender application. Every user is not familiar with IP addresses, nor port number, so the main idea was to simplify the “asking for information” task.
In order to work, the sender application only needs a port number. This port will be used for a TCP connection in order to transmit media types. On the other hand, the receiver needs 3 informations to work properly: the host address, its TCP port number, and a local port number that will be used to receive RTP data.
In order to make it easier, we settled a notion of public stream. In the sending application, there is a check box and a text field. If the user fill in those fields, then the sender will also connect a servlet-like module to register a stream. Anyone connected to the website will be able to see all the required informations to connect the stream sender. In addition, a .rml file will be created by the servlet-like module, and everyone will be allowed to download this file, which, as explained before, contains everything for connecting a remote stream.
And since this kind of file is registered, and can be opened with our RTP receiver filter, then almost every media-player compatible players will be able to open it directly. To sum up, the final user will only be required to visit a web page in order to display a video.


On this screenshot we can see the entire process: first, a sender application binds 2 streams to 2 different ports. Both streams are defined as “public”, and a short description is given. So before listening for stream client, the application will notify the web server about those 2 streams. (The black window is the web server).
As we can see, any web browser can access the dynamic web page generated by the servlet-like module. This page displays the IP address of the sender, the port used, and the short description. If the user click on the IP address, then the web server will send a .rml file, which can be read directly by an appropriate player, or by the main receiver software. So the final user just needs to open Internet Explorer or another web browser and to click on the stream he wants to see.

NSIS Installers

For this project, we had to develop many applications. Since those applications were most of time using the same methods, we made all those applications using Dynamic Linked Libraries, or DLL.
In addition, our custom file type needed to be registered else the Windows media subsystem will be unable to associate it with our RTP source filter.
Finally, filters are Windows components, and as almost every Windows component, they require to be registered as well.

Knowing that we might need to modify the registry base several times, using an installer rather than a compressed archive, like zip, in order to copy our application was a natural idea.

NSIS, or NullSoft Installer System has the advantage to be free, and a script based installer builder. So here below are the results we got after writing several lines of script:


The script

The compiler

The final result

TeapotWare

TeapotWare is the name of an open source SDK. Being the main author of this software framework, I used it as possible for this project. The point of this SDK is to allow programmers to write cross-platforms code dealing with advanced multimedia processes.
It covers many fields, like networking, mathematics, 3D, media streaming, and is a module-based SDK, which means that changes can be done easily and without any influence for the programmer using TeapotWare.
Here below is a sample, to illustrate how simple it is to use this SDK:


int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hInstP, LPSTR lpCmdLine, int nCmdShow)
{
TWMODMANAGER mgr;
TWMEDIASTREAM *stream;
TWSTREAMMOD *strmmodl
strmmod=(TWSTREAMMOD*)mgr.LoadMod("twstream.twm"); //easiest way to load a module
strmmod->Init(); //initialize the module
stream=(TWMEDIASTREAM*)strmmod->GetVideoStream(0); //retrieve the 1st webcam
stream->Init(); //initialize the webcam
stream->SetOutput(1200,1201); //bind the stream to the ports 1200 & 1201 stream->Play(); //play the stream (threaded)
TWSTRING str=“”;
std::cout<<“Type exit to quit” while(str!=“exit”) std::cin>>str; //main loop
stream->Stop();
strmmod->ReleaseStream(stream);
strmmod->Release();
mgr.Release();
return 0;
}

This example illustrates particularly the effectiveness of TeapotWare. Only 20 lines for this example, but it will use the data of the 1st connected webcam. TV card, or any connected device, and be a stream server for the generated video. So anyone can connect the port 1200 of this machine, and if the application is running, the video will be sent over the network, using RTP protocol.

Leave a Reply

Your email address will not be published. Required fields are marked *