using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using NAudio.Wave; namespace NAudio.MediaFoundation { /// /// Main interface for using Media Foundation with NAudio /// public static class MediaFoundationApi { private static bool initialized; /// /// initializes MediaFoundation - only needs to be called once per process /// public static void Startup() { if (!initialized) { var sdkVersion = MediaFoundationInterop.MF_SDK_VERSION; // Windows Vista check var os = Environment.OSVersion; if (os.Version.Major == 6 && os.Version.Minor == 0) sdkVersion = 1; MediaFoundationInterop.MFStartup((sdkVersion << 16) | MediaFoundationInterop.MF_API_VERSION, 0); initialized = true; } } /// /// Enumerate the installed MediaFoundation transforms in the specified category /// /// A category from MediaFoundationTransformCategories /// public static IEnumerable EnumerateTransforms(Guid category) { MediaFoundationInterop.MFTEnumEx(category, _MFT_ENUM_FLAG.MFT_ENUM_FLAG_ALL, null, null, out var interfacesPointer, out var interfaceCount); var interfaces = new IMFActivate[interfaceCount]; for (int n = 0; n < interfaceCount; n++) { var ptr = Marshal.ReadIntPtr(new IntPtr(interfacesPointer.ToInt64() + n*Marshal.SizeOf(interfacesPointer))); interfaces[n] = (IMFActivate) Marshal.GetObjectForIUnknown(ptr); } foreach (var i in interfaces) { yield return i; } Marshal.FreeCoTaskMem(interfacesPointer); } /// /// uninitializes MediaFoundation /// public static void Shutdown() { if (initialized) { MediaFoundationInterop.MFShutdown(); initialized = false; } } /// /// Creates a Media type /// public static IMFMediaType CreateMediaType() { MediaFoundationInterop.MFCreateMediaType(out IMFMediaType mediaType); return mediaType; } /// /// Creates a media type from a WaveFormat /// public static IMFMediaType CreateMediaTypeFromWaveFormat(WaveFormat waveFormat) { var mediaType = CreateMediaType(); try { MediaFoundationInterop.MFInitMediaTypeFromWaveFormatEx(mediaType, waveFormat, Marshal.SizeOf(waveFormat)); } catch (Exception) { Marshal.ReleaseComObject(mediaType); throw; } return mediaType; } /// /// Creates a memory buffer of the specified size /// /// Memory buffer size in bytes /// The memory buffer public static IMFMediaBuffer CreateMemoryBuffer(int bufferSize) { MediaFoundationInterop.MFCreateMemoryBuffer(bufferSize, out IMFMediaBuffer buffer); return buffer; } /// /// Creates a sample object /// /// The sample object public static IMFSample CreateSample() { MediaFoundationInterop.MFCreateSample(out IMFSample sample); return sample; } /// /// Creates a new attributes store /// /// Initial size /// The attributes store public static IMFAttributes CreateAttributes(int initialSize) { MediaFoundationInterop.MFCreateAttributes(out IMFAttributes attributes, initialSize); return attributes; } /// /// Creates a media foundation byte stream based on a stream object /// (usable with WinRT streams) /// /// The input stream /// A media foundation byte stream public static IMFByteStream CreateByteStream(object stream) { // n.b. UWP apps should use MediaFoundationInterop.MFCreateMFByteStreamOnStreamEx(stream, out byteStream); IMFByteStream byteStream; if (stream is IStream) { MediaFoundationInterop.MFCreateMFByteStreamOnStream(stream as IStream, out byteStream); } else { throw new ArgumentException("Stream must be IStream in desktop apps"); } return byteStream; } /// /// Creates a source reader based on a byte stream /// /// The byte stream /// A media foundation source reader public static IMFSourceReader CreateSourceReaderFromByteStream(IMFByteStream byteStream) { MediaFoundationInterop.MFCreateSourceReaderFromByteStream(byteStream, null, out IMFSourceReader reader); return reader; } } }