MediaFoundation CreateWaveFormatFormMediaType

Dec 2, 2012 at 12:38 AM

small complement

 

// MediaFoundationHelper.cs
public static WaveFormat CreateWaveFormatFromMediaType(IMFMediaType mediatype)
{
	WaveFormat wF;
	int pcbSize = 0;
	MediaFoundationInterop.MFCreateWaveFormatExFromMFMediaType(mediatype, out wF, out pcbSize);


	return (WaveFormat)wF;
}

// Modify in MediaFoundationInterop.cs

/// <summary>
/// Converts a Media Foundation audio media type to a WAVEFORMATEX structure.
// </summary>
/// TODO: try making second parameter out WaveFormatExtraData
[DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)]
		internal static extern void MFCreateWaveFormatExFromMFMediaType
(
	IMFMediaType pMFType,
	out WaveFormat wf,
	out int pcbSize,
	int flags = 0
);

Coordinator
Dec 2, 2012 at 6:43 AM

hi Manu, thanks for this,although I think you may need to use WaveFormatExtraData in the function prototype, or you could end up missing the extra bytes. CreateWaveFormatFromMediaType should still return a WaveFormat though.

Mark

Dec 8, 2012 at 7:47 AM

I took the time to check with the documentation and with some audio files.

This version is probably better fit.

 

[DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)]
internal static extern void MFCreateWaveFormatExFromMFMediaType
(
	IMFMediaType pMFType,
	out WaveFormatExtensible wf,
	out int pcbSize,
	int flags = 0
);


public static WaveFormat CreateWaveFormatFromMediaType(IMFMediaType mediatype)
{
			
	WaveFormatExtensible wF;
	int pcbSize = 0;	
	MFCreateWaveFormatExFromMFMediaType(mediatype, out wF, out pcbSize);

	if (wF.Encoding == WaveFormatEncoding.Extensible)
		return wF;
	else
	{
		var xx = (WaveFormat)wF;
		return xx;
	}
}

Coordinator
Dec 9, 2012 at 7:00 AM

It really will have to be WaveFormatExtraData or a WaveFormat using NAudio's WaveFormatCustomMarshaller. The trouble is, waveformats can be any length, so you must use a class that is big enough to hold the largest possible WaveFormat, otherwise the marshaller will not copy all the data across. However, for Windows 8 store apps, the custom marshaller cannot be used, so it might mean I have to use an IntPtr, and manually choose which derived WaveFormat class to marshal it into.

Dec 9, 2012 at 7:14 AM

I had not seen WaveFormatCustomMarshaler & WaveFormatExtraData.

Gloupss Sorry, I tested this solution.

Dec 9, 2012 at 7:29 AM

 

I change my routine somewhat.
I do not have audio file with ExtraData to complementary tests.


[DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)]
internal static extern void MFCreateWaveFormatExFromMFMediaType
(
	IMFMediaType pMFType,
	out IntPtr wf,
	out int pcbSize,
	int flags = 0
);


public static WaveFormat CreateWaveFormatFromMediaType(IMFMediaType mediatype)
{
	IntPtr ptr;
	int pcbSize = 0;
	MFCreateWaveFormatExFromMFMediaType(mediatype, out ptr, out pcbSize);

	return WaveFormat.MarshalFromPtr(ptr);
		
}

Coordinator
Dec 9, 2012 at 7:34 AM

It is formats like MP3, AAC (and some types of ADPCM) that tend to have extra data after the WaveFormat structure. The most I have ever seen is about 40 bytes. You could perhaps enumerate all MF decoder's input media types and create their WaveFormat's and see what the largest value of pcbSize you get is.

Dec 9, 2012 at 7:36 AM

 

For the moment pcbSize = 18 (standard type) or 40 (with extensible format)

Jan 27 at 2:18 AM
Edited Jan 27 at 2:45 AM
I got this working. Refer to thread:

https://naudio.codeplex.com/discussions/526991