3. A Silverlight-based chunking media player
We
showed you how to build a desktop progressive-downloading media player
for video podcasts. Although the desktop application is great for that
richer client experience, we also want to show you how to provide a
web-based cross-platform Silverlight experience.
Chunking Video in Silverlight
Go back to the Silverlight player that you created earlier and modify the XAML to the following:
<MediaElement x:Name="myVideo" AutoPlay="False"/>
Although the XAML is similar to the WPF version, there are some subtle differences. In the Silverlight version, you use AutoPlay="False" to specify that you don’t want the video to play automatically; in the WPF version, you set LoadedBehavior="Manual". You’re also not going to set a source for the MediaElement; you’ll do this programmatically in the code-behind.
Listing 5 shows the On_Load event of the Silverlight media player.
Listing 5. On_Load event of the Silverlight media player
At the code calls GetNextChunk to start downloading the chunks of data and at playing the video is delayed for 10 seconds by sending the thread to sleep. At the video starts playing back from isolated storage.
Warning
Sending the thread to sleep is
bad production practice. You should never send the UI thread to sleep.
In production, use a background timer that monitors the download
progress, and start playing the video back at a suitable threshold.
The Chunking Methodology for Silverlight
You’ll use the same
methodology to chunk the data that you used in the WPF example. You’re
going to split the data into manageable chunks and then stitch the
chunks back together client-side.
The
browser plug-in model prevents the use of certain request headers
because they’re considered reserved and are available only to the
browser. The following restricted headers are used by BLOB storage APIs
and are unavailable to use in Silverlight: Authorization , Date (you can use x-ms-date as a workaround), and Range (you can use x-ms-range as a workaround).
|
Although you could split the files using the x-ms-range header (instead of using the Range
header as you did in the WPF version), it might be kind of interesting
to presplit the files into chunks and store the chunks in BLOB storage.
To split the files, use the
same code that we used in the WPF example, but instead of stitching the
file back together, you’re going to save a separate file for each chunk.
For example, the file VideoPodcast01.wmv would be split into the
following chunks: VideoPodcast01_1.wmv, VideoPodcast01_2.wmv, . . .,
VideoPodcast01_12.wmv.
Finally, you need to upload each chunk to BLOB storage using a tool like Chris Hay’s Azure Blob Browser.
Tip
By presplitting the
files, you can potentially distribute the files across a greater number
of servers (or even domains). Distributing files in this way would be
useful if you decided to use a content delivery network (CDN) in combination with BLOB storage. You could also
instruct the browser to cache the chunks; if the file wasn’t fully downloaded, the next download would be much quicker.
To use the presplit version
of the chunks, your Silverlight application needs to use the following
code to replace the WPF version of the GetNextChunk method:
private void GetNextChunk()
{
string baseUri = @"http://silverlightukstorage.blob.core.windows.net/";
string videoUri = baseUri+"podcasts/videopodcast01_"+nextRange+".wmv";
nextRange++;
HttpWebRequest hwr =
CreateHttpRequest(new Uri(videoUri), "GET", new TimeSpan(0, 0, 30));
hwr.BeginGetResponse(new AsyncCallback(webRequest_Callback), hwr);
}
This code manually requests the
chunk that’s stored in your container by continually incrementing the
chunk in the URI for each download request.
The major difference between
this example and using adaptive streaming is that we don’t have multiple
encodings of the video at different bitrates. You could easily modify
these samples to have videos encoded at different bitrates available and
to detect the best bitrate for the client.
Saving to Isolated Storage
Silverlight
can directly access the filesystem only via a user-initiated action.
Silverlight applications can, however, write data directly to an
isolated storage area without user initiation.
If you don’t mind user-initiated actions, you can always use the SaveFileDialog rather than isolated storage.
You need to be aware that if
you’re downloading files of any real size, you’ll probably need a
user-initiated action to increase the isolated storage default limits.
In this case, you’d probably do just as well to use the SaveFileDialog.
|
In the Silverlight version of
the media player, you’re going to use the isolated storage area to save
the video locally. Although the video podcast has been presplit into
chunks, you still have to combine the chunks into a single file so the
media player can play back the video. The method of saving and combining
the chunks is similar to that used in the WPF version except that
you’re using isolated storage. Listing 6 shows the Silverlight version of SaveChunk.
Listing 6. SaveChunk for Silverlight
Although you’ve had to do some slight workarounds, now you’ve got a working version of the media player in Silverlight.
Congratulations! You’ve
built a WPF video player and a Silverlight video player. Now let’s look
at how you can improve the performance of the video delivery by using
content delivery networks (CDNs).