Introduction
Working on sites of online television we, as a KB_Soft Group team faced a task of checking channels relevance, which were offered by site visitors for viewing. It is great when there are several thousands of channels on the site and a convenient access to these channels is offered. But it is bad that a half of these channels are invalid. In order to be sure that site visitors are offered actually valid channels for viewing, we needed to make a check of channel states on a regular basis. And it would be nice if such a check would be made automatically — without participation from a human.
Thus, a task of a regular check of channels relevance was formed. In this article I will tell you about one of the most important components of channels check system — StreamChecker
.
This is a module, which checks the state of a specified Media Stream. Media Stream Tester is a small application for testing StreamChecker
functionality. Media Stream Tester is completely ready to use. If you want a simple instrument for checking Media Streams, then Media Stream Tester is exactly what you need. If you need to get information about Media Stream and carry out a custom processing, then you can use the StreamChecker
class in your application. Media Stream source code will serve a good example of how to use the StreamChecker
class, and this article will allow you to understand how this class works.
Background
Media Streams can be different and that is why a “head-on” decision — to write a module, which will connect itself with the stream and check its state, is too laborious. We looked at the task from another point of view — it is required to be able to check the channels which can be played back by a player used by the site (this player is Windows Media Player ®). And we decided that the best way to check the stream is to try to play it back in Windows Media Player ®.
This is how we decided to make it:
- Create an instance of Windows Media Player object (invisible and soundless)
- Give it a command to open and played back Media Stream
- Wait for some time for the stream to open and playback
- Collect maximum of data about a stream
- Close the stream
In order to work with Windows Media Player it is needed to add to assembly a COM reference to Windows Media Player (WMPLib).
- Creating of instance of Windows Media Player is simple:
WMPLib.WindowsMediaPlayer player = new WMPLib.WindowsMediaPlayer ();
player.settings.mute = true;
AutoResetEvent waitEvent = new AutoResetEvent (false);
CheckResult result = new CheckResult ();
player.PlayStateChange += new
WMPLib._WMPOCXEvents_PlayStateChangeEventHandler(
player_PlayStateChange);
The last string of the code is subscribed for an event “state of stream playback changed” in order to be able to know that the stream started to playback. Below, you will see this method code. As soon as the playback started, we set an event in order to abort playback waiting:
void player_PlayStateChange (int NewState)
{
try
{
switch (NewState)
{
case 3:
scanResult.isOnline = true;
waitEvent.Set ();
break;
}
}
catch (Exception ex)
{
MessageBox.Show (ex.Message);
}
}
- This is how to open and playback the stream:
player.settings.autoStart = true;
player.URL = streamURL;
- Stream opening and playback waiting looks like that:
TimeSpan openTimeout = TimeSpan.FromSeconds (10);
int openTimeout = 20;
bool waitResult = waitEvent.WaitOne (openTimeout, false);
if (!waitResult) return result;
TimeSpan readTimeout = TimeSpan.FromSeconds (30);
Thread.Sleep (readTimeout);
- The following data are received about the stream:
canResult.bandWidth = player.network.bandWidth;
scanResult.bitRate = player.network.bitRate;
scanResult.frameRate = player.network.frameRate;
scanResult.encodedFrameRate = player.network.encodedFrameRate;
scanResult.framesSkipped = player.network.framesSkipped;
scanResult.receivedPackets = player.network.receivedPackets;
scanResult.recoveredPackets = player.network.recoveredPackets;
scanResult.lostPackets = player.network.lostPackets;
scanResult.receptionQuality = player.network.receptionQuality;
scanResult.sourceProtocol = player.network.sourceProtocol;
scanResult.imageSourceWidth = player.currentMedia.imageSourceWidth;
scanResult.imageSourceHeight = player.currentMedia.imageSourceHeight;
- The stream is closing like that:
player.close ();
Comments to Use
This method presupposes interacting with the User's desktop, that is why it is unsuitable for use in services. It is necessary that a message handling loop would be in the application. Also, it was discovered during testing, that simultaneous scanning of several stream causes fatal errors in Media Player. That is why it is advisable to refuse multithreaded channel checks.
References
- This page contains the latest version of this article and the C# implementation of the class described in the article.
History
- 15 October, 2008 -- Original version posted.