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;
}
}
}