This project has moved and is read-only. For the latest updates, please go here.

Player Framework support for Win 8.1 - how hard it is?

Feb 19, 2014 at 5:11 AM
Is this something that can be expected soon?
I need it and could probably try to port it from the phone - but I have no media experience...
Coordinator
Feb 19, 2014 at 9:26 AM
I'm not sure exactly how much work would be involved. I started looking at it a few weeks ago, but did not get any further than concluding that the plugin model had changed. The last go 'round, it only took a couple of hours to get from not having worked with Player Framework before to a working plugin for WP8 (and, I've heard, the same code pretty much just works for WP7 as well, barring a couple of trivial fixes to get it to compile). Most of that time was spent figuring out how the plugins are supposed to work. An example custom-stream plugin--something that implements a Microsoft.PlayerFramework.IPlugin for a Windows.Media.Core.MediaStreamSource or IMediaSource--for Win 8.1's Player Framework would go a long way towards simplifying things. There may be something like that in the PF source code, but I didn't see one in the quick glance that I did take.

The plugin would do something along the lines of creating an instance of MediaStreamFascade, giving an IHttpClients (just "new HttpClients()", unless you need something odd) and a callback to receive the media stream source to the constructor. This is what the WP8 callback looks like:
     public Task SetSourceAsync(IMediaStreamSource mediaStreamSource)
     {
         Debug.WriteLine("MediaElementWrapper.SetSourceAsync()");
         var mss = (MediaStreamSource)mediaStreamSource;
         return Dispatcher.DispatchAsync(() => SetSource(mss));
     }
Note that the IMediaStreamSource is in SM.Media.MediaParser and that Win8's MediaStreamSource is not a base class for SM.Media.WinRtMediaStreamSource, so things look a bit different on Win8.1 where the callback is forwarded to WinRtMediaElementManager.SetSourceAsync() (and yes, that convoluted path can probably be simplified, but it is a bit complicated by needing to conform to the same interfaces that the other platforms use):
     public Task SetSourceAsync(IMediaStreamSource source)
     {
         Debug.WriteLine("WinRtMediaElementManager.SetSourceAsync()");
         var mss = source as WinRtMediaStreamSource;
         if (null == mss)
             throw new ArgumentException("source type is invalid", "source");
         return Dispatch(() =>
                         {
                             Debug.WriteLine("WinRtMediaElementManager.SetSourceAsync() handler");
                             source.ValidateEvent(MediaStreamFsm.MediaEvent.MediaStreamSourceAssigned);
                             if (null != _mediaElement)
                             {
                                 var mediaElement = _mediaElement;
                                 _mediaElement = null;
                                 _destroyMediaElement(mediaElement);
                             }
                             _mediaElement = _createMediaElement();
                             mss.RegisterMediaStreamSourceHandler(ms => Dispatch(() => _mediaElement.SetMediaStreamSource(ms)));
                         });
     }
Anyhow, that all gets to the point where a WinRtMediaStreamSource is created and, through RegisterMediaStreamSourceHandler, it knows what to do with the Windows.Media.Core.MediaStreamSource, once it has been created.

The whole thing gets kicked off when IMediaStreamFascade.Source is set to a URL for a recognized type of playlist (.m3u8, .m3u, or .pls) or media segment (.aac, .ac3, .mp3, or .ts [*]). Shortly thereafter, but very likely after the IMediaStreamFascade.Source setter returns, the callback passed to RegisterMediaStreamSourceHandler should get invoked (from some arbitrary thread).

The trick, then, is to figure out how to get a URL from Player Framework to the plugin and then how to get the resulting IMediaSource back to Player Framework.

I will get around to doing this, but without a simple example to copy or such, that is probably not going to happen until mid-March (to take a wild guess). If anyone that knows the Win8 PF plugin architecture would like to chime in...

[*] Something the system can handle natively (like a simple .mp3 URL) should not waste CPU cycles going through the phonesm code, but the code needs to recognize them in order to deal with playlists that have segments of those types.
Apr 1, 2015 at 10:17 AM
Hi, I am really excited in finding this project. I was working with a windows phone music player app based on SL 8.0. Now we are going to change to Universal app, the missing of AudioPlayerAgent, AudioStreamingAgent and MediaStreamSource make me confuse. In previous project, we download music and parse/ play it at the same time with the AudioPlayerAgent, AudioStreamingAgent and MediaStreamSource. Now maybe I can find the solution from your project.

But I still have some confusion, I hope you can help me:
  • The difference among SetFileSource, SetMediaSource and SetStreamSource.
  • I play local music with SetFileSource, I want to replace old MediaStreamSource with SetMediaSource, but there no useful information.
  • We want to implement equalizer (I don't know whether it is right word, my meaning is some effect for the song), so we need pares the local as MediaSource, that's right?
  • And for dynamic rate song, (like VBR/CBR), I don't find solution to process it.
It's very grateful if I can get your feedback.

Greetings
Fei
Coordinator
Apr 2, 2015 at 9:37 AM
fjaweihyafei wrote:
Hi, I am really excited in finding this project. I was working with a windows phone music player app based on SL 8.0. Now we are going to change to Universal app, the missing of AudioPlayerAgent, AudioStreamingAgent and MediaStreamSource make me confuse. In previous project, we download music and parse/ play it at the same time with the AudioPlayerAgent, AudioStreamingAgent and MediaStreamSource. Now maybe I can find the solution from your project.

But I still have some confusion, I hope you can help me:
  • The difference among SetFileSource, SetMediaSource and SetStreamSource.
These are member functions on MediaPlayer. They have different types of arguments, letting one play media from different sources. For example, SetFileSource() takes an IStorageFile. The one you would probably find to be of most interest is SetMediaSource(), which takes an IMediaSource (typically, an instance of MediaStreamSource).
  • I play local music with SetFileSource, I want to replace old MediaStreamSource with SetMediaSource, but there no useful information.
Microsoft has an example here. In phonesm, a MediaStreamSource instance is created by WinRtMediaStreamConfigurator's CreateMediaStreamSource(). There are some sample universal apps (and a WP8.1 background audio app) if you download a recent version of phonesm (right now, that would be 1.4.7 alpha) and open Samples.WinRT.sln or grab the latest source and open HlsView.VS2013.sln.

Note that in WinRT, one creates a MediaStreamSource and subscribes to some events on that object, whereas with Silverlight one derived a new class from MediaStreamSource.
  • We want to implement equalizer (I don't know whether it is right word, my meaning is some effect for the song), so we need pares the local as MediaSource, that's right?
You may want to dig deeper into Microsoft Media Foundation. Here's an example from Microsoft: "Media extensions sample".

If your application need to do heavy duty math, then you should strongly consider using native code since that can more easily take advantage of the platform's SIMD support (e.g., the ARM NEON instructions).
  • And for dynamic rate song, (like VBR/CBR), I don't find solution to process it.
The current phonesm code works with multiple oddball MP3 and AAC files as well as Shoutcast-type internet radio stations. I'm not sure things would work too well if the sample rate or channel count changed during playback.
It's very grateful if I can get your feedback.
You're welcome.
Greetings
Fei