diff --git a/ISCamRecorder/H264Writer.cs b/ISCamRecorder/H264Writer.cs new file mode 100644 index 0000000..9ad4451 --- /dev/null +++ b/ISCamRecorder/H264Writer.cs @@ -0,0 +1,100 @@ +using NAudio.MediaFoundation; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +//using System.Threading.Tasks; + +namespace ISCamRecorder { + class H264Writer + { + private IMFSinkWriter _writer; + private int _streamIndex; + + public H264Writer( string path, TIS.Imaging.FrameType inputType, int fps, int bitrate ) + { + System.Diagnostics.Debug.Assert(inputType.Subtype == TIS.Imaging.MediaSubtypes.RGB32); + + CreateWriter(path, inputType.Width, inputType.Height, fps, bitrate); + } + + private void CreateWriter(string path, int width, int height, int fps, int bitrate) + { + var MFVideoFormat_RGB32 = new Guid("00000016-0000-0010-8000-00AA00389B71"); + var MFVideoFormat_H264 = new Guid("34363248-0000-0010-8000-00AA00389B71"); + var MF_MT_INTERLACE_MODE = new Guid("e2724bb8-e676-4806-b4b2-a8d6efb44ccd"); + var MFVideoInterlace_Progressive = 2; + var MF_MT_FRAME_SIZE = new Guid("1652c33d-d6b2-4012-b834-72030849a37d"); + var MF_MT_FRAME_RATE = new Guid("c459a2e8-3d2c-4e44-b132-fee5156c7bb0"); + var MF_MT_PIXEL_ASPECT_RATIO = new Guid("c6376a1e-8d0a-4027-be45-6d9a0ad39bb6"); + + MediaFoundationInterop.MFCreateSinkWriterFromURL(path, null, null, out _writer); + + MediaFoundationInterop.MFCreateMediaType(out IMFMediaType outType); + outType.SetGUID(MediaFoundationAttributes.MF_MT_MAJOR_TYPE, MediaTypes.MFMediaType_Video); + outType.SetGUID(MediaFoundationAttributes.MF_MT_SUBTYPE, MFVideoFormat_H264); + outType.SetUINT32(MediaFoundationAttributes.MF_MT_AVG_BITRATE, bitrate); + outType.SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); + outType.SetUINT64(MF_MT_FRAME_SIZE, ((long)width) << 32 | (long)height); + outType.SetUINT64(MF_MT_FRAME_RATE, ((long)fps) << 32 | (long)1); + outType.SetUINT64(MF_MT_PIXEL_ASPECT_RATIO, ((long)1) << 32 | (long)1); + _writer.AddStream(outType, out _streamIndex); + + MediaFoundationInterop.MFCreateMediaType(out IMFMediaType inType); + inType.SetGUID(MediaFoundationAttributes.MF_MT_MAJOR_TYPE, MediaTypes.MFMediaType_Video); + inType.SetGUID(MediaFoundationAttributes.MF_MT_SUBTYPE, MFVideoFormat_RGB32); + inType.SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); + inType.SetUINT64(MF_MT_FRAME_SIZE, ((long)width) << 32 | (long)height); + inType.SetUINT64(MF_MT_FRAME_RATE, ((long)fps) << 32 | (long)1); + inType.SetUINT64(MF_MT_PIXEL_ASPECT_RATIO, ((long)1) << 32 | (long)1); + _writer.SetInputMediaType(_streamIndex, inType, null); + } + + + public void Begin() + { + _writer.BeginWriting(); + } + + [System.Runtime.InteropServices.DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] + private static extern void MFCopyImage(IntPtr pDest, int lDestStride, IntPtr pSrc, int lSrcStride, uint dwWidthInBytes, uint dwLines); + + private void WriteFrame(IntPtr data, int width, int height, long ts, long dt) + { + int stride = width * 4; + int cbBuffer = stride * height; + + MediaFoundationInterop.MFCreateMemoryBuffer(cbBuffer, out IMFMediaBuffer buffer); + + buffer.Lock(out IntPtr ptr, out int maxLength, out int currentLength); + MFCopyImage(ptr, stride, data, stride, (uint)stride, (uint)height); + buffer.Unlock(); + buffer.SetCurrentLength(cbBuffer); + + MediaFoundationInterop.MFCreateSample(out IMFSample sample); + + sample.AddBuffer(buffer); + + sample.SetSampleTime(ts); + sample.SetSampleDuration(dt); + + _writer.WriteSample(_streamIndex, sample); + + System.Runtime.InteropServices.Marshal.ReleaseComObject(sample); + System.Runtime.InteropServices.Marshal.ReleaseComObject(buffer); + } + + public void Write( TIS.Imaging.IFrameQueueBuffer buffer ) + { + long ts = (long)(buffer.FrameMetadata.SampleStartTime * 10000000); + long dt = (long)((buffer.FrameMetadata.SampleEndTime - buffer.FrameMetadata.SampleStartTime) * 10000000); + + WriteFrame(buffer.GetIntPtr(), buffer.FrameType.Width, buffer.FrameType.Height, ts, dt); + } + + public void End() + { + _writer.DoFinalize(); + } + } +} diff --git a/ISCamRecorder/ISCamRecorder.csproj b/ISCamRecorder/ISCamRecorder.csproj index 24f4ed3..0fe4fb3 100644 --- a/ISCamRecorder/ISCamRecorder.csproj +++ b/ISCamRecorder/ISCamRecorder.csproj @@ -72,6 +72,7 @@ + Form @@ -80,6 +81,18 @@ + + + + + + + + + + + + diff --git a/ISCamRecorder/ISCamera.cs b/ISCamRecorder/ISCamera.cs index d38da35..14c2972 100644 --- a/ISCamRecorder/ISCamera.cs +++ b/ISCamRecorder/ISCamera.cs @@ -122,16 +122,24 @@ // 保存先確保 var outDir2 = Path.Combine(outDir, _CamID); Directory.CreateDirectory(outDir2); + // 動画保存準備 + int BITRATE = 4 * 1000000; + var movieFile = Path.Combine(outDir, $"{_CamID}.mp4"); + var writer = new H264Writer(movieFile, + _RecSink.OutputFrameType, (int)FrameRate, BITRATE); + writer.Begin(); // ファイル保存 for (int i = 0; i < _bufferlist.Length; i++) { + writer.Write(_bufferlist[i]); //このフレームの最初のパケットをドライバが受信した時刻が格納されます。 - string strSampleStartTime = _bufferlist[i].FrameMetadata.DriverFrameFirstPacketTime.ToString(@"hhmmss\.fff"); - + string strSampleStartTime = _bufferlist[i].FrameMetadata. + DriverFrameFirstPacketTime.ToString(@"hhmmss\.fff"); var fileName = $"{_CamID}_{strSampleStartTime}.jpg"; var filePath = Path.Combine(outDir2, fileName); FrameExtensions.SaveAsJpeg(_bufferlist[i], filePath, 80); } - // バッファメモリ解放 + // 終了処理 + writer.End(); ClearBuffer(); Debug.WriteLine($"{_CamID} ends saving."); } diff --git a/ISCamRecorder/MainForm.cs b/ISCamRecorder/MainForm.cs index 90c91e7..d0dc944 100644 --- a/ISCamRecorder/MainForm.cs +++ b/ISCamRecorder/MainForm.cs @@ -10,6 +10,7 @@ using System.Diagnostics; using System.Reflection; using System.IO; +using NAudio.MediaFoundation; namespace ISCamRecorder { public partial class MainForm : Form { @@ -24,6 +25,7 @@ /// コンストラクタ /// public MainForm() { + MediaFoundationApi.Startup(); InitializeComponent(); } @@ -188,6 +190,7 @@ /// private void BtnRecodeMovie_Click(object sender, EventArgs e) { if (BtnRecodeMovie.Text.Equals("中断")) { + // 中断は機能せず _Cameras.ForEach(c => c.StopRecoding()); } else { BtnRecodeMovie.Enabled = false; @@ -214,6 +217,7 @@ // 保存 BtnRecodeMovie.Text = "保存中"; BtnRecodeMovie.BackColor = Color.Aqua; + //_Cameras[0].SaveToFile(outputDir); for (var i = 0; i < _Cameras.Count; i++) { var cam = _Cameras[i]; tasks[i] = Task.Run(() => cam.SaveToFile(outputDir)); diff --git a/ISCamRecorder/NAudio/MediaFoundation/IMFAttributes.cs b/ISCamRecorder/NAudio/MediaFoundation/IMFAttributes.cs new file mode 100644 index 0000000..35dd320 --- /dev/null +++ b/ISCamRecorder/NAudio/MediaFoundation/IMFAttributes.cs @@ -0,0 +1,169 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace NAudio.MediaFoundation +{ + /// + /// Provides a generic way to store key/value pairs on an object. + /// http://msdn.microsoft.com/en-gb/library/windows/desktop/ms704598%28v=vs.85%29.aspx + /// + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("2CD2D921-C447-44A7-A13C-4ADABFC247E3")] + public interface IMFAttributes + { + /// + /// Retrieves the value associated with a key. + /// + void GetItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, Out] IntPtr pValue); + + /// + /// Retrieves the data type of the value associated with a key. + /// + void GetItemType([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pType); + + /// + /// Queries whether a stored attribute value equals a specified PROPVARIANT. + /// + void CompareItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); + + /// + /// Compares the attributes on this object with the attributes on another object. + /// + void Compare([MarshalAs(UnmanagedType.Interface)] IMFAttributes pTheirs, int matchType, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); + + /// + /// Retrieves a UINT32 value associated with a key. + /// + void GetUINT32([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int punValue); + + /// + /// Retrieves a UINT64 value associated with a key. + /// + void GetUINT64([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out long punValue); + + /// + /// Retrieves a double value associated with a key. + /// + void GetDouble([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out double pfValue); + + /// + /// Retrieves a GUID value associated with a key. + /// + void GetGUID([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out Guid pguidValue); + + /// + /// Retrieves the length of a string value associated with a key. + /// + void GetStringLength([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcchLength); + + /// + /// Retrieves a wide-character string associated with a key. + /// + void GetString([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, int cchBufSize, + out int pcchLength); + + /// + /// Retrieves a wide-character string associated with a key. This method allocates the memory for the string. + /// + void GetAllocatedString([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, + out int pcchLength); + + /// + /// Retrieves the length of a byte array associated with a key. + /// + void GetBlobSize([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcbBlobSize); + + /// + /// Retrieves a byte array associated with a key. + /// + void GetBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out, MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, + out int pcbBlobSize); + + /// + /// Retrieves a byte array associated with a key. This method allocates the memory for the array. + /// + void GetAllocatedBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out IntPtr ip, out int pcbSize); + + /// + /// Retrieves an interface pointer associated with a key. + /// + void GetUnknown([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, + [MarshalAs(UnmanagedType.IUnknown)] out object ppv); + + /// + /// Associates an attribute value with a key. + /// + void SetItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr Value); + + /// + /// Removes a key/value pair from the object's attribute list. + /// + void DeleteItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey); + + /// + /// Removes all key/value pairs from the object's attribute list. + /// + void DeleteAllItems(); + + /// + /// Associates a UINT32 value with a key. + /// + void SetUINT32([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue); + + /// + /// Associates a UINT64 value with a key. + /// + void SetUINT64([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue); + + /// + /// Associates a double value with a key. + /// + void SetDouble([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue); + + /// + /// Associates a GUID value with a key. + /// + void SetGUID([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, MarshalAs(UnmanagedType.LPStruct)] Guid guidValue); + + /// + /// Associates a wide-character string with a key. + /// + void SetString([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, MarshalAs(UnmanagedType.LPWStr)] string wszValue); + + /// + /// Associates a byte array with a key. + /// + void SetBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, + int cbBufSize); + + /// + /// Associates an IUnknown pointer with a key. + /// + void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnknown); + + /// + /// Locks the attribute store so that no other thread can access it. + /// + void LockStore(); + + /// + /// Unlocks the attribute store. + /// + void UnlockStore(); + + /// + /// Retrieves the number of attributes that are set on this object. + /// + void GetCount(out int pcItems); + + /// + /// Retrieves an attribute at the specified index. + /// + void GetItemByIndex(int unIndex, out Guid pGuidKey, [In, Out] IntPtr pValue); + + /// + /// Copies all of the attributes from this object into another attribute store. + /// + void CopyAllItems([In, MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest); + } +} \ No newline at end of file diff --git a/ISCamRecorder/NAudio/MediaFoundation/IMFByteStream.cs b/ISCamRecorder/NAudio/MediaFoundation/IMFByteStream.cs new file mode 100644 index 0000000..971d7e9 --- /dev/null +++ b/ISCamRecorder/NAudio/MediaFoundation/IMFByteStream.cs @@ -0,0 +1,103 @@ +using System; +using System.Runtime.InteropServices; + +namespace NAudio.MediaFoundation +{ + /// + /// IMFByteStream + /// http://msdn.microsoft.com/en-gb/library/windows/desktop/ms698720%28v=vs.85%29.aspx + /// + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("ad4c1b00-4bf7-422f-9175-756693d9130d")] + public interface IMFByteStream + { + /// + /// Retrieves the characteristics of the byte stream. + /// virtual HRESULT STDMETHODCALLTYPE GetCapabilities(/*[out]*/ __RPC__out DWORD *pdwCapabilities) = 0; + /// + void GetCapabilities(ref int pdwCapabiities); + + /// + /// Retrieves the length of the stream. + /// virtual HRESULT STDMETHODCALLTYPE GetLength(/*[out]*/ __RPC__out QWORD *pqwLength) = 0; + /// + void GetLength(ref long pqwLength); + + /// + /// Sets the length of the stream. + /// virtual HRESULT STDMETHODCALLTYPE SetLength(/*[in]*/ QWORD qwLength) = 0; + /// + void SetLength(long qwLength); + + /// + /// Retrieves the current read or write position in the stream. + /// virtual HRESULT STDMETHODCALLTYPE GetCurrentPosition(/*[out]*/ __RPC__out QWORD *pqwPosition) = 0; + /// + void GetCurrentPosition(ref long pqwPosition); + + /// + /// Sets the current read or write position. + /// virtual HRESULT STDMETHODCALLTYPE SetCurrentPosition(/*[in]*/ QWORD qwPosition) = 0; + /// + void SetCurrentPosition(long qwPosition); + + /// + /// Queries whether the current position has reached the end of the stream. + /// virtual HRESULT STDMETHODCALLTYPE IsEndOfStream(/*[out]*/ __RPC__out BOOL *pfEndOfStream) = 0; + /// + void IsEndOfStream([MarshalAs(UnmanagedType.Bool)] ref bool pfEndOfStream); + + /// + /// Reads data from the stream. + /// virtual HRESULT STDMETHODCALLTYPE Read(/*[size_is][out]*/ __RPC__out_ecount_full(cb) BYTE *pb, /*[in]*/ ULONG cb, /*[out]*/ __RPC__out ULONG *pcbRead) = 0; + /// + void Read(IntPtr pb, int cb, ref int pcbRead); + + /// + /// Begins an asynchronous read operation from the stream. + /// virtual /*[local]*/ HRESULT STDMETHODCALLTYPE BeginRead(/*[out]*/ _Out_writes_bytes_(cb) BYTE *pb, /*[in]*/ ULONG cb, /*[in]*/ IMFAsyncCallback *pCallback, /*[in]*/ IUnknown *punkState) = 0; + /// + void BeginRead(IntPtr pb, int cb, IntPtr pCallback, IntPtr punkState); + + /// + /// Completes an asynchronous read operation. + /// virtual /*[local]*/ HRESULT STDMETHODCALLTYPE EndRead(/*[in]*/ IMFAsyncResult *pResult, /*[out]*/ _Out_ ULONG *pcbRead) = 0; + /// + void EndRead(IntPtr pResult, ref int pcbRead); + + /// + /// Writes data to the stream. + /// virtual HRESULT STDMETHODCALLTYPE Write(/*[size_is][in]*/ __RPC__in_ecount_full(cb) const BYTE *pb, /*[in]*/ ULONG cb, /*[out]*/ __RPC__out ULONG *pcbWritten) = 0; + /// + void Write(IntPtr pb, int cb, ref int pcbWritten); + + /// + /// Begins an asynchronous write operation to the stream. + /// virtual /*[local]*/ HRESULT STDMETHODCALLTYPE BeginWrite(/*[in]*/ _In_reads_bytes_(cb) const BYTE *pb, /*[in]*/ ULONG cb, /*[in]*/ IMFAsyncCallback *pCallback, /*[in]*/ IUnknown *punkState) = 0; + /// + void BeginWrite(IntPtr pb, int cb, IntPtr pCallback, IntPtr punkState); + + /// + /// Completes an asynchronous write operation. + /// virtual /*[local]*/ HRESULT STDMETHODCALLTYPE EndWrite(/*[in]*/ IMFAsyncResult *pResult, /*[out]*/ _Out_ ULONG *pcbWritten) = 0; + /// + void EndWrite(IntPtr pResult, ref int pcbWritten); + + /// + /// Moves the current position in the stream by a specified offset. + /// virtual HRESULT STDMETHODCALLTYPE Seek(/*[in]*/ MFBYTESTREAM_SEEK_ORIGIN SeekOrigin, /*[in]*/ LONGLONG llSeekOffset, /*[in]*/ DWORD dwSeekFlags, /*[out]*/ __RPC__out QWORD *pqwCurrentPosition) = 0; + /// + void Seek(int SeekOrigin, long llSeekOffset, int dwSeekFlags, ref long pqwCurrentPosition); + + /// + /// Clears any internal buffers used by the stream. + /// virtual HRESULT STDMETHODCALLTYPE Flush( void) = 0; + /// + void Flush(); + + /// + /// Closes the stream and releases any resources associated with the stream. + /// virtual HRESULT STDMETHODCALLTYPE Close( void) = 0; + /// + void Close(); + } +} \ No newline at end of file diff --git a/ISCamRecorder/NAudio/MediaFoundation/IMFMediaBuffer.cs b/ISCamRecorder/NAudio/MediaFoundation/IMFMediaBuffer.cs new file mode 100644 index 0000000..0f79776 --- /dev/null +++ b/ISCamRecorder/NAudio/MediaFoundation/IMFMediaBuffer.cs @@ -0,0 +1,34 @@ +using System; +using System.Runtime.InteropServices; + +namespace NAudio.MediaFoundation +{ + /// + /// IMFMediaBuffer + /// http://msdn.microsoft.com/en-gb/library/windows/desktop/ms696261%28v=vs.85%29.aspx + /// + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("045FA593-8799-42b8-BC8D-8968C6453507")] + public interface IMFMediaBuffer + { + /// + /// Gives the caller access to the memory in the buffer. + /// + void Lock(out IntPtr ppbBuffer, out int pcbMaxLength, out int pcbCurrentLength); + /// + /// Unlocks a buffer that was previously locked. + /// + void Unlock(); + /// + /// Retrieves the length of the valid data in the buffer. + /// + void GetCurrentLength(out int pcbCurrentLength); + /// + /// Sets the length of the valid data in the buffer. + /// + void SetCurrentLength(int cbCurrentLength); + /// + /// Retrieves the allocated size of the buffer. + /// + void GetMaxLength(out int pcbMaxLength); + } +} \ No newline at end of file diff --git a/ISCamRecorder/NAudio/MediaFoundation/IMFMediaType.cs b/ISCamRecorder/NAudio/MediaFoundation/IMFMediaType.cs new file mode 100644 index 0000000..e7d2d3f --- /dev/null +++ b/ISCamRecorder/NAudio/MediaFoundation/IMFMediaType.cs @@ -0,0 +1,196 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace NAudio.MediaFoundation +{ + /// + /// Represents a description of a media format. + /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms704850%28v=vs.85%29.aspx + /// + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("44AE0FA8-EA31-4109-8D2E-4CAE4997C555")] + public interface IMFMediaType : IMFAttributes + { + /// + /// Retrieves the value associated with a key. + /// + new void GetItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, Out] IntPtr pValue); + + /// + /// Retrieves the data type of the value associated with a key. + /// + new void GetItemType([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pType); + + /// + /// Queries whether a stored attribute value equals a specified PROPVARIANT. + /// + new void CompareItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); + + /// + /// Compares the attributes on this object with the attributes on another object. + /// + new void Compare([MarshalAs(UnmanagedType.Interface)] IMFAttributes pTheirs, int matchType, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); + + /// + /// Retrieves a UINT32 value associated with a key. + /// + new void GetUINT32([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int punValue); + + /// + /// Retrieves a UINT64 value associated with a key. + /// + new void GetUINT64([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out long punValue); + + /// + /// Retrieves a double value associated with a key. + /// + new void GetDouble([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out double pfValue); + + /// + /// Retrieves a GUID value associated with a key. + /// + new void GetGUID([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out Guid pguidValue); + + /// + /// Retrieves the length of a string value associated with a key. + /// + new void GetStringLength([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcchLength); + + /// + /// Retrieves a wide-character string associated with a key. + /// + new void GetString([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, int cchBufSize, + out int pcchLength); + + /// + /// Retrieves a wide-character string associated with a key. This method allocates the memory for the string. + /// + new void GetAllocatedString([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, + out int pcchLength); + + /// + /// Retrieves the length of a byte array associated with a key. + /// + new void GetBlobSize([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcbBlobSize); + + /// + /// Retrieves a byte array associated with a key. + /// + new void GetBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out, MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, + out int pcbBlobSize); + + /// + /// Retrieves a byte array associated with a key. This method allocates the memory for the array. + /// + new void GetAllocatedBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out IntPtr ip, out int pcbSize); + + /// + /// Retrieves an interface pointer associated with a key. + /// + new void GetUnknown([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, + [MarshalAs(UnmanagedType.IUnknown)] out object ppv); + + /// + /// Associates an attribute value with a key. + /// + new void SetItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value); + + /// + /// Removes a key/value pair from the object's attribute list. + /// + new void DeleteItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey); + + /// + /// Removes all key/value pairs from the object's attribute list. + /// + new void DeleteAllItems(); + + /// + /// Associates a UINT32 value with a key. + /// + new void SetUINT32([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue); + + /// + /// Associates a UINT64 value with a key. + /// + new void SetUINT64([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue); + + /// + /// Associates a double value with a key. + /// + new void SetDouble([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue); + + /// + /// Associates a GUID value with a key. + /// + new void SetGUID([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, MarshalAs(UnmanagedType.LPStruct)] Guid guidValue); + + /// + /// Associates a wide-character string with a key. + /// + new void SetString([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, MarshalAs(UnmanagedType.LPWStr)] string wszValue); + + /// + /// Associates a byte array with a key. + /// + new void SetBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, + int cbBufSize); + + /// + /// Associates an IUnknown pointer with a key. + /// + new void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnknown); + + /// + /// Locks the attribute store so that no other thread can access it. + /// + new void LockStore(); + + /// + /// Unlocks the attribute store. + /// + new void UnlockStore(); + + /// + /// Retrieves the number of attributes that are set on this object. + /// + new void GetCount(out int pcItems); + + /// + /// Retrieves an attribute at the specified index. + /// + new void GetItemByIndex(int unIndex, out Guid pGuidKey, [In, Out] IntPtr pValue); + + /// + /// Copies all of the attributes from this object into another attribute store. + /// + new void CopyAllItems([In, MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest); + + /// + /// Retrieves the major type of the format. + /// + void GetMajorType(out Guid pguidMajorType); + + /// + /// Queries whether the media type is a compressed format. + /// + void IsCompressedFormat([MarshalAs(UnmanagedType.Bool)] out bool pfCompressed); + + /// + /// Compares two media types and determines whether they are identical. + /// + [PreserveSig] + int IsEqual([In, MarshalAs(UnmanagedType.Interface)] IMFMediaType pIMediaType, ref int pdwFlags); + + /// + /// Retrieves an alternative representation of the media type. + /// + + void GetRepresentation([In] Guid guidRepresentation, ref IntPtr ppvRepresentation); + + /// + /// Frees memory that was allocated by the GetRepresentation method. + /// + void FreeRepresentation([In] Guid guidRepresentation, [In] IntPtr pvRepresentation); + } +} \ No newline at end of file diff --git a/ISCamRecorder/NAudio/MediaFoundation/IMFSample.cs b/ISCamRecorder/NAudio/MediaFoundation/IMFSample.cs new file mode 100644 index 0000000..dac68bb --- /dev/null +++ b/ISCamRecorder/NAudio/MediaFoundation/IMFSample.cs @@ -0,0 +1,238 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace NAudio.MediaFoundation +{ + /// + /// http://msdn.microsoft.com/en-gb/library/windows/desktop/ms702192%28v=vs.85%29.aspx + /// + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("c40a00f2-b93a-4d80-ae8c-5a1c634f58e4")] + public interface IMFSample : IMFAttributes + { + /// + /// Retrieves the value associated with a key. + /// + new void GetItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, Out] IntPtr pValue); + + /// + /// Retrieves the data type of the value associated with a key. + /// + new void GetItemType([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pType); + + /// + /// Queries whether a stored attribute value equals a specified PROPVARIANT. + /// + new void CompareItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); + + /// + /// Compares the attributes on this object with the attributes on another object. + /// + new void Compare([MarshalAs(UnmanagedType.Interface)] IMFAttributes pTheirs, int matchType, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); + + /// + /// Retrieves a UINT32 value associated with a key. + /// + new void GetUINT32([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int punValue); + + /// + /// Retrieves a UINT64 value associated with a key. + /// + new void GetUINT64([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out long punValue); + + /// + /// Retrieves a double value associated with a key. + /// + new void GetDouble([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out double pfValue); + + /// + /// Retrieves a GUID value associated with a key. + /// + new void GetGUID([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out Guid pguidValue); + + /// + /// Retrieves the length of a string value associated with a key. + /// + new void GetStringLength([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcchLength); + + /// + /// Retrieves a wide-character string associated with a key. + /// + new void GetString([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, int cchBufSize, + out int pcchLength); + + /// + /// Retrieves a wide-character string associated with a key. This method allocates the memory for the string. + /// + new void GetAllocatedString([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, + out int pcchLength); + + /// + /// Retrieves the length of a byte array associated with a key. + /// + new void GetBlobSize([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcbBlobSize); + + /// + /// Retrieves a byte array associated with a key. + /// + new void GetBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out, MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, + out int pcbBlobSize); + + /// + /// Retrieves a byte array associated with a key. This method allocates the memory for the array. + /// + new void GetAllocatedBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out IntPtr ip, out int pcbSize); + + /// + /// Retrieves an interface pointer associated with a key. + /// + new void GetUnknown([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, + [MarshalAs(UnmanagedType.IUnknown)] out object ppv); + + /// + /// Associates an attribute value with a key. + /// + new void SetItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value); + + /// + /// Removes a key/value pair from the object's attribute list. + /// + new void DeleteItem([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey); + + /// + /// Removes all key/value pairs from the object's attribute list. + /// + new void DeleteAllItems(); + + /// + /// Associates a UINT32 value with a key. + /// + new void SetUINT32([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue); + + /// + /// Associates a UINT64 value with a key. + /// + new void SetUINT64([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue); + + /// + /// Associates a double value with a key. + /// + new void SetDouble([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue); + + /// + /// Associates a GUID value with a key. + /// + new void SetGUID([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, MarshalAs(UnmanagedType.LPStruct)] Guid guidValue); + + /// + /// Associates a wide-character string with a key. + /// + new void SetString([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, MarshalAs(UnmanagedType.LPWStr)] string wszValue); + + /// + /// Associates a byte array with a key. + /// + new void SetBlob([In, MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, + int cbBufSize); + + /// + /// Associates an IUnknown pointer with a key. + /// + new void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnknown); + + /// + /// Locks the attribute store so that no other thread can access it. + /// + new void LockStore(); + + /// + /// Unlocks the attribute store. + /// + new void UnlockStore(); + + /// + /// Retrieves the number of attributes that are set on this object. + /// + new void GetCount(out int pcItems); + + /// + /// Retrieves an attribute at the specified index. + /// + new void GetItemByIndex(int unIndex, out Guid pGuidKey, [In, Out] IntPtr pValue); + + /// + /// Copies all of the attributes from this object into another attribute store. + /// + new void CopyAllItems([In, MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest); + + /// + /// Retrieves flags associated with the sample. + /// + void GetSampleFlags(out int pdwSampleFlags); + + /// + /// Sets flags associated with the sample. + /// + void SetSampleFlags(int dwSampleFlags); + + /// + /// Retrieves the presentation time of the sample. + /// + void GetSampleTime(out long phnsSampletime); + + /// + /// Sets the presentation time of the sample. + /// + void SetSampleTime(long hnsSampleTime); + + /// + /// Retrieves the duration of the sample. + /// + void GetSampleDuration(out long phnsSampleDuration); + + /// + /// Sets the duration of the sample. + /// + void SetSampleDuration(long hnsSampleDuration); + + /// + /// Retrieves the number of buffers in the sample. + /// + void GetBufferCount(out int pdwBufferCount); + + /// + /// Retrieves a buffer from the sample. + /// + void GetBufferByIndex(int dwIndex, out IMFMediaBuffer ppBuffer); + + /// + /// Converts a sample with multiple buffers into a sample with a single buffer. + /// + void ConvertToContiguousBuffer(out IMFMediaBuffer ppBuffer); + + /// + /// Adds a buffer to the end of the list of buffers in the sample. + /// + void AddBuffer(IMFMediaBuffer pBuffer); + + /// + /// Removes a buffer at a specified index from the sample. + /// + void RemoveBufferByIndex(int dwIndex); + + /// + /// Removes all buffers from the sample. + /// + void RemoveAllBuffers(); + + /// + /// Retrieves the total length of the valid data in all of the buffers in the sample. + /// + void GetTotalLength(out int pcbTotalLength); + + /// + /// Copies the sample data to a buffer. + /// + void CopyToBuffer(IMFMediaBuffer pBuffer); + } +} \ No newline at end of file diff --git a/ISCamRecorder/NAudio/MediaFoundation/IMFSinkWriter.cs b/ISCamRecorder/NAudio/MediaFoundation/IMFSinkWriter.cs new file mode 100644 index 0000000..fc72d39 --- /dev/null +++ b/ISCamRecorder/NAudio/MediaFoundation/IMFSinkWriter.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace NAudio.MediaFoundation +{ + /// + /// Implemented by the Microsoft Media Foundation sink writer object. + /// + [ComImport, Guid("3137f1cd-fe5e-4805-a5d8-fb477448cb3d"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IMFSinkWriter + { + /// + /// Adds a stream to the sink writer. + /// + void AddStream([In, MarshalAs(UnmanagedType.Interface)] IMFMediaType pTargetMediaType, out int pdwStreamIndex); + /// + /// Sets the input format for a stream on the sink writer. + /// + void SetInputMediaType([In] int dwStreamIndex, [In, MarshalAs(UnmanagedType.Interface)] IMFMediaType pInputMediaType, [In, MarshalAs(UnmanagedType.Interface)] IMFAttributes pEncodingParameters); + /// + /// Initializes the sink writer for writing. + /// + void BeginWriting(); + /// + /// Delivers a sample to the sink writer. + /// + void WriteSample([In] int dwStreamIndex, [In, MarshalAs(UnmanagedType.Interface)] IMFSample pSample); + /// + /// Indicates a gap in an input stream. + /// + void SendStreamTick([In] int dwStreamIndex, [In] long llTimestamp); + /// + /// Places a marker in the specified stream. + /// + void PlaceMarker([In] int dwStreamIndex, [In] IntPtr pvContext); + /// + /// Notifies the media sink that a stream has reached the end of a segment. + /// + void NotifyEndOfSegment([In] int dwStreamIndex); + /// + /// Flushes one or more streams. + /// + void Flush([In] int dwStreamIndex); + /// + /// (Finalize) Completes all writing operations on the sink writer. + /// + void DoFinalize(); + /// + /// Queries the underlying media sink or encoder for an interface. + /// + void GetServiceForStream([In] int dwStreamIndex, [In] ref Guid guidService, [In] ref Guid riid, out IntPtr ppvObject); + /// + /// Gets statistics about the performance of the sink writer. + /// + void GetStatistics([In] int dwStreamIndex, [In, Out] ref MF_SINK_WRITER_STATISTICS pStats); + } +} diff --git a/ISCamRecorder/NAudio/MediaFoundation/MF_SINK_WRITER_STATISTICS.cs b/ISCamRecorder/NAudio/MediaFoundation/MF_SINK_WRITER_STATISTICS.cs new file mode 100644 index 0000000..5f30fb9 --- /dev/null +++ b/ISCamRecorder/NAudio/MediaFoundation/MF_SINK_WRITER_STATISTICS.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace NAudio.MediaFoundation +{ + /// + /// Contains statistics about the performance of the sink writer. + /// + [StructLayout(LayoutKind.Sequential)] + public class MF_SINK_WRITER_STATISTICS + { + /// + /// The size of the structure, in bytes. + /// + public int cb; + /// + /// The time stamp of the most recent sample given to the sink writer. + /// + public long llLastTimestampReceived; + /// + /// The time stamp of the most recent sample to be encoded. + /// + public long llLastTimestampEncoded; + /// + /// The time stamp of the most recent sample given to the media sink. + /// + public long llLastTimestampProcessed; + /// + /// The time stamp of the most recent stream tick. + /// + public long llLastStreamTickReceived; + /// + /// The system time of the most recent sample request from the media sink. + /// + public long llLastSinkSampleRequest; + /// + /// The number of samples received. + /// + public long qwNumSamplesReceived; + /// + /// The number of samples encoded. + /// + public long qwNumSamplesEncoded; + /// + /// The number of samples given to the media sink. + /// + public long qwNumSamplesProcessed; + /// + /// The number of stream ticks received. + /// + public long qwNumStreamTicksReceived; + /// + /// The amount of data, in bytes, currently waiting to be processed. + /// + public int dwByteCountQueued; + /// + /// The total amount of data, in bytes, that has been sent to the media sink. + /// + public long qwByteCountProcessed; + /// + /// The number of pending sample requests. + /// + public int dwNumOutstandingSinkSampleRequests; + /// + /// The average rate, in media samples per 100-nanoseconds, at which the application sent samples to the sink writer. + /// + public int dwAverageSampleRateReceived; + /// + /// The average rate, in media samples per 100-nanoseconds, at which the sink writer sent samples to the encoder + /// + public int dwAverageSampleRateEncoded; + /// + /// The average rate, in media samples per 100-nanoseconds, at which the sink writer sent samples to the media sink. + /// + public int dwAverageSampleRateProcessed; + } +} diff --git a/ISCamRecorder/NAudio/MediaFoundation/MediaFoundationAttributes.cs b/ISCamRecorder/NAudio/MediaFoundation/MediaFoundationAttributes.cs new file mode 100644 index 0000000..a756ad6 --- /dev/null +++ b/ISCamRecorder/NAudio/MediaFoundation/MediaFoundationAttributes.cs @@ -0,0 +1,286 @@ +using System; +using System.Collections.Generic; +using System.Text; +using NAudio.Utils; + +namespace NAudio.MediaFoundation +{ + /// + /// Media Foundation attribute guids + /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms696989%28v=vs.85%29.aspx + /// + public static class MediaFoundationAttributes + { + /// + /// Specifies whether an MFT performs asynchronous processing. + /// + public static readonly Guid MF_TRANSFORM_ASYNC = new Guid("f81a699a-649a-497d-8c73-29f8fed6ad7a"); + + /// + /// Enables the use of an asynchronous MFT. + /// + public static readonly Guid MF_TRANSFORM_ASYNC_UNLOCK = new Guid("e5666d6b-3422-4eb6-a421-da7db1f8e207"); + + /// + /// Contains flags for an MFT activation object. + /// + [FieldDescription("Transform Flags")] + public static readonly Guid MF_TRANSFORM_FLAGS_Attribute = new Guid("9359bb7e-6275-46c4-a025-1c01e45f1a86"); + + /// + /// Specifies the category for an MFT. + /// + [FieldDescription("Transform Category")] + public static readonly Guid MF_TRANSFORM_CATEGORY_Attribute = new Guid("ceabba49-506d-4757-a6ff-66c184987e4e"); + + /// + /// Contains the class identifier (CLSID) of an MFT. + /// + [FieldDescription("Class identifier")] + public static readonly Guid MFT_TRANSFORM_CLSID_Attribute = new Guid("6821c42b-65a4-4e82-99bc-9a88205ecd0c"); + + /// + /// Contains the registered input types for a Media Foundation transform (MFT). + /// + [FieldDescription("Input Types")] + public static readonly Guid MFT_INPUT_TYPES_Attributes = new Guid("4276c9b1-759d-4bf3-9cd0-0d723d138f96"); + + /// + /// Contains the registered output types for a Media Foundation transform (MFT). + /// + [FieldDescription("Output Types")] + public static readonly Guid MFT_OUTPUT_TYPES_Attributes = new Guid("8eae8cf3-a44f-4306-ba5c-bf5dda242818"); + + /// + /// Contains the symbolic link for a hardware-based MFT. + /// + public static readonly Guid MFT_ENUM_HARDWARE_URL_Attribute = new Guid("2fb866ac-b078-4942-ab6c-003d05cda674"); + + /// + /// Contains the display name for a hardware-based MFT. + /// + [FieldDescription("Name")] + public static readonly Guid MFT_FRIENDLY_NAME_Attribute = new Guid("314ffbae-5b41-4c95-9c19-4e7d586face3"); + + /// + /// Contains a pointer to the stream attributes of the connected stream on a hardware-based MFT. + /// + public static readonly Guid MFT_CONNECTED_STREAM_ATTRIBUTE = new Guid("71eeb820-a59f-4de2-bcec-38db1dd611a4"); + + /// + /// Specifies whether a hardware-based MFT is connected to another hardware-based MFT. + /// + public static readonly Guid MFT_CONNECTED_TO_HW_STREAM = new Guid("34e6e728-06d6-4491-a553-4795650db912"); + + /// + /// Specifies the preferred output format for an encoder. + /// + [FieldDescription("Preferred Output Format")] + public static readonly Guid MFT_PREFERRED_OUTPUTTYPE_Attribute = new Guid("7e700499-396a-49ee-b1b4-f628021e8c9d"); + + /// + /// Specifies whether an MFT is registered only in the application's process. + /// + public static readonly Guid MFT_PROCESS_LOCAL_Attribute = new Guid("543186e4-4649-4e65-b588-4aa352aff379"); + + /// + /// Contains configuration properties for an encoder. + /// + public static readonly Guid MFT_PREFERRED_ENCODER_PROFILE = new Guid("53004909-1ef5-46d7-a18e-5a75f8b5905f"); + + /// + /// Specifies whether a hardware device source uses the system time for time stamps. + /// + public static readonly Guid MFT_HW_TIMESTAMP_WITH_QPC_Attribute = new Guid("8d030fb8-cc43-4258-a22e-9210bef89be4"); + + /// + /// Contains an IMFFieldOfUseMFTUnlock pointer, which can be used to unlock the MFT. + /// + public static readonly Guid MFT_FIELDOFUSE_UNLOCK_Attribute = new Guid("8ec2e9fd-9148-410d-831e-702439461a8e"); + + /// + /// Contains the merit value of a hardware codec. + /// + public static readonly Guid MFT_CODEC_MERIT_Attribute = new Guid("88a7cb15-7b07-4a34-9128-e64c6703c4d3"); + + /// + /// Specifies whether a decoder is optimized for transcoding rather than for playback. + /// + public static readonly Guid MFT_ENUM_TRANSCODE_ONLY_ATTRIBUTE = new Guid("111ea8cd-b62a-4bdb-89f6-67ffcdc2458b"); + + // Presentation descriptor attributes: + // http://msdn.microsoft.com/en-gb/library/windows/desktop/aa367736%28v=vs.85%29.aspx + + /// + /// Contains a pointer to the proxy object for the application's presentation descriptor. + /// + [FieldDescription("PMP Host Context")] + public static readonly Guid MF_PD_PMPHOST_CONTEXT = new Guid("6c990d31-bb8e-477a-8598-0d5d96fcd88a"); + + /// + /// Contains a pointer to the presentation descriptor from the protected media path (PMP). + /// + [FieldDescription("App Context")] + public static readonly Guid MF_PD_APP_CONTEXT = new Guid("6c990d32-bb8e-477a-8598-0d5d96fcd88a"); + + /// + /// Specifies the duration of a presentation, in 100-nanosecond units. + /// + [FieldDescription("Duration")] + public static readonly Guid MF_PD_DURATION = new Guid("6c990d33-bb8e-477a-8598-0d5d96fcd88a"); + + /// + /// Specifies the total size of the source file, in bytes. + /// + [FieldDescription("Total File Size")] + public static readonly Guid MF_PD_TOTAL_FILE_SIZE = new Guid("6c990d34-bb8e-477a-8598-0d5d96fcd88a"); + + /// + /// Specifies the audio encoding bit rate for the presentation, in bits per second. + /// + [FieldDescription("Audio encoding bitrate")] + public static readonly Guid MF_PD_AUDIO_ENCODING_BITRATE = new Guid("6c990d35-bb8e-477a-8598-0d5d96fcd88a"); + + /// + /// Specifies the video encoding bit rate for the presentation, in bits per second. + /// + [FieldDescription("Video Encoding Bitrate")] + public static readonly Guid MF_PD_VIDEO_ENCODING_BITRATE = new Guid("6c990d36-bb8e-477a-8598-0d5d96fcd88a"); + + /// + /// Specifies the MIME type of the content. + /// + [FieldDescription("MIME Type")] + public static readonly Guid MF_PD_MIME_TYPE = new Guid("6c990d37-bb8e-477a-8598-0d5d96fcd88a"); + + /// + /// Specifies when a presentation was last modified. + /// + [FieldDescription("Last Modified Time")] + public static readonly Guid MF_PD_LAST_MODIFIED_TIME = new Guid("6c990d38-bb8e-477a-8598-0d5d96fcd88a"); + + /// + /// The identifier of the playlist element in the presentation. + /// + [FieldDescription("Element ID")] + public static readonly Guid MF_PD_PLAYBACK_ELEMENT_ID = new Guid("6c990d39-bb8e-477a-8598-0d5d96fcd88a"); + + /// + /// Contains the preferred RFC 1766 language of the media source. + /// + [FieldDescription("Preferred Language")] + public static readonly Guid MF_PD_PREFERRED_LANGUAGE = new Guid("6c990d3a-bb8e-477a-8598-0d5d96fcd88a"); + + /// + /// The time at which the presentation must begin, relative to the start of the media source. + /// + [FieldDescription("Playback boundary time")] + public static readonly Guid MF_PD_PLAYBACK_BOUNDARY_TIME = new Guid("6c990d3b-bb8e-477a-8598-0d5d96fcd88a"); + + /// + /// Specifies whether the audio streams in the presentation have a variable bit rate. + /// + [FieldDescription("Audio is variable bitrate")] + public static readonly Guid MF_PD_AUDIO_ISVARIABLEBITRATE = new Guid("33026ee0-e387-4582-ae0a-34a2ad3baa18"); + + /// + /// Media type Major Type + /// + [FieldDescription("Major Media Type")] + public static readonly Guid MF_MT_MAJOR_TYPE = new Guid("48eba18e-f8c9-4687-bf11-0a74c9f96a8f"); + /// + /// Media Type subtype + /// + [FieldDescription("Media Subtype")] + public static readonly Guid MF_MT_SUBTYPE = new Guid("f7e34c9a-42e8-4714-b74b-cb29d72c35e5"); + /// + /// Audio block alignment + /// + [FieldDescription("Audio block alignment")] + public static readonly Guid MF_MT_AUDIO_BLOCK_ALIGNMENT = new Guid("322de230-9eeb-43bd-ab7a-ff412251541d"); + /// + /// Audio average bytes per second + /// + [FieldDescription("Audio average bytes per second")] + public static readonly Guid MF_MT_AUDIO_AVG_BYTES_PER_SECOND = new Guid("1aab75c8-cfef-451c-ab95-ac034b8e1731"); + /// + /// Audio number of channels + /// + [FieldDescription("Audio number of channels")] + public static readonly Guid MF_MT_AUDIO_NUM_CHANNELS = new Guid("37e48bf5-645e-4c5b-89de-ada9e29b696a"); + /// + /// Audio samples per second + /// + [FieldDescription("Audio samples per second")] + public static readonly Guid MF_MT_AUDIO_SAMPLES_PER_SECOND = new Guid("5faeeae7-0290-4c31-9e8a-c534f68d9dba"); + /// + /// Audio bits per sample + /// + [FieldDescription("Audio bits per sample")] + public static readonly Guid MF_MT_AUDIO_BITS_PER_SAMPLE = new Guid("f2deb57f-40fa-4764-aa33-ed4f2d1ff669"); + + /// + /// Enables the source reader or sink writer to use hardware-based Media Foundation transforms (MFTs). + /// + [FieldDescription("Enable Hardware Transforms")] + public static readonly Guid MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS = new Guid("a634a91c-822b-41b9-a494-4de4643612b0"); + + /// + /// Contains additional format data for a media type. + /// + [FieldDescription("User data")] + public static readonly Guid MF_MT_USER_DATA = new Guid("b6bc765f-4c3b-40a4-bd51-2535b66fe09d"); + + /// + /// Specifies for a media type whether each sample is independent of the other samples in the stream. + /// + [FieldDescription("All samples independent")] + public static readonly Guid MF_MT_ALL_SAMPLES_INDEPENDENT = new Guid("c9173739-5e56-461c-b713-46fb995cb95f"); + + /// + /// Specifies for a media type whether the samples have a fixed size. + /// + [FieldDescription("Fixed size samples")] + public static readonly Guid MF_MT_FIXED_SIZE_SAMPLES = new Guid("b8ebefaf-b718-4e04-b0a9-116775e3321b"); + + /// + /// Contains a DirectShow format GUID for a media type. + /// + [FieldDescription("DirectShow Format Guid")] + public static readonly Guid MF_MT_AM_FORMAT_TYPE = new Guid("73d1072d-1870-4174-a063-29ff4ff6c11e"); + + /// + /// Specifies the preferred legacy format structure to use when converting an audio media type. + /// + [FieldDescription("Preferred legacy format structure")] + public static readonly Guid MF_MT_AUDIO_PREFER_WAVEFORMATEX = new Guid("a901aaba-e037-458a-bdf6-545be2074042"); + + /// + /// Specifies for a media type whether the media data is compressed. + /// + [FieldDescription("Is Compressed")] + public static readonly Guid MF_MT_COMPRESSED = new Guid("3afd0cee-18f2-4ba5-a110-8bea502e1f92"); + + /// + /// Approximate data rate of the video stream, in bits per second, for a video media type. + /// + [FieldDescription("Average bitrate")] + public static readonly Guid MF_MT_AVG_BITRATE = new Guid("20332624-fb0d-4d9e-bd0d-cbf6786c102e"); + + /// + /// Specifies the payload type of an Advanced Audio Coding (AAC) stream. + /// 0 - The stream contains raw_data_block elements only + /// 1 - Audio Data Transport Stream (ADTS). The stream contains an adts_sequence, as defined by MPEG-2. + /// 2 - Audio Data Interchange Format (ADIF). The stream contains an adif_sequence, as defined by MPEG-2. + /// 3 - The stream contains an MPEG-4 audio transport stream with a synchronization layer (LOAS) and a multiplex layer (LATM). + /// + [FieldDescription("AAC payload type")] + public static readonly Guid MF_MT_AAC_PAYLOAD_TYPE = new Guid("bfbabe79-7434-4d1c-94f0-72a3b9e17188"); + + /// + /// Specifies the audio profile and level of an Advanced Audio Coding (AAC) stream, as defined by ISO/IEC 14496-3. + /// + [FieldDescription("AAC Audio Profile Level Indication")] + public static readonly Guid MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION = new Guid("7632f0e6-9538-4d61-acda-ea29c8c14456"); + } +} diff --git a/ISCamRecorder/NAudio/MediaFoundation/MediaFoundationHelpers.cs b/ISCamRecorder/NAudio/MediaFoundation/MediaFoundationHelpers.cs new file mode 100644 index 0000000..b0a116f --- /dev/null +++ b/ISCamRecorder/NAudio/MediaFoundation/MediaFoundationHelpers.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using System.Runtime.InteropServices.ComTypes; + +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; +#if !NETFX_CORE + var os = Environment.OSVersion; + if (os.Version.Major == 6 && os.Version.Minor == 0) + sdkVersion = 1; +#endif + MediaFoundationInterop.MFStartup((sdkVersion << 16) | MediaFoundationInterop.MF_API_VERSION, 0); + initialized = true; + } + } + + /// + /// uninitializes MediaFoundation + /// + public static void Shutdown() + { + if (initialized) + { + MediaFoundationInterop.MFShutdown(); + initialized = false; + } + } + + /// + /// Creates a Media type + /// + public static IMFMediaType CreateMediaType() + { + IMFMediaType mediaType; + MediaFoundationInterop.MFCreateMediaType(out mediaType); + return mediaType; + } + + /// + /// Creates a memory buffer of the specified size + /// + /// Memory buffer size in bytes + /// The memory buffer + public static IMFMediaBuffer CreateMemoryBuffer(int bufferSize) + { + IMFMediaBuffer buffer; + MediaFoundationInterop.MFCreateMemoryBuffer(bufferSize, out buffer); + return buffer; + } + + /// + /// Creates a sample object + /// + /// The sample object + public static IMFSample CreateSample() + { + IMFSample sample; + MediaFoundationInterop.MFCreateSample(out sample); + return sample; + } + + /// + /// Creates a new attributes store + /// + /// Initial size + /// The attributes store + public static IMFAttributes CreateAttributes(int initialSize) + { + IMFAttributes attributes; + MediaFoundationInterop.MFCreateAttributes(out attributes, initialSize); + return attributes; + } + } +} diff --git a/ISCamRecorder/NAudio/MediaFoundation/MediaFoundationInterop.cs b/ISCamRecorder/NAudio/MediaFoundation/MediaFoundationInterop.cs new file mode 100644 index 0000000..f583ca1 --- /dev/null +++ b/ISCamRecorder/NAudio/MediaFoundation/MediaFoundationInterop.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; + +namespace NAudio.MediaFoundation +{ + /// + /// Interop definitions for MediaFoundation + /// thanks to Lucian Wischik for the initial work on many of these definitions (also various interfaces) + /// n.b. the goal is to make as much of this internal as possible, and provide + /// better .NET APIs using the MediaFoundationApi class instead + /// + public static class MediaFoundationInterop + { + /// + /// Initializes Microsoft Media Foundation. + /// + [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] + public static extern void MFStartup(int version, int dwFlags = 0); + + /// + /// Shuts down the Microsoft Media Foundation platform + /// + [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] + public static extern void MFShutdown(); + + /// + /// Creates an empty media type. + /// + [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] + internal static extern void MFCreateMediaType(out IMFMediaType ppMFType); + + /// + /// Creates the sink writer from a URL or byte stream. + /// + [DllImport("mfreadwrite.dll", ExactSpelling = true, PreserveSig = false)] + public static extern void MFCreateSinkWriterFromURL([In, MarshalAs(UnmanagedType.LPWStr)] string pwszOutputURL, + [In] IMFByteStream pByteStream, [In] IMFAttributes pAttributes, [Out] out IMFSinkWriter ppSinkWriter); + + /// + /// Creates an empty media sample. + /// + [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] + internal static extern void MFCreateSample([Out] out IMFSample ppIMFSample); + + /// + /// Allocates system memory and creates a media buffer to manage it. + /// + [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] + internal static extern void MFCreateMemoryBuffer( + int cbMaxLength, [Out] out IMFMediaBuffer ppBuffer); + + /// + /// Creates an empty attribute store. + /// + [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] + internal static extern void MFCreateAttributes( + [Out, MarshalAs(UnmanagedType.Interface)] out IMFAttributes ppMFAttributes, + [In] int cInitialSize); + + /// + /// All streams + /// + public const int MF_SOURCE_READER_ALL_STREAMS = unchecked((int)0xFFFFFFFE); + /// + /// First audio stream + /// + public const int MF_SOURCE_READER_FIRST_AUDIO_STREAM = unchecked((int)0xFFFFFFFD); + /// + /// First video stream + /// + public const int MF_SOURCE_READER_FIRST_VIDEO_STREAM = unchecked((int)0xFFFFFFFC); + /// + /// Media source + /// + public const int MF_SOURCE_READER_MEDIASOURCE = unchecked((int)0xFFFFFFFF); + /// + /// Media Foundation SDK Version + /// + public const int MF_SDK_VERSION = 0x2; + /// + /// Media Foundation API Version + /// + public const int MF_API_VERSION = 0x70; + /// + /// Media Foundation Version + /// + public const int MF_VERSION = (MF_SDK_VERSION << 16) | MF_API_VERSION; + + + } +} diff --git a/ISCamRecorder/NAudio/MediaFoundation/MediaTypes.cs b/ISCamRecorder/NAudio/MediaFoundation/MediaTypes.cs new file mode 100644 index 0000000..c9ddec4 --- /dev/null +++ b/ISCamRecorder/NAudio/MediaFoundation/MediaTypes.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Text; +using NAudio.Utils; + +namespace NAudio.MediaFoundation +{ + /// + /// Major Media Types + /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa367377%28v=vs.85%29.aspx + /// + public static class MediaTypes + { + /// + /// Default + /// + public static readonly Guid MFMediaType_Default = new Guid("81A412E6-8103-4B06-857F-1862781024AC"); + /// + /// Audio + /// + [FieldDescription("Audio")] + public static readonly Guid MFMediaType_Audio = new Guid("73647561-0000-0010-8000-00aa00389b71"); + /// + /// Video + /// + [FieldDescription("Video")] + public static readonly Guid MFMediaType_Video = new Guid("73646976-0000-0010-8000-00aa00389b71"); + /// + /// Protected Media + /// + [FieldDescription("Protected Media")] + public static readonly Guid MFMediaType_Protected = new Guid("7b4b6fe6-9d04-4494-be14-7e0bd076c8e4"); + /// + /// Synchronized Accessible Media Interchange (SAMI) captions. + /// + [FieldDescription("SAMI captions")] + public static readonly Guid MFMediaType_SAMI = new Guid("e69669a0-3dcd-40cb-9e2e-3708387c0616"); + /// + /// Script stream + /// + [FieldDescription("Script stream")] + public static readonly Guid MFMediaType_Script = new Guid("72178c22-e45b-11d5-bc2a-00b0d0f3f4ab"); + /// + /// Still image stream. + /// + [FieldDescription("Still image stream")] + public static readonly Guid MFMediaType_Image = new Guid("72178c23-e45b-11d5-bc2a-00b0d0f3f4ab"); + /// + /// HTML stream. + /// + [FieldDescription("HTML stream")] + public static readonly Guid MFMediaType_HTML = new Guid("72178c24-e45b-11d5-bc2a-00b0d0f3f4ab"); + /// + /// Binary stream. + /// + [FieldDescription("Binary stream")] + public static readonly Guid MFMediaType_Binary = new Guid("72178c25-e45b-11d5-bc2a-00b0d0f3f4ab"); + /// + /// A stream that contains data files. + /// + [FieldDescription("File transfer")] + public static readonly Guid MFMediaType_FileTransfer = new Guid("72178c26-e45b-11d5-bc2a-00b0d0f3f4ab"); + } +} diff --git a/ISCamRecorder/NAudio/Utils/FieldDescriptionAttribute.cs b/ISCamRecorder/NAudio/Utils/FieldDescriptionAttribute.cs new file mode 100644 index 0000000..6330368 --- /dev/null +++ b/ISCamRecorder/NAudio/Utils/FieldDescriptionAttribute.cs @@ -0,0 +1,33 @@ +using System; + +namespace NAudio.Utils +{ + /// + /// Allows us to add descriptions to interop members + /// + [AttributeUsage(AttributeTargets.Field)] + public class FieldDescriptionAttribute : Attribute + { + /// + /// The description + /// + public string Description { get; } + + /// + /// Field description + /// + public FieldDescriptionAttribute(string description) + { + Description = description; + } + + /// + /// String representation + /// + /// + public override string ToString() + { + return Description; + } + } +}