June 2006 - Posts

Windows Presentation Foundation - Day 4 - Optimizing video performance

Click here for an overview of all posts in this series.

 
Before I go into the details of today's exercise I'll provide some quick links and useful information first. A few days ago Microsoft released a Post Beta 2 June CTP version of the .net Framework 3.0. Although it is always tempting to install the latest and greatest version, I advise against it as the Interactive Designer only works with the Beta 2 version. I have also had some problems installing the June version of the SDK and VS add-in. Until further notice my posts assume a Beta 2 installation.
 
It is fun to see the WPF community growing little by little. Lee Brimelow, a very experienced Flash developer, has started an excellent WPF blog. His blog contains a number of small but powerful WPF examples that include full source code. He approaches everything from a Flash developer's point of view, which is a good thing. He has also authored a good article comparing WPF with Flash, which is spot on.
 
On to the good stuff. Having played around with some samples, looked at the SDK and read some blog entries I feel comfortable enough to create some code and...gasp... give some advice with respect to performance.
 
The full source code and a compiled binary can be downloaded here.
 


Our final result


Quite a few of the WPF showcases use a cool reflective surface that mirrors whatever action is going on, e.g. a movie, in real time. An obvious way to do this is to use 2 media elements with the same movie, vertically mirror one of the movies and add a transparency mask. Although in theory this works, it is very inefficient as the video needs to be streamed twice and decoded twice, which uses a lot of CPU and network bandwidth. It is also very difficult to keep the two video sources exactly in sync.
 
A better way to do this is to create one MediaElement, create a vertically mirrored rectangle, and assign the MediaElement's VisualBrush to it.
 
Sounds simple right, here is how we do it.
  1. Start Interactive Designer and create a new project
     
  2. Make the background of the Canvas black or use a fancy gradient to create a horizon
     
  3. In the Library window, select the MediaElement and draw it on the top 2/3 of the Canvas
     
  4. With the MediaElement still selected, navigate to the Properties Window and specify a video stream in the Source property, e.g. mms://wm.microsoft.com/ms/msnse/0606/27918/NathanDunlap_MBR.wmv
     
  5. Use the Rectangle Tool from the Toolbox Window to draw a rectangle about 1/3 of the height of the canvas straight underneath the MediaElement. I use gridlines and '0' margins to position everything and line things up, but you can also do it the quick and dirty way.
     
  6. Use the Properties Window to give the rectangle a name, in this case 'Reflection'
     
  7. To vertically mirror the rectangle, grab the handle at the top middle of the rectangle and flip it vertically by dragging it underneath the bottom line of the rectangle.


The look of the fully created Scene in ID

 
Make sure you save often as ID crashes frequently. I had to perform the previous steps about 3 times due to all kind of crashes.
 
 
Now for the tricky bit, we need to create a vertical opacity mask in the Reflection rectangle. Follow the steps outline below:
  1. Select the Reflection rectangle
     
  2. In the Appearance Window select the OpacityMask
     
  3. Select the Linear Gradient Brush, the third icon from the left
     
  4. Select the right most gradient stop, the white one, and give it an 'A' (Alpha) of 0. The Opacity mask now blends from opaque to transparent.
     
  5. To rotate the Opacity Mask 90 degrees, select the Brush Transform Icon from the Tools Window. Rotate the arrow in the reflection rectangle by 90 degrees until the white part of the gradient is at the top (Weird, you would expect it to be the other way around and have the transparency at the bottom). After rotating, move the arrow 50% up and make it 2/3 of the original size. This provides a more realistic reflection


Creating the opacity mask

 
The scene is now finished, we just need to add a little bit of code to assign the Video's brush to the reflection rectangle:
  1. Open scene1.xaml.cs using the Projects Window
     
  2. Add the following code to the constructor to create a new VisualBrush and assign it to the rectangle.

    // Insert code required on object creation below this point.
    Reflection.Fill = new VisualBrush(MediaElement);
That is it, press F5 to see the final results.
 
Because we have been a bit naughty it doesn't work 100% as expected. The reflection takes the full size of the rectangle while the video may be much smaller. The reason for this is, most likely, that we didn't wait for the video to finish initialising (and thereby determining the video's width) before assigning it to the rectangle.
 
There are 2 solutions, either wait for the video to initialise or draw a Border element around the video and use that border's VisualBrush, including the embedded video, as the reflection. The Border has a fixed width so we don't need to wait for it to finish loading.
 
I secretly thought that this video would play roughly using the same CPU percentage as it would take Windows Media Player. Unfortunately that is not the case, even when we remove the reflection. While Windows Media Player only takes 10% CPU time, this WPF application almost maxes out one of the cores of my Core Duo CPU. If Anyone can shed any light on this then that would be much appreciated as the current performance is unacceptable, especially considering my Laptop has a 512MB Radeon X1600.
 

Windows Presentation Foundation - Day 3 - What I have learned so far

Click here for an overview of all posts in this series.

 
Ok, so Day 2 was really interesting, especially because the documentation in the SDK is not very up to date or correct. This required me to be very creative to get things to work. The good thing is that playing around is often the best way to learn a new technology.
 
During my experimentations I also played around with the Interactive Designer (ID) by copying XAML between VS and ID and creating some animations. ID Shows promise, but it is not quite there yet. The user interface for the timeline is quite basic especially when compared to the Macromedia Flash one. For example it does not seem to be possible to insert frames or easily move (key) frames to a different position without selecting them painstakingly one by one.
 
One of the things I like is the ability to copy the XAML between ID and VS. For example, I had absolutely no idea how to absolutely position an element in a grid. The easiest way to find this out is to just do it in ID and see what XAML is generated. It turns out that you don't position elements with TOP, LEFT etc properties, but by setting the margin attribute. Unconventional, but there is probably a good reason for doing it this way.
 
Unfortunately, the moment you add any kind of animation to a scene in ID it no longer seems to be possible to copy the XAML to VS due to some problems with XML namespaces. I have posted a question on Channel 9 to find a workaround, but have yet to receive a reply. I know I should not copy and paste XAML around, but I just need to know what is going on under the hood.
 
Anyone who worked through the articles in the SDK I suggested on Day 2 will have noticed that the documentation is not very accurate and up-to-date. Fortunately you can provide feedback to Microsoft's documentation team by clicking on the link at the bottom of each page in the documentation. They are very responsive as I received a personal reply and a thank you in a matter of hours.
 
The integration of WPF in Visual Studio is coming along quite nicely, but it is not there yet. VS seems to crash more than often, especially when terminating a debug session. The Intellisense list for the objects and elements are also massive. It would be nice if the most common properties and properties that are part of the object itself, not one of the base objects, would be listed in a separate section at the top of the Intellisense window.
 
Switching to the visual designer for a XAML file in VS also results in errors too often. For example, when the specified source of an image element does not exist then it is not possible to switch to the designer. It would be nice if the offending object would be disabled or skipped. 
 
XAMLPad is quite useful as well for previewing XAML. Unfortunately it is not very happy when event handlers such as 'Click' have been specified, it just refuses to display the file. I would prefer it if these handlers could optionally be skipped as it takes a lot of time to manually remove all these attributes from the XAML.
 
The VisualBrush element rocks! More about that in the future.
 
Finally, as these are still early days, you cannot rely on Googling for help. Too few people use WPF or have posted about it. This, naturally, is just a matter of time.
 

Windows Presentation Foundation - Day 2 - Using the SDK

Click here for an overview of all posts in this series.

 
Having installed all the prerequisites and tools, see Day 1, we have to start somewhere. It is always good to get your hands dirty and work your way through a couple of examples in the SDK.
 
Follow the steps listed below:
  • Launch the SDK from  the Start Menu / All Programs / Microsoft Windows SDK / Windows SDK Documentation
     
  • Navigate to WinFX Development / Windows Presentation Foundation / Getting Started / Get started using Windows Presentation Foundation
     
  • Work your way through the following simple exercises:
     
    • Hello World
    • Use "XAML" to Create a Simple Layout
    • Use "XAML" to Create a Complex Layout
    • Create a Dynamic "XAML" Page (The documentation for this exercise seems broken in Beta 2, you may need to be a bit creative. I have reported this to Microsoft's SDK documentation team and receceived a reply within hours)
    • Create a Multipage Application
       
  • In the navigation tree navigate to the 'How-to Topics / Create a Windows Presentation Foundation' and execute the exercise.

That is it for today, it shouldn't take you too long.

Windows Presentation Foundation - Day 1 - Getting started

Click here for an overview of all posts in this series.

 
Over the next few weeks, hopefully not months, I will dive, head first, into the new Microsoft .net Framework 3.0. I will focus mainly on Windows Presentation Foundation (WPF), but I may sneak in some Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF, not WWF as that one was already taken ;-).
 
I will get some help from one of the few real world WPF experts, Andrew Whiddett, who created the excellent WPF based Nascar kiosk. I will blog about my experiences so if you are interested subscribe to my RSS feed.
 
So, before we can do anything we need to setup our development environment with all the required development tools, SDKs and runtime components.
 
We are currently at Beta 2, but as versions and links will be changing I am only going to provide one link, which is to the new .net Framework 3 site. From here you can download the .net framework 3.0 and all other components.
 
Click on the download link and download:
  • WinFX runtime components.
  • Windows SDK for WinFX Runtime Components
  • Microsoft Visual Studio Extensions - Development Tools for WinFX
After everything has been installed we need to verify that it works. The easiest thing is to open and compile one of the examples that come with the SDK. All WPF Samples are available in the following ZIP file:
C:\Program Files\Microsoft SDKs\Windows\v1.0\samples\WPFSamples.zip
Unzip the archive and open one of the examples such as:
C:\Program Files\Microsoft SDKs\Windows\v1.0\samples\WPFSamples\Demos\15Puzzle\Csharp\15Puzzle.csproj
And execute it.
 
Andrew also advices to download the following as it will probably come in handy: