2. A WPF-based adaptive-streaming video player
Now
we’re going to tell you how to build a WPF-based media player that can
adaptively stream your video. Your media player will look exactly like
the WPF media player displayed in figure 1.
Adaptive streaming is
a technique that most content delivery networks (CDNs) use to deliver
high-performance video. This technique is also used in IIS adaptive
streaming, although BLOB storage won’t deliver in multiple bitrates.
Warning
The following code is
intended as an example to show you how you can use adaptive streaming.
This isn’t production-quality code (not by a long shot).
Playing the Video
The following XAML is used to play the video in WPF:
<MediaElement x:Name="myVideo" Source="videopodcast01.wmv"
LoadedBehavior="Manual"/>
MediaElement is a
built-in control that allows you to play movies in WPF applications. In
this example, we’re downloading the movie (mymovie.wmv) to the same
folder that the WPF movie player application resides in. The source
attribute states where the MediaElement should look for the movie.
By default, the MediaElement
automatically starts playing the movie on startup. Because the movie
hasn’t been downloaded yet, you need to prevent the movie from
automatically playing by setting the attribute LoadedBehavior to Manual.
The Chunking Methodology for WPF
You’re going to download the
movie in chunks of 100 Kb. Only one chunk will be downloaded at a time
and each newly downloaded chunk will be appended to the previously
downloaded chunk. Listing 1 shows that as soon as the movie player is loaded, it starts downloading the chunks. After 10 seconds, the movie starts playing.
Listing 1. Chunking movies with the WPF movie player
Before we look more carefully at the code used to progressively download the video, let’s talk a bit about the Range header.
Using the Range Header
When a GET
request is made using either the storage client or via an HTTP request,
the entire file is downloaded by default. The code shown in listing 2 will download videopodcast01.wmv from the public container, podcasts.
Listing 2. Using the storage client to download a video file
The code in listing 2
will download the entire movie; in this example, we want to split the
movie up into manageable chunks. Currently, the storage client sample
code doesn’t provide the ability to download a specified portion of the
file, even though the underlying REST API does support this. The code
shown in listing 3 will download the entire podcast using HttpWebRequest.
Listing 3. Using HttpWebRequest to download a video file
At , you generate the HttpWebRequest with the standard required headers . At , you use the Download-File method to invoke the request and download the file to disk. The implementation of the DownloadFile method is available in the online samples.
If you don’t want to download the entire video file, you can use the Range
header to specify the range of bytes that you want to download. The
following code would restrict the download to the first 100,000 bytes of
the file, and can be used in listing 3 at :
Not only can you restrict the number of bytes using the Range header, you can also use it to progressively download the file in chunks.
Downloading Chunks of Data
When the WPF movie player was loaded, we made a call to GetNextChunk() in listing 1. In listing 4, we show you how GetNextChunk is implemented, and how to use the Range header to progressively download the movie.
Listing 4. Downloading the data in chunks
The GetNextChunk
method will download 100 Kb of data from the BLOB storage service
asynchronously. This method will be called every time you need to
download a new chunk of video; it’s called for the first time when the
application is loaded in the fourth line in listing 1.
In listing 4, you create a standard HTTP web request at ;
this is the same method that you used to create requests earlier. The
video (videopodcast01.wmv) that you’re downloading resides in a public
container called podcasts that’s held in your storage account. After you’ve created the request, you add the Range header to restrict the download to the next 100 Kb chunk.
At you’re making an asynchronous HTTP web request to the BLOB storage service, with a callback to . On the request callback , the downloaded data is retrieved, and you call the SaveChunk method , which will append the downloaded chunk to the videopodcast01.wmv file on the local disk. Finally, you call GetNextChunk again to get the next chunk of data.
In our simple example, we
used time-based buffering to delay the playback of the movie. Although
time-based buffering is suitable for our example, in a production
scenario you should start playing the movie after a portion of the movie
has been downloaded. We also don’t make any provision for variable
download speeds; you might want to extend the sample to handle
situations in which the playback speed is faster than the download
speed.
|
Now you have a working version of a
WPF progressive-downloading media player, which shows that you can use
BLOB storage as a storage service for desktop clients. With some tweaks
you can build media players that perform similarly to a streaming
service.