MVH/NAudio-2.2.1/NAudio.Wasapi/MediaFoundation/MediaFoundationHelpers.cs

162 lines
5.6 KiB
C#
Raw Normal View History

2024-06-07 00:47:07 +02:00
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using NAudio.Wave;
namespace NAudio.MediaFoundation
{
/// <summary>
/// Main interface for using Media Foundation with NAudio
/// </summary>
public static class MediaFoundationApi
{
private static bool initialized;
/// <summary>
/// initializes MediaFoundation - only needs to be called once per process
/// </summary>
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;
}
}
/// <summary>
/// Enumerate the installed MediaFoundation transforms in the specified category
/// </summary>
/// <param name="category">A category from MediaFoundationTransformCategories</param>
/// <returns></returns>
public static IEnumerable<IMFActivate> 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);
}
/// <summary>
/// uninitializes MediaFoundation
/// </summary>
public static void Shutdown()
{
if (initialized)
{
MediaFoundationInterop.MFShutdown();
initialized = false;
}
}
/// <summary>
/// Creates a Media type
/// </summary>
public static IMFMediaType CreateMediaType()
{
MediaFoundationInterop.MFCreateMediaType(out IMFMediaType mediaType);
return mediaType;
}
/// <summary>
/// Creates a media type from a WaveFormat
/// </summary>
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;
}
/// <summary>
/// Creates a memory buffer of the specified size
/// </summary>
/// <param name="bufferSize">Memory buffer size in bytes</param>
/// <returns>The memory buffer</returns>
public static IMFMediaBuffer CreateMemoryBuffer(int bufferSize)
{
MediaFoundationInterop.MFCreateMemoryBuffer(bufferSize, out IMFMediaBuffer buffer);
return buffer;
}
/// <summary>
/// Creates a sample object
/// </summary>
/// <returns>The sample object</returns>
public static IMFSample CreateSample()
{
MediaFoundationInterop.MFCreateSample(out IMFSample sample);
return sample;
}
/// <summary>
/// Creates a new attributes store
/// </summary>
/// <param name="initialSize">Initial size</param>
/// <returns>The attributes store</returns>
public static IMFAttributes CreateAttributes(int initialSize)
{
MediaFoundationInterop.MFCreateAttributes(out IMFAttributes attributes, initialSize);
return attributes;
}
/// <summary>
/// Creates a media foundation byte stream based on a stream object
/// (usable with WinRT streams)
/// </summary>
/// <param name="stream">The input stream</param>
/// <returns>A media foundation byte stream</returns>
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;
}
/// <summary>
/// Creates a source reader based on a byte stream
/// </summary>
/// <param name="byteStream">The byte stream</param>
/// <returns>A media foundation source reader</returns>
public static IMFSourceReader CreateSourceReaderFromByteStream(IMFByteStream byteStream)
{
MediaFoundationInterop.MFCreateSourceReaderFromByteStream(byteStream, null, out IMFSourceReader reader);
return reader;
}
}
}