Video streaming using Windows Media Services (Part 1)

This post talks about unicast and on-demand streaming of a video.

On-demand unicast is the way when you would like the clients to have control on the playback and require only one server connection per client. The user experience here is similar to playing a movie from a DVD player where you would be able to pause, rewind, fast-forward the media content unlike the broadcast multicast/unicast where the user has no choice to control the playback.

To deliver content to users by using a streaming method, you can save the content to a Windows Media server, and then assign the content to a publishing point. You can then provide users with access to the content by either creating an announcement file or by supplying users with the URL of the publishing point.

image

In the figure, there is an on-demand publishing point named TV1 on the Windows Media server called Server1. This publishing point identifies the location of the content you want to stream.

Windows Media Services requires no additional configuration and is ready for on-demand streaming. All you need to do is place the file that you want to stream in the default Windows Media Services content directory. The file can be either a Windows Media file or an .mp3 file. A Windows Media file is a file containing audio, video, or script data that is stored in Windows Media Format (file name extensions, such as .wma, .wme, .wms, .wmv, .wmx, .wmz, or .wvx)

  • Copy the file to the %systemdrive%\Wmpub\WMRoot folder on your Windows Media server. Your server is now ready to stream the file.

After installing the Windows Media Services 2009, if you start the control panel and check the ‘Control Protocol’ option,  by default the only enabled option is RTSP (Real Time Streaming Protocol)  So basically your streams would respond to a mms://<url> link for you and open in Windows Media Player or something that plays back that media. Microsoft Media Server (MMS) is the name of Microsoft’s proprietary network streaming protocol used to transfer unicast data in Windows Media Services. To get your stream play in Silverlight, you have to enable the HTTP-based streaming. Silverlight basically looks at the mms:// <url> and translates that to get the stream over HTTP instead. The default port 80 might already be taken by IIS.  Right click on the HTTP control protocol and choose properties, then choose the IP addresses and/or the port you want it to operate on.  Save those settings and then enable the protocol.

To become more familiar with Windows Media Services capabilities, take the tour here. Start >> Run and then type %systemroot%\system32\windows media\server\admin\mmc\hta\tour_.hta

To start the Windows Media Services management interface and configure your streaming media server, Start >> Run and then type %systemroot%\system32\windows media\server\admin\mmc\wmsadmin.msc

More details about streaming can be obtained here:

 

Customizing Silverlight install experience

If you do not have Silverlight plug-in installed in your browser, the default experience is the Install Microsoft Silverlight message flashed on your screen.

sl2

The highlighted portion of the html file is actually responsible for this. If you want to customize this message to tell the user why he needs Silverlight and how does it improve his viewing experience, you need to fiddle with this code. The same can be achieved also by inserting the <PluginNotInstalledTemplate> piece into the aspx page.

sl1

 

 

 

 

 

 

 

 

 

sl3 

If you already have Silverlight installed, to test this out, just disable the add ons

AddOns-2 AddOns-1

CREATE AGGREGATE failed because type concatenate does not conform to UDAGG specification due to method ‘Accumulate’.

Please follow these steps to solve the issue:

1. Open the project in Visual Studio

2. Click on the project properties

3. Go to the Database tab and click on the browse button next to the connection string. You will get the Add Database Reference dialog.

Step 1

4. Click on Add New Reference

Step 2

5. In the New Database Reference dialog, enter the details for the database where you want to deploy the assembly and create the user defined aggregate.

Step 3

6. Now drop and reregister the assembly and then create aggregate function in the database you want.

User defined aggregate function in SQL Server 2005

Find here the list of SQL Server aggregate functions.

Create a SQL Server project in Visual Studio 2005 or above. While creating the project provide the database information where you want to register the aggregate function.

Create Project

To create an aggregate function to concatenate the values of a column to a comma separated value, use the following code. Take a look at this article for more information on the methods a user defined aggregate must implement.

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[SqlUserDefinedAggregate(
Format.UserDefined, //use clr serialization to serialize the intermediate result
IsInvariantToNulls = true, //optimizer property
IsInvariantToDuplicates = false, //optimizer property
IsInvariantToOrder = false, //optimizer property
MaxByteSize = 8000)]//maximum size in bytes of persisted value

 

public class Concatenate : IBinarySerialize
{
/// <summary>
/// The variable that holds the intermediate result of the concatenation
/// </summary>
private StringBuilder intermediateResult;

/// <summary>
/// Initialize the internal data structures
/// </summary>
public void Init()
{
this.intermediateResult = new StringBuilder();
}

/// <summary>
/// Accumulate the next value, not if the value is null
/// </summary>
/// <param name=”value”></param>
public void Accumulate(SqlInt32 value)
{
if (value.IsNull)
{
return;
}

this.intermediateResult.Append(value.Value.ToString()).Append(‘,’);
}

/// <summary>
/// Merge the partially computed aggregate with this aggregate.
/// </summary>
/// <param name=”other”></param>
public void Merge(Concatenate other)
{
this.intermediateResult.Append(other.intermediateResult);
}

/// <summary>
/// Called at the end of aggregation, to return the results of the aggregation.
/// </summary>
/// <returns></returns>
public SqlString Terminate()
{
string output = string.Empty;
//delete the trailing comma, if any
if (this.intermediateResult != null
&& this.intermediateResult.Length > 0)
{
output = this.intermediateResult.ToString(0, this.intermediateResult.Length – 1);
}

return new SqlString(output);
}

public void Read(BinaryReader r)
{
intermediateResult = new StringBuilder(r.ReadString());
}

public void Write(BinaryWriter w)
{
w.Write(this.intermediateResult.ToString());
}
}

To enable SQL Server for CLR integration, click Start > Programs > Microsoft SQL Server 2005 > Configuration Tools > SQL Server Surface Area Configuration

SQL Server 2005 Surface Area Configuration

Click on Surface Area Configuration for Features, choose the CLR integration and check the Enable CLR integration option.

SQL Server 2005 Surface Area Configuration

How to register the assembly in SQL Server 2005

CREATE ASSEMBLY StringUtilities FROM ‘<file path>’
GO
CREATE AGGREGATE CONCAT (@input NVARCHAR(200)) RETURNS NVARCHAR(MAX)
EXTERNAL NAME StringUtilities.Concatenate
GO
GRANT EXEC ON dbo.CONCAT TO PUBLIC
GO

Usage:

For example, below is Table1. A query on Table1 like this SELECT Column1, Column2, CONCAT(Column3) FROM Table1 GROUPBY Column1, Column2 would return a result set A,B,’1,6’.

Column 1 Column 2 Column 3
Row 1 A B 1
Row 2 A B 6

Applying style to a grid view row

In the RowDataBound event of the grid view add this

e.Row.Style [ "border-top" ] = “3px solid Green”;

The code below applies the border style on all borders of the row.

e.Row.BorderStyle = BorderStyle.Solid;
e.Row.BorderWidth = new Unit(3);
e.Row.BorderColor = System.Drawing.Color.Green;

Identity of the check box in a grid view which triggered a post back

In the checkedchanged event, you can obtain the identity of the check box in the grid view that raised the event.

CheckBox check= (CheckBox)sender ;
GridViewRow row= (GridViewRow)check.NamingContainer ;
int rowIndex = row.RowIndex;

Tool tip for drop down list items

To provide tool tip for the drop down list items, after binding the drop down list to a data source, loop through the items and set the title attribute.

for (int count = 0; count < ddList.Items.Count; count++)
{
ddList.Items[count].Attributes.Add(“title”, ddList.Items[count].Text);
}

But if

  • you are using an object data source to directly bind your drop down
  • you have too many drop downs in your page
  • your drop down lists are inside a grid view

a better way to implement the same is to have your master page identify the drop down controls and set the title attribute in all the pages using the master page.

protected void ContentPlaceHolder_PreRender(object sender, EventArgs e)
{
BindTooltip(ContentPlaceHolder.Controls);
}

___________________________________________________________

You may put the following code in a Helper / Utility class file.

public static void BindTooltip(System.Web.UI.Page page)
{
if (page == null || page.Form == null)
return;
BindTooltip(page.Form.Controls);
}

___________________________________________________________

public static void BindTooltip(ControlCollection ctrlCol)
{
try
{
if (ctrlCol == null)
return;
for (int count = 0; count < ctrlCol.Count; count++)
{
try
{
Control control = ctrlCol[count];
if (control.HasControls())
{
BindTooltip(control.Controls);
}
else
{
if (control.GetType().IsSubclassOf(typeof(ListControl)))
{
ListControl listControl = (ListControl)control;
BindTooltip(listControl);
}
}
}
catch { }
}
}
catch (Exception ex) { }
}

___________________________________________________________

public static void BindTooltip(ListControl listControl)
{
for (int itemCount = 0; itemCount < listControl.Items.Count; itemCount++)
{
listControl.Items[itemCount].Attributes.Add(“title”,listControl.Items[itemCount].Text);
}
}

Case sensitive search in a SQL query

If you have duplicates in your table and you want a specific entry you might want to do a case sensitive search. Looking up for matching username and passwords might be another instance.

Search for a name ’Amy’  in a table ‘Contacts’  among duplicate entries like ‘Amy’, ‘amy’, ‘AMY’.

DECLARE @strName VARCHAR(10)
SET @strName = ‘Amy’
SELECT * FROM contact WHERE CAST([Name] AS VARBINARY(10)) = CAST(@strName AS VARBINARY(10))

Primary key reset in SQL Server

To reset the primary key of a table with auto primary key set in SQL Server

To start from 1

DBCC CHECKIDENT(‘<tablename>’, RESEED, 0)

To start from a specific number, say n

DBCC CHECKIDENT(‘<tablename>’, RESEED, n-1)

SQL Server setup issue

Issue :

SQL Server Setup failed to obtain system account information for the ASPNET account. To proceed, reinstall the .NET Framework, and then run SQL Server Setup again.

Solution:

1. Open Visual Studio Command Prompt

2. Run this command aspnet_regiis -i

ss

-i option installs the version of ASP.NET that is associated with Aspnet_regiis.exe. Click here for more information on the ASP.Net IIS registration tool

Follow

Get every new post delivered to your Inbox.