public void ProcessingThread() { while (true) { m_SampleReady.WaitOne(); IMFMediaBuffer pInput = null; try { // Get the data buffer from the input sample. If the sample has // multiple buffers, you might be able to get (slightly) better // performance processing each buffer in turn rather than forcing // a new, full-sized buffer to get created. m_hr = InputSample.ConvertToContiguousBuffer(out pInput); if (Succeeded(m_hr)) { m_hr = DoWork(pInput); } } catch (Exception e) { m_hr = (HResult)Marshal.GetHRForException(e); } finally { // If (somewhere) there is .Net code that is holding on to an instance of // the same buffer as pInput, this will yank the RCW out from underneath // it, probably causing it to crash. But if we don't release it, our memory // usage explodes. SafeRelease(pInput); m_SampleDone.Set(); } } }
protected override HResult OnProcessOutput(ref MFTOutputDataBuffer pOutputSamples) { HResult hr = HResult.S_OK; if (pOutputSamples.pSample == IntPtr.Zero) { // Synchronous MFTs don't (by default) have an IMFAttributes. // So I'm putting the sample number on the actual sample, just // to have some place to put it. MFError throwonhr = InputSample.SetUINT32(m_SampleCountGuid, m_iSampleCount); m_iSampleCount++; // The output sample is the input sample. pOutputSamples.pSample = Marshal.GetIUnknownForObject(InputSample); // Release the current input sample so we can get another one. InputSample = null; } else { hr = HResult.E_INVALIDARG; } return(hr); }
protected override HResult OnProcessInput() { HResult hr = HResult.S_OK; // While we accept types that *might* be interlaced, if we actually receive // an interlaced sample, reject it. if (m_MightBeInterlaced) { int ix; // Returns a bool: true = interlaced, false = progressive hr = InputSample.GetUINT32(MFAttributesClsid.MFSampleExtension_Interlaced, out ix); if (hr != HResult.S_OK || ix != 0) { hr = HResult.E_FAIL; } } if (Succeeded(hr)) { // Tell the background thread to start processing; m_SampleReady.Set(); } return(hr); }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// This is the routine that performs the transform. Assumes InputSample is set. /// /// An override of the abstract version in TantaMFTBase_Sync. /// </summary> /// <param name="outputSampleDataStruct">The structure to populate with output data.</param> /// <returns>S_Ok unless error.</returns> /// <history> /// 01 Nov 18 Cynic - Ported In /// </history> protected override HResult OnProcessOutput(ref MFTOutputDataBuffer outputSampleDataStruct) { HResult hr = HResult.S_OK; IMFMediaBuffer outputMediaBuffer = null; // we are processing in place, the input sample is the output sample, the media buffer of the // input sample is the media buffer of the output sample. try { // Get the data buffer from the input sample. If the sample contains more than one buffer, // this method copies the data from the original buffers into a new buffer, and replaces // the original buffer list with the new buffer. The new buffer is returned in the inputMediaBuffer parameter. // If the sample contains a single buffer, this method returns a pointer to the original buffer. // In typical use, most samples do not contain multiple buffers. hr = InputSample.ConvertToContiguousBuffer(out outputMediaBuffer); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to InputSample.ConvertToContiguousBuffer failed. Err=" + hr.ToString()); } // now that we have an output buffer, do the work to implement the appropriate rotate mode. // Writing into outputMediaBuffer will write to the approprate location in the outputSample FlipImageInBuffer(outputMediaBuffer); // increment this for the client/transform communications demonstrator code m_FrameCount++; // Set status flags. outputSampleDataStruct.dwStatus = MFTOutputDataBufferFlags.None; // The output sample is the input sample. We get a new IUnknown for the Input // sample since we are going to release it below. The client will release this // new IUnknown outputSampleDataStruct.pSample = Marshal.GetIUnknownForObject(InputSample); } finally { // clean up SafeRelease(outputMediaBuffer); // Release the current input sample so we can get another one. // the act of setting it to null releases it because the property // is coded that way InputSample = null; } return(HResult.S_OK); }
private void CheckBeltUsage() { if ((!UIUnityEvents.shouldBlockButtonInput && base.enabled) && !ConsoleWindow.IsVisible()) { Inventory inventory = this.inventory; if (inventory != null) { InventoryHolder inventoryHolder = inventory.inventoryHolder; if (inventoryHolder != null) { int beltNum = InputSample.PollItemButtons(); if (beltNum != -1) { inventoryHolder.BeltUse(beltNum); } } } } }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Processes the input. Most of the transformation happens in OnProcessOutput /// so all we need to do here is check to see if the sample is interlaced and, if /// it is, discard it. /// /// Expects InputSample to be set. /// </summary> /// <returns>S_Ok or E_FAIL.</returns> /// <history> /// 01 Nov 18 Cynic - Ported over /// </history> protected override HResult OnProcessInput() { HResult hr = HResult.S_OK; // While we accept types that *might* be interlaced, if we actually receive // an interlaced sample, reject it. if (m_MightBeInterlaced == true) { int ix; // Returns a bool: true = interlaced, false = progressive hr = InputSample.GetUINT32(MFAttributesClsid.MFSampleExtension_Interlaced, out ix); if (hr != HResult.S_OK || ix != 0) { hr = HResult.E_FAIL; } } return(hr); }
/// <summary> /// This is the routine that performs the transform. Unless the sinkWriter object /// is set all we do is pass the sample on. If the sink writer object is set /// we give the sample to it for writing. There are two modes - one where we just /// give the sinkwriter the input sample and the other where we clone the input /// sample and rebase the timestamps. /// /// An override of the abstract version in MFTBase_Sync. /// </summary> /// <param name="pOutputSamples">The structure to populate with output values.</param> /// <returns>S_Ok unless error.</returns> protected override HResult OnProcessOutput(ref MFTOutputDataBuffer outputSampleDataStruct) { HResult hr = HResult.S_OK; IMFMediaBuffer inputMediaBuffer = null; IMFSample sinkWriterSample = null; IMFAttributes sampleAttributes; // in this MFT we are processing in place, the input sample is the output sample, the media buffer of the // input sample is the media buffer of the output sample. Thats for the pipeline. If a sink writer exists // we also write the sample data out to the sink writer. This provides the effect of displaying on the // screen and simultaneously recording. // There are two ways the sink writer can be given the media sample data. It can just be given the // input sample directly or a copy of the sample can be made and that copy given to the sink writer. // There is also an additional complication - the sample has a timestamp and video cameras tend // to just use the current date and time as a timestamp. There are several reports that MP4 files // need to have their first frame starting at zero and then every subsequent frame adjusted to that // new base time. Certainly the Microsoft supplied example code (and see the // CaptureToFileViaReaderWriter also) take great care to do this. This requirement does not // seem to exist - my tests indicate it is not necessary to start from 0 in the mp4 file. Maybe the // Sink Writer has been improved and now does this automatically. For demonstration purposes // the timebase-rebase functionality has been included and choosing that mode copies the sample // and resets the time. If the user does not rebase the time we simply send the input sample // to the Sink Writer as-is. try { // Set status flags. outputSampleDataStruct.dwStatus = MFTOutputDataBufferFlags.None; // The output sample is the input sample. We get a new IUnknown for the Input // sample since we are going to release it below. The client will release this // new IUnknown outputSampleDataStruct.pSample = Marshal.GetIUnknownForObject(InputSample); // are we recording? if (workingSinkWriter != null) { // we do everything in a lock lock (sinkWriterLockObject) { // are we in timebase rebase mode? if (wantTimebaseRebase == false) { // we are not. Just give the input sample to the Sink Writer which will // write it out. hr = workingSinkWriter.WriteSample(sinkWriterVideoStreamId, InputSample); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to WriteSample(a) failed. Err=" + hr.ToString()); } } else { // the timebase rebase option has been chosen. We need to create a copy of the input sample // so we can adjust the time on it. // Get the data buffer from the input sample. If the sample contains more than one buffer, // this method copies the data from the original buffers into a new buffer, and replaces // the original buffer list with the new buffer. The new buffer is returned in the inputMediaBuffer parameter. // If the sample contains a single buffer, this method returns a pointer to the original buffer. // In typical use, most samples do not contain multiple buffers. hr = InputSample.ConvertToContiguousBuffer(out inputMediaBuffer); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to InputSample.ConvertToContiguousBuffer failed. Err=" + hr.ToString()); } // get some other things from the input sample hr = InputSample.GetSampleDuration(out long sampleDuration); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to InputSample.GetSampleDuration failed. Err=" + hr.ToString()); } hr = InputSample.GetTotalLength(out int sampleSize); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to InputSample.GetTotalLength failed. Err=" + hr.ToString()); } hr = InputSample.GetSampleTime(out long sampleTimeStamp); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to InputSample.GetSampleTime failed. Err=" + hr.ToString()); } // get the attributes from the input sample if (InputSample is IMFAttributes) { sampleAttributes = (InputSample as IMFAttributes); } else { sampleAttributes = null; } // we have all the information we need to create a new output sample sinkWriterSample = WMFUtils.CreateMediaSampleFromBuffer(sampleTimeStamp, sampleDuration, inputMediaBuffer, sampleSize, sampleAttributes); if (sinkWriterSample == null) { throw new Exception("OnProcessOutput, Error on call to CreateMediaSampleFromBuffer sinkWriterSample == null"); } // we have a sample, if so is it the first non null one? if (isFirstSample) { // yes it is set up our timestamp firstSampleBaseTime = sampleTimeStamp; isFirstSample = false; } // rebase the time stamp sampleTimeStamp -= firstSampleBaseTime; hr = sinkWriterSample.SetSampleTime(sampleTimeStamp); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to InputSample.SetSampleTime failed. Err=" + hr.ToString()); } // write the sample out hr = workingSinkWriter.WriteSample(sinkWriterVideoStreamId, sinkWriterSample); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to WriteSample(b) failed. Err=" + hr.ToString()); } } } } } finally { // clean up if (inputMediaBuffer != null) { Marshal.ReleaseComObject(inputMediaBuffer); } if (sinkWriterSample != null) { Marshal.ReleaseComObject(sinkWriterSample); } // Release the current input sample so we can get another one. // the act of setting it to null releases it because the property // is coded that way InputSample = null; } return(HResult.S_OK); }
protected void UpdateInput() { bool flag; bool flag2; InventoryHolder inventoryHolder = this.inventoryHolder; PlayerClient.InputFunction(base.gameObject); if (inventoryHolder != null) { ItemModFlags modFlags = inventoryHolder.modFlags; flag = (modFlags & ItemModFlags.Lamp) == ItemModFlags.Other; flag2 = (modFlags & ItemModFlags.Laser) == ItemModFlags.Other; } else { flag = flag2 = true; } InputSample sample = InputSample.Poll(flag, flag2); sample.info__crouchBlocked = this.crouch_was_blocked; bool flag3 = base.GetLocal <FallDamage>().GetLegInjury() > 0f; if (flag3) { sample.crouch = true; sample.jump = false; } if (((sample.walk <= 0f) || (Mathf.Abs(sample.strafe) >= 0.05f)) || ((sample.attack2 || this._inventory.isCrafting) || flag3)) { sample.sprint = false; } float num = 1f; if (this._inventory.isCrafting) { num *= 0.5f; } if (flag3) { num *= 0.5f; } InputSample.MovementScale = num; if (inventoryHolder != null) { object item = inventoryHolder.InvokeInputItemPreFrame(ref sample); this.ProcessInput(ref sample); inventoryHolder.InvokeInputItemPostFrame(item, ref sample); } else { this.ProcessInput(ref sample); } this.CheckBeltUsage(); if (this.wasSprinting && !sample.sprint) { this.SprintingStopped(); } else if (!this.wasSprinting && sample.sprint) { this.SprintingStarted(); } }
private void ProcessInput(ref InputSample sample) { bool isGrounded; bool isSliding; CCMotor ccmotor = base.ccmotor; if (ccmotor != null) { CCMotor.InputFrame frame; isGrounded = ccmotor.isGrounded; isSliding = ccmotor.isSliding; if (!isGrounded && !isSliding) { sample.sprint = false; sample.crouch = false; sample.aim = false; sample.info__crouchBlocked = false; if (!this.wasInAir) { this.wasInAir = true; this.magnitudeAir = ccmotor.input.moveDirection.magnitude; this.midairStartPos = base.transform.position; } this.lastFrameVelocity = ccmotor.velocity; } else if (this.wasInAir) { this.wasInAir = false; this.magnitudeAir = 1f; this.landingSpeedPenaltyTime = 0f; if ((base.transform.position.y < this.midairStartPos.y) && (Mathf.Abs((float)(base.transform.position.y - this.midairStartPos.y)) > 2f)) { base.idMain.GetLocal <FallDamage>().SendFallImpact(this.lastFrameVelocity); } this.lastFrameVelocity = Vector3.zero; this.midairStartPos = Vector3.zero; } bool flag3 = sample.crouch || sample.info__crouchBlocked; frame.jump = sample.jump; frame.moveDirection.x = sample.strafe; frame.moveDirection.y = 0f; frame.moveDirection.z = sample.walk; frame.crouchSpeed = !sample.crouch ? 1f : -1f; if (frame.moveDirection != Vector3.zero) { float num2; float num3; float magnitude = frame.moveDirection.magnitude; if (magnitude < 1f) { frame.moveDirection = (Vector3)(frame.moveDirection / magnitude); magnitude *= magnitude; frame.moveDirection = (Vector3)(frame.moveDirection * magnitude); } else if (magnitude > 1f) { frame.moveDirection = (Vector3)(frame.moveDirection / magnitude); } if (InputSample.MovementScale < 1f) { if (InputSample.MovementScale > 0f) { frame.moveDirection = (Vector3)(frame.moveDirection * InputSample.MovementScale); } else { frame.moveDirection = Vector3.zero; } } Vector3 moveDirection = frame.moveDirection; moveDirection.x *= this.controlConfig.sprintScaleX; moveDirection.z *= this.controlConfig.sprintScaleY; if ((sample.sprint && !flag3) && !sample.aim) { num2 = Time.deltaTime * this.sprintInMulTime; } else { sample.sprint = false; num2 = -Time.deltaTime; } frame.moveDirection += (Vector3)(moveDirection * this.controlConfig.curveSprintAddSpeedByTime.EvaluateClampedTime(ref this.sprintTime, num2)); if (flag3) { num3 = Time.deltaTime * this.crouchInMulTime; } else { num3 = -Time.deltaTime; } frame.moveDirection = (Vector3)(frame.moveDirection * this.controlConfig.curveCrouchMulSpeedByTime.EvaluateClampedTime(ref this.crouchTime, num3)); frame.moveDirection = base.transform.TransformDirection(frame.moveDirection); if (this.wasInAir) { float a = frame.moveDirection.magnitude; if (!Mathf.Approximately(a, this.magnitudeAir)) { frame.moveDirection = (Vector3)(frame.moveDirection / a); frame.moveDirection = (Vector3)(frame.moveDirection * this.magnitudeAir); } } else { frame.moveDirection = (Vector3)(frame.moveDirection * this.controlConfig.curveLandingSpeedPenalty.EvaluateClampedTime(ref this.landingSpeedPenaltyTime, Time.deltaTime)); } } else { this.sprinting = false; this.exitingSprint = false; this.sprintTime = 0f; this.crouchTime = !sample.crouch ? 0f : this.controlConfig.curveCrouchMulSpeedByTime.GetEndTime(); this.magnitudeAir = 1f; } if (DebugInput.GetKey(KeyCode.H)) { frame.moveDirection = (Vector3)(frame.moveDirection * 100f); } ccmotor.input = frame; if (ccmotor.stepMode == CCMotor.StepMode.Elsewhere) { ccmotor.Step(); } } else { isSliding = false; isGrounded = true; } Character idMain = base.idMain; Crouchable crouchable = idMain.crouchable; if (idMain != null) { Angle2 eyesAngles = base.eyesAngles; eyesAngles.yaw = Mathf.DeltaAngle(0f, base.eyesAngles.yaw + sample.yaw); eyesAngles.pitch = base.ClampPitch((float)(eyesAngles.pitch + sample.pitch)); base.eyesAngles = eyesAngles; ushort flags = idMain.stateFlags.flags; if (crouchable != null) { this.crouch_smoothing.AddSeconds((double)Time.deltaTime); crouchable.LocalPlayerUpdateCrouchState(ccmotor, ref sample.crouch, ref sample.info__crouchBlocked, ref this.crouch_smoothing); } int num6 = ((((((((((((!sample.aim ? 0 : 4) | (!sample.sprint ? 0 : 2)) | (!sample.attack ? 0 : 8)) | (!sample.attack2 ? 0 : 0x100)) | (!sample.crouch ? 0 : 1)) | (((sample.strafe == 0f) && (sample.walk == 0f)) ? 0 : 0x40)) | (!LockCursorManager.IsLocked() ? 0x80 : 0)) | (!isGrounded ? 0x10 : 0)) | (!isSliding ? 0 : 0x20)) | (!this.bleeding ? 0 : 0x200)) | (!sample.lamp ? 0 : 0x800)) | (!sample.laser ? 0 : 0x1000)) | (!sample.info__crouchBlocked ? 0 : 0x400); idMain.stateFlags = num6; if (flags != num6) { idMain.Signal_State_FlagsChanged(false); } } this.crouch_was_blocked = sample.info__crouchBlocked; if (sample.inventory) { RPOS.Toggle(); } if (Input.GetKeyDown(KeyCode.Escape)) { RPOS.Hide(); } }
override protected HResult OnProcessOutput(ref MFTOutputDataBuffer pOutputSamples) { HResult hr = HResult.S_OK; MFError throwonhr; // Since we don't specify MFTOutputStreamInfoFlags.ProvidesSamples, this can't be null. if (pOutputSamples.pSample != IntPtr.Zero) { long hnsDuration; long hnsTime; IMFMediaBuffer pInput = null; IMFMediaBuffer pOutput = null; IMFSample pOutSample = null; try { // Get the data buffer from the input sample. If the sample has // multiple buffers, you might be able to get (slightly) better // performance processing each buffer in turn rather than forcing // a new, full-sized buffer to get created. throwonhr = InputSample.ConvertToContiguousBuffer(out pInput); // Turn pointer to interface pOutSample = Marshal.GetUniqueObjectForIUnknown(pOutputSamples.pSample) as IMFSample; // Get the output buffer. throwonhr = pOutSample.ConvertToContiguousBuffer(out pOutput); OnProcessOutput(pInput, pOutput); // Set status flags. pOutputSamples.dwStatus = MFTOutputDataBufferFlags.None; // Copy the duration and time stamp from the input sample, // if present. hr = InputSample.GetSampleDuration(out hnsDuration); if (Succeeded(hr)) { throwonhr = pOutSample.SetSampleDuration(hnsDuration); } hr = InputSample.GetSampleTime(out hnsTime); if (Succeeded(hr)) { throwonhr = pOutSample.SetSampleTime(hnsTime); } } finally { SafeRelease(pInput); SafeRelease(pOutput); SafeRelease(pOutSample); // Release the current input sample so we can get another one. InputSample = null; } } else { return(HResult.E_INVALIDARG); } return(HResult.S_OK); }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// This is the routine that performs the transform. Assumes InputSample is set. /// /// An override of the abstract version in TantaMFTBase_Sync. /// </summary> /// <param name="outputSampleDataStruct">The structure to populate with output data.</param> /// <returns>S_Ok unless error.</returns> /// <history> /// 01 Nov 18 Cynic - Ported In /// </history> protected override HResult OnProcessOutput(ref MFTOutputDataBuffer outputSampleDataStruct) { long hnsDuration; long hnsTime; HResult hr = HResult.S_OK; IMFMediaBuffer inputMediaBuffer = null; IMFMediaBuffer outputMediaBuffer = null; IMFSample outputSample = null; // Since we don't specify MFTOutputStreamInfoFlags.ProvidesSamples, this can't be null. // we expect the caller to have allocated the memory for this if (outputSampleDataStruct.pSample == IntPtr.Zero) { return(HResult.E_INVALIDARG); } try { // Get the data buffer from the input sample. If the sample contains more than one buffer, // this method copies the data from the original buffers into a new buffer, and replaces // the original buffer list with the new buffer. The new buffer is returned in the inputMediaBuffer parameter. // If the sample contains a single buffer, this method returns a pointer to the original buffer. // In typical use, most samples do not contain multiple buffers. hr = InputSample.ConvertToContiguousBuffer(out inputMediaBuffer); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to InputSample.ConvertToContiguousBuffer failed. Err=" + hr.ToString()); } // Turn pointer into an interface. The GetUniqueObjectForIUnknown method ensures that we // receive a unique Runtime Callable Wrapper, because it does not match an IUnknown pointer // to an existing object. Use this method when you have to create a unique RCW that is not // impacted by other code that calls the ReleaseComObject method. outputSample = Marshal.GetUniqueObjectForIUnknown(outputSampleDataStruct.pSample) as IMFSample; if (outputSample == null) { throw new Exception("OnProcessOutput call to GetUniqueObjectForIUnknown failed. outputSample == null"); } // Now get the output buffer. A media sample contains zero or more buffers. Each buffer manages a block of // memory, and is represented by the IMFMediaBuffer interface. A sample can have multiple buffers. // The buffers are kept in an ordered list and accessed by index value. This call gets us a single // pointer to a single contigous buffer which is much more useful. hr = outputSample.ConvertToContiguousBuffer(out outputMediaBuffer); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to InputSample.ConvertToContiguousBuffer failed. Err=" + hr.ToString()); } // now that we have an input and output buffer, do the work to convert them to grayscale. // Writing into outputMediaBuffer will write to the approprate location in the outputSample // since we took care to Marshal it that way ConvertMediaBufferToGrayscale(inputMediaBuffer, outputMediaBuffer); // Set status flags. outputSampleDataStruct.dwStatus = MFTOutputDataBufferFlags.None; // Copy the duration from the input sample, if present. The // Media Session needs these in order to keep everything sync'ed hr = InputSample.GetSampleDuration(out hnsDuration); if (hr == HResult.S_OK) { hr = outputSample.SetSampleDuration(hnsDuration); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to OutSample.SetSampleDuration failed. Err=" + hr.ToString()); } } // Copy the time stamp from the input sample, if present. hr = InputSample.GetSampleTime(out hnsTime); if (hr == HResult.S_OK) { hr = outputSample.SetSampleTime(hnsTime); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to OutSample.SetSampleTime failed. Err=" + hr.ToString()); } } } finally { // clean up SafeRelease(inputMediaBuffer); SafeRelease(outputMediaBuffer); SafeRelease(outputSample); // Release the current input sample so we can get another one. // the act of setting it to null releases it because the property // is coded that way InputSample = null; } return(HResult.S_OK); }