Пример #1
0
        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);
            }
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
            }
        }
Пример #4
0
        //-------------------------------------------------------------------
        // 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
        }
Пример #5
0
        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;
        }
Пример #6
0
        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));
            }
        }
Пример #7
0
        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;
        }
Пример #8
0
        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);
        }