Mike Taulty's Blog
Bits and Bytes from Microsoft UK
Windows 8.1: Beaming Media via PlayTo By Reference

Blogs

Mike Taulty's Blog

Elsewhere

Archives

One of the things that I really like about Windows devices is the ability to transfer around music and video via “Play To”. I don't think it's unique to Windows by any means and I keep seeing it on Kindle commercials in the UK but on Windows If I’m sitting and listening to a bit of James Taylor at Christmas in Xbox Music on my laptop;

image

then I can pop out to the charms bar, pick out devices;

image

find my Xbox (as an example of a DLNA receiver);

image

image

and then the music plays from the Xbox rather than from the local PC – naturally, I can also do this with video although in both cases the Xbox Music app checks the content for protection here before it allows it to be played to another device like this – in my case I’m playing an .mp3 off my hard drive so the app lets me do it.

I can bring the music back to the local machine using the charms again.

This kind of PlayTo functionality has been in Windows for quite a while – I don’t remember exactly when it arrived but it certainly pre-dates Windows 8 which really brought it more to the forefront and, rather than hiding it away on a menu option inside of Media Player, it’s available to every app and discoverable via the charms bar to every user.

There are some changes in the way that Windows 8.1 handles PlayTo though – there’s a bit of coverage of this in the Build 2013 video below (around the 22m mark);

and I thought I'd make a basic blank app that allowed me to try out a feature that I'd heard about called "Play To By Reference". Getting PlayTo up and running can be as simple as pointing a MediaElement to an online video, i.e. with a piece of XAML;

  <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <MediaElement x:Name="mediaElement" AreTransportControlsEnabled="True"
                  Source="http://ie.microsoft.com/testdrive/Graphics/VideoFormatSupport/big_buck_bunny_trailer_480p_high.mp4" 
                  AutoPlay="True"/>
  </Grid>

and then some code to set up the PlayToManager and give it the MediaElement as a source;

public sealed partial class MainPage : Page
  {
    public MainPage()
    {
      this.InitializeComponent();
      this.Loaded += OnLoaded;
    }
    void OnLoaded(object sender, RoutedEventArgs e)
    {
      var manager = PlayToManager.GetForCurrentView();
      manager.SourceRequested += OnSourceRequested;
    }
    void OnSourceRequested(PlayToManager sender, PlayToSourceRequestedEventArgs args)
    {
      var deferral = args.SourceRequest.GetDeferral();

      Dispatcher.RunAsync(
        CoreDispatcherPriority.Normal,
        () =>
        {
          args.SourceRequest.SetSource(this.mediaElement.PlayToSource);
          deferral.Complete();
        });
    }
  }

I couldn't decide in that particular OnSourceRequested method whether it's better to await the call to CoreDispatcher.RunAsync() and then complete the Deferral object passed to me or whether to complete it as I do above in the method passed across to Dispatcher.RunAsync(). If the Deferral object wasn't thread-agile then one choice would be obvious but (if that was the case and I hope it's not) the whole idea of a Deferral object might be a lot less useful.

With that in place, I get a UI that can play a video and can PlayTo on that video to send it to (e.g.) my Xbox.

image

image

and that nice, new AreTransportControlsEnabled property means that the developer using a MediaElement does not have to create "transport controls" any more for play/pause and so on because the control has them built-in if you want to use them and switch on the flag.

As the top picture shows, I also get to play this media to my other devices via PlayTo with this very small piece of code.

One of the things I always found a bit "odd" about this scenario is that the media is actually being downloaded from the web to my laptop and then my laptop is streaming it to my Xbox. My natural assumption would have been that the logic would run something like this;

  1. PlayTo source determines where the media is coming from.
  2. For networked media, target tells source whether it can access that media or not.
    1. If the target can access the media, it plays it independently.
    2. If the target can't, it streams it from the source.
  3. For non-networked media, the source streams it to the target.

But I don't think it works like that. The PlayTo source gets the media and streams it over to the PlayTo target.

I think that's one of the reasons why an app like Xbox Music can't stream content that's protected by DRM from my laptop to my Xbox. That doesn't happen. What I get instead when I try and share content in Xbox Music that I don't have locally stored on my PC I get an error saying that's not possible;

image

Similarly, if I'm using my own app and I'm streaming that Big Buck Bunny video from my laptop across to the Xbox via PlayTo and then I disconnect my laptop from the network, I see the video frame freeze on the Xbox and it displays a "playback error" - the Xbox is streaming the video from my laptop rather than going out to the source of the video on the internet and accessing it from there.

In Windows 8.1 the MediaElement has a new property that relates to PlayTo - a property called PreferredPlayToUriSource which enables the idea of "PlayTo by Reference" which I think is somewhat closer to passing a URI to the content from the PlayTo Source to the PlayTo target.

If I change my XAML to enable that (I deliberately tried to choose 2 different URLs below);

    <MediaElement x:Name="mediaElement" AreTransportControlsEnabled="True"
                  Source="http://mirrorblender.top-ix.org/peach/bigbuckbunny_movies/big_buck_bunny_720p_surround.avi"
                  PlayToPreferredSourceUri="http://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_480p_surround-fix.avi"
                  AutoPlay="True"/>

and I switch from using an Xbox as a PlayTo target and, instead, make use of Windows Media Player running on a second machine then what I first see when the video starts to play on the remote device is content being streamed from the source device;

image

i.e. in that screenshot above taken on the target device, the video is being pulled from my laptop which is the IP address highlighted.

However, if I unplug that source laptop from the network then the behaviour I see is the target machine pauses for a little while and then restarts the video (in this case) from the PreferredPlayToUriSource - I see it reaching out;

image

and pulling content directly from blender.org.

I'm not sure whether in other scenarios (e.g. if the content was under DRM) that things would work this way - I'd imagine that the target would go directly to the PreferredPlayToUriSource rather than attempting to stream from the source which is what happens in my little test case here.


Posted Fri, Dec 13 2013 5:28 PM by mtaulty
Filed under: , , , ,

Comments

Jason Haley wrote Interesting Finds: December 14, 2013
on Sat, Dec 14 2013 1:24 PM

Interesting Finds: December 14, 2013

Sallye wrote re: Windows 8.1: Beaming Media via PlayTo By Reference
on Sun, Feb 2 2014 4:12 PM

I had one because my Xbox 360 came with one. It wrkeod for a while, but considering how well I take care of my things, I didn't expect it to suddenly stop working. It's cheap and not very comfortable. I preferred the original Xbox headset that went around the back of the head. I also never had a problem with that one. It lasted as long as I needed it to. I would suggest using this until it breaks, and it will, then move on to something else. Perhaps the wireless headset. You can't really play online without some sort of headset.