KB_Soft Group - Software Vendor's Development Partner
Start page
Site map
Contacts
   

 

   

Introduction

Working on sites of online television we, as a KBSoft 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 is invalid. In order to be sure that site visitors are offered actually valid channels for viewing, it was needed to make a check of channels state on a regular basis. And it would be nice if such a check would be made automatically � without participation of 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 StreamChecker class in your application. Media Stream source code will serve a good example how to use StreamChecker class, and this article will allow 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 demanded 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).

1) Creating of instance of Windows Media Player is simple:
WMPLib.WindowsMediaPlayer player = new WMPLib.WindowsMediaPlayer ();            
player.settings.mute = true;	//switch off a sound
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: // The current media item is playing.

                scanResult.isOnline = true;
                waitEvent.Set ();
                break;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show (ex.Message);
    }
}


2) This is how to open and playback the stream:
player.settings.autoStart = true;
player.URL = streamURL;

3) Stream opening and playback waiting looks like that.
//
// We are waiting for the start of playback for 10 seconds.
//

TimeSpan openTimeout = TimeSpan.FromSeconds (10);
int openTimeout = 20;
bool waitResult = waitEvent.WaitOne (openTimeout, false);

//
// It was impossible to play the stream back.
//

if (!waitResult) return result; 
//
// Playingback the stream for 30 seconds, in order to collect statistic.
//

TimeSpan readTimeout = TimeSpan.FromSeconds (30);
Thread.Sleep (readTimeout);

4) The following data are received about the stream.
//
// ##Bandwidth.
//
canResult.bandWidth = player.network.bandWidth;                   

//
// ##Bitrate.
//
scanResult.bitRate = player.network.bitRate;                    

//
// ##The frameRate property retrieves the current video frame rate in 
// frames per hundred seconds. For example, a value of 2998 indicates 
// 29.98 frames per second.
//
scanResult.frameRate = player.network.frameRate;                    

//
// The encodedFrameRate property retrieves the video frame rate 
// specified by the content author in frames per second
//
scanResult.encodedFrameRate = player.network.encodedFrameRate;                    

//
// The framesSkipped property retrieves the total number of frames 
// skipped during playback.
//
scanResult.framesSkipped = player.network.framesSkipped;                    

//
// The receivedPackets property retrieves the number of packets received.
//
scanResult.receivedPackets = player.network.receivedPackets;                    

//
// The recoveredPackets property retrieves the number of recovered 
// packets.
//
scanResult.recoveredPackets = player.network.recoveredPackets;                    

//
// The lostPackets property retrieves the number of packets lost.
//
scanResult.lostPackets = player.network.lostPackets;                    

//
// The receptionQuality property retrieves the percentage of packets 
// received in the last 30 seconds.
//
scanResult.receptionQuality = player.network.receptionQuality;                    

//
// The sourceProtocol property retrieves the source protocol used to 
// receive data.
//
scanResult.sourceProtocol = player.network.sourceProtocol;                    

//
// The imageSourceHeight property retrieves the height of the current 
// media item in pixels.
//
scanResult.imageSourceWidth = player.currentMedia.imageSourceWidth;                    

//
// The imageSourceWidth property retrieves the width of the current 
// media item in pixels.
//
scanResult.imageSourceHeight = player.currentMedia.imageSourceHeight;


5) The stream is closing like that.
player.close ();

   

Comments to use

    This method presupposes interact with User 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 from multithreaded channels check.