/// <summary> /// Creates a new DMO Output Data Buffer structure /// </summary> /// <param name="maxBufferSize">Maximum buffer size</param> public DmoOutputDataBuffer(int maxBufferSize) { pBuffer = new MediaBuffer(maxBufferSize); dwStatus = DmoOutputDataBufferFlags.None; rtTimestamp = 0; referenceTimeDuration = 0; }
/// <summary> /// Creates a new DmoOutputDataBuffer. /// </summary> /// <param name="bufferSize">The maxlength (in bytes) of the internally used MediaBuffer.</param> public DmoOutputDataBuffer(int bufferSize) { Buffer = new MediaBuffer(bufferSize); Status = OutputDataBufferFlags.None; Timestamp = 0; TimeLength = 0; }
/// <summary> /// Dispose /// </summary> public void Dispose() { if (pBuffer != null) { ((MediaBuffer)pBuffer).Dispose(); pBuffer = null; GC.SuppressFinalize(this); } }
/// <summary> /// Disposes the internally used MediaBuffer. /// </summary> public void Dispose() { if (Buffer != null) { (Buffer as MediaBuffer).Dispose(); Buffer = null; } GC.SuppressFinalize(this); }
/// <summary> /// The constructor. The parameters to the base class /// describe the number of input and output streams, which /// DirectShow calls Pins, followed by the number of parameters /// this class supports (can be zero), and the timeformat of those /// parameters (should include ParamClass.TimeFormatFlags.Reference /// if NumParameters > 0). /// </summary> public DmoSplit() : base(InputPinCount, OutputPinCount, NumParams, TimeFormatFlags.Reference) { m_Log.Write("Constructor\r\n"); // Initialize the data members m_TimeStamp = 0; m_TimeLength = 0; m_cbInData = 0; m_Flags = 0; m_InBuffer = IntPtr.Zero; m_pBuffer = null; }
/// <summary> /// The constructor. The parameters to the base class /// describe the number of input and output streams, which /// DirectShow calls Pins, followed by the number of parameters /// this class supports (can be zero), and the timeformat of those /// parameters (should include ParamClass.TimeFormatFlags.Reference /// if NumParameters > 0). /// </summary> public DmoFlip() : base(InputPinCount, OutputPinCount, NumParams, TimeFormatFlags.Reference) { m_Log.Write("Constructor\r\n"); // Initialize the data members m_Width = 0; m_Height = 0; m_Stride = 0; m_BPP = 0; m_TimeStamp = 0; m_TimeLength = 0; m_cbInData = 0; m_Flags = 0; m_InBuffer = IntPtr.Zero; m_pBuffer = null; // Start describing the parameters this DMO supports. Building this // structure (painful as it is) will allow the base class to automatically // support IMediaParamInfo & IMediaParams, which allow clients to find // out what parameters you support, and to set them. // Our parameter has a minimum value of zero, and a max of // FlipMode.LAST, and a default of DEFAULTMODE; See the MSDN // docs for MP_PARAMINFO for a description of the other parameters ParamInfo p = new ParamInfo(); p.mopCaps = MPCaps.Jump; p.mpdMinValue.vInt = 0; p.mpdMaxValue.vInt = (int)FlipMode.LAST; p.mpdNeutralValue.vInt = (int)DEFAULTMODE; p.mpType = MPType.ENUM; p.szLabel = ""; p.szUnitText = "FlipMode"; // Parameter #0, using the struct, and a format string (described in MSDN // under IMediaParamInfo::GetParamText). Note that when marshaling strings, // .NET will add another \0 ParamDefine(0, p, "FlipMode\0\0None\0FlipY\0FlipX\0FlipY|FlipX\0"); }
/// <summary> /// COM entry point for IMediaObject.ProcessInput /// </summary> /// <remarks> /// There should be no need to modify or override this method. It will call the /// abstract and virtual methods to perform its work. /// </remarks> public int ProcessInput( int ulStreamIndex, IMediaBuffer pBuffer, DMOInputDataBuffer dwFlags, long rtTimestamp, long rtTimelength ) { int hr; try { // Avoid multi-threaded access issues lock(this) { m_Log.Write(string.Format("ProcessInput ({0}, {1}, {2}, {3})\r\n", ulStreamIndex, dwFlags, rtTimestamp, rtTimelength)); if (pBuffer != null) { // Validate the stream number if (ulStreamIndex < m_NumInputs && ulStreamIndex >= 0) { // Validate flags if ( (dwFlags & ~(DMOInputDataBuffer.SyncPoint | DMOInputDataBuffer.Time | DMOInputDataBuffer.TimeLength)) == 0) { // Make sure all streams have media types set and resources are allocated hr = AllocateStreamingResources(); if (hr >= 0) { // If we aren't accepting input, forget it if (InternalAcceptingInput(ulStreamIndex) == S_OK) { m_fFlushed = false; hr = InternalProcessInput( ulStreamIndex, pBuffer, dwFlags, rtTimestamp, rtTimelength); } else { hr = DMOResults.E_NotAccepting; } } } else { hr = E_INVALIDARG; } } else { hr = DMOResults.E_InvalidStreamIndex; } } else { hr = E_POINTER; } } } catch (Exception e) { // Generic handling of all exceptions. While .NET will turn exceptions into // HRESULTS "automatically", I prefer to have some place I can set a breakpoint. hr = CatFail(e); } return hr; }
/// <summary> /// Process Input /// </summary> /// <param name="inputStreamIndex">Input Stream index</param> /// <param name="mediaBuffer">Media Buffer</param> /// <param name="flags">Flags</param> /// <param name="timestamp">Timestamp</param> /// <param name="duration">Duration</param> public void ProcessInput(int inputStreamIndex, IMediaBuffer mediaBuffer, DmoInputDataBufferFlags flags, long timestamp, long duration) { Marshal.ThrowExceptionForHR(mediaObject.ProcessInput(inputStreamIndex, mediaBuffer, flags, timestamp, duration)); }
/////////////////////////////////////////////////////////////////////////////// // Construction and Initializing methods // /////////////////////////////////////////////////////////////////////////////// #region CONSTRUCTION /// <summary> /// Initializes a new instance of the DmoOverlay class. /// The parameters to the base class /// describe the number of input and output streams, which /// DirectShow calls Pins, followed by the number of parameters /// this class supports (can be zero), and the timeformat of those /// parameters (should include ParamClass.TimeFormatFlags.Reference /// if NumParameters > 0). /// </summary> public DmoOverlay() : base(InputPinCount, OutputPinCount, NumParams, TimeFormatFlags.Reference) { // Initialize the data members this.streamWidth = 0; this.streamHeight = 0; this.streamStride = 0; this.streamBBP = 0; this.bufferTimeStamp = 0; this.bufferTimeLength = 0; this.bufferByteCount = 0; this.bufferFlags = 0; this.bufferPointer = IntPtr.Zero; this.buffer = null; // Start describing the parameters this DMO supports. Building this // structure (painful as it is) will allow the base class to automatically // support IMediaParamInfo & IMediaParams, which allow clients to find // out what parameters you support, and to set them. // See the MSDN // docs for MP_PARAMINFO for a description of the other parameters ParamInfo gazeX = new ParamInfo(); gazeX.mopCaps = MPCaps.Jump; gazeX.mpdMinValue.vInt = 0; gazeX.mpdMaxValue.vInt = 2000; gazeX.mpdNeutralValue.vInt = 1; gazeX.mpType = MPType.INT; gazeX.szLabel = "GazeX"; gazeX.szUnitText = "Pixel"; ParamInfo gazeY = new ParamInfo(); gazeY.mopCaps = MPCaps.Jump; gazeY.mpdMinValue.vInt = 0; gazeY.mpdMaxValue.vInt = 2000; gazeY.mpdNeutralValue.vInt = 1; gazeY.mpType = MPType.INT; gazeY.szLabel = "GazeY"; gazeY.szUnitText = "Pixel"; ParamInfo mouseX = new ParamInfo(); mouseX.mopCaps = MPCaps.Jump; mouseX.mpdMinValue.vInt = 0; mouseX.mpdMaxValue.vInt = 2000; mouseX.mpdNeutralValue.vInt = 1; mouseX.mpType = MPType.INT; mouseX.szLabel = "MouseX"; mouseX.szUnitText = "Pixel"; ParamInfo mouseY = new ParamInfo(); mouseY.mopCaps = MPCaps.Jump; mouseY.mpdMinValue.vInt = 0; mouseY.mpdMaxValue.vInt = 2000; mouseY.mpdNeutralValue.vInt = 1; mouseY.mpType = MPType.INT; mouseY.szLabel = "MouseY"; mouseY.szUnitText = "Pixel"; // Parameter #0, using the struct, and a format string (described in MSDN // under IMediaParamInfo::GetParamText). Note that when marshaling strings, // .NET will add another \0 ParamDefine(0, gazeX, "GazeX\0Pixel\0"); ParamDefine(1, gazeY, "GazeY\0Pixel\0"); ParamDefine(2, mouseX, "MouseX\0Pixel\0"); ParamDefine(3, mouseY, "MouseY\0Pixel\0"); // Initialize the buffers for the gaze and mouse cursor overlay bitmaps. Bitmap circleBitmap = (Bitmap)Properties.Resources.Circle; Rectangle circleRect = new Rectangle(0, 0, circleBitmap.Width, circleBitmap.Height); this.gazeCursorSize = circleRect.Size; this.gazeCursorData = circleBitmap.LockBits(circleRect, ImageLockMode.ReadOnly, circleBitmap.PixelFormat); // Get the address of the first line. IntPtr gazeCursorScan0Pointer = this.gazeCursorData.Scan0; // Declare an array to hold the bytes of the bitmap. int gazeCursorBytes = this.gazeCursorData.Stride * this.gazeCursorData.Height; this.gazeCursorArgbValues = new byte[gazeCursorBytes]; // Copy the RGB values into the array. Marshal.Copy(gazeCursorScan0Pointer, this.gazeCursorArgbValues, 0, gazeCursorBytes); Bitmap arrowBitmap = Properties.Resources.Arrow; Rectangle cursorRect = new Rectangle(0, 0, arrowBitmap.Width, arrowBitmap.Height); this.mouseCursorSize = cursorRect.Size; this.mouseCursorData = arrowBitmap.LockBits(cursorRect, ImageLockMode.ReadOnly, arrowBitmap.PixelFormat); // Get the address of the first line. IntPtr mouseCursorScan0Pointer = this.mouseCursorData.Scan0; // Declare an array to hold the bytes of the bitmap. int mouseCursorBytes = this.mouseCursorData.Stride * this.mouseCursorData.Height; this.mouseCursorArgbValues = new byte[mouseCursorBytes]; // Copy the RGB values into the array. Marshal.Copy(mouseCursorScan0Pointer, this.mouseCursorArgbValues, 0, mouseCursorBytes); }
/// <summary> /// COM entry point for IMediaObject.ProcessInput /// </summary> /// <param name="streamIndex">Zero-based index of an input stream on the DMO.</param> /// <param name="bufferVal">Pointer to the buffer's IMediaBuffer interface.</param> /// <param name="flags">Bitwise combination of zero or /// more flags from the DMO_INPUT_DATA_BUFFER_FLAGS enumeration.</param> /// <param name="timestamp">Time stamp that /// specifies the start time of the data in the buffer. /// If the buffer has a valid time stamp, set the DMO_INPUT_DATA_BUFFERF_TIME /// flag in the flags parameter. Otherwise, the DMO ignores this value.</param> /// <param name="timelength">Reference time specifying the duration /// of the data in the buffer. If this value is valid, set /// the DMO_INPUT_DATA_BUFFERF_TIMELENGTH flag in the flags /// parameter. Otherwise, the DMO ignores this value.</param> /// <returns>A HRESULT value.</returns> /// <remarks> /// There should be no need to modify or override this method. It will call the /// abstract and virtual methods to perform its work. /// </remarks> public int ProcessInput( int streamIndex, IMediaBuffer bufferVal, DMOInputDataBuffer flags, long timestamp, long timelength) { int hr; try { // Avoid multi-threaded access issues lock (this) { if (bufferVal != null) { // Validate the stream number if (streamIndex < this.numInputs && streamIndex >= 0) { // Validate flags if ((flags & ~(DMOInputDataBuffer.SyncPoint | DMOInputDataBuffer.Time | DMOInputDataBuffer.TimeLength)) == 0) { // Make sure all streams have media types set and resources are allocated hr = this.AllocateStreamingResources(); if (hr >= 0) { // If we aren't accepting input, forget it if (this.InternalAcceptingInput(streamIndex) == SOK) { this.flushed = false; hr = this.InternalProcessInput( streamIndex, bufferVal, flags, timestamp, timelength); } else { hr = DMOResults.E_NotAccepting; } } } else { hr = EINVALIDARG; } } else { hr = DMOResults.E_InvalidStreamIndex; } } else { hr = EPOINTER; } } } catch (Exception e) { // Generic handling of all exceptions. While .NET will turn exceptions into // HRESULTS "automatically", I prefer to have some place I can set a breakpoint. hr = this.CatFail(e); } return hr; }
internal static unsafe int CalliMethodPtr(void* _basePtr, int streamIndex, IMediaBuffer mediaBuffer, InputDataBufferFlags flags, long timestamp, long timeduration, void* p) { throw new NotImplementedException(); }
/// <summary> /// Release all info for the most recent input buffer /// </summary> private void ReleaseInputBuffs() { if (m_pBuffer != null) { Marshal.ReleaseComObject(m_pBuffer); m_pBuffer = null; } m_InBuffer = IntPtr.Zero; m_cbInData = 0; m_Flags = 0; // I specifically DON'T release the TimeStamp so we can keep track of where we are }
/// <summary> /// Accept the input buffers to be processed. You'll want to read /// the MSDN docs on this one. One point worth noting is that DMO /// doesn't require that one complete block be passed at a time. /// Picture a case where raw data is being read from a file, and your /// DMO is the first to process it. The chunk of data you receive /// might represent one image, 5 images, half an image, etc. Likewise, /// your input could contain both video and audio that you are splitting /// into two output streams. /// That helps explain some of the parameters you see here and in /// InternalProcessOutput. /// Note that while DMO doesn't insist on it, for this sample, we /// specifically request that only complete buffers be provided. /// </summary> /// <param name="dwInputStreamIndex">Stream Index</param> /// <param name="pBuffer">Interface that holds the input data</param> /// <param name="dwFlags">Flags to control input processing</param> /// <param name="rtTimestamp">Timestamp of the sample</param> /// <param name="rtTimelength">Duration of the sample</param> /// <returns>S_FALSE if there is no output, S_OK otherwise</returns> protected override int InternalProcessInput( int dwInputStreamIndex, [In] IMediaBuffer pBuffer, DMOInputDataBuffer dwFlags, long rtTimestamp, long rtTimelength) { // Check state - if we already have a buffer, we shouldn't be getting another Debug.Assert(m_pBuffer == null); int cbData; int hr = pBuffer.GetBufferAndLength(out m_InBuffer, out m_cbInData); if (hr >= 0) { // Ignore zero length buffers if (m_cbInData > 0) { m_pBuffer = pBuffer; // Cast the input flags to become output flags m_Flags = (DMOOutputDataBufferFlags)dwFlags; // If there is a time, store it if (0 == (dwFlags & DMOInputDataBuffer.Time)) { m_TimeStamp = MAX_TIME; } else { m_TimeStamp = rtTimestamp; } // If there is a TimeLength, store it if (0 == (dwFlags & DMOInputDataBuffer.TimeLength)) { m_TimeLength = -1; } else { m_TimeLength = rtTimelength; } hr = S_OK; } else { ReleaseInputBuffs(); hr = S_FALSE; } } return hr; }
internal static unsafe int CalliMethodPtr(void *_basePtr, int streamIndex, IMediaBuffer mediaBuffer, InputDataBufferFlags flags, long timestamp, long timeduration, void *p) { throw new NotImplementedException(); }
/// <summary> /// Release all info for the most recent input buffer /// </summary> private void ReleaseInputBuffs() { if (this.buffer != null) { Marshal.ReleaseComObject(this.buffer); this.buffer = null; } this.bufferPointer = IntPtr.Zero; this.bufferByteCount = 0; this.bufferFlags = 0; // I specifically DON'T release the TimeStamp so we can keep track of where we are }
/// <summary> /// Accept the input buffers to be processed. You'll want to read /// the MSDN docs on this one. One point worth noting is that DMO /// doesn't require that one complete block be passed at a time. /// Picture a case where raw data is being read from a file, and your /// DMO is the first to process it. The chunk of data you receive /// might represent one image, 5 images, half an image, etc. Likewise, /// your input could contain both video and audio that you are splitting /// into two output streams. /// That helps explain some of the parameters you see here and in /// InternalProcessOutput. /// Note that while DMO doesn't insist on it, for this sample, we /// specifically request that only complete buffers be provided. /// </summary> /// <param name="inputStreamIndex">Stream Index</param> /// <param name="mediaBuffer">Interface that holds the input data</param> /// <param name="flags">Flags to control input processing</param> /// <param name="timestamp">Timestamp of the sample</param> /// <param name="timelength">Duration of the sample</param> /// <returns>S_FALSE if there is no output, S_OK otherwise</returns> protected override int InternalProcessInput( int inputStreamIndex, [In] IMediaBuffer mediaBuffer, DMOInputDataBuffer flags, long timestamp, long timelength) { // Check state - if we already have a buffer, we shouldn't be getting another Debug.Assert(this.buffer == null, "We already have a buffer, we shouldn't be getting another"); int hr = mediaBuffer.GetBufferAndLength(out this.bufferPointer, out this.bufferByteCount); if (hr >= 0) { // Ignore zero length buffers if (this.bufferByteCount > 0) { this.buffer = mediaBuffer; // Cast the input flags to become output flags this.bufferFlags = (DMOOutputDataBufferFlags)flags; // If there is a time, store it if (0 == (flags & DMOInputDataBuffer.Time)) { this.bufferTimeStamp = MaxTime; } else { this.bufferTimeStamp = timestamp; } // If there is a TimeLength, store it if (0 == (flags & DMOInputDataBuffer.TimeLength)) { this.bufferTimeLength = -1; } else { this.bufferTimeLength = timelength; } hr = SOK; } else { this.ReleaseInputBuffs(); hr = SFALSE; } } return hr; }
/// <summary> /// (Abstract) Accept input buffers to be processed /// </summary> /// <param name="dwInputStreamIndex">Input stream number</param> /// <param name="pBuffer">Input buffer to process</param> /// <param name="dwFlags">Processing flags</param> /// <param name="rtTimestamp">Timestamp of sample(s)</param> /// <param name="rtTimelength">Length of sample(s)</param> /// <returns>S_OK if the operation completes successfully, S_FALSE if there /// is no input to process.</returns> /// <remarks> /// This method is called by the abstract class. It passes the actual data to be process to the /// implementor. Commonly, the implementor stores these values, waiting for the call to /// InternalProcessOutput (which contains the buffers into which the results are to be stored), at /// which point they are released. /// </remarks> protected abstract int InternalProcessInput(int dwInputStreamIndex, IMediaBuffer pBuffer, DMOInputDataBuffer dwFlags, long rtTimestamp, long rtTimelength);
/// <summary> /// Delivers a buffer to the specified input stream. /// </summary> /// <param name="inputStreamIndex">Zero-based index of an input stream on the DMO.</param> /// <param name="mediaBuffer">The mediabuffer which has to be processed.</param> /// <param name="flags">Flags to describe the mediabuffer.</param> /// <param name="timestamp">Time stamp that specifies the start time of the data in the buffer. If the buffer has a valid time stamp, set the Time flag in the flags parameter.</param> /// <param name="timeduration">Reference time specifying the duration of the data in the buffer. If the buffer has a valid time stamp, set the TimeLength flag in the flags parameter.</param> public unsafe void ProcessInput(int inputStreamIndex, IMediaBuffer mediaBuffer, InputDataBufferFlags flags, long timestamp, long timeduration) { int result = ProcessInputNative(inputStreamIndex, mediaBuffer, flags, timestamp, timeduration); if (result == (int)HResult.S_FALSE) return; DmoException.Try(result, n, "ProcessInput"); }
/// <summary> /// (Abstract) Accept input buffers to be processed /// </summary> /// <param name="inputStreamIndex">Input stream number</param> /// <param name="bufferVal">Input buffer to process</param> /// <param name="flags">Processing flags</param> /// <param name="timestamp">Timestamp of sample(s)</param> /// <param name="timelength">Length of sample(s)</param> /// <returns>S_OK if the operation completes successfully, S_FALSE if there /// is no input to process.</returns> /// <remarks> /// This method is called by the abstract class. It passes the actual data to be process to the /// implementor. Commonly, the implementor stores these values, waiting for the call to /// InternalProcessOutput (which contains the buffers into which the results are to be stored), at /// which point they are released. /// </remarks> protected abstract int InternalProcessInput(int inputStreamIndex, IMediaBuffer bufferVal, DMOInputDataBuffer flags, long timestamp, long timelength);
/// <summary> /// Delivers a buffer to the specified input stream. /// </summary> /// <param name="inputStreamIndex">Zero-based index of an input stream on the DMO.</param> /// <param name="mediaBuffer">The mediabuffer which has to be processed.</param> /// <param name="flags">Flags to describe the mediabuffer.</param> public void ProcessInput(int inputStreamIndex, IMediaBuffer mediaBuffer, InputDataBufferFlags flags) { ProcessInput(inputStreamIndex, mediaBuffer, flags, 0, 0); }
/// <summary> /// Delivers a buffer to the specified input stream. /// </summary> /// <param name="inputStreamIndex">Zero-based index of an input stream on the DMO.</param> /// <param name="mediaBuffer">The <see cref="MediaBuffer"/> to process.</param> /// <param name="flags">Bitwise combination of <see cref="InputDataBufferFlags.None"/> or more flags from the <see cref="InputDataBufferFlags"/> enumeration.</param> public void ProcessInput(int inputStreamIndex, IMediaBuffer mediaBuffer, InputDataBufferFlags flags) { ProcessInput(inputStreamIndex, mediaBuffer, flags, 0, 0); }
/// <summary> /// Delivers a buffer to the specified input stream. /// </summary> /// <param name="inputStreamIndex">Zero-based index of an input stream on the DMO.</param> /// <param name="mediaBuffer">The mediabuffer which has to be processed.</param> /// <param name="flags">Flags to describe the mediabuffer.</param> /// <param name="timestamp">Time stamp that specifies the start time of the data in the buffer. If the buffer has a valid time stamp, set the Time flag in the flags parameter.</param> /// <param name="timeduration">Reference time specifying the duration of the data in the buffer. If the buffer has a valid time stamp, set the TimeLength flag in the flags parameter.</param> /// <returns>HRESULT</returns> public unsafe int ProcessInputNative(int inputStreamIndex, IMediaBuffer mediaBuffer, InputDataBufferFlags flags, long timestamp, long timeduration) { return InteropCalls.CalliMethodPtr(_basePtr, inputStreamIndex, mediaBuffer, flags, timestamp, timeduration, ((void**)(*(void**)_basePtr))[21]); }
/// <summary> /// Delivers a buffer to the specified input stream. /// </summary> /// <param name="inputStreamIndex">Zero-based index of an input stream on the DMO.</param> /// <param name="mediaBuffer">The <see cref="MediaBuffer"/> to process.</param> /// <param name="flags">Bitwise combination of <see cref="InputDataBufferFlags.None"/> or more flags from the <see cref="InputDataBufferFlags"/> enumeration.</param> /// <param name="timestamp"> /// Time stamp that specifies the start time of the data in the buffer. If the buffer has a valid /// time stamp, set the Time flag in the flags parameter. /// </param> /// <param name="timeduration"> /// Reference time specifying the duration of the data in the buffer. If the buffer has a valid /// time stamp, set the TimeLength flag in the flags parameter. /// </param> /// <returns>HRESULT</returns> public unsafe int ProcessInputNative(int inputStreamIndex, IMediaBuffer mediaBuffer, InputDataBufferFlags flags, long timestamp, long timeduration) { return(InteropCalls.CalliMethodPtr(UnsafeBasePtr, inputStreamIndex, mediaBuffer, flags, timestamp, timeduration, ((void **)(*(void **)UnsafeBasePtr))[21])); }
internal MuxedStreamDeliveredEventArgs(IMediaBuffer stream, ulong offset) { Stream = stream; Offset = (long)offset; }