Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

DownloadProgress, DownloadProgressOffset, and BufferProgress of the MediaElement

0.00/5 (No votes)
24 Dec 2013 1  
This article is about the DownloadProgress, DownloadProgressOffset, and BufferProgress of the MediaElement.

MediaElementDownloadProgress

Introduction

This article is about the DownloadProgress, DownloadProgressOffset, and BufferProgress properties of MediaElement.

Background

I was working with MediaElement as I had a requirement to play a video from an HTTP URL. I encountered a strange issue. In a normal scenario, MediaElement’s DownloadProgress property updates a UI progress bar. It works correctly while downloading and the DownloadProgress increases. But, when the user clicks another position in the file, the DownloadProgress value becomes 1.0 (100%) and the same with DownloadProgressOffset. After some time, it corrects itself. You can find this same issue at the following link: http://silverlight.net/forums/p/69162/167219.aspx.

Before explaining the issue, let me explain some definitions that I would use to explain the issue in showing the DownloadProgress and the DownloadProgressOffset.

Byte Range Request

HTTP requests have an option to do a partial content range request. To explain it, let’s take a scenario. Say, I want to request a very large file from a service, but before I do so, I want to find out exactly how large it is and whether the service supports “range requests”. To do this, I make a HEAD request to the large resource I want to retrieve. The HEAD method is a standard HTTP method that acts as if I’ve made a GET request, but it returns only the headers and not the body. This allows me to find out information about the resource without actually taking the time or using the bandwidth to download it. For example, I can read the Content-Length header and determine the size of the resource.

Another header of great importance is the Accept-Ranges header. If it’s present, it may contain a value “bytes”. If so, I know that I can make a GET request and request a byte range to retrieve only those bytes. This is the first important key component.

So, now, I know I can make a range request to the service, which I do by sending a standard GET request including a Range header that specifies the range of bytes I’m requesting, like so: Range: bytes=0-999. The service should then respond with a 206 Partial Content status code, a Content-Range header, and the requested range of bytes. This is the second key component.

I should note that the service cannot force the client to make a range request. It is entirely up to the client to make such requests, so the service should honor all standard GET requests that do not contain a Range header by sending back the full representation of the requested resource. If your service allows range requests, it is to your benefit to tell the client with an Accept-Ranges header. If you want to explicitly tell the client that you do not allow range requests, send a value of “none” back with the Accept-Ranges header.

I got this definition from the following article, so in case it is not clear to you, you can refer to the following article: http://benramsey.com/archives/206-partial-content-and-range-requests/.

DownloadProgress

The DownloadProgress property of MediaElement is a percentage indicating the amount of download completed for content located on a remote server. The value ranges from 0 to 1. Multiply it by 100 to get the percentage. The default value is 0. When this property is set, the DownloadProgressChanged event occurs.

DownloadProgressOffset

It gets the offset of the download progress of the MediaElement. When the user seeks to a point in the download progress (for example, 30 seconds into the video), that becomes the offset for the download progress.

BufferingProgress

Gets a value that indicates the current buffering progress. It is the amount of buffering that is completed for the media content. The value ranges from 0 to 1. Multiply by 100 to obtain a percentage. The default value is 0. The BufferingProgressChanged event occurs whenever the BufferingProgress property is updated by 0.05 or more, or reaches 1.0. In some cases, the BufferingProgress value does not remain at 1 as the media plays.

Explanation of the Issue

When the user plays an HTTP URL, it downloads the file, and DowloadProgress and DownloadProgressOffest works fine, but when the user changes the position of the play or when the first time “seek” operation happens, the player actually fires a BRR, and the index of the WMV file (which is at the end of the file) will be downloaded. At this point, the DownloadProgress and the DownloadProgressOffset both would be very near to the end point, so after some time, the DownloadProgress and the DownloadProgressOffset both reach 100%, which actually means the index file downloaded completely. After this, DownloadProgress will go back to the seek point.

Using the Code

There is nothing much to explain in the code. It is self-explanatory. I am using the DownloadProgressChanged and BufferingProgressChanged events to set the DownloadProgress, DownloadProgressOffset and BufferOffset progressbars.

private void VideoMediaElement_MediaOpened(object sender, RoutedEventArgs e)
{
    //VideoMediaElement.Position = TimeSpan.FromDays(1);
    //VideoMediaElement.Position = TimeSpan.FromSeconds(0);
}

private void Video_BufferingProgressChanged(object sender, RoutedEventArgs e)
{
    BufferProgress.Value = VideoMediaElement.BufferingProgress * 100;
    DownloadProgress.Value = VideoMediaElement.DownloadProgress * 100;
    OffsetValue.Value = VideoMediaElement.DownloadProgressOffset * 100;
}

private void Video_DownloadProgressChanged(object sender, RoutedEventArgs e)
{
    DownloadProgress.Value = VideoMediaElement.DownloadProgress * 100;
    OffsetValue.Value = VideoMediaElement.DownloadProgressOffset * 100;
}

private void Pause_Click(object sender, RoutedEventArgs e)
{
    VideoMediaElement.Pause();
}
private void Play_Click(object sender, RoutedEventArgs e)
{
    if (!Uri.IsWellFormedUriString(URI.Text, UriKind.Absolute))
    {
        MessageBox.Show("Invalid URI");
        return;
    }
    VideoMediaElement.Source = new Uri(URI.Text);
    VideoMediaElement.Play();
}
private void Stop_Click(object sender, RoutedEventArgs e)
{
    VideoMediaElement.Stop();
}
private void Farward_Click(object sender, RoutedEventArgs e)
{
    //if (VideoMediaElement.CurrentState != MediaElementState.Buffering) 
    VideoMediaElement.Position = VideoMediaElement.Position + 
                      TimeSpan.FromSeconds(Int16.Parse(Amount.Text));
}
private void Backward_Click(object sender, RoutedEventArgs e)
{
    //if (VideoMediaElement.CurrentState != MediaElementState.Buffering) 
    VideoMediaElement.Position = VideoMediaElement.Position - 
                      TimeSpan.FromSeconds(Int16.Parse(Amount.Text));
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here