65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Windows Media Foundation 进行视频编码器和元数据读取

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (4投票s)

2011年8月11日

Ms-PL

2分钟阅读

viewsIcon

30591

使用 Windows Media Foundation 进行视频编码器和元数据读取

1996-1997年,随着 Internet Explorer 3.0 的发布,微软发布了一套用于处理媒体内容(例如电影)的 API。他们当时称之为 Quartz。这是一个非常方便的接口集合,因此被业界广泛使用。现在我们称之为 DirectShow。 岁月流逝,但 DirectShow 仍然保持不变。它运行良好,而且运行得非常好。几年前,微软决定需要改变,并开始为 Windows Vista、7 和 8 设计一个新的基于 COM 的多媒体框架。他们称之为 Media Foundation。这个框架更加通用和可扩展,但也更加复杂。今天,我们将学习如何使用 Media Foundation 检测视频或音频文件的编解码器信息,并与 DirectShow SDK 进行比较。那么,让我们开始吧...

Spaghetti COM

使用 DirectShow 检测媒体文件的编解码器

这很简单。创建一个新的媒体检测器实例

var mediaDet = (IMediaDet)new MediaDet();

将你的文件放入其中

var hr = mediaDet.put_Filename(fileName);

枚举媒体流

int streamCount;     
hr = mediaDet.get_OutputStreams(out streamCount);

获取每个流

for (int i = 0; i < streamCount; i++) {     
hr = mediaDet.put_CurrentStream(i);

检测其类型

Guid streamType;     
hr = mediaDet.get_StreamType(out streamType);

如果类型是视频,则获取 FourCC 编解码器代码 并解密

if (streamType == MediaType.Video) {     
var mediaType = new AMMediaType();
hr = mediaDet.get_StreamMediaType(mediaType);
if (mediaType.formatType == FormatType.VideoInfo) {     
var videoHeader = (VideoInfoHeader)Marshal.PtrToStructure
                  (mediaType.formatPtr, typeof(VideoInfoHeader));
var fourCC = FourCCToString(videoHeader.BmiHeader.Compression);     
}

你还可以获取流长度并检索其他属性。

double streamLength;     
hr = mediaDet.get_StreamLength(out streamLength);

关于此 API 的托管签名呢?没问题,它来了 + FourCC 解码器作为奖励。

   private static string FourCCToString(int fourcc) {     
      byte[] bytes = new byte[4];
      bytes[0] = (byte)(fourcc & 0x000000ff); fourcc = fourcc >> 8;     
      bytes[1] = (byte)(fourcc & 0x000000ff); fourcc = fourcc >> 8;      
      bytes[2] = (byte)(fourcc & 0x000000ff); fourcc = fourcc >> 8;      
      bytes[3] = (byte)(fourcc & 0x000000ff);
      return Encoding.ASCII.GetString(bytes);     
   }
   static public class MediaType {     
      public static readonly Guid Null = Guid.Empty;      
      public static readonly Guid Video = new Guid(0×73646976, 
      0×0000, 0×0010, 0×80, 0×00, 0×00, 
      0xaa, 0×00, 0×38, 0x9b, 0×71);      
      public static readonly Guid Audio = new Guid(0×73647561, 
      0×0000, 0×0010, 0×80, 0×00, 0×00, 
      0xaa, 0×00, 0×38, 0x9b, 0×71);      
   }
   static public class FormatType {     
      public static readonly Guid Null = Guid.Empty;
      public static readonly Guid None = new Guid(0x0F6417D6, 0xc318, 
      0x11d0, 0xa4, 0x3f, 0×00, 0xa0, 0xc9, 0×22, 0×31, 0×96);     
      public static readonly Guid VideoInfo = new Guid(0x05589f80, 0xc356, 
      0x11ce, 0xbf, 0×01, 0×00, 0xaa, 0×00, 0×55, 0×59, 0x5a);      
      public static readonly Guid VideoInfo2 = new Guid(0xf72a76A0, 0xeb0a, 
      0x11d0, 0xac, 0xe4, 0×00, 0×00, 0xc0, 0xcc, 0×16, 0xba);      
      public static readonly Guid WaveEx = new Guid(0x05589f81, 0xc356, 
      0x11ce, 0xbf, 0×01, 0×00, 0xaa, 0×00, 0×55, 0×59, 0x5a);      
      public static readonly Guid MpegVideo = new Guid(0x05589f82, 0xc356, 
      0x11ce, 0xbf, 0×01, 0×00, 0xaa, 0×00, 0×55, 0×59, 0x5a);      
      public static readonly Guid MpegStreams = new Guid(0x05589f83, 0xc356, 
      0x11ce, 0xbf, 0×01, 0×00, 0xaa, 0×00, 0×55, 0×59, 0x5a);      
      public static readonly Guid DvInfo = new Guid(0x05589f84, 0xc356, 
      0x11ce, 0xbf, 0×01, 0×00, 0xaa, 0×00, 0×55, 0×59, 0x5a);      
      public static readonly Guid AnalogVideo = new Guid(0x0482dde0, 
      0×7817, 0x11cf, 0x8a, 0×03, 0×00, 0xaa, 0×00, 0x6e, 0xcb, 0×65);      
      public static readonly Guid Mpeg2Video = new Guid(0xe06d80e3, 
      0xdb46, 0x11cf, 0xb4, 0xd1, 0×00, 0×80, 0x5f, 0x6c, 0xbb, 0xea);      
      public static readonly Guid DolbyAC3 = new Guid(0xe06d80e4, 0xdb46, 
      0x11cf, 0xb4, 0xd1, 0×00, 0×80, 0x5f, 0x6c, 0xbb, 0xea);      
      public static readonly Guid Mpeg2Audio = new Guid(0xe06d80e5, 0xdb46, 
      0x11cf, 0xb4, 0xd1, 0×00, 0×80, 0x5f, 0x6c, 0xbb, 0xea);      
      public static readonly Guid WSS525 = new Guid(0xc7ecf04d, 0×4582, 
      0×4869, 0x9a, 0xbb, 0xbf, 0xb5, 0×23, 0xb6, 0x2e, 0xdf);      
      public static readonly Guid ETDTFilter_Tagged = new Guid(0xC4C4C4D1, 
      0×0049, 0x4E2B, 0×98, 0xFB, 0×95, 
      0×37, 0xF6, 0xCE, 0×51, 0x6D);      
      public static readonly Guid CPFilters_Processed = new Guid(0x6739b36f, 
      0x1d5f, 0x4ac2, 0×81, 0×92, 0×28, 0xbb, 0xe, 0×73, 0xd1, 0x6a);      
   }
   [ComImport, Guid("65BD0711-24D2-4ff7-9324-ED2E5D3ABAFA")]     
   public class MediaDet {      
   }
   [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), 
   Guid("65BD0710-24D2-4ff7-9324-ED2E5D3ABAFA")]     
   public interface IMediaDet {      
      [PreserveSig]      
      int get_Filter([MarshalAs(UnmanagedType.IUnknown)] out object pVal);
      [PreserveSig]     
      int put_Filter([MarshalAs(UnmanagedType.IUnknown)] object newVal);
      [PreserveSig]     
      int get_OutputStreams(out int pVal);
      [PreserveSig]     
      int get_CurrentStream(out int pVal);
      [PreserveSig]     
      int put_CurrentStream(int newVal);
      [PreserveSig]     
      int get_StreamType(out Guid pVal);
      [PreserveSig]     
      int get_StreamTypeB([MarshalAs(UnmanagedType.BStr)] out string pVal);
      [PreserveSig]     
      int get_StreamLength(out double pVal);
      [PreserveSig]     
      int get_Filename([MarshalAs(UnmanagedType.BStr)] out string pVal);
      [PreserveSig]     
      int put_Filename([MarshalAs(UnmanagedType.BStr)] string newVal);
      [PreserveSig]     
      int GetBitmapBits(double StreamTime, out int pBufferSize, 
      [In] IntPtr pBuffer, int Width, int Height);
      [PreserveSig]     
      int WriteBitmapBits(double StreamTime, int Width, int Height, 
      [In, MarshalAs(UnmanagedType.BStr)] string ilename);
      [PreserveSig]     
      int get_StreamMediaType([Out, MarshalAs(UnmanagedType.LPStruct)] AMMediaType pVal);      

      [PreserveSig]      
      int GetSampleGrabber(out ISampleGrabber ppVal);
      [PreserveSig]     
      int get_FrameRate(out double pVal);
      [PreserveSig]     
      int EnterBitmapGrabMode(double SeekTime);      
   }
   [ComImport, Guid("6B652FFF-11FE-4fce-92AD-0266B5D7C78F"), 
   InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]     
   public interface ISampleGrabber {      
      [PreserveSig]      
      int SetOneShot([In, MarshalAs(UnmanagedType.Bool)] bool OneShot);
      [PreserveSig]     
      int SetMediaType([In, MarshalAs(UnmanagedType.LPStruct)] AMMediaType pmt);
      [PreserveSig]     
      int GetConnectedMediaType([Out, MarshalAs(UnmanagedType.LPStruct)] AMMediaType pmt);
      [PreserveSig]     
      int SetBufferSamples([In, MarshalAs(UnmanagedType.Bool)] bool BufferThem);
      [PreserveSig]     
      int GetCurrentBuffer(ref int pBufferSize, IntPtr pBuffer);
      [PreserveSig]     
      int GetCurrentSample(out IMediaSample ppSample);
      [PreserveSig]     
      int SetCallback(ISampleGrabberCB pCallback, int WhichMethodToCallback);      
   }
   [ComImport, Guid("0579154A-2B53-4994-B0D0-E773148EFF85"), 
   InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]     
   public interface ISampleGrabberCB {      
      [PreserveSig]      
      int SampleCB(double SampleTime, IMediaSample pSample);
      [PreserveSig]     
      int BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen);      
   }
   [ComImport, Guid("56a8689a-0ad4-11ce-b03a-0020af0ba770"), 
   InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]     
   public interface IMediaSample {      
      [PreserveSig]      
      int GetPointer([Out] out IntPtr ppBuffer);      
      [PreserveSig]      
      int GetSize();
      [PreserveSig]     
      int GetTime([Out] out long pTimeStart, [Out] out long pTimeEnd);
      [PreserveSig]     
      int SetTime([In, MarshalAs(UnmanagedType.LPStruct)] LONG pTimeStart, 
      [In, MarshalAs(UnmanagedType.LPStruct)] LONG pTimeEnd);
      [PreserveSig]     
      int IsSyncPoint();
      [PreserveSig]     
      int SetSyncPoint([In, MarshalAs(UnmanagedType.Bool)] bool bIsSyncPoint);
      [PreserveSig]     
      int IsPreroll();
      [PreserveSig]     
      int SetPreroll([In, MarshalAs(UnmanagedType.Bool)] bool bIsPreroll);
      [PreserveSig]     
      int GetActualDataLength();
      [PreserveSig]     
      int SetActualDataLength([In] int len);
      [PreserveSig]     
      int GetMediaType([Out, MarshalAs(UnmanagedType.LPStruct)] out AMMediaType ppMediaType);
      [PreserveSig]     
      int SetMediaType([In, MarshalAs(UnmanagedType.LPStruct)] AMMediaType pMediaType);
      [PreserveSig]     
      int IsDiscontinuity();
      [PreserveSig]     
      int SetDiscontinuity([In, MarshalAs(UnmanagedType.Bool)] bool bDiscontinuity);
      [PreserveSig]     
      int GetMediaTime([Out] out long pTimeStart, [Out] out long pTimeEnd);
      [PreserveSig]     
      int SetMediaTime([In, MarshalAs(UnmanagedType.LPStruct)] 
      LONG pTimeStart, [In, MarshalAs(UnmanagedType.LPStruct)] LONG pTimeEnd);      
   }
   [StructLayout(LayoutKind.Sequential)]     
   public class AMMediaType {      
      public Guid majorType;      
      public Guid subType;      
      [MarshalAs(UnmanagedType.Bool)]      
      public bool fixedSizeSamples;      
      [MarshalAs(UnmanagedType.Bool)]      
      public bool temporalCompression;      
      public int sampleSize;      
      public Guid formatType;      
      public IntPtr unkPtr;       
      public int formatSize;      
      public IntPtr formatPtr;      
   }
   [StructLayout(LayoutKind.Sequential)]     
   public class VideoInfoHeader {      
      public RECT SrcRect;      
      public RECT TargetRect;      
      public int BitRate;      
      public int BitErrorRate;      
      public long AvgTimePerFrame;      
      public BitmapInfoHeader BmiHeader;      
   }
   [StructLayout(LayoutKind.Sequential, Pack = 2)]     
   public class BitmapInfoHeader {      
      public int Size;      
      public int Width;      
      public int Height;      
      public short Planes;      
      public short BitCount;      
      public int Compression;      
      public int ImageSize;      
      public int XPelsPerMeter;      
      public int YPelsPerMeter;      
      public int ClrUsed;      
      public int ClrImportant;      
   }
   [StructLayout(LayoutKind.Sequential)]      
   public class RECT {      
      public int left;      
      public int top;      
      public int right;      
      public int bottom;      
   }
   [StructLayout(LayoutKind.Sequential)]     
   public class LONG {      
      private long Value;      
   }      
}

看起来很简单吗?确实很简单。但是有两个问题。一个是微软已经将所有这些接口 定义为已弃用。第二个(这可能是 DirectShow 被弃用的原因),这些接口并非真正可扩展。现在让我们看看如何在 Media Foundation 中完成。

使用 Media Foundation 检测媒体文件的编解码器

首先,我们需要创建解析器的源

IMFSourceResolver res;     
var hr = MFCreateSourceResolver(out res);

然后创建实际的解析器对象

IMFMediaSource source = null;     
var objectType = MF_OBJECT_TYPE.Invalid;      
object srs;      
hr = res.CreateObjectFromURL(filePath, MFResolution.MediaSource, null, out objectType, out srs);      
objectType == MF_OBJECT_TYPE.MediaSource;      
source = (IMFMediaSource)srs;

有了它,我们需要创建描述符。

IMFPresentationDescriptor desc;     
source.CreatePresentationDescriptor(out desc);

现在我们拥有了获取流计数和检索流所需的一切。

int count;     
desc.GetStreamDescriptorCount(out count);
for (int i = 0; i < count; i++) {     
IMFStreamDescriptor descriptor;      
bool selected;      
desc.GetStreamDescriptorByIndex(i, out selected, out descriptor);      
if (selected) {

让我们获取类型处理程序以获取格式

IMFMediaTypeHandler handler;     
descriptor.GetMediaTypeHandler(out handler);      
IMFMediaType type;      
handler.GetCurrentMediaType(out type);
Guid mediaType;     
type.GetMajorType(out mediaType);      
if (mediaType == MFMediaType.Video) {

然后获取实际的媒体类型和解码器代码

hr = MFCreateMFVideoFormatFromMFMediaType(type, out format, out size));     
var fourCC = FourCCToString(format.surfaceInfo.Format);

看起来比 DirectShow 方法更复杂。让我们看看实际的接口定义。

[DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)]     
public static extern void MFShutdown();
[DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)]     
public static extern void MFStartup(int Version, MFSTARTUP dwFlags);
[DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)]     
public static extern int MFCreateMFVideoFormatFromMFMediaType([In] 
IMFMediaType pMFType, out MFVIDEOFORMAT ppMFVF, out int pcbSize);      
      
[DllImport("mf.dll", ExactSpelling = true, PreserveSig = false)]      
public static extern int MFCreateSourceResolver(out IMFSourceResolver ppISourceResolver);
[DllImport("mf.dll", ExactSpelling = true, PreserveSig = false)]     
public static extern void MFGetService
([In, MarshalAs(UnmanagedType.Interface)] object punkObject, 
[In, MarshalAs(UnmanagedType.LPStruct)] Guid guidService, 
[In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, 
[Out, MarshalAs(UnmanagedType.Interface)] out object ppvObject);
#region INTERFACES
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), 
Guid("FBE5A32D-A497-4B61-BB85-97B1A848A6E3")]     
public interface IMFSourceResolver {      
   int CreateObjectFromURL([In, MarshalAs(UnmanagedType.LPWStr)] string pwszURL, 
   [In] MFResolution dwFlags, IPropertyStore pProps, out MF_OBJECT_TYPE pObjectType, 
   [MarshalAs(UnmanagedType.IUnknown)] out object ppObject);
   int CreateObjectFromByteStream([In, MarshalAs(UnmanagedType.Interface)] 
   IMFByteStream pByteStream, [In, MarshalAs(UnmanagedType.LPWStr)] string pwszURL, 
   [In] MFResolution dwFlags, 
   [In, MarshalAs(UnmanagedType.Interface)] IPropertyStore pProps, 
   out MF_OBJECT_TYPE pObjectType, [MarshalAs(UnmanagedType.IUnknown)] out object ppObject);
   int BeginCreateObjectFromURL([In, MarshalAs(UnmanagedType.LPWStr)] string pwszURL, 
   MFResolution dwFlags, IPropertyStore pProps, 
   [MarshalAs(UnmanagedType.IUnknown)] out object ppIUnknownCancelCookie, 
   IMFAsyncCallback pCallback, [In, MarshalAs(UnmanagedType.IUnknown)] object punkState);
   int EndCreateObjectFromURL(IMFAsyncResult pResult, out MF_OBJECT_TYPE pObjectType, 
   [MarshalAs(UnmanagedType.Interface)] out object ppObject);
   int BeginCreateObjectFromByteStream([In, MarshalAs(UnmanagedType.Interface)] 
   IMFByteStream pByteStream, [In, MarshalAs(UnmanagedType.LPWStr)] string pwszURL, 
   [In] MFResolution dwFlags, IPropertyStore pProps, [MarshalAs(UnmanagedType.IUnknown)] 
   out object ppIUnknownCancelCookie, IMFAsyncCallback pCallback, 
   [MarshalAs(UnmanagedType.IUnknown)] object punkState);
   int EndCreateObjectFromByteStream(IMFAsyncResult pResult, 
   out MF_OBJECT_TYPE pObjectType, [MarshalAs(UnmanagedType.IUnknown)] 
   out object ppObject);
   int CancelObjectCreation([In, MarshalAs(UnmanagedType.IUnknown)] 
   object pIUnknownCancelCookie);     
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), 
Guid("AD4C1B00-4BF7-422F-9175-756693D9130D")]     
public interface IMFByteStream {      
   void GetCapabilities(out MFBYTESTREAM pdwCapabilities);
   void GetLength(out long pqwLength);
   void SetLength([In] long qwLength);
   void GetCurrentPosition(out long pqwPosition);
   void SetCurrentPosition([In] long qwPosition);
   void IsEndOfStream([MarshalAs(UnmanagedType.Bool)] out bool pfEndOfStream);
   void Read(IntPtr pb, [In] int cb, out int pcbRead);
   void BeginRead(IntPtr pb, [In] int cb, 
   [In, MarshalAs(UnmanagedType.Interface)] 
   IMFAsyncCallback pCallback, [In, MarshalAs(UnmanagedType.IUnknown)] 
   object pUnkState);
   void EndRead([In, MarshalAs(UnmanagedType.Interface)] 
   IMFAsyncResult pResult, out int pcbRead);
   void Write(IntPtr pb, [In] int cb, out int pcbWritten);
   void BeginWrite(IntPtr pb, [In] int cb, 
   [In, MarshalAs(UnmanagedType.Interface)] IMFAsyncCallback pCallback, 
   [In, MarshalAs(UnmanagedType.IUnknown)] object pUnkState);
   void EndWrite([In, MarshalAs(UnmanagedType.Interface)] 
   IMFAsyncResult pResult, out int pcbWritten);
   void Seek([In] MFBYTESTREAM_SEEK_ORIGIN SeekOrigin, 
   [In] long llSeekOffset, [In] MFBYTESTREAM_SEEK_FLAG dwSeekFlags, 
   out long pqwCurrentPosition);
   void Flush();
   void Close();     
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), 
Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]     
public interface IPropertyStore {      
   [MethodImpl(MethodImplOptions.InternalCall, 
   MethodCodeType = MethodCodeType.Runtime)]      
   void GetCount(out uint cProps);
   [MethodImpl(MethodImplOptions.InternalCall, 
   MethodCodeType = MethodCodeType.Runtime)]     
   void GetAt([In] uint iProp, out PROPERTYKEY pkey);
   [MethodImpl(MethodImplOptions.InternalCall, 
   MethodCodeType = MethodCodeType.Runtime)]     
   void GetValue([In] PROPERTYKEY key, out PROPVARIANT pv);
   [MethodImpl(MethodImplOptions.InternalCall, 
   MethodCodeType = MethodCodeType.Runtime)]     
   void SetValue([In] PROPERTYKEY key, [In] ref PROPVARIANT  pv);
   [MethodImpl(MethodImplOptions.InternalCall, 
   MethodCodeType = MethodCodeType.Runtime)]     
   void Commit();      
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), 
Guid("A27003CF-2354-4F2A-8D6A-AB7CFF15437E")]     
public interface IMFAsyncCallback {      
   void GetParameters(out MFASYNC pdwFlags, out MFASYNC_CALLBACK_QUEUE pdwQueue);
   void Invoke([In, MarshalAs(UnmanagedType.Interface)] IMFAsyncResult pAsyncResult);     
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), 
Guid("AC6B7889-0740-4D51-8619-905994A55CC6")]     
public interface IMFAsyncResult {      
   void GetState([MarshalAs(UnmanagedType.IUnknown)] out object ppunkState);
   [PreserveSig]     
   int GetStatus();
   void SetStatus([In, MarshalAs(UnmanagedType.Error)] int hrStatus);
   void GetObject([MarshalAs(UnmanagedType.Interface)] out object ppObject);
   [PreserveSig]     
   IntPtr GetStateNoAddRef();      
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), 
Guid("DF598932-F10C-4E39-BBA2-C308F101DAA3")]     
public interface IMFMediaEvent : IMFAttributes {      
   #region IMFAttributes methods
   new void GetItem([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, IntPtr pValue);
   new void GetItemType([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out MF_ATTRIBUTE_TYPE pType);
   new void CompareItem([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, IntPtr Value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult);
   new void Compare([MarshalAs(UnmanagedType.Interface)] 
   IMFAttributes pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, 
   [MarshalAs(UnmanagedType.Bool)] out bool pbResult);
   new void GetUINT32([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out int punValue);
   new void GetUINT64([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out long punValue);
   new void GetDouble([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out double pfValue);
   new void GetGUID([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out Guid pguidValue);
   new void GetStringLength([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out int pcchLength);
   new void GetString([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, 
   int cchBufSize, out int pcchLength);
   new void GetAllocatedString([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, out int pcchLength);
   new void GetBlobSize([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out int pcbBlobSize);
   new void GetBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [Out, MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, out int pcbBlobSize);
   // Use GetBlob instead of this     
   new void GetAllocatedBlob([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out IntPtr ip, out int pcbSize);
   new void GetUnknown([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, 
   [MarshalAs(UnmanagedType.IUnknown)] out object ppv);
   new void SetItem([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, IntPtr Value);
   new void DeleteItem([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey);
   new void DeleteAllItems();
   new void SetUINT32([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, int unValue);
   new void SetUINT64([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, long unValue);
   new void SetDouble([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, double fValue);
   new void SetGUID([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [In, MarshalAs(UnmanagedType.LPStruct)] Guid guidValue);
   new void SetString([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [In, MarshalAs(UnmanagedType.LPWStr)] string wszValue);
   new void SetBlob([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [In, MarshalAs(UnmanagedType.LPArray, 
   SizeParamIndex = 2)] byte[] pBuf, int cbBufSize);
   new void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnknown);
   new void LockStore();
   new void UnlockStore();
   new void GetCount(out int pcItems);
   new void GetItemByIndex(int unIndex, out Guid pguidKey, IntPtr pValue);
   new void CopyAllItems([In, MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest);
   #endregion     
   void GetType(out MediaEventType pmet);
   void GetExtendedType(out Guid pguidExtendedType);
   void GetStatus([MarshalAs(UnmanagedType.Error)] out int phrStatus);
   void GetValue([In, Out] ref object pvValue);     
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), 
Guid("03CB2711-24D7-4DB6-A17F-F3A7A479A536")]     
public interface IMFPresentationDescriptor : IMFAttributes {
   #region IMFAttributes methods
   new void GetItem([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, IntPtr pValue);
   new void GetItemType([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out MF_ATTRIBUTE_TYPE pType);
   new void CompareItem([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, IntPtr Value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult);
   new void Compare([MarshalAs(UnmanagedType.Interface)] 
   IMFAttributes pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, 
   [MarshalAs(UnmanagedType.Bool)] out bool pbResult);
   new void GetUINT32([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out int punValue);
   new void GetUINT64([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out long punValue);
   new void GetDouble([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out double pfValue);
   new void GetGUID([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out Guid pguidValue);
   new void GetStringLength([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out int pcchLength);
   new void GetString([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, 
   int cchBufSize, out int pcchLength);
   new void GetAllocatedString([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] 
   out string ppwszValue, out int pcchLength);
   new void GetBlobSize([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out int pcbBlobSize);
   new void GetBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [Out, MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, out int pcbBlobSize);
   // Use GetBlob instead of this     
   new void GetAllocatedBlob([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out IntPtr ip, out int pcbSize);
   new void GetUnknown([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, 
   [MarshalAs(UnmanagedType.IUnknown)] out object ppv);
   new void SetItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr Value);
   new void DeleteItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey);
   new void DeleteAllItems();
   new void SetUINT32([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue);
   new void SetUINT64([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue);
   new void SetDouble([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue);
   new void SetGUID([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [In, MarshalAs(UnmanagedType.LPStruct)] Guid guidValue);
   new void SetString([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [In, MarshalAs(UnmanagedType.LPWStr)] string wszValue);
   new void SetBlob([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [In, MarshalAs(UnmanagedType.LPArray, 
   SizeParamIndex = 2)] byte[] pBuf, int cbBufSize);
   new void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnknown);
   new void LockStore();
   new void UnlockStore();
   new void GetCount(out int pcItems);
   new void GetItemByIndex(int unIndex, out Guid pguidKey, IntPtr pValue);
   new void CopyAllItems([In, MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest);
   #endregion
   void GetStreamDescriptorCount(out int pdwDescriptorCount);
   void GetStreamDescriptorByIndex([In] int dwIndex, 
   [MarshalAs(UnmanagedType.Bool)] out bool pfSelected, 
   [MarshalAs(UnmanagedType.Interface)] out IMFStreamDescriptor ppDescriptor);
   void SelectStream([In] int dwDescriptorIndex);
   void DeselectStream([In] int dwDescriptorIndex);
   void Clone([MarshalAs(UnmanagedType.Interface)] 
   out IMFPresentationDescriptor ppPresentationDescriptor);     
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), 
Guid("56C03D9C-9DBB-45F5-AB4B-D80F47C05938")]     
public interface IMFStreamDescriptor : IMFAttributes {      
   #region IMFAttributes methods
   new void GetItem([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, IntPtr pValue);
   new void GetItemType([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out MF_ATTRIBUTE_TYPE pType);
   new void CompareItem([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, IntPtr Value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult);
   new void Compare([MarshalAs(UnmanagedType.Interface)] 
   IMFAttributes pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, 
   [MarshalAs(UnmanagedType.Bool)] out bool pbResult);
   new void GetUINT32([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out int punValue);
   new void GetUINT64([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out long punValue);
   new void GetDouble([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out double pfValue);
   new void GetGUID([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out Guid pguidValue);
   new void GetStringLength([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out int pcchLength);
   new void GetString([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [Out, MarshalAs(UnmanagedType.LPWStr)] 
   StringBuilder pwszValue, int cchBufSize, out int pcchLength);
   new void GetAllocatedString([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, out int pcchLength);
   new void GetBlobSize([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out int pcbBlobSize);
   new void GetBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [Out, MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, out int pcbBlobSize);
   // Use GetBlob instead of this     
   new void GetAllocatedBlob([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out IntPtr ip, out int pcbSize);
   new void GetUnknown([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, 
   [MarshalAs(UnmanagedType.IUnknown)] out object ppv);
   new void SetItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr Value);
   new void DeleteItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey);
   new void DeleteAllItems();
   new void SetUINT32
   ([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue);
   new void SetUINT64
   ([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue);
   new void SetDouble
   ([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue);
   new void SetGUID
   ([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [In, MarshalAs(UnmanagedType.LPStruct)] Guid guidValue);
   new void SetString([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [In, MarshalAs(UnmanagedType.LPWStr)] string wszValue);
   new void SetBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, int cbBufSize);
   new void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [In, MarshalAs(UnmanagedType.IUnknown)] object pUnknown);
   new void LockStore();
   new void UnlockStore();
   new void GetCount(out int pcItems);
   new void GetItemByIndex(int unIndex, out Guid pguidKey, IntPtr pValue);
   new void CopyAllItems
   ([In, MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest);
   #endregion
   void GetStreamIdentifier(out int pdwStreamIdentifier);
   void GetMediaTypeHandler([MarshalAs(UnmanagedType.Interface)] 
   out IMFMediaTypeHandler ppMediaTypeHandler);     
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), 
Guid("44AE0FA8-EA31-4109-8D2E-4CAE4997C555")]     
public interface IMFMediaType : IMFAttributes {
   #region IMFAttributes methods
   new void GetItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   IntPtr pValue);
   new void GetItemType([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out MF_ATTRIBUTE_TYPE pType);
   new void CompareItem([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, IntPtr Value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult);
   new void Compare([MarshalAs(UnmanagedType.Interface)] 
   IMFAttributes pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, 
   [MarshalAs(UnmanagedType.Bool)] out bool pbResult);
   new void GetUINT32([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out int punValue);
   new void GetUINT64([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out long punValue);
   new void GetDouble([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out double pfValue);
   new void GetGUID([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out Guid pguidValue);
   new void GetStringLength([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out int pcchLength);
   new void GetString([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, 
   int cchBufSize, out int pcchLength);
   new void GetAllocatedString([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, out int pcchLength);
   new void GetBlobSize([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   out int pcbBlobSize);
   new void GetBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [Out, MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, out int pcbBlobSize);
   // Use GetBlob instead of this     
   new void GetAllocatedBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   out IntPtr ip, out int pcbSize);
   new void GetUnknown([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, 
   [MarshalAs(UnmanagedType.IUnknown)] out object ppv);
   new void SetItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr Value);
   new void DeleteItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey);
   new void DeleteAllItems();
   new void SetUINT32
   ([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue);
   new void SetUINT64
   ([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue);
   new void SetDouble
   ([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue);
   new void SetGUID
   ([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [In, MarshalAs(UnmanagedType.LPStruct)] Guid guidValue);
   new void SetString
   ([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [In, MarshalAs(UnmanagedType.LPWStr)] string wszValue);
   new void SetBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, int cbBufSize);
   new void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [In, MarshalAs(UnmanagedType.IUnknown)] object pUnknown);
   new void LockStore();
   new void UnlockStore();
   new void GetCount(out int pcItems);
   new void GetItemByIndex(int unIndex, out Guid pguidKey, IntPtr pValue);
   new void CopyAllItems([In, MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest);
   #endregion
   void GetMajorType(out Guid pguidMajorType);
   void IsCompressedFormat([MarshalAs(UnmanagedType.Bool)] out bool pfCompressed);
   [PreserveSig]     
   int IsEqual([In, MarshalAs(UnmanagedType.Interface)] 
   IMFMediaType pIMediaType, out MF_MEDIATYPE_EQUAL pdwFlags);
   void GetRepresentation([In, MarshalAs(UnmanagedType.Struct)] 
   Guid guidRepresentation, out IntPtr ppvRepresentation);
   void FreeRepresentation([In, MarshalAs(UnmanagedType.Struct)] 
   Guid guidRepresentation, [In] IntPtr pvRepresentation);     
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), 
Guid("2CD2D921-C447-44A7-A13C-4ADABFC247E3")]     
public interface IMFAttributes {      
   void GetItem([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, IntPtr pValue);
   void GetItemType([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out MF_ATTRIBUTE_TYPE pType);
   void CompareItem([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, IntPtr Value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult);
   void Compare([MarshalAs(UnmanagedType.Interface)] 
   IMFAttributes pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, 
   [MarshalAs(UnmanagedType.Bool)] out bool pbResult);
   void GetUINT32([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out int punValue);
   void GetUINT64([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out long punValue);
   void GetDouble([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out double pfValue);
   void GetGUID([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out Guid pguidValue);
   void GetStringLength([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out int pcchLength);
   void GetString([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, 
   int cchBufSize, out int pcchLength);
   void GetAllocatedString([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, out int pcchLength);
   void GetBlobSize([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out int pcbBlobSize);
   void GetBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [Out, MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, out int pcbBlobSize);
   void GetAllocatedBlob([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, out IntPtr ip, out int pcbSize);
   void GetUnknown([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, 
   [MarshalAs(UnmanagedType.IUnknown)] out object ppv);
   void SetItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr Value);
   void DeleteItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey);
   void DeleteAllItems();
   void SetUINT32([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, int unValue);
   void SetUINT64([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, long unValue);
   void SetDouble([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, double fValue);
   void SetGUID([In, MarshalAs(UnmanagedType.LPStruct)] 
   Guid guidKey, [In, MarshalAs(UnmanagedType.LPStruct)] Guid guidValue);
   void SetString([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [In, MarshalAs(UnmanagedType.LPWStr)] string wszValue);
   void SetBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, int cbBufSize);
   void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, 
   [In, MarshalAs(UnmanagedType.IUnknown)] object pUnknown);
   void LockStore();
   void UnlockStore();
   void GetCount(out int pcItems);
   void GetItemByIndex(int unIndex, out Guid pguidKey, IntPtr pValue);
   void CopyAllItems([In, MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest);     
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), 
Guid("2CD0BD52-BCD5-4B89-B62C-EADC0C031E7D")]     
public interface IMFMediaEventGenerator {      
   void GetEvent([In] IMFMediaEvent dwFlags, 
   [MarshalAs(UnmanagedType.Interface)] out IMFMediaEvent ppEvent);
   void BeginGetEvent([In, MarshalAs(UnmanagedType.Interface)] 
   IMFAsyncCallback pCallback, [In, MarshalAs(UnmanagedType.IUnknown)] object o);
   void EndGetEvent(IMFAsyncResult pResult, out IMFMediaEvent ppEvent);
   void QueueEvent([In] MediaEventType met, 
   [In, MarshalAs(UnmanagedType.LPStruct)] Guid guidExtendedType, 
   [In] int hrStatus, [In] ref object pvValue);     
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), 
Guid("E93DCF6C-4B07-4E1E-8123-AA16ED6EADF5")]     
public interface IMFMediaTypeHandler {      
   void IsMediaTypeSupported([In, MarshalAs(UnmanagedType.Interface)] 
   IMFMediaType pMediaType, IntPtr ppMediaType);
   void GetMediaTypeCount(out int pdwTypeCount);
   void GetMediaTypeByIndex([In] int dwIndex, 
   [MarshalAs(UnmanagedType.Interface)] out IMFMediaType ppType);
   void SetCurrentMediaType([In, MarshalAs(UnmanagedType.Interface)] 
   IMFMediaType pMediaType);
   void GetCurrentMediaType([MarshalAs(UnmanagedType.Interface)] out 
   IMFMediaType ppMediaType);
   void GetMajorType(out Guid pguidMajorType);     
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), 
Guid("279A808D-AEC7-40C8-9C6B-A6B492C78A66")]      
public interface IMFMediaSource : IMFMediaEventGenerator {      
   #region IMFMediaEventGenerator methods
   #pragma warning disable 109     
   new void GetEvent([In] MF_EVENT_FLAG dwFlags, 
   [MarshalAs(UnmanagedType.Interface)] out IMFMediaEvent ppEvent);      
   #pragma warning restore 109
   new void BeginGetEvent([In, MarshalAs(UnmanagedType.Interface)] 
   IMFAsyncCallback pCallback, [In, MarshalAs(UnmanagedType.IUnknown)] object o);
   new void EndGetEvent(IMFAsyncResult pResult, out IMFMediaEvent ppEvent);
   new void QueueEvent([In] MediaEventType met, 
   [In, MarshalAs(UnmanagedType.LPStruct)] Guid guidExtendedType, 
   [In] int hrStatus, [In] ref object pvValue);
   #endregion
   void GetCharacteristics(out MFMEDIASOURCE_CHARACTERISTICS pdwCharacteristics);
   void CreatePresentationDescriptor
   (out IMFPresentationDescriptor ppPresentationDescriptor);
   void Start([In, MarshalAs(UnmanagedType.Interface)] 
   IMFPresentationDescriptor pPresentationDescriptor, 
   [In, MarshalAs(UnmanagedType.LPStruct)] Guid pguidTimeFormat, 
   [In] ref object pvarStartPosition);
   void Stop();
   void Pause();
   void Shutdown();     
}
#endregion

还有一些数据对象

#region WM
      #region STRUCTS     
      #pragma warning restore 618
      [StructLayout(LayoutKind.Sequential, Pack = 8)]     
      public class MFVIDEOFORMAT {      
         public int dwSize;      
         public MFVideoInfo videoInfo;      
         public Guid guidFormat;      
         public MFVideoCompressedInfo compressedInfo;      
         public MFVideoSurfaceInfo surfaceInfo;      
      }
      [StructLayout(LayoutKind.Sequential, Pack = 4)]     
      public struct MFVideoSurfaceInfo {      
         public int Format;      
         public int PaletteEntries;      
         public MFPaletteEntry[] Palette;      
      }
      [StructLayout(LayoutKind.Explicit, Pack = 1)]     
      public struct MFPaletteEntry {      
         [FieldOffset(0)]      
         public MFARGB ARGB;      
         [FieldOffset(0)]      
         public MFAYUVSample AYCbCr;      
      }
      [StructLayout(LayoutKind.Sequential, Pack = 1)]     
      public struct MFAYUVSample {      
         public byte bCrValue;      
         public byte bCbValue;      
         public byte bYValue;      
         public byte bSampleAlpha8;      
      }
      [StructLayout(LayoutKind.Sequential, Pack = 1)]     
      public struct MFARGB {      
         public byte rgbBlue;      
         public byte rgbGreen;      
         public byte rgbRed;      
         public byte rgbAlpha;      
      }
      [StructLayout(LayoutKind.Sequential, Pack = 8)]     
      public struct MFVideoCompressedInfo {      
         public long AvgBitrate;      
         public long AvgBitErrorRate;      
         public int MaxKeyFrameSpacing;      
      }
      [StructLayout(LayoutKind.Sequential, Pack = 8)]     
      public struct MFVideoInfo {      
         public int dwWidth;      
         public int dwHeight;      
         public MFRatio PixelAspectRatio;      
         public MFVideoChromaSubsampling SourceChromaSubsampling;      
         public MFVideoInterlaceMode InterlaceMode;      
         public MFVideoTransferFunction TransferFunction;      
         public MFVideoPrimaries ColorPrimaries;      
         public MFVideoTransferMatrix TransferMatrix;      
         public MFVideoLighting SourceLighting;      
         public MFRatio FramesPerSecond;      
         public MFNominalRange NominalRange;      
         public MFVideoArea GeometricAperture;      
         public MFVideoArea MinimumDisplayAperture;      
         public MFVideoArea PanScanAperture;      
         public MFVideoFlags VideoFlags;      
      }
      [StructLayout(LayoutKind.Sequential, Pack = 4)]     
      public struct MFRatio {      
         public int Numerator;      
         public int Denominator;
         public MFRatio(int n, int d) {     
            Numerator = n;      
            Denominator = d;      
         }      
      }
      [StructLayout(LayoutKind.Sequential, Pack = 4)]     
      public class MFVideoArea {      
         public MFOffset OffsetX;      
         public MFOffset OffsetY;      
         public SIZE Area;
         public MFVideoArea() {     
            OffsetX = new MFOffset();      
            OffsetY = new MFOffset();      
         }
         public MFVideoArea(float x, float y, int width, int height) {     
            OffsetX = new MFOffset(x);      
            OffsetY = new MFOffset(y);      
            Area = new SIZE(width, height);      
         }
         public void MakeArea(float x, float y, int width, int height) {     
            OffsetX.MakeOffset(x);      
            OffsetY.MakeOffset(y);      
            Area.cx = width;      
            Area.cy = height;      
         }      
      }
      [StructLayout(LayoutKind.Sequential, Pack = 2)]     
      public class MFOffset {      
         public short fract;      
         public short Value;
         public MFOffset() {     
         }
         public MFOffset(float v) {     
            Value = (short)v;      
            fract = (short)(65536 * (v – Value));      
         }
         public void MakeOffset(float v) {     
            Value = (short)v;      
            fract = (short)(65536 * (v – Value));      
         }
         public float GetOffset() {     
            return ((float)Value) + (((float)fract) / 65536.0f);      
         }      
      }      
      #endregion
      #region ENUMS     
      public enum MFVideoInterlaceMode {      
         FieldInterleavedLowerFirst = 4,      
         FieldInterleavedUpperFirst = 3,      
         FieldSingleLower = 6,      
         FieldSingleUpper = 5,      
         ForceDWORD = 0x7fffffff,      
         Last = 8,      
         MixedInterlaceOrProgressive = 7,      
         Progressive = 2,      
         Unknown = 0      
      }
      public enum MFVideoChromaSubsampling {     
         Cosited = 7,      
         DV_PAL = 6,      
         ForceDWORD = 0x7fffffff,      
         Horizontally_Cosited = 4,      
         Last = 8,      
         MPEG1 = 1,      
         MPEG2 = 5,      
         ProgressiveChroma = 8,      
         Unknown = 0,      
         Vertically_AlignedChromaPlanes = 1,      
         Vertically_Cosited = 2      
      }
      public enum MFVideoTransferFunction {     
         Func10 = 1,      
         Func18 = 2,      
         Func20 = 3,      
         Func22 = 4,      
         Func240M = 6,      
         Func28 = 8,      
         Func709 = 5,      
         ForceDWORD = 0x7fffffff,      
         Last = 9,      
         sRGB = 7,      
         Unknown = 0      
      }
      public enum MFVideoPrimaries {     
         BT470_2_SysBG = 4,      
         BT470_2_SysM = 3,      
         BT709 = 2,      
         EBU3213 = 7,      
         ForceDWORD = 0x7fffffff,      
         Last = 9,      
         reserved = 1,      
         SMPTE_C = 8,      
         SMPTE170M = 5,      
         SMPTE240M = 6,      
         Unknown = 0      
      }
      public enum MFVideoTransferMatrix {     
         BT601 = 2,      
         BT709 = 1,      
         ForceDWORD = 0x7fffffff,      
         Last = 4,      
         SMPTE240M = 3,      
         Unknown = 0      
      }
      public enum MFVideoLighting {     
         Bright = 1,      
         Dark = 4,      
         Dim = 3,      
         ForceDWORD = 0x7fffffff,      
         Last = 5,      
         Office = 2,      
         Unknown = 0      
      }
      public enum MFNominalRange {     
         MFNominalRange_0_255 = 1,      
         MFNominalRange_16_235 = 2,      
         MFNominalRange_48_208 = 3,      
         MFNominalRange_ForceDWORD = 0x7fffffff,      
         MFNominalRange_Last = 4,      
         MFNominalRange_Normal = 1,      
         MFNominalRange_Unknown = 0,      
         MFNominalRange_Wide = 2      
      }
      [Flags]     
      public enum MFVideoFlags : long {      
         PAD_TO_Mask = 0×0001 | 0×0002,      
         PAD_TO_None = 0 * 0×0001,      
         PAD_TO_4x3 = 1 * 0×0001,      
         PAD_TO_16x9 = 2 * 0×0001,      
         SrcContentHintMask = 0×0004 | 0×0008 | 0×0010,      
         SrcContentHintNone = 0 * 0×0004,      
         SrcContentHint16x9 = 1 * 0×0004,      
         SrcContentHint235_1 = 2 * 0×0004,      
         AnalogProtected = 0×0020,      
         DigitallyProtected = 0×0040,      
         ProgressiveContent = 0×0080,      
         FieldRepeatCountMask = 0×0100 | 0×0200 | 0×0400,      
         FieldRepeatCountShift = 8,      
         ProgressiveSeqReset = 0×0800,      
         PanScanEnabled = 0×20000,      
         LowerFieldFirst = 0×40000,      
         BottomUpLinearRep = 0×80000,      
         DXVASurface = 0×100000,      
         RenderTargetSurface = 0×400000,      
         ForceQWORD = 0x7FFFFFFF      
      }
      [Flags]     
      public enum MF_EVENT_FLAG {      
         None = 0,      
         NoWait = 0×00000001      
      }
      public enum MFASYNC_CALLBACK_QUEUE {     
         Undefined = 0×00000000,      
         Standard = 0×00000001,      
         RT = 0×00000002,      
         IO = 0×00000003,      
         Timer = 0×00000004,      
         LongFunction = 0×00000007,      
         PrivateMask = unchecked((int)0xFFFF0000),      
         All = unchecked((int)0xFFFFFFFF)      
      }
      [Flags]     
      public enum MFASYNC {      
         None = 0,      
         FastIOProcessingCallback = 0×00000001,      
         SignalCallback = 0×00000002      
      }
      public enum MFSTARTUP {     
         NoSocket = 0×1,      
         Lite = 0×1,      
         Full = 0      
      }
      [Flags]     
      public enum MFResolution {      
         None = 0×0,      
         MediaSource = 0×00000001,      
         ByteStream = 0×00000002,      
         ContentDoesNotHaveToMatchExtensionOrMimeType = 0×00000010,      
         KeepByteStreamAliveOnFail = 0×00000020,      
         Read = 0×00010000,      
         Write = 0×00020000      
      }
      [Flags]     
      public enum MFBYTESTREAM {      
         None = 0×00000000,      
         IsReadable = 0×00000001,      
         IsWritable = 0×00000002,      
         IsSeekable = 0×00000004,      
         IsRemote = 0×00000008,      
         IsDirectory = 0×00000080,      
         HasSlowSeek = 0×00000100,      
         IsPartiallyDownloaded = 0×00000200      
      }
      public enum MFBYTESTREAM_SEEK_ORIGIN {     
         Begin,      
         Current      
      }
      [Flags]     
      public enum MFBYTESTREAM_SEEK_FLAG {      
         None = 0,      
         CancelPendingIO = 1      
      }
      public enum MF_OBJECT_TYPE {     
         MediaSource,      
         ByteStream,      
         Invalid      
      }
      public enum MediaEventType {     
         MEUnknown = 0,      
         MEError = (MEUnknown + 1),      
         MEExtendedType = (MEError + 1),      
         MESessionUnknown = 100,      
         MESessionTopologySet = (MESessionUnknown + 1),      
         MESessionTopologiesCleared = (MESessionTopologySet + 1),      
         MESessionStarted = (MESessionTopologiesCleared + 1),      
         MESessionPaused = (MESessionStarted + 1),      
         MESessionStopped = (MESessionPaused + 1),      
         MESessionClosed = (MESessionStopped + 1),      
         MESessionEnded = (MESessionClosed + 1),      
         MESessionRateChanged = (MESessionEnded + 1),      
         MESessionScrubSampleComplete = (MESessionRateChanged + 1),      
         MESessionCapabilitiesChanged = (MESessionScrubSampleComplete + 1),      
         MESessionTopologyStatus = (MESessionCapabilitiesChanged + 1),      
         MESessionNotifyPresentationTime = (MESessionTopologyStatus + 1),      
         MENewPresentation = (MESessionNotifyPresentationTime + 1),      
         MELicenseAcquisitionStart = (MENewPresentation + 1),      
         MELicenseAcquisitionCompleted = (MELicenseAcquisitionStart + 1),      
         MEIndividualizationStart = (MELicenseAcquisitionCompleted + 1),      
         MEIndividualizationCompleted = (MEIndividualizationStart + 1),      
         MEEnablerProgress = (MEIndividualizationCompleted + 1),      
         MEEnablerCompleted = (MEEnablerProgress + 1),      
         MEPolicyError = (MEEnablerCompleted + 1),      
         MEPolicyReport = (MEPolicyError + 1),      
         MEBufferingStarted = (MEPolicyReport + 1),      
         MEBufferingStopped = (MEBufferingStarted + 1),      
         MEConnectStart = (MEBufferingStopped + 1),      
         MEConnectEnd = (MEConnectStart + 1),      
         MEReconnectStart = (MEConnectEnd + 1),      
         MEReconnectEnd = (MEReconnectStart + 1),      
         MERendererEvent = (MEReconnectEnd + 1),      
         MESessionStreamSinkFormatChanged = (MERendererEvent + 1),      
         MESourceUnknown = 200,      
         MESourceStarted = (MESourceUnknown + 1),      
         MEStreamStarted = (MESourceStarted + 1),      
         MESourceSeeked = (MEStreamStarted + 1),      
         MEStreamSeeked = (MESourceSeeked + 1),      
         MENewStream = (MEStreamSeeked + 1),      
         MEUpdatedStream = (MENewStream + 1),      
         MESourceStopped = (MEUpdatedStream + 1),      
         MEStreamStopped = (MESourceStopped + 1),      
         MESourcePaused = (MEStreamStopped + 1),      
         MEStreamPaused = (MESourcePaused + 1),      
         MEEndOfPresentation = (MEStreamPaused + 1),      
         MEEndOfStream = (MEEndOfPresentation + 1),      
         MEMediaSample = (MEEndOfStream + 1),      
         MEStreamTick = (MEMediaSample + 1),      
         MEStreamThinMode = (MEStreamTick + 1),      
         MEStreamFormatChanged = (MEStreamThinMode + 1),      
         MESourceRateChanged = (MEStreamFormatChanged + 1),      
         MEEndOfPresentationSegment = (MESourceRateChanged + 1),      
         MESourceCharacteristicsChanged = (MEEndOfPresentationSegment + 1),      
         MESourceRateChangeRequested = (MESourceCharacteristicsChanged + 1),      
         MESourceMetadataChanged = (MESourceRateChangeRequested + 1),      
         MESequencerSourceTopologyUpdated = (MESourceMetadataChanged + 1),      
         MESinkUnknown = 300,      
         MEStreamSinkStarted = (MESinkUnknown + 1),      
         MEStreamSinkStopped = (MEStreamSinkStarted + 1),      
         MEStreamSinkPaused = (MEStreamSinkStopped + 1),      
         MEStreamSinkRateChanged = (MEStreamSinkPaused + 1),      
         MEStreamSinkRequestSample = (MEStreamSinkRateChanged + 1),      
         MEStreamSinkMarker = (MEStreamSinkRequestSample + 1),      
         MEStreamSinkPrerolled = (MEStreamSinkMarker + 1),      
         MEStreamSinkScrubSampleComplete = (MEStreamSinkPrerolled + 1),      
         MEStreamSinkFormatChanged = (MEStreamSinkScrubSampleComplete + 1),      
         MEStreamSinkDeviceChanged = (MEStreamSinkFormatChanged + 1),      
         MEQualityNotify = (MEStreamSinkDeviceChanged + 1),      
         MESinkInvalidated = (MEQualityNotify + 1),      
         MEAudioSessionNameChanged = (MESinkInvalidated + 1),      
         MEAudioSessionVolumeChanged = (MEAudioSessionNameChanged + 1),      
         MEAudioSessionDeviceRemoved = (MEAudioSessionVolumeChanged + 1),      
         MEAudioSessionServerShutdown = (MEAudioSessionDeviceRemoved + 1),      
         MEAudioSessionGroupingParamChanged = (MEAudioSessionServerShutdown + 1),      
         MEAudioSessionIconChanged = (MEAudioSessionGroupingParamChanged + 1),      
         MEAudioSessionFormatChanged = (MEAudioSessionIconChanged + 1),      
         MEAudioSessionDisconnected = (MEAudioSessionFormatChanged + 1),      
         MEAudioSessionExclusiveModeOverride = (MEAudioSessionDisconnected + 1),      
         METrustUnknown = 400,      
         MEPolicyChanged = (METrustUnknown + 1),      
         MEContentProtectionMessage = (MEPolicyChanged + 1),      
         MEPolicySet = (MEContentProtectionMessage + 1),      
         MEWMDRMLicenseBackupCompleted = 500,      
         MEWMDRMLicenseBackupProgress = 501,      
         MEWMDRMLicenseRestoreCompleted = 502,      
         MEWMDRMLicenseRestoreProgress = 503,      
         MEWMDRMLicenseAcquisitionCompleted = 506,      
         MEWMDRMIndividualizationCompleted = 508,      
         MEWMDRMIndividualizationProgress = 513,      
         MEWMDRMProximityCompleted = 514,      
         MEWMDRMLicenseStoreCleaned = 515,      
         MEWMDRMRevocationDownloadCompleted = 516,      
         MEReservedMax = 10000      
      }
      public enum MF_ATTRIBUTE_TYPE {     
         None = 0×0,      
         Blob = 0×1011,      
         Double = 0×5,      
         Guid = 0×48,      
         IUnknown = 13,      
         String = 0x1f,      
         Uint32 = 0×13,      
         Uint64 = 0×15      
      }
      public enum MF_ATTRIBUTES_MATCH_TYPE {     
         OurItems,      
         TheirItems,      
         AllItems,      
         InterSection,      
         Smaller      
      }
      [Flags]     
      public enum MFMEDIASOURCE_CHARACTERISTICS {      
         None = 0,      
         IsLive = 0×1,      
         CanSeek = 0×2,      
         CanPause = 0×4,      
         HasSlowSeek = 0×8      
      }
      [Flags]     
      public enum MF_MEDIATYPE_EQUAL {      
         None = 0,      
         MajorTypes = 0×00000001,      
         FormatTypes = 0×00000002,      
         FormatData = 0×00000004,      
         FormatUserData = 0×00000008      
      }      
      #endregion
      #endregion

有些繁琐,对吧?确实如此!但是这些接口是可扩展的。例如,这种方法增加了一些价值。

使用 Media Foundation 读取媒体元数据

现在,当我们完成了大部分工作后,元数据就变得轻而易举了。我们所需要做的就是获取服务句柄...

object s;     
MFGetService(source, MFServices.MF_PROPERTY_HANDLER_SERVICE, typeof(IPropertyStore).GUID, out s);      
var store = (IPropertyStore)s;

...并从属性包中获取信息

track.Album = _getInfo<string>(store, MFPropertyKeys.AlbumTitle);     
track.Name = _getInfo<string>(store, MFPropertyKeys.Title);      
track.Comments = _getInfo<string>(store, MFPropertyKeys.Comment);      
track.Duration = TimeSpan.FromTicks(_getInfo<long>(store, Interop.MFPropertyKeys.MediaDuration));      
…

这些接口使用 COM 属性包来检索不变类型的信息

private static T _getInfo<T>(IPropertyStore store, PROPERTYKEY key) {     
         PROPVARIANT val;      
         store.GetValue(key, out val);      
        return (T)val.Value;      
      }

这是此对象在托管代码中的外观

[StructLayout(LayoutKind.Sequential)]     
public class PROPERTYKEY {
public PROPERTYKEY(Guid tid, uint id) {     
fmtid = tid;      
pid = id;      
}
public Guid fmtid;
public uint pid;     
}
#pragma warning disable 618     
[StructLayout(LayoutKind.Explicit)]      
public struct PROPVARIANT {      
[FieldOffset(0)]      
short vt;      
[FieldOffset(2)]      
short wReserved1;      
[FieldOffset(4)]      
short wReserved2;      
[FieldOffset(6)]      
short wReserved3;      
[FieldOffset(8)]      
sbyte cVal;      
[FieldOffset(8)]      
byte bVal;      
[FieldOffset(8)]      
short iVal;      
[FieldOffset(8)]      
ushort uiVal;      
[FieldOffset(8)]      
int lVal;      
[FieldOffset(8)]      
uint ulVal;      
[FieldOffset(8)]      
int intVal;      
[FieldOffset(8)]      
uint uintVal;      
[FieldOffset(8)]      
long hVal;      
[FieldOffset(8)]      
long uhVal;      
[FieldOffset(8)]      
float fltVal;      
[FieldOffset(8)]      
double dblVal;      
[FieldOffset(8)]      
bool boolVal;      
[FieldOffset(8)]      
int scode;      
[FieldOffset(8)]      
DateTime date;      
[FieldOffset(8)]      
FILETIME filetime;      
[FieldOffset(8)]      
BLOB blobVal;      
[FieldOffset(8)]      
IntPtr pwszVal;
private byte[] _getBlob() {     
var result = new byte[blobVal.cbSize];      
Marshal.Copy(blobVal.pBlobData, result, 0, result.Length);      
return result;      
}
public object Value {     
get {      
VarEnum ve = (VarEnum)vt;      
switch (ve) {      
case VarEnum.VT_I1:      
return bVal;      
case VarEnum.VT_I2:      
return iVal;      
case VarEnum.VT_I4:      
return lVal;      
case VarEnum.VT_I8:      
return hVal;      
case VarEnum.VT_INT:      
return iVal;      
case VarEnum.VT_UI4:      
return ulVal;      
case VarEnum.VT_UI8:      
return uhVal;      
case VarEnum.VT_LPWSTR:      
return Marshal.PtrToStringUni(pwszVal);      
case VarEnum.VT_BLOB:      
return _getBlob();      
case VarEnum.VT_EMPTY:      
case VarEnum.VT_NULL:      
return null;      
}      
throw new NotImplementedException("PROPVARIANT: " + ve.ToString());      
}      
}      
}

还有一些额外的类和 GUID 来完成解决方案

public static class MFAttributesClsid {     
public static readonly Guid MF_PD_DURATION = new Guid
(0x6c990d33, 0xbb8e, 0x477a, 0×85, 
0×98, 0xd, 0x5d, 0×96, 0xfc, 0xd8, 0x8a);      
public static readonly Guid MF_MT_SUBTYPE = 
new Guid(0xf7e34c9a, 0x42e8, 0×4714, 0xb7, 0x4b, 0xcb, 
0×29, 0xd7, 0x2c, 0×35, 0xe5);      
public static readonly Guid MF_MT_AVG_BITRATE = 
new Guid(0×20332624, 0xfb0d, 0x4d9e, 0xbd, 0x0d, 0xcb, 0xf6, 
0×78, 0x6c, 0×10, 0x2e);      
}
public static class MFMediaType {     
public static readonly Guid Default = new Guid(0x81A412E6, 
0×8103, 0x4B06, 0×85, 0x7F, 0×18, 0×62, 
0×78, 0×10, 0×24, 0xAC);      
public static readonly Guid Audio = new Guid(0×73647561, 
0×0000, 0×0010, 0×80, 0×00, 0×00, 
0xAA, 0×00, 0×38, 0x9B, 0×71);      
public static readonly Guid Video = new Guid(0×73646976, 
0×0000, 0×0010, 0×80, 0×00, 0×00, 
0xAA, 0×00, 0×38, 0x9B, 0×71);      
}
public static class MFServices {     
public static readonly Guid MF_PROPERTY_HANDLER_SERVICE = 
new Guid(0xa3face02, 0x32b8, 0x41dd, 0×90, 0xe7, 0x5f, 0xef, 
0x7c, 0×89, 0×91, 0xb5);      
}
public static class MFPropertyKeys {     
public static readonly PROPERTYKEY Title = new PROPERTYKEY
(new Guid(0xf29f85e0, 0x4ff9, 0×1068, 0xab, 0×91, 
0×08, 0×00, 0x2b, 0×27, 0xb3, 0xd9), 2);      
public static readonly PROPERTYKEY AlbumTitle = new PROPERTYKEY
(new Guid(0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0×00, 
0×60, 0×97, 0xC6, 0×86, 0xF6), 4);      
public static readonly PROPERTYKEY Author = new PROPERTYKEY
(new Guid(0xF29F85E0, 0x4FF9, 0×1068, 0xAB, 0×91, 
0×08, 0×00, 0x2B, 0×27, 0xB3, 0xD9), 4);      
public static readonly PROPERTYKEY AudioCompression = 
new PROPERTYKEY(new Guid(0×64440490, 0x4C8B, 0x11D1, 0x8B, 
0×70, 0×08, 0×00, 0×36, 0xB1, 0x1A, 0×03), 10);      
public static readonly PROPERTYKEY AudioFormat = new PROPERTYKEY
(new Guid(0×64440490, 0x4C8B, 0x11D1, 0x8B, 0×70, 
0×08, 0×00, 0×36, 0xB1, 0x1A, 0×03), 2);      
public static readonly PROPERTYKEY Category = new PROPERTYKEY
(new Guid(0xD5CDD502, 0x2E9C, 0x101B, 0×93, 0×97, 
0×08, 0×00, 0x2B, 0x2C, 0xF9, 0xAE), 2);      
public static readonly PROPERTYKEY Company = new PROPERTYKEY
(new Guid(0xD5CDD502, 0x2E9C, 0x101B, 0×93, 0×97, 
0×08, 0×00, 0x2B, 0x2C, 0xF9, 0xAE), 15);      
public static readonly PROPERTYKEY Copyright = 
new PROPERTYKEY(new Guid(0×64440492, 0x4C8B, 0x11D1, 0x8B, 
0×70, 0×08, 0×00, 0×36, 0xB1, 0x1A, 0×03), 11);      
public static readonly PROPERTYKEY Comment = new PROPERTYKEY
(new Guid(0xF29F85E0, 0x4FF9, 0×1068, 0xAB, 0×91, 
0×08, 0×00, 0x2B, 0×27, 0xB3, 0xD9), 6);      
public static readonly PROPERTYKEY MediaDuration = new PROPERTYKEY
(new Guid(0×64440490, 0x4C8B, 0x11D1, 0x8B, 0×70, 0×08, 
0×00, 0×36, 0xB1, 0x1A, 0×03), 3);      
public static readonly PROPERTYKEY VideoCompression = new PROPERTYKEY
(new Guid(0×64440491, 0x4C8B, 0x11D1, 0x8B, 0×70, 0×08, 
0×00, 0×36, 0xB1, 0x1A, 0×03), 10);      
public static readonly PROPERTYKEY VideoDirector = new PROPERTYKEY
(new Guid(0×64440492, 0x4C8B, 0x11D1, 0x8B, 0×70, 0×08, 
0×00, 0×36, 0xB1, 0x1A, 0×03), 20);      
public static readonly PROPERTYKEY VideoFourCC = new PROPERTYKEY
(new Guid(0×64440491, 0x4C8B, 0x11D1, 0x8B, 0×70, 0×08, 
0×00, 0×36, 0xB1, 0x1A, 0×03), 44);      
}

我们几乎完成了。唯一不要忘记的是释放所有 COM 对象(Marshal.ReleaseComObject(…))以防止内存泄漏,并初始化和关闭 Media Foundation

MFStartup(0×10070, Interop.MFSTARTUP.Lite);     
…      
MFShutdown();

你选择使用哪种方法:简单但不受支持,或者复杂但可扩展的方法。两者都会产生相同的结果。祝你愉快,做一个好人。

相关文章

  1. 在 C# 中从 PEM 格式导入 RSA 私钥
© . All rights reserved.