About the Author

Travis Schilling is focused on the Rich Client Stack of .NET that manifests his programming expertise in software technologies like C#, WPF, Silverlight, ADO.Net, WCF, and HTML5. His software expertise crosses the latest genre of cutting edge computing devices like the Microsoft Surface and the XBOX Kinect. After graduating from Neumont University in Salt Lake City, Utah with a Bachelor’s degree in Computer Science, Travis became a Software Engineer at InterKnowlogy in Carlsbad, CA. Travis has an expertise in NUI (The Natural User Interface) having built numerous multi-touch and gesture based interfaces for software applications. Travis is a Windows Developer 4 Microsoft Certified Professional Developer. When not architecting, designing and building software, Travis is often found in the gym, conquering the galaxy in StarCraft 2 or playing his bass guitar. Travis’ loves are his Nissan 370z and hanging with friends and family.

Stream HTML5 Video from Azure Blob Storage

I’ve been looking into what needs to be done in order to stream videos hosted in Microsoft Azure’s Blob storage with the HTML5 <video> control. Once I got over a few little hiccups, the process was very straight forward.

The Process

I followed the Video On The Web section of the online book Dive Into HTML5 by Mark Pilgrim for the overall process. It provides a couple nice pictures stating which browser supports which codec. I was disappointed with the fact that there isn’t one codec supported by all the mainstream browsers, so to support all you have to have at least 2.

I decided that I would take my video and encode it in the H.264 and OGG formats. NOTE: The document above is a bit old but the steps provide a good idea of what to set to accomplish the encoding. Once the two versions were ready I created a simple .html page and hosted it in my local IIS just to test out that I had done the encoding correctly. Below is what I had.

<!DOCTYPE html>
<html>
<body>
<h1>Test</h1>
<video width="576" height="320" controls>
	<source src="tbbt_s1e1.mp4"  type='video/mp4; codecs="avc1.42e01e, mp4a.40.2"'>
	<source src="tbbt_s1e1.ogv"  type='video/ogg; codecs="theora, vorbis"'>
</video>
</body>
</html>

The HTML5 <video> control is really straight forward to use. The controls attribute tells the browser to display its prebuilt controls and there are 2 ways to specify the source video file(s). The first way only uses one file so if the browser doesn’t support it, then you can’t watch. The second way is what I followed, and it allowed me to provide multiple video files allowing the browser to choose the codec it supports.

When I viewed the page the video player controls showed up, but the videos didn’t work. The important thing I missed was to make sure IIS had the correct MIME type defined for the videos (MIME Types Rear Their Ugly Head section of the document above). After adding the following MIME types to the root IIS node the videos played.

Extension MIME type
.ogv video/ogv
.mp4 video/mp4

 
With the videos functioning, I then moved on to hosting the video files in my Blob Azure Development Storage and pointing to those files. Previously I had created a little application to upload files to Blob storage, so I used it to upload the files instead of any of the Azure file explorer applications.

I then pointed the .html file above to the Azure urls and got the player again with the video not working.

<!DOCTYPE html>
<html>
<body>
<h1>Test</h1>
<video width="576" height="320" controls>
	<source src="http://127.0.0.1:10000/devstoreaccount1/videocontainer/c625cff5-6f03-4e89-a8b3-43f29b97f14b.mp4"  type='video/mp4; codecs="avc1.42e01e, mp4a.40.2"'>
	<source src="http://127.0.0.1:10000/devstoreaccount1/videocontainer/4e3f4531-e3d2-407f-8a78-bea8d540d537.ogv"  type='video/ogg; codecs="theora, vorbis"'>
</video>
</body>
</html>

Turns out I ran into the exact same MIME type issue. My application didn’t set the Content Type property of each Blob to the correct type so Azure wouldn’t allow it to be streamed out, but it could be downloaded. To quickly change this I used Azure Storage Explorer to point to my Development Storage and change the Content Type of each of the files to their respective MIME type specified in the table above.

I then browsed to the .html file again and the videos played!

Codec Issues
When encoding the video to the H.264 and OGG formats I ran into a few issues. First I used HandBrake and Firefogg (requires Firefox) respectively to encode the files, but while HandBrake worked, the file Firefogg provided didn’t have audio when played in Firefox. I then switched to using ffmpeg2theora hoping that would fix the issue, but it didn’t. I then tried encoding them for the WebM codec, but that still didn’t work. In a final attempt I took the H.264(.mp4) file that HandBrake output(since it was working great) and used Miro Video Converter to convert it to a OGG(.ogv) file. This new version worked in Firefox, so what I thought was an issue with Firefox or my hosting just turned out to be an encoding problem.

I also ran into an issue viewing the H.264 version in IE9, but it turned out to be a Compatibility View issue that I documented here

I still have a ton to learn about Azure Storage, HTML5 Video and Codecs, but I think this was a good start.

HTML5 Video and IE9 Compatibility View

When messing around with HTML5 and its <video> I had it working great in IE9 on my machine using the H.264 codec. I then had some of my coworkers attempt to view my .html file which I had hosted in IIS on my machine. Everyone could view the page but the video player only showed up for one guy. I was baffled and started on a wild goose chase trying to figure out what was different between my machine, the one that worked and all the other machines.

Finally I started comparing the HTML being displayed in each IE9 browser using the Developer Tools (these can be accessed easily by pressing F12).

In the 2 browsers that showed the video, the HTML looked totally correct. In the others the <video> tag was closed prematurely and the <!DOCTYPE html> tag at the top was a comment instead of valid HTML. Then I noticed what the issue was. My page was being shown in IE9 Compatibility View which doesn’t support HTML5, which totally explained the weird behavior.

It turns out that the default settings in IE9 are to view all intranet sites in Compatibility View. This seems totally backwards to me as a developer as I am usually dealing with the latest and greatest (which Compatibility View is not). To change this press alt, then choose Tools, select Compatibility View settings, and then uncheck Display intranet sites in Compatibility View.

With this change on everyone’s machines they can now all view the HTML5 video hosted in my IIS.

XamlReader, Loose ResourceDictionary Files, and the ParserContext

In a few WPF projects that I have been on I have needed to load in loose ResourceDictionary files to provide different runtime styling. When there isn’t any external content being referenced (ie. images, videos, etc…) it is as simple as calling XamlReader.Load and then merging the dictionary into the application’s resources:

var resourceDictionary = XamlReader.Load(fileStream) as ResourceDictionary;
if(resourceDictionary != null)
{
    Resources.MergedDictionaries.Add(resourceDictionary)
}

When external content is being referenced there is the possibility that the XamlReader won’t be able to find those files, even if they are in the exact same folder as the ResourceDictionary files. To solve this issue, you will need to create a ParserContext and set its BaseUri to the root folder containing the files. For example, if the ResourceDictionary and content files are located in a folder called RuntimeResources, which is in the same folder as the application’s exe, then the BaseUri needs to point to that RuntimeResources folder. Then when the XamlReader loads the ResourceDictionary, it uses the provided ParserContext to know where to look for the actual files. NOTE: In the ResourceDictionary you will still need to include the root folder (RuntimeResources) at the beginning of the uri otherwise it will look in the parent directory for the desired file.

Below is the related code:

C#

var applicationDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if(!String.IsNullOrEmpty(applicationDirectory ))
{

    var runtimeResourcesDirectory = Path.Combine(applicationDirectory , "RuntimeResources");
    var pc = new ParserContext
    {
        BaseUri = new Uri(runtimeResourcesDirectory , UriKind.Absolute)
    };
    if(Directory.Exists(runtimeResourcesDirectory ))
    {
        foreach (string resourceDictionaryFile in Directory.GetFiles(runtimeResourcesDirectory , "*.xaml"))
        {
            using (Stream s = File.Open(resourceDictionaryFile, FileMode.Open, FileAccess.Read))
            {
                try
                {
                    var resourceDictionary = XamlReader.Load(s, pc) as ResourceDictionary;
                    if (resourceDictionary != null)
                    {
                        Resources.MergedDictionaries.Add(resourceDictionary);
                    }
                }
                catch
                {
                    MessageBox.Show("Invalid xaml: " + resourceDictionaryFile);
                }
            }
        }
    }
}

Resource Dictionary

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
			    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

	<ImageBrush x:Key="LogoImage"
			  ImageSource="RuntimeResources/logo.png" />

</ResourceDictionary>

Now you’ve got the ability to change your WPF application’s styling at runtime.

Creating and Registering Windows 7 Bootable VHDs

Here at InterKnowlogy we have the benefit of working on a lot of cutting edge technologies. A good deal of our first looks at different technologies involve installing alpha/beta bits that may or may not install or uninstall properly and may or may not play nice with existing technologies that we use in other projects. The simple way to keep from destabilizing your system is in creating a Virtual PC and running it with any number of applications (VMware, VirtualBox, Windows Virtual PC, etc…). Doing this keeps your existing system clean and free from any possibilities of errors occurring. However with most Virtual PCs they are utilizing virtual drivers and not running straight off the physical hardware so it doesn’t function as quickly as your main OS, and on top of that you have to share RAM between the two. If you need to switch back and forth continuously between the two then this is just something you have to deal with. However, if you are able to have everything on just the Virtual PC AND are running Windows 7 (for both your actual OS and VPC) then you have another option.

Windows Virtual PC utilizes a file with the extension .vhd for its virtual hard drive. It contains everything for the entire OS and instead of using the VHD through Windows Virtual PC, in Windows 7 you can register that VHD into the boot menu and, on startup, boot straight into it like it is an OS installed on your machine.

Create Bootable VHD

  1. Open Computer Management and switch to Disk Management View
  2. Select Create VHD from the Action menu
  3. Choose location, disk format (can be either Fixed or Dynamic), disk size (30GB Min Recommended), and finish. The creation process might take 5-10 min. There won’t be any extra dialog, just a progress bar at the bottom.
  4. Right-click on the new disk that shows up in Disk Management and initialize it with a MBR partition style.
  5. Right-click on the initialized partition and select New Simple Volume. Go through the wizard. The only thing that you will want to change is the Volume Label on the Format Partition screen. Make a note of the drive letter that is assigned on the 3rd screen in the dialog as you will use this later.

Install Windows 7

  1. Install the Windows Automated Installation Kit for Windows 7 to get access to the ImageX utility which is located at C:\Program Files\Windows AIK\Tools in either the x86 or amd64 folders.
  2. In Disk Management make sure that the VHD that was created and initialized is attached (Action->Attach VHD)
  3. Open a command prompt and change directory to either C:\Program Files\Windows AIK\Tools\x86 (if you are installing Windows 7 32bit) or C:\Program Files\Windows AIK\Tools\amd64 (if you are installing Windows 7 64bit).
  4. Then run the following command:
    imagex /apply d:\sources\install.wim 1 x:\
    
    1. d:\sources\install.wim is the location of the “install.wim” file in the Windows 7 media (mounted ISO file or DVD)
    2. 1 is the image index of the OS. 1 can be assumed, however to check what it is you can run the command: imagex /info d:\sources\install.wim and look at the Image Index
    3. x:\ is the drive letter for the attached VHD that you made note of earlier
  5. Once the ImageX utility has finished, run the following command to add this drive to the boot menu as the default boot OS:
    bcdboot x:\Windows
    
    1. Using this command will make this your default OS to boot into on the boot screen. The easiest way to change this is to get to Advanced system settings (via the computer properties screen), select Settings… in the Startup and Recovery section, and then change the value in the Default operating system dropdown.

Change the OS name in the boot loader

The next time you start up your machine, you’ll notice there is now an additional Windows 7. The big question is which one is your main OS and which is your new bootable VHD. So before you restart or shutdown your machine you’ll want to rename your bootable VHD description.

  1. Open a command prompt and run the following command to see all the boot loader entries:
    bcdedit
    

    Example Windows Boot Loader Entries
    The top Windows Boot Loader section is of a bootable VHD and the bottom one is for the main OS.

  2. Find the Windows Boot Loader entry that has its device value pointing to your vhd file. This will be the actual location (and while in your main OS will start with vhd)  ie. vhd=[C:]\VHDs\Win764bit.vhd
  3. Copy the identifier value (including the curly braces) for that entry ie. {5e6085cb-8f65-11de-8f7c-92487039f837}
  4. Enter the following command to change the description:
    bcdedit /set {5e6085cb-8f65-11de-8f7c-92487039f837} description “New Description”
    
    1. {5e6085cb-8f65-11de-8f7c-92487039f837} is the identifier you copied
    2. “New Description” is the value you want to have show up in the boot menu. Make sure to keep the quotation marks if you use spaces.

Now when the boot loader shows up you’ll be able to tell which OS is which.

Now you can have the “sandboxed” benefit of a Virtual PC with the performance of a non-virtual OS.

Resources

Scott Hanselman’s Computer Zen

Aviraj Ajgekar’s Blog

Virtual Varia