override protected void OnProcessSample(IMFSample pInputSample, bool Discontinuity, int InputMessageNumber) { MFError throwonhr; // Set the Discontinuity flag on the sample that's going to OutputSample. HandleDiscontinuity(Discontinuity, pInputSample); int cb; int cbBytesProcessed = 0; // How much data we processed. int cbInputLength; IntPtr pbInputData = IntPtr.Zero; IMFMediaBuffer pInputBuffer; // Convert to a single contiguous buffer. // NOTE: This does not cause a copy unless there are multiple buffers throwonhr = pInputSample.ConvertToContiguousBuffer(out pInputBuffer); try { // Lock the input buffer. throwonhr = pInputBuffer.Lock(out pbInputData, out cb, out cbInputLength); // Round to the next lowest multiple of nBlockAlign. cbBytesProcessed = cbInputLength - (cbInputLength % m_Alignment); // Process the data. ProcessAudio(pbInputData, pbInputData, cbBytesProcessed / m_Alignment); // Set the data length on the output buffer. throwonhr = pInputBuffer.SetCurrentLength(cbBytesProcessed); long hnsTime = 0; // Ignore failure if the input sample does not have a time stamp. This is // not an error condition. The client may not care about time stamps, and // we don't need them. if (Succeeded(pInputSample.GetSampleTime(out hnsTime))) { long hnsDuration = (cbBytesProcessed / m_AvgBytesPerSec) * UNITS; m_rtTimestamp = hnsTime + hnsDuration; } else { m_rtTimestamp = -1; } OutputSample(pInputSample, InputMessageNumber); } finally { if (pbInputData != IntPtr.Zero) { pInputBuffer.Unlock(); } SafeRelease(pInputBuffer); } }
private bool ShouldDropSample(IMFSample pSample) { if (!_isVideo) { return(false); } bool fCleanPoint = MFExtern.MFGetAttributeUINT32(pSample, MFSampleExtension_CleanPoint, 0) > 0; bool fDrop = _flRate != 1.0f && !fCleanPoint; long hnsTimeStamp = 0; ThrowIfError(pSample.GetSampleTime(out hnsTimeStamp)); if (!fDrop && _fDropTime) { if (_fInitDropTime) { _hnsStartDroppingAt = hnsTimeStamp; _fInitDropTime = false; } fDrop = hnsTimeStamp < (_hnsStartDroppingAt + _hnsAmountToDrop); if (!fDrop) { //Debug.WriteLine($"Ending dropping time on sample ts={hnsTimeStamp} _hnsStartDroppingAt={_hnsStartDroppingAt} _hnsAmountToDrop={_hnsAmountToDrop}"); ResetDropTime(); } else { //Debug.WriteLine($"Dropping sample ts={hnsTimeStamp} _hnsStartDroppingAt={_hnsStartDroppingAt} _hnsAmountToDrop={_hnsAmountToDrop}"); } } if (!fDrop && (_eDropMode == MFQualityDropMode.Mode1 || _fWaitingForCleanPoint)) { // Only key frames fDrop = !fCleanPoint; if (fCleanPoint) { _fWaitingForCleanPoint = false; } if (fDrop) { //Debug.WriteLine($"Dropping sample ts={hnsTimeStamp}"); } } return(fDrop); }
private void DuplicateSample(IMFSample pInSample, out IMFSample pOutSample) { MFError throwonhr; int flags; long lTime; throwonhr = MFExtern.MFCreateSample(out pOutSample); throwonhr = pInSample.CopyAllItems(pOutSample); HResult hr = pInSample.GetSampleDuration(out lTime); if (Succeeded(hr)) { throwonhr = pOutSample.SetSampleDuration(lTime); } hr = pInSample.GetSampleTime(out lTime); if (Succeeded(hr)) { throwonhr = pOutSample.SetSampleTime(lTime); } hr = pInSample.GetSampleFlags(out flags); if (Succeeded(hr)) { throwonhr = pOutSample.SetSampleFlags(flags); } IMFMediaBuffer mb; throwonhr = MFExtern.MFCreateMemoryBuffer(m_imageHeightInPixels * m_imageWidthInPixels * 4, out mb); try { // Set the data size on the output buffer. throwonhr = mb.SetCurrentLength(m_cbImageSizeOutput); throwonhr = pOutSample.AddBuffer(mb); } finally { SafeRelease(mb); } }
//------------------------------------------------------------------- // Name: WriteSampleToFile // Description: Output one media sample to the file. //------------------------------------------------------------------- void WriteSampleToFile(IMFSample pSample) { int hr; int i; long time; int cBufferCount; // Number of buffers in the sample. IntPtr pData; int cbData = 0; int cbWritten = 0; // Get the time stamp hr = pSample.GetSampleTime(out time); MFError.ThrowExceptionForHR(hr); // If the time stamp is too early, just discard this sample. if (time < m_StartTime) { return; } // Note: If there is no time stamp on the sample, proceed anyway. // Find how many buffers are in this sample. hr = pSample.GetBufferCount(out cBufferCount); MFError.ThrowExceptionForHR(hr); // Loop through all the buffers in the sample. for (int iBuffer = 0; iBuffer < cBufferCount; iBuffer++) { IMFMediaBuffer pBuffer = null; hr = pSample.GetBufferByIndex(iBuffer, out pBuffer); MFError.ThrowExceptionForHR(hr); try { // Lock the buffer and write the data to the file. hr = pBuffer.Lock(out pData, out i, out cbData); MFError.ThrowExceptionForHR(hr); hr = m_pByteStream.Write(pData, cbData, out cbWritten); MFError.ThrowExceptionForHR(hr); hr = pBuffer.Unlock(); MFError.ThrowExceptionForHR(hr); // Update the running tally of bytes written. m_cbDataWritten += cbData; } finally { SafeRelease(pBuffer); } } // for loop }
protected bool IsSampleTimePassed(IMFClock pClock, IMFSample pSample) { Debug.Assert(pClock != null); Debug.Assert(pSample != null); if (pSample == null || pClock == null) { throw new COMException("IsSampleTimePassed", E_Pointer); } int hr; bool bRet = false; long hnsTimeNow = 0; long hnsSystemTime = 0; long hnsSampleStart = 0; long hnsSampleDuration = 0; // The sample might lack a time-stamp or a duration, and the // clock might not report a time. try { hr = pClock.GetCorrelatedTime(0, out hnsTimeNow, out hnsSystemTime); MFError.ThrowExceptionForHR(hr); hr = pSample.GetSampleTime(out hnsSampleStart); MFError.ThrowExceptionForHR(hr); hr = pSample.GetSampleDuration(out hnsSampleDuration); MFError.ThrowExceptionForHR(hr); if (hnsSampleStart + hnsSampleDuration < hnsTimeNow) { bRet = true; } } catch { } return bRet; }
protected void CompleteFrameStep(IMFSample pSample) { int hr; long hnsSampleTime = 0; long hnsSystemTime = 0; // Update our state. m_FrameStep.state = FrameStepRate.Complete; m_FrameStep.pSampleNoRef = IntPtr.Zero; // Notify the EVR that the frame-step is complete. NotifyEvent(EventCode.StepComplete, IntPtr.Zero, IntPtr.Zero); // FALSE = completed (not cancelled) // If we are scrubbing (rate == 0), also send the "scrub time" event. if (IsScrubbing()) { // Get the time stamp from the sample. try { hr = pSample.GetSampleTime(out hnsSampleTime); MFError.ThrowExceptionForHR(hr); } catch { // No time stamp. Use the current presentation time. if (m_pClock != null) { hr = m_pClock.GetCorrelatedTime(0, out hnsSampleTime, out hnsSystemTime); MFError.ThrowExceptionForHR(hr); } } // This event (EventCode.ScrubTime) isn't defined until DirectShowNet v2.1 NotifyEvent((EventCode)0x23, new IntPtr((int)hnsSampleTime), new IntPtr(hnsSampleTime >> 32)); } }
public bool ProcessSample(IMFSample pSample, out int plNextSleep) { int hr; long hnsPresentationTime = 0; long hnsTimeNow = 0; long hnsSystemTime = 0; bool bPresentNow = true; plNextSleep = 0; if (m_pClock != null) { // Get the sample's time stamp. It is valid for a sample to // have no time stamp. try { hr = pSample.GetSampleTime(out hnsPresentationTime); MFError.ThrowExceptionForHR(hr); // Get the clock time. (But if the sample does not have a time stamp, // we don't need the clock time.) hr = m_pClock.GetCorrelatedTime(0, out hnsTimeNow, out hnsSystemTime); MFError.ThrowExceptionForHR(hr); } catch { } // Calculate the time until the sample's presentation time. // A negative value means the sample is late. long hnsDelta = hnsPresentationTime - hnsTimeNow; if (m_fRate < 0) { // For reverse playback, the clock runs backward. Therefore the delta is reversed. hnsDelta = -hnsDelta; } if (hnsDelta < -m_PerFrame_1_4th) { // This sample is late. bPresentNow = true; } else if (hnsDelta > (3 * m_PerFrame_1_4th)) { // This sample is still too early. Go to sleep. plNextSleep = Utils.MFTimeToMsec(hnsDelta - (3 * m_PerFrame_1_4th)); // Adjust the sleep time for the clock rate. (The presentation clock runs // at m_fRate, but sleeping uses the system clock.) plNextSleep = (int)(plNextSleep / Math.Abs(m_fRate)); // Don't present yet. bPresentNow = false; } } if (bPresentNow) { m_pCB.PresentSample(pSample, hnsPresentationTime); // pSample released by caller along with DeQueue } return bPresentNow; }
public bool ProcessSample(IMFSample pSample, out int plNextSleep) { HResult hr; long hnsPresentationTime = 0; long hnsTimeNow = 0; long hnsSystemTime = 0; bool bPresentNow = true; plNextSleep = 0; if (m_pClock != null) { // Get the sample's time stamp. It is valid for a sample to // have no time stamp. try { hr = pSample.GetSampleTime(out hnsPresentationTime); MFError.ThrowExceptionForHR(hr); // Get the clock time. (But if the sample does not have a time stamp, // we don't need the clock time.) hr = m_pClock.GetCorrelatedTime(0, out hnsTimeNow, out hnsSystemTime); MFError.ThrowExceptionForHR(hr); } catch { } // Calculate the time until the sample's presentation time. // A negative value means the sample is late. long hnsDelta = hnsPresentationTime - hnsTimeNow; if (m_fRate < 0) { // For reverse playback, the clock runs backward. Therefore the delta is reversed. hnsDelta = -hnsDelta; } if (hnsDelta < -m_PerFrame_1_4th) { // This sample is late. bPresentNow = true; } else if (hnsDelta > (3 * m_PerFrame_1_4th)) { // This sample is still too early. Go to sleep. plNextSleep = Utils.MFTimeToMsec(hnsDelta - (3 * m_PerFrame_1_4th)); // Adjust the sleep time for the clock rate. (The presentation clock runs // at m_fRate, but sleeping uses the system clock.) plNextSleep = (int)(plNextSleep / Math.Abs(m_fRate)); // Don't present yet. bPresentNow = false; } } if (bPresentNow) { m_pCB.PresentSample(pSample, hnsPresentationTime); // pSample released by caller along with DeQueue } return(bPresentNow); }