/// <summary> /// See if the specified parameter value falls within the allowable range /// </summary> /// <param name="m">Value to check</param> /// <returns>true if the parameter value is valid</returns> private bool CheckRange(MPData m) { bool bRet; switch (m_DataType) { case MPType.BOOL: case MPType.ENUM: case MPType.INT: bRet = (m.vInt >= m_MinVal.vInt && m.vInt <= m_MaxVal.vInt); break; case MPType.FLOAT: bRet = (m.vFloat >= m_MinVal.vFloat && m.vFloat <= m_MaxVal.vFloat); break; default: Debug.Assert(false, "Invalid Type"); bRet = false; break; } return bRet; }
private void SetDMOParams(DirectShowLib.IBaseFilter dmoWrapperFilter) { int hr; Guid g; int i; int pc; ParamInfo pInfo; IMediaParamInfo paramInfo = dmoWrapperFilter as IMediaParamInfo; // With a little effort, a generic parameter handling routine // could be produced. You know the number of parameters (GetParamCount), // the type of the parameter (pInfo.mpType), the range of values for // int and float (pInfo.mpdMinValue, pInfo.mpdMaxValue), if the parameter is an // enum, you have the strings (GetParamText). hr = paramInfo.GetParamCount(out pc); DMOError.ThrowExceptionForHR(hr); // Walk all the parameters for (int pCur = 0; pCur < pc; pCur++) { IntPtr ip; hr = paramInfo.GetParamInfo(pCur, out pInfo); DMOError.ThrowExceptionForHR(hr); hr = paramInfo.GetParamText(0, out ip); DMOError.ThrowExceptionForHR(hr); try { string sName, sUnits; string[] sEnum; ParseParamText(ip, out sName, out sUnits, out sEnum); Debug.WriteLine(string.Format("Parameter name: {0}", sName)); Debug.WriteLine(string.Format("Parameter units: {0}", sUnits)); // Not all params will have enumerated strings. if (pInfo.mpType == MPType.ENUM) { // The final entry in "splitted" will be a blank (used to terminate the list). for (int x = 0; x < sEnum.Length; x++) { Debug.WriteLine(string.Format("Parameter Enum strings: {0} = {1}", x, sEnum[x])); } } } finally { Marshal.FreeCoTaskMem(ip); } } hr = paramInfo.GetCurrentTimeFormat(out g, out i); DMOError.ThrowExceptionForHR(hr); hr = paramInfo.GetSupportedTimeFormat(0, out g); DMOError.ThrowExceptionForHR(hr); MPData o = new MPData(); m_param = dmoWrapperFilter as IMediaParams; o.vInt = 0; hr = m_param.SetParam(0, o); DMOError.ThrowExceptionForHR(hr); }
public MPEnvelopes(MPData iDefaultValue, MPCaps iValidCaps, MPType mt, MPData min, MPData max) { // Store the neutralValue, min/max value range, data type and supported curve types m_DefaultValue = iDefaultValue; m_ValidCaps = (int)iValidCaps; m_DataType = mt; m_MinVal = min; m_MaxVal = max; // Create an array to hold the segments (size = 3 was chosen arbitrarily) m_Envelope = new ArrayList(3); // Create one segment that spans all time containing the default values MPEnvelopeSegment e = new MPEnvelopeSegment(); e.flags = MPFlags.BeginNeutralVal; e.iCurve = MPCaps.Jump; e.rtStart = 0; e.rtEnd = MAX_TIME; e.valStart = m_DefaultValue; e.valEnd = m_DefaultValue; m_Envelope.Add(e); }
/// <summary> /// Calculate the parameter value at a specified time /// /// While there are routines written for all the curve types, I'm not enough /// of a math whiz to feel comfortable that I got it right. I stole the code /// from elsewhere and converted it to c#, so there's a chance I messed up. /// </summary> /// <param name="rt">Time at which to calculate</param> /// <returns>MPData value for that time based in the specified Curve</returns> public MPData CalcValueForTime(long rt) { long ir, ic; float p; MPData ret; MPEnvelopeSegment m = FindEnvelopeForTime(rt); switch(m.iCurve) { case MPCaps.Jump: // Not quite sure how I want to do this. Consider an envelope // that goes from time 0 to 10, and value 55 to 99. Obviously // at time 0, you return 55. At times 1 thru 9, I assume you // also return 55 (although one could argue they should return // 99). At time 10, you return 99. // If you never have a timestamp that exactly equals 10, you // would never get the new value. Seems odd. Well, that's // how I've written it, anyway. if (rt < m.rtEnd) { ret = m.valStart; } else { ret = m.valEnd; } break; case MPCaps.Linear: ir = m.rtEnd - m.rtStart; ic = rt - m.rtStart; p = ic / ir; ret = new MPData(); if (m_DataType == MPType.FLOAT) { ret.vFloat = (m.valEnd.vFloat - m.valStart.vFloat) * p; } else { ret.vInt = (int)((m.valEnd.vInt - m.valStart.vInt) * p); } break; case MPCaps.InvSquare: ir = m.rtEnd - m.rtStart; ic = rt - m.rtStart; p = ic / ir; p = (float)Math.Sqrt(p); ret = new MPData(); if (m_DataType == MPType.FLOAT) { ret.vFloat = (m.valEnd.vFloat - m.valStart.vFloat) * p; } else { ret.vInt = (int)((m.valEnd.vInt - m.valStart.vInt) * p); } break; case MPCaps.Sine: ir = m.rtEnd - m.rtStart; ic = rt - m.rtStart; p = ic / ir; p = (float)((Math.Sin(p * Math.PI - (Math.PI/2)) + 1) / 2); ret = new MPData(); if (m_DataType == MPType.FLOAT) { ret.vFloat = (m.valEnd.vFloat - m.valStart.vFloat) * p; } else { ret.vInt = (int)((m.valEnd.vInt - m.valStart.vInt) * p); } break; case MPCaps.Square: ir = m.rtEnd - m.rtStart; ic = rt - m.rtStart; p = ic / ir; p = p * p; ret = new MPData(); if (m_DataType == MPType.FLOAT) { ret.vFloat = (m.valEnd.vFloat - m.valStart.vFloat) * p; } else { ret.vInt = (int)((m.valEnd.vInt - m.valStart.vInt) * p); } break; default: Debug.Assert(false, "Invalid flag!"); ret = new MPData(); break; } return ret; }
/// <summary> /// COM entry point for IMediaParams.GetParam /// </summary> /// <remarks> /// There should be no need to modify or override this method. See /// <see cref="IMediaObjectImpl.ParamDefine"/> and <see cref="IMediaObjectImpl.ParamCalcValueForTime"/> /// for details about how this works. /// </remarks> public int GetParam(int dwParamIndex, out MPData pValue) { int hr; try { lock(this) { m_Log.Write("GetParam\r\n"); // If the requested parameter is within range if (dwParamIndex < m_Params.Parms.Length && dwParamIndex >= 0) { // Read the value pValue = m_Params.Envelopes[dwParamIndex].CalcValueForTime(InternalGetCurrentTime()); hr = S_OK; } else { pValue = new MPData(); hr = E_INVALIDARG; } } } 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); // Have to have this to make the compiler happy. pValue = new MPData(); } return hr; }
/// <summary> /// COM entry point for IMediaParams.SetParam /// </summary> /// <remarks> /// There should be no need to modify or override this method. See /// <see cref="IMediaObjectImpl.ParamDefine"/> and <see cref="IMediaObjectImpl.ParamCalcValueForTime"/> /// for details about how this works. /// </remarks> public int SetParam(int dwParamIndex, MPData value) { int hr; try { lock(this) { m_Log.Write("SetParam\r\n"); // Check to see if the index is in range if (dwParamIndex < m_Params.Parms.Length && dwParamIndex >= 0) { // Make an envelope that spans from current to end of stream MPEnvelopeSegment m = new MPEnvelopeSegment(); m.flags = MPFlags.Standard; m.iCurve = MPCaps.Jump; m.rtStart = 0; m.rtEnd = long.MaxValue; m.valStart = value; m.valEnd = value; // Add the struct to the envelope hr = m_Params.Envelopes[dwParamIndex].AddSegment(m); } else { hr = E_INVALIDARG; } } } 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> /// See if the specified parameter value falls within the allowable range /// </summary> /// <param name="m">Value to check</param> /// <returns>true if the parameter value is valid</returns> private bool CheckRange(MPData m) { bool returnValue; switch (this.dataType) { case MPType.BOOL: case MPType.ENUM: case MPType.INT: returnValue = m.vInt >= this.minValue.vInt && m.vInt <= this.maxValue.vInt; break; case MPType.FLOAT: returnValue = m.vFloat >= this.minValue.vFloat && m.vFloat <= this.maxValue.vFloat; break; default: Debug.Assert(false, "Invalid Type"); returnValue = false; break; } return returnValue; }
/////////////////////////////////////////////////////////////////////////////// // Construction and Initializing methods // /////////////////////////////////////////////////////////////////////////////// #region CONSTRUCTION /// <summary> /// Initializes a new instance of the MPEnvelopes class. /// </summary> /// <param name="newDefaultValue">An <see cref="MPData"/> with the default value</param> /// <param name="newValidCaps">The valid capabilities</param> /// <param name="newMPType">The <see cref="MPType"/> of the envelope.</param> /// <param name="newMinValue">The <see cref="MPData"/> with the minimal value for the envelope.</param> /// <param name="newMaxValue">The <see cref="MPData"/> with the maximal value for the envelope.</param> public MPEnvelopes( MPData newDefaultValue, MPCaps newValidCaps, MPType newMPType, MPData newMinValue, MPData newMaxValue) { // Store the neutralValue, min/max value range, data type and supported curve types this.defaultValue = newDefaultValue; this.validCaps = (int)newValidCaps; this.dataType = newMPType; this.minValue = newMinValue; this.maxValue = newMaxValue; // Create an array to hold the segments (size = 3 was chosen arbitrarily) this.envelope = new ArrayList(3); // Create one segment that spans all time containing the default values MPEnvelopeSegment e = new MPEnvelopeSegment(); e.flags = MPFlags.BeginNeutralVal; e.iCurve = MPCaps.Jump; e.rtStart = 0; e.rtEnd = MaxTime; e.valStart = this.defaultValue; e.valEnd = this.defaultValue; this.envelope.Add(e); }
/// <summary> /// Creates the parameter connection for the gaze and mouse location /// properties of the dmo filter. /// </summary> /// <param name="dmoWrapperFilter"> /// The <see cref="IBaseFilter"/> interface /// of the dmo wrapper filter. /// </param> private void SetDMOParams(IBaseFilter dmoWrapperFilter) { if (dmoWrapperFilter == null) { return; } int hr; this.dmoParams = dmoWrapperFilter as IMediaParams; this.gazeX = new MPData(); this.gazeX.vInt = 0; hr = this.dmoParams.SetParam(0, this.gazeX); DMOError.ThrowExceptionForHR(hr); this.gazeY = new MPData(); this.gazeY.vInt = 0; hr = this.dmoParams.SetParam(1, this.gazeY); DMOError.ThrowExceptionForHR(hr); this.mouseX = new MPData(); this.mouseX.vInt = 0; hr = this.dmoParams.SetParam(2, this.mouseX); DMOError.ThrowExceptionForHR(hr); this.mouseY = new MPData(); this.mouseY.vInt = 0; hr = this.dmoParams.SetParam(3, this.mouseY); DMOError.ThrowExceptionForHR(hr); }
/// <summary> /// Sets the parameters for the mixer DMO according to /// the given <see cref="VideoExportProperties"/> /// </summary> /// <param name="dmoWrapperFilter">The <see cref="IBaseFilter"/> /// that contains the DMO.</param> /// <param name="exportProperties">The <see cref="VideoExportProperties"/> /// to use.</param> private void SetDMOParams(IBaseFilter dmoWrapperFilter, VideoExportProperties exportProperties) { int hr; IMediaParams dmoParams = dmoWrapperFilter as IMediaParams; MPData outputBackground = new MPData(); MPData streamTop = new MPData(); MPData streamLeft = new MPData(); MPData streamHeight = new MPData(); MPData streamWidth = new MPData(); MPData streamAlpha = new MPData(); // Get Background color Color bkg = exportProperties.OutputVideoColor; // Convert to integer value AARRGGBB outputBackground.vInt = bkg.ToArgb(); // Set DMO param hr = dmoParams.SetParam(0, outputBackground); DMOError.ThrowExceptionForHR(hr); streamLeft.vFloat = exportProperties.GazeVideoProperties.StreamPosition.Left; hr = dmoParams.SetParam(1, streamLeft); DMOError.ThrowExceptionForHR(hr); streamTop.vFloat = exportProperties.GazeVideoProperties.StreamPosition.Top; hr = dmoParams.SetParam(2, streamTop); DMOError.ThrowExceptionForHR(hr); streamWidth.vFloat = exportProperties.GazeVideoProperties.StreamPosition.Width; hr = dmoParams.SetParam(3, streamWidth); DMOError.ThrowExceptionForHR(hr); streamHeight.vFloat = exportProperties.GazeVideoProperties.StreamPosition.Height; hr = dmoParams.SetParam(4, streamHeight); DMOError.ThrowExceptionForHR(hr); streamAlpha.vFloat = exportProperties.GazeVideoProperties.StreamAlpha; hr = dmoParams.SetParam(5, streamAlpha); DMOError.ThrowExceptionForHR(hr); streamLeft.vFloat = exportProperties.UserVideoProperties.StreamPosition.Left; hr = dmoParams.SetParam(6, streamLeft); DMOError.ThrowExceptionForHR(hr); streamTop.vFloat = exportProperties.UserVideoProperties.StreamPosition.Top; hr = dmoParams.SetParam(7, streamTop); DMOError.ThrowExceptionForHR(hr); streamWidth.vFloat = exportProperties.UserVideoProperties.StreamPosition.Width; hr = dmoParams.SetParam(8, streamWidth); DMOError.ThrowExceptionForHR(hr); streamHeight.vFloat = exportProperties.UserVideoProperties.StreamPosition.Height; hr = dmoParams.SetParam(9, streamHeight); DMOError.ThrowExceptionForHR(hr); streamAlpha.vFloat = exportProperties.UserVideoProperties.StreamAlpha; hr = dmoParams.SetParam(10, streamAlpha); DMOError.ThrowExceptionForHR(hr); }
/// <summary> /// COM entry point for IMediaParams.GetParam /// </summary> /// <param name="paramIndex">[in] Zero-based index of the parameter, /// or DWORD_ALLPARAMS to apply the value to every parameter.</param> /// <param name="dataValue">[out] Pointer to a variable of type /// MPData that receives the parameter value.</param> /// <returns>Returns an HRESULT value.</returns> /// <remarks> /// There should be no need to modify or override this method. See /// <see cref="IMediaObjectImpl.ParamDefine"/> and <see cref="IMediaObjectImpl.ParamCalcValueForTime"/> /// for details about how this works. /// </remarks> public int GetParam(int paramIndex, out MPData dataValue) { int hr; try { lock (this) { // If the requested parameter is within range if (paramIndex < this.paramsClass.Parms.Length && paramIndex >= 0) { // Read the value dataValue = this.paramsClass.Envelopes[paramIndex].CalcValueForTime(this.InternalGetCurrentTime()); hr = SOK; } else { dataValue = new MPData(); hr = EINVALIDARG; } } } 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); // Have to have this to make the compiler happy. dataValue = new MPData(); } return hr; }