Ed Ayers
Ed Ayers

Reputation: 1354

Windows 8 passing a Stream to a MFSourceReader

I am trying to make a program that can take an .mp3 file from the user's Music Library, and convert it using the Windows Media Foundation's IMFSourceReader into an array containing PCM values for some exciting DSP action. However, I'm having problems.

My solution has two projects; a C#/XAML one containing UI code and a C++ Library containing some native code for working with Media Foundation and XAudio2 plus some public ref classes which the C# code can interact with.

I can't use MFCreateSourceReaderFromURL because it returns an ACCESS DENIED HRESULT even if you have the Music Library capability in the app manifest. So it looks like I'm going to have to use either MFCreateSourceReaderFromByteStream or MFCreateSourceReaderFromMediaSource. Now, it's easy enough to access the music file using Windows.Storage.KnownFolders.MusicLibrary and get a Stream or an IInputStream along with a few other stream types but how can I convert this to an IMFByteStream or an IMFMediaSource or just in some way decode the mp3 to a byte array with PCM values?

I have also entertained the idea of resaving the music file in the app folder so that I can use MFCreateSourceReaderFromURL or perhaps it would be possible to bypass working with Media Foundation directly and use something like Windows.Media.Transcoding to do the conversion to PCM. I'm not sure this is what the Transcoding namespace is for though.

I have spent hours reading through the Media Foundation documentation and I found a glimmer of hope with MFCreateMFByteStreamOnStream which can convert from COM's IStream to a byte stream but I will need to find/write a wrapper to convert my .net stream to an IStream. Before I set off on this task I just want to make sure that I am going in the right direction or is there a better way to do this?

Thanks in advance. Also apologies in advance if I have made a stupid mistake or missed some crucial aspect of working with these libraries.

Upvotes: 4

Views: 3125

Answers (3)

BlueStrat
BlueStrat

Reputation: 2304

Late to the party, complementing the original answer, for those who want to take the route of wrapping a managed stream with a COM IStream interface, here is a good implementation.

Upvotes: 0

Omid B.
Omid B.

Reputation: 356

If you can make a component out of it (licensed or not), i'd be interested. I am not aware of any component that can transcode a MP4, WMA or M4A audio file to PCM under WinRT. Unfortunately, Windows 8 does not support recording an audio file as PCM.

Upvotes: 0

Ed Ayers
Ed Ayers

Reputation: 1354

OK everyone, I know you are all clamouring to answer this question but after 2 days of headscratching I have found a solution. You can pass an Windows::Storage::Streams::IRandomAccessStream^ object to MFCreateMFByteStreamOnStreamEx ( http://msdn.microsoft.com/en-us/library/windows/desktop/hh162754(v=vs.85).aspx ) by casting it to (IUnknown*) like so:

ComPtr<IMFByteStream> spMFByteStream = nullptr; 

MFCreateMFByteStreamOnStreamEx((IUnknown*)streamHandle, &spMFByteStream);

//remember to add your own HRESULT error handling code

ComPtr<IMFSourceReader> _sourceReader = nullptr;

MFCreateSourceReaderFromByteStream(spMFByteStream.Get(),nullptr,&_sourceReader);

With streamHandle being the IRandomAcessStream^ that you want to give to the Source Reader. Here is a code sample with it running

Time for some toast.

Upvotes: 5

Related Questions