Example #1
0
        public static byte[] GetDataFromMediaSample(IMFSample sample)
        {
            IMFMediaBuffer pMediaBuffer = null;
            IntPtr         pBuffer;
            int            maxLen = 0, curLen = 0;

            //HResult hr = sample.LockStore();
            HResult hr = sample.ConvertToContiguousBuffer(out pMediaBuffer);

            MFError.ThrowExceptionForHR(hr);
            try
            {
                hr = pMediaBuffer.Lock(out pBuffer, out maxLen, out curLen);
                MFError.ThrowExceptionForHR(hr);

                try
                {
                    byte[] data = new byte[curLen];
                    Marshal.Copy(pBuffer, data, 0, curLen);
                    return(data);
                }
                finally
                {
                    hr = pMediaBuffer.Unlock();
                }
            }
            finally
            {
                //hr = sample.UnlockStore();
                COMBase.SafeRelease(pMediaBuffer);
            }
        }
Example #2
0
        /// <summary>
        /// Disposes the <see cref="MFResampler"/> object.
        /// </summary>
        public void Dispose()
        {
            if (this.resampler != null)
            {
                Marshal.ReleaseComObject(this.resampler);
                this.resampler = null;
            }

            if (this.inputBuffer != null)
            {
                Marshal.ReleaseComObject(this.inputBuffer);
                this.inputBuffer = null;
            }

            if (this.inputSample != null)
            {
                Marshal.ReleaseComObject(this.inputSample);
                this.inputSample = null;
            }

            if (this.outputBuffer != null)
            {
                Marshal.ReleaseComObject(this.outputBuffer);
                this.outputBuffer = null;
            }

            if (this.outputSample != null)
            {
                Marshal.ReleaseComObject(this.outputSample);
                this.outputSample = null;
            }
        }
Example #3
0
        /// <summary>
        /// Reads data out of the source, passing it through the transform
        /// </summary>
        /// <param name="buffer">Output buffer</param>
        /// <param name="offset">Offset within buffer to write to</param>
        /// <param name="count">Desired byte count</param>
        /// <returns>Number of bytes read</returns>
        // Token: 0x06000A55 RID: 2645 RVA: 0x0001DF5C File Offset: 0x0001C15C
        public int Read(byte[] buffer, int offset, int count)
        {
            if (this.transform == null)
            {
                this.transform = this.CreateTransform();
                this.InitializeTransformForStreaming();
            }
            int i = 0;

            if (this.outputBufferCount > 0)
            {
                i += this.ReadFromOutputBuffer(buffer, offset, count - i);
            }
            while (i < count)
            {
                IMFSample imfsample = this.ReadFromSource();
                if (imfsample == null)
                {
                    this.EndStreamAndDrain();
                    i += this.ReadFromOutputBuffer(buffer, offset + i, count - i);
                    break;
                }
                if (!this.initializedForStreaming)
                {
                    this.InitializeTransformForStreaming();
                }
                this.transform.ProcessInput(0, imfsample, 0);
                Marshal.ReleaseComObject(imfsample);
                this.ReadFromTransform();
                i += this.ReadFromOutputBuffer(buffer, offset + i, count - i);
            }
            return(i);
        }
Example #4
0
        // Token: 0x06000945 RID: 2373 RVA: 0x0001B0A0 File Offset: 0x000192A0
        private long ConvertOneBuffer(IMFSinkWriter writer, int streamIndex, IWaveProvider inputProvider, long position, byte[] managedBuffer)
        {
            long           num            = 0L;
            IMFMediaBuffer imfmediaBuffer = MediaFoundationApi.CreateMemoryBuffer(managedBuffer.Length);
            int            count;

            imfmediaBuffer.GetMaxLength(out count);
            IMFSample imfsample = MediaFoundationApi.CreateSample();

            imfsample.AddBuffer(imfmediaBuffer);
            IntPtr destination;
            int    num2;

            imfmediaBuffer.Lock(out destination, out count, out num2);
            int num3 = inputProvider.Read(managedBuffer, 0, count);

            if (num3 > 0)
            {
                num = MediaFoundationEncoder.BytesToNsPosition(num3, inputProvider.WaveFormat);
                Marshal.Copy(managedBuffer, 0, destination, num3);
                imfmediaBuffer.SetCurrentLength(num3);
                imfmediaBuffer.Unlock();
                imfsample.SetSampleTime(position);
                imfsample.SetSampleDuration(num);
                writer.WriteSample(streamIndex, imfsample);
            }
            else
            {
                imfmediaBuffer.Unlock();
            }
            Marshal.ReleaseComObject(imfsample);
            Marshal.ReleaseComObject(imfmediaBuffer);
            return(num);
        }
Example #5
0
        // Token: 0x06000A59 RID: 2649 RVA: 0x0001E1A8 File Offset: 0x0001C3A8
        private IMFSample ReadFromSource()
        {
            int num = this.sourceProvider.Read(this.sourceBuffer, 0, this.sourceBuffer.Length);

            if (num == 0)
            {
                return(null);
            }
            IMFMediaBuffer imfmediaBuffer = MediaFoundationApi.CreateMemoryBuffer(num);
            IntPtr         destination;
            int            num2;
            int            num3;

            imfmediaBuffer.Lock(out destination, out num2, out num3);
            Marshal.Copy(this.sourceBuffer, 0, destination, num);
            imfmediaBuffer.Unlock();
            imfmediaBuffer.SetCurrentLength(num);
            IMFSample imfsample = MediaFoundationApi.CreateSample();

            imfsample.AddBuffer(imfmediaBuffer);
            imfsample.SetSampleTime(this.inputPosition);
            long num4 = MediaFoundationTransform.BytesToNsPosition(num, this.sourceProvider.WaveFormat);

            imfsample.SetSampleDuration(num4);
            this.inputPosition += num4;
            Marshal.ReleaseComObject(imfmediaBuffer);
            return(imfsample);
        }
Example #6
0
        public HResult ProcessSample(IMFSample pSample)
        {
            Debug.WriteLine("StreamSink:ProcessSample");

            if (pSample == null)
            {
                return(E_INVALIDARG);
            }

            HResult hr;

            lock (this)
            {
                hr = CheckShutdown();
                if (Failed(hr))
                {
                    return(hr);
                }

                hr = ProcessSampleInternal(pSample);
                if (Failed(hr))
                {
                    return(hr);
                }

                hr = QueueEvent(MediaEventType.MEStreamSinkRequestSample, Guid.Empty, S_OK, null);
                if (Failed(hr))
                {
                    return(hr);
                }
            }
            return(hr);
        }
Example #7
0
        private void CleanSampleQueue()
        {
            object    spEntry;
            IMFSample spSample = null;

            // For video streams leave first key frame.
            if (_isVideo)
            {
                while (_samples.Count > 0)
                {
                    spEntry = _samples.Dequeue();

                    if (spEntry is IMFSample && Convert.ToBoolean(MFExtern.MFGetAttributeUINT32(spSample, MFSampleExtension_CleanPoint, 0)))
                    {
                        break;
                    }
                }
            }

            _samples.Clear();

            if (spSample != null)
            {
                _samples.Enqueue(spSample);
            }
        }
Example #8
0
        // Processes media sample received from the header
        internal void ProcessSample(StspSampleHeader sampleHead, IMFSample sample)
        {
            Debug.Assert(sample != null);

            try
            {
                ThrowIfError(CheckShutdown());
                // Set sample attributes
                SetSampleAttributes(sampleHead, sample);

                // Check if we are in propper state if so deliver the sample otherwise just skip it and don't treat it as an error.
                if (_eSourceState == SourceState.SourceState_Started)
                {
                    // Put sample on the list
                    _samples.Enqueue(sample);
                    // Deliver samples
                    DeliverSamples();
                }
                else
                {
                    Throw(HResult.MF_E_UNEXPECTED);
                }
            }
            catch (Exception ex)
            {
                HandleError(ex.HResult);
            }
        }
Example #9
0
        public void ScheduleSample(IMFSample pSample, bool bPresentNow)
        {
            if (m_bSchedulerThread == false)
            {
                throw new COMException("Scheduler thread not started", (int)HResult.MF_E_NOT_INITIALIZED);
            }

            if (bPresentNow || (m_pClock == null))
            {
                // Present the sample immediately.
                m_pCB.PresentSample(pSample, 0);
                SafeRelease(pSample);
            }
            else
            {
                // Queue the sample and ask the scheduler thread to wake up.
                lock (m_ScheduledSamples)
                {
                    m_ScheduledSamples.Enqueue(pSample);
                }

                lock (m_ScheduledSamples)
                {
                    m_EventQueue.Enqueue(ScheduleEvent.eSchedule);
                }
                m_hMsgEvent.Set();
            }
        }
Example #10
0
        override protected void OnProcessSample(IMFSample pInputSample, bool Discontinuity, int InputMessageNumber)
        {
            MFError throwonhr;

            IMFMediaBuffer pInput;

            // 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
                throwonhr = pInputSample.GetUINT32(MFAttributesClsid.MFSampleExtension_Interlaced, out ix);

                if (ix != 0)
                {
                    SafeRelease(pInputSample);
                    return;
                }
            }

            // Set the Discontinuity flag on the sample that's going to OutputSample.
            HandleDiscontinuity(Discontinuity, pInputSample);

            int  i     = MFExtern.MFGetAttributeUINT32(Attributes, ClsidRotate, 0);
            bool IsOdd = (i & 1) == 1;

            // Does the specified rotation give a different orientation than
            // the old one?
            if (IsOdd != m_WasOdd)
            {
                // Yes, change the output type.
                OutputSample(null, InputMessageNumber);
                m_WasOdd = IsOdd;
            }

            // 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 = pInputSample.ConvertToContiguousBuffer(out pInput);

            try
            {
                // Process it.
                DoWork(pInput, (RotateFlipType)i);

                // Send the modified input sample to the output sample queue.
                OutputSample(pInputSample, InputMessageNumber);
            }
            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);
            }
        }
Example #11
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);
            }
        }
Example #12
0
        private HResult ToMFSample(IBufferPacket packet, out IMFSample sample)
        {
            sample = null;
            IMFSample spSample;

            var hr = MFExtern.MFCreateSample(out spSample);

            if (MFError.Failed(hr))
            {
                return(hr);
            }

            //Get the media buffer
            IMFMediaBuffer mediaBuffer;

            hr = StreamConvertor.ConverToMediaBuffer(packet, out mediaBuffer);
            if (MFError.Failed(hr))
            {
                return(hr);
            }
            var len = 0;

            mediaBuffer.GetCurrentLength(out len);
            hr = spSample.AddBuffer(mediaBuffer);
            if (MFError.Failed(hr))
            {
                return(hr);
            }

            sample = spSample;
            return(hr);
        }
Example #13
0
        override protected void OnProcessSample(IMFSample pInputSample, bool Discontinuity, int InputMessageNumber)
        {
            MFError throwonhr;

            IMFMediaBuffer pInput;

            // Set the Discontinuity flag on the sample that's going to OutputSample.
            HandleDiscontinuity(Discontinuity, pInputSample);

            // 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 = pInputSample.ConvertToContiguousBuffer(out pInput);

            try
            {
                // Process it.
                DoWork(pInput);

                // Send the modified input sample to the output sample queue.
                OutputSample(pInputSample, InputMessageNumber);

                m_FrameCount++;
            }
            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);
            }
        }
Example #14
0
        protected void Draw()
        {
            HResult   hr;
            IMFSample mfsample = null;

            try
            {
                // 現在表示すべき IMFSample が TextureMediaSink の TMS_SAMPLE 属性に設定されているので、それを取得する。
                if ((hr = this.MediaSinkAttributes.GetUnknown(TMS_SAMPLE, out mfsample)).Failed())
                {
                    return;
                }
                if (null == mfsample)
                {
                    return;                                                                              // 未設定
                }
                var sample = new SharpDX.MediaFoundation.Sample(Marshal.GetIUnknownForObject(mfsample)); // MediaFoundation.NET to SharpDX.MediaFoundation

                // 注意:
                // 変数 mfsample は RCW(Runtime Callable Wrapper) オブジェクトであり、内部に COM (ネイティブIMFSample) への参照を保持している。
                // このあと mfsample への参照が 0 になっても、内部の COM は mfsample が GC によりファイナライズされるまで Release されないことに注意。(RCW の仕様)
                // D3D11TextureMediaSink.dll では、mfsample の内包する COM の実体がこのプログラム(とdll)が終了するまで不変であるよう設計されているため、直接の問題はない。
                // (RCW による同一の COM への AddRef は1回しか行われないので、mfsample に何度値を設定しても、内部の COM 参照カウンタは初回以降増加しない。)

                // IMFSample からメディアバッファを取得。
                using (var mediaBuffer = sample.GetBufferByIndex(0))
                {
                    // メディアバッファからDXGIバッファを取得。
                    using (var dxgiBuffer = mediaBuffer.QueryInterfaceOrNull <SharpDX.MediaFoundation.DXGIBuffer>())
                    {
                        // DXGIバッファから転送元 Texture2D を取得。
                        dxgiBuffer.GetResource(typeof(SharpDX.Direct3D11.Texture2D).GUID, out IntPtr ppv);
                        using (var texture = new SharpDX.Direct3D11.Texture2D(ppv))
                        {
                            // 転送元 Texture2D のサブリソースインデックスを取得。
                            int subIndex = dxgiBuffer.SubresourceIndex;

                            //
                            // これで、IMFSample から ID3D11Texture2D を取得することができた。
                            // 今回のデモでは、これを単純に SwapChain に矩形描画することにする。
                            //

                            // SwapChain から転送先 Texture2D を取得。
                            using (var dst = this.DXGISwapChain.GetBackBuffer <SharpDX.Direct3D11.Texture2D>(0))
                            {
                                // 転送。
                                this.D3DDevice.ImmediateContext.CopySubresourceRegion(texture, subIndex, null, dst, 0);
                            }
                        }
                    }
                }
            }
            finally
            {
                // GetUnknown で TMS_SAMPLE を得たとき、その IMFSample は TextureMediaSink から更新されないよう lock されている。
                // この lock を解除するために、TMS_SAMPLE 属性に何か(なんでもいい)を SetUnknwon する。これで IMFSample が TextureMediaSink から更新可能になる。
                this.MediaSinkAttributes.SetUnknown(TMS_SAMPLE, mfsample);
            }
        }
Example #15
0
        /// <summary>
        /// Sets the presentation time of the sample.
        /// </summary>
        /// <param name="sample">A valid IMFSample instance.</param>
        /// <param name="sampleTime">The presentation time.</param>
        /// <returns>If this function succeeds, it returns the S_OK member. Otherwise, it returns another HResult's member that describe the error.</returns>
        public static HResult SetSampleTime(this IMFSample sample, TimeSpan sampleTime)
        {
            if (sample == null)
            {
                throw new ArgumentNullException("sample");
            }

            return(sample.SetSampleTime(sampleTime.Ticks));
        }
Example #16
0
        void SET_SAMPLE_ATTRIBUTE(StspSampleHeader sampleHeader, IMFSample pSample, Guid flag, StspSampleFlags flagValue)
        {
            var value = (int)flagValue;

            if ((value & sampleHeader.dwFlagMasks) == value)
            {
                ThrowIfError(pSample.SetUINT32(flag, ((value & sampleHeader.dwFlags) == value) ? 1 : 0));
            }
        }
Example #17
0
        /// <summary>
        /// Disposes the <see cref="WasapiCaptureClient"/> object.
        /// </summary>
        public void Dispose()
        {
            if (this.captureThread != null)
            {
                this.shutdownEvent.Set();
                this.captureThread.Join();
                this.captureThread = null;
            }

            if (this.shutdownEvent != null)
            {
                this.shutdownEvent.Close();
                this.shutdownEvent = null;
            }

            if (this.audioClient != null)
            {
                Marshal.ReleaseComObject(this.audioClient);
                this.audioClient = null;
            }

            if (this.captureClient != null)
            {
                Marshal.ReleaseComObject(this.captureClient);
                this.captureClient = null;
            }

            if (this.resampler != null)
            {
                Marshal.ReleaseComObject(this.resampler);
                this.resampler = null;
            }

            if (this.inputBuffer != null)
            {
                Marshal.ReleaseComObject(this.inputBuffer);
                this.inputBuffer = null;
            }

            if (this.inputSample != null)
            {
                Marshal.ReleaseComObject(this.inputSample);
                this.inputSample = null;
            }

            if (this.outputBuffer != null)
            {
                Marshal.ReleaseComObject(this.outputBuffer);
                this.outputBuffer = null;
            }

            if (this.outputSample != null)
            {
                Marshal.ReleaseComObject(this.outputSample);
                this.outputSample = null;
            }
        }
Example #18
0
        public static long GetSampleTime(this IMFSample obj)
        {
            if (obj == null)
            {
                throw new ArgumentNullException(nameof(obj));
            }

            obj.GetSampleTime(out var value).ThrowOnError();
            return(value);
        }
Example #19
0
        public static long GetSampleDuration(this IMFSample input)
        {
            if (input == null)
            {
                throw new ArgumentNullException(nameof(input));
            }

            input.GetSampleDuration(out var value).ThrowOnError();
            return(value);
        }
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Called when the sample grabber sink processes a sample. We can use this
        /// to do what we want with the sample
        /// </summary>
        /// <param name="guidMajorMediaType">the media type</param>
        /// <param name="sampleFlags">the sample flags</param>
        /// <param name="sampleSize">the sample size</param>
        /// <param name="sampleDuration">the sample duration</param>
        /// <param name="sampleTimeStamp">the sample time</param>
        /// <param name="sampleBuffer">the sample buffer</param>
        /// <param name="sampleAttributes">the attributes for the sample</param>
        /// <history>
        ///    01 Nov 18  Cynic - Ported in
        /// </history>
        public HResult OnProcessSampleEx(Guid guidMajorMediaType, int sampleFlags, long sampleTimeStamp, long sampleDuration, IntPtr sampleBuffer, int sampleSize, IMFAttributes sampleAttributes)
        {
            IMFSample outputSample = null;
            HResult   hr;

            try
            {
                if (sinkWriter == null)
                {
                    string errMsg = "OnProcessSample, Error sinkWriter==null";
                    SampleGrabberAsyncCallBackError(this, errMsg, null);
                    return(HResult.E_FAIL);
                }

                // we have all the information we need to create a new output sample
                outputSample = TantaWMFUtils.CreateMediaSampleFromIntPtr(sampleFlags, sampleTimeStamp, sampleDuration, sampleBuffer, sampleSize, sampleAttributes);
                if (outputSample == null)
                {
                    string errMsg = "OnProcessSample, Error on call to CreateMediaSampleFromBuffer outputSample == null";
                    SampleGrabberAsyncCallBackError(this, errMsg, null);
                    return(HResult.E_FAIL);
                }

                lock (sinkWriter)
                {
                    // write the sample out
                    hr = sinkWriter.WriteSample(sinkWriterMediaStreamId, outputSample);
                    if (Failed(hr))
                    {
                        string errMsg = "OnProcessSample, Error on WriteSample =" + hr.ToString();
                        SampleGrabberAsyncCallBackError(this, errMsg, null);
                        return(hr);
                    }

                    // if you do not set MF_SINK_WRITER_DISABLE_THROTTLING on the sink writer, the
                    // calls below can sometimes be useful to avoid the sink writer stalling for a bit
                    // while it waits for one stream or the other. In fact is a bit disconcerting
                    // that we do not seem to get any of these in the sample grabber.

                    //    sinkWriter.SendStreamTick(sinkWriterMediaStreamId, sampleTimeStamp);
                    //    sinkWriter.NotifyEndOfSegment(sinkWriterMediaStreamId);
                }
            }
            finally
            {
                if (outputSample != null)
                {
                    Marshal.ReleaseComObject(outputSample);
                    outputSample = null;
                }
            }

            return(HResult.S_OK);
        }
Example #21
0
        protected MFTBase()
        {
            Trace("MFTImplementation");

            m_TransformLockObject = new object();

            m_pInputType  = null;
            m_pOutputType = null;

            m_pSample = null;
        }
Example #22
0
        private long ConvertOneBuffer(IMFSinkWriter writer, int streamIndex, IWaveProvider inputProvider, long position, byte[] managedBuffer, int seconds, ref bool flag)
        {
            long           durationConverted = 0;
            int            maxLength;
            IMFMediaBuffer buffer = MediaFoundationApi.CreateMemoryBuffer(managedBuffer.Length);

            buffer.GetMaxLength(out maxLength);

            IMFSample sample = MediaFoundationApi.CreateSample();

            sample.AddBuffer(buffer);

            IntPtr ptr;
            int    currentLength;

            buffer.Lock(out ptr, out maxLength, out currentLength);
            int oneLength = inputProvider.WaveFormat.AverageBytesPerSecond;
            int read      = 0;

            if (flag)
            {
                for (int i = 0; i < seconds; i++)
                {
                    read = inputProvider.Read(managedBuffer, 0, oneLength);
                }
                flag = false;
            }
            else
            {
                read = inputProvider.Read(managedBuffer, 0, oneLength);
            }

            if (read > 0)
            {
                durationConverted = BytesToNsPosition(read, inputProvider.WaveFormat);
                Marshal.Copy(managedBuffer, 0, ptr, read);
                buffer.SetCurrentLength(read);
                buffer.Unlock();
                sample.SetSampleTime(position);
                sample.SetSampleDuration(durationConverted);
                writer.WriteSample(streamIndex, sample);
                //writer.Flush(streamIndex);
            }
            else
            {
                buffer.Unlock();
            }

            Marshal.ReleaseComObject(sample);
            Marshal.ReleaseComObject(buffer);
            return(durationConverted);
        }
Example #23
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);
        }
        //-----------------------------------------------------------------------------
        // ReturnSample
        //
        // Returns a sample to the pool.
        //-----------------------------------------------------------------------------

        public void ReturnSample(IMFSample pSample)
        {
            lock (this)
            {
                if (!m_bInitialized)
                {
                    throw new COMException("SamplePool::ReturnSample", (int)HResult.MF_E_NOT_INITIALIZED);
                }

                m_VideoSampleQueue.Enqueue(pSample);

                m_cPending--;  // Since we're locked, we don't need InterlockedDecrement
            }
        }
Example #25
0
        /// <summary>
        /// Retrieves the presentation time of the sample.
        /// </summary>
        /// <param name="sample">A valid IMFSample instance.</param>
        /// <param name="sampleTime">Receives the presentation time.</param>
        /// <returns>If this function succeeds, it returns the S_OK member. Otherwise, it returns another HResult's member that describe the error.</returns>
        public static HResult GetSampleTime(this IMFSample sample, out TimeSpan sampleTime)
        {
            if (sample == null)
            {
                throw new ArgumentNullException("sample");
            }

            long tmp;

            HResult hr = sample.GetSampleDuration(out tmp);

            sampleTime = hr.Succeeded() ? TimeSpan.FromTicks(tmp) : default(TimeSpan);

            return(hr);
        }
Example #26
0
        override protected void OnProcessSample(IMFSample pInputSample, bool Discontinuity, int InputMessageNumber)
        {
            // Set the Discontinuity flag on the sample that's going to OutputSample.
            HandleDiscontinuity(Discontinuity, pInputSample);

            // Since m_pAttributes is not threadsafe, bad things
            // could happen here if m_ThreadCount > 1.  If I really
            // needed to support multiple threads here, I would
            // probably copy the m_Slims.Wait() logic from OutputSample.
            MFError throwonhr = Attributes.SetUINT32(m_SampleCountGuid, m_iSampleCount);

            m_iSampleCount++;

            // Send the unmodified input sample to the output sample queue.
            OutputSample(pInputSample, InputMessageNumber);
        }
Example #27
0
        //todo: put the process work to background thread to speed up.
        public HResult ProcessSample(IMFSample videoSample)
        {
            HResult hr = HResult.S_OK;

            MFTOutputStatusFlags mftOutFlags;
            MFTOutputStreamInfo  StreamInfo;

            if (videoSample == null)
            {
                return(hr);
            }

            pDecoderTransform.ProcessInput(0, videoSample, 0);
            pDecoderTransform.GetOutputStatus(out mftOutFlags);
            pDecoderTransform.GetOutputStreamInfo(0, out StreamInfo);

            while (true)
            {
                IMFMediaBuffer resultBuffer;
                //reset the cache buffer.
                MFExtern.MFCreateMemoryBuffer(StreamInfo.cbSize, out resultBuffer);
                _mftOutSample.RemoveAllBuffers();
                _mftOutSample.AddBuffer(resultBuffer);

                ProcessOutputStatus outputStatus;
                var mftProcessOutput = pDecoderTransform.ProcessOutput(0, 1, _mftOutBufferContainer, out outputStatus);
                if (mftProcessOutput == HResult.MF_E_TRANSFORM_NEED_MORE_INPUT)
                {
                    //continue provice input data.
                    break;
                }
                else if (_mftOutBufferContainer[0].dwStatus == MFTOutputDataBufferFlags.Incomplete)
                {
                    //todo: the decoded data include more than one samples,we need to receive all data items.
                }
                else
                {
                    IMFMediaBuffer buffer;
                    _mftOutSample.ConvertToContiguousBuffer(out buffer);
                    invokeDecodeComplete(buffer, StreamInfo.cbSize);
                }
            }

            return(hr);
        }
Example #28
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);
            }
        }
Example #29
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Called when the sample grabber sink processes a sample. We can use this
        /// to do what we want with the media data
        /// </summary>
        /// <param name="guidMajorMediaType">the media type</param>
        /// <param name="sampleFlags">the sample flags</param>
        /// <param name="sampleSize">the sample size</param>
        /// <param name="sampleDuration">the sample duration</param>
        /// <param name="sampleTimeStamp">the sample time</param>
        /// <param name="sampleBuffer">the sample buffer</param>
        /// <param name="sampleAttributes">the attributes for the sample</param>
        /// <history>
        ///    01 Nov 18  Cynic - Ported in
        /// </history>
        public HResult OnProcessSampleEx(Guid guidMajorMediaType, int sampleFlags, long sampleTimeStamp, long sampleDuration, IntPtr sampleBuffer, int sampleSize, IMFAttributes sampleAttributes)
        {
            IMFSample outputSample = null;
            HResult   hr;

            try
            {
                if (sinkWriter == null)
                {
                    string errMsg = "OnProcessSample, Error sinkWriter==null";
                    SampleGrabberAsyncCallBackError(this, errMsg, null);
                    return(HResult.E_FAIL);
                }

                // we have all the information we need to create a new output sample
                outputSample = TantaWMFUtils.CreateMediaSampleFromIntPtr(sampleFlags, sampleTimeStamp, sampleDuration, sampleBuffer, sampleSize, null);
                if (outputSample == null)
                {
                    string errMsg = "OnProcessSample, Error on call to CreateMediaSampleFromBuffer outputSample == null";
                    SampleGrabberAsyncCallBackError(this, errMsg, null);
                    return(HResult.E_FAIL);
                }

                // write the sample out
                hr = sinkWriter.WriteSample(sinkWriterMediaStreamId, outputSample);
                if (Failed(hr))
                {
                    string errMsg = "OnProcessSample, Error on WriteSample =" + hr.ToString();
                    SampleGrabberAsyncCallBackError(this, errMsg, null);
                    return(hr);
                }
            }
            finally
            {
                if (outputSample != null)
                {
                    Marshal.ReleaseComObject(outputSample);
                    outputSample = null;
                }
            }

            return(HResult.S_OK);
        }
Example #30
0
        protected override int OnFrame(IMFSample pSample, IMFMediaBuffer pBuffer, long llTimestamp, string ssFormat)
        {
            int hr;

            if (IsCapturing())
            {
                if (BFirstSample)
                {
                    LlBaseTime   = llTimestamp;
                    BFirstSample = false;
                }

                // re-base the time stamp
                llTimestamp -= LlBaseTime;

                hr = pSample.SetSampleTime(llTimestamp);

                //if (Succeeded(hr))
                //{
                //    var displayTask = Task<int>.Factory.StartNew(() => Draw.DrawFrame(pBuffer));
                //    var recordTask = Task<int>.Factory.StartNew(() => PWriter.WriteSample(0, pSample));
                //    Task.WaitAll(displayTask, recordTask);
                //    hr = displayTask.Result;
                //    if (Succeeded(hr))
                //        hr = recordTask.Result;
                //}
                //Parallel.Invoke(()=>Draw.DrawFrame(pBuffer),()=> PWriter.WriteSample(0, pSample));
                if (Succeeded(hr))
                {
                    hr = Draw.DrawFrame(pBuffer, !string.IsNullOrEmpty(ssFormat), ssFormat);
                }
                if (Succeeded(hr))
                {
                    hr = PWriter.WriteSample(0, pSample);
                }
            }
            else
            {
                hr = Draw.DrawFrame(pBuffer, !string.IsNullOrEmpty(ssFormat), ssFormat);
            }
            return(hr);
        }
Example #31
0
        protected void DeliverSample(IMFSample pSample, bool bRepaint)
        {
            Debug.Assert(pSample != null);

            D3DPresentEngine.DeviceState state;

            // If we are not actively playing, OR we are scrubbing (rate = 0) OR this is a
            // repaint request, then we need to present the sample immediately. Otherwise,
            // schedule it normally.

            bool bPresentNow = ((m_RenderState != RenderState.Started) || IsScrubbing() || bRepaint);

            // Check the D3D device state.
            int hr = S_Ok;
            try
            {
                m_pD3DPresentEngine.CheckDeviceState(out state);
                m_scheduler.ScheduleSample(pSample, bPresentNow);
            }
            catch (Exception e)
            {
                // Notify the EVR that we have failed during streaming. The EVR will notify the
                // pipeline (ie, it will notify the Filter Graph Manager in DirectShow or the
                // Media Session in Media Foundation).
                hr = Marshal.GetHRForException(e);
                NotifyEvent(EventCode.ErrorAbort, new IntPtr(hr), IntPtr.Zero);
                throw;
            }

            if (state == D3DPresentEngine.DeviceState.DeviceReset)
            {
                // The Direct3D device was re-set. Notify the EVR.
                NotifyEvent(EventCode.DisplayChanged, IntPtr.Zero, IntPtr.Zero);
            }
        }
Example #32
0
        protected void DeliverFrameStepSample(IMFSample pSample)
        {
            // For rate 0, discard any sample that ends earlier than the clock time.
            if (IsScrubbing() && (m_pClock != null) && IsSampleTimePassed(m_pClock, pSample))
            {
                // Discard this sample.
                Marshal.ReleaseComObject(pSample);
            }
            else if (m_FrameStep.state >= FrameStepRate.Scheduled)
            {
                // A frame was already submitted. Put this sample on the frame-step queue,
                // in case we are asked to step to the next frame. If frame-stepping is
                // cancelled, this sample will be processed normally.
                m_FrameStep.samples.Enqueue(pSample);
            }
            else
            {
                // We're ready to frame-step.

                // Decrement the number of steps.
                if (m_FrameStep.steps > 0)
                {
                    m_FrameStep.steps--;
                }

                if (m_FrameStep.steps > 0)
                {
                    // This is not the last step. Discard this sample.
                    Marshal.ReleaseComObject(pSample);
                }
                else if (m_FrameStep.state == FrameStepRate.WaitingStart)
                {
                    // This is the right frame, but the clock hasn't started yet. Put the
                    // sample on the frame-step queue. When the clock starts, the sample
                    // will be processed.
                    m_FrameStep.samples.Enqueue(pSample);
                }
                else
                {
                    // This is the right frame *and* the clock has started. Deliver this sample.
                    DeliverSample(pSample, false);

                    // Save this value.
                    m_FrameStep.SetSample(pSample);

                    // NOTE: We do not AddRef the IUnknown pointer, because that would prevent the
                    // sample from invoking the OnSampleFree callback after the sample is presented.
                    // We use this IUnknown pointer purely to identify the sample later; we never
                    // attempt to dereference the pointer.

                    // Update our state.
                    m_FrameStep.state = FrameStepRate.Scheduled;
                }
            }
        }
Example #33
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));
            }
        }
Example #34
0
        //-----------------------------------------------------------------------------
        // CreateD3DSample
        //
        // Creates an sample object (IMFSample) to hold a Direct3D swap chain.
        //-----------------------------------------------------------------------------
        protected void CreateD3DSample(IDirect3DSwapChain9 pSwapChain, out IMFSample ppVideoSample)
        {
            int hr;
            IDirect3DSurface9 pSurface = null;

            // Caller holds the object lock.
            try
            {
                // Get the back buffer surface.
                pSwapChain.GetBackBuffer(0, D3DBACKBUFFER_TYPE.Mono, out pSurface);

                // Create the sample.
                hr = MFExtern.MFCreateVideoSampleFromSurface(pSurface, out ppVideoSample);
                MFError.ThrowExceptionForHR(hr);
            }
            finally
            {
                SafeRelease(pSurface); pSurface = null;
            }
        }
Example #35
0
 protected abstract int OnFrame(IMFSample pSample, IMFMediaBuffer pBuffer, long llTimestamp, string ssFormat);
Example #36
0
        protected void TrackSample(IMFSample pSample)
        {
            IMFTrackedSample pTracked = null;

            pTracked = (IMFTrackedSample)pSample;
            int hr = pTracked.SetAllocator(this, null);
            MFError.ThrowExceptionForHR(hr);
        }
Example #37
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;
        }
Example #38
0
 protected override int OnFrame(IMFSample pSample, IMFMediaBuffer pBuffer, long llTimestamp, string ssFormat)
     => Draw.DrawFrame(pBuffer, !string.IsNullOrEmpty(ssFormat), ssFormat);
Example #39
0
 public void Dispose()
 {
     Sample = null;
     if (Target != null)
     {
         Target.Dispose();
         Target = null;
     }
 }
Example #40
0
        protected override int OnFrame(IMFSample pSample, IMFMediaBuffer pBuffer, long llTimestamp, string ssFormat)
        {
            int hr;
            if (IsCapturing())
            {
                if (BFirstSample)
                {
                    LlBaseTime = llTimestamp;
                    BFirstSample = false;
                }

                // re-base the time stamp
                llTimestamp -= LlBaseTime;

                hr = pSample.SetSampleTime(llTimestamp);

                //if (Succeeded(hr))
                //{
                //    var displayTask = Task<int>.Factory.StartNew(() => Draw.DrawFrame(pBuffer));
                //    var recordTask = Task<int>.Factory.StartNew(() => PWriter.WriteSample(0, pSample));
                //    Task.WaitAll(displayTask, recordTask);
                //    hr = displayTask.Result;
                //    if (Succeeded(hr))
                //        hr = recordTask.Result;
                //}
                //Parallel.Invoke(()=>Draw.DrawFrame(pBuffer),()=> PWriter.WriteSample(0, pSample));
                if (Succeeded(hr))
                    hr = Draw.DrawFrame(pBuffer, !string.IsNullOrEmpty(ssFormat), ssFormat);
                if (Succeeded(hr))
                    hr = PWriter.WriteSample(0, pSample);
            }
            else
                hr = Draw.DrawFrame(pBuffer, !string.IsNullOrEmpty(ssFormat), ssFormat);
            return hr;
        }
Example #41
0
        //-----------------------------------------------------------------------------
        // GetSample
        //
        // Gets a sample from the pool. If no samples are available, the method
        // returns ppSample = null
        //-----------------------------------------------------------------------------
        public void GetSample(out IMFSample ppSample)
        {
            lock (this)
            {
                if (!m_bInitialized)
                {
                    throw new COMException("SamplePool::GetSample1", MFError.MF_E_NOT_INITIALIZED);
                }

                if (m_VideoSampleQueue.Count == 0)
                {
                    ppSample = null;
                    return;
                }

                // Get a sample from the allocated queue.
                ppSample = (IMFSample)m_VideoSampleQueue.Dequeue();

                m_cPending++;  // Since we're locked, we don't need InterlockedIncrement
            }
        }
Example #42
0
        //-----------------------------------------------------------------------------
        // PresentSample
        //
        // Presents a video frame.
        //
        // pSample:  Pointer to the sample that contains the surface to present. If
        //           this parameter is NULL, the method paints a black rectangle.
        // llTarget: Target presentation time.
        //
        // This method is called by the scheduler and/or the presenter.
        //-----------------------------------------------------------------------------
        public void PresentSample(IMFSample pSample, long llTarget)
        {
            int hr;
            IMFMediaBuffer pBuffer = null;
            IDirect3DSurface9 pSurface = null;
            IDirect3DSwapChain9 pSwapChain = null;
            object o;

            try
            {
                if (pSample != null)
                {
                    // Get the buffer from the sample.
                    hr = pSample.GetBufferByIndex(0, out pBuffer);
                    MFError.ThrowExceptionForHR(hr);

                    // Get the surface from the buffer.
                    hr = MFExtern.MFGetService(pBuffer, MFServices.MR_BUFFER_SERVICE, typeof(IDirect3DSurface9).GUID, out o);
                    MFError.ThrowExceptionForHR(hr);
                    pSurface = o as IDirect3DSurface9;
                }
                else if (m_pSurfaceRepaint != null)
                {
                    // Redraw from the last surface.
                    pSurface = m_pSurfaceRepaint;
                }

                if (pSurface != null)
                {
                    // Get the swap chain from the surface.
                    pSurface.GetContainer(typeof(IDirect3DSwapChain9).GUID, out o);
                    pSwapChain = o as IDirect3DSwapChain9;

                    // Present the swap chain.
                    PresentSwapChain(pSwapChain, pSurface);

                    // Store this pointer in case we need to repaint the surface.
                    if (m_pSurfaceRepaint != pSurface)
                    {
                        SafeRelease(m_pSurfaceRepaint);
                        m_pSurfaceRepaint = pSurface;
                    }
                }
                else
                {
                    // No surface. All we can do is paint a black rectangle.
                    PaintFrameWithGDI();
                }
            }
            catch (Exception e)
            {
                hr = Marshal.GetHRForException(e);
                if (hr == (int)D3DError.DeviceLost || hr == (int)D3DError.DeviceNotReset || hr == (int)D3DError.DeviceHung)
                {
                    // We failed because the device was lost. Fill the destination rectangle.
                    PaintFrameWithGDI();

                    // Ignore. We need to reset or re-create the device, but this method
                    // is probably being called from the scheduler thread, which is not the
                    // same thread that created the device. The Reset(Ex) method must be
                    // called from the thread that created the device.

                    // The presenter will detect the state when it calls CheckDeviceState()
                    // on the next sample.
                }
            }
            finally
            {
                SafeRelease(pSwapChain); pSwapChain = null;
                //SafeRelease(pSurface); pSurface = null;
                SafeRelease(pBuffer); pBuffer = null;
            }
        }
Example #43
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;
        }
Example #44
0
        protected void SetDesiredSampleTime(IMFSample pSample, long hnsSampleTime, long hnsDuration)
        {
            if (pSample == null)
            {
                throw new COMException("SetDesiredSampleTime", E_Pointer);
            }

            IMFDesiredSample pDesired = null;

            pDesired = (IMFDesiredSample)pSample;

            // This method has no return value.
            pDesired.SetDesiredSampleTimeAndDuration(hnsSampleTime, hnsDuration);

            //SafeRelease(pDesired);
        }
Example #45
0
        public void ScheduleSample(IMFSample pSample, bool bPresentNow)
        {
            if (m_bSchedulerThread == false)
            {
                throw new COMException("Scheduler thread not started", MFError.MF_E_NOT_INITIALIZED);
            }

            if (bPresentNow || (m_pClock == null))
            {
                // Present the sample immediately.
                m_pCB.PresentSample(pSample, 0);
                SafeRelease(pSample);
            }
            else
            {
                // Queue the sample and ask the scheduler thread to wake up.
                lock (m_ScheduledSamples)
                {
                    m_ScheduledSamples.Enqueue(pSample);
                }

                lock (m_ScheduledSamples)
                {
                    m_EventQueue.Enqueue(ScheduleEvent.eSchedule);
                }
                m_hMsgEvent.Set();
            }
        }
Example #46
0
        //-----------------------------------------------------------------------------
        // ReturnSample
        //
        // Returns a sample to the pool.
        //-----------------------------------------------------------------------------
        public void ReturnSample(IMFSample pSample)
        {
            lock (this)
            {
                if (!m_bInitialized)
                {
                    throw new COMException("SamplePool::ReturnSample", MFError.MF_E_NOT_INITIALIZED);
                }

                m_VideoSampleQueue.Enqueue(pSample);

                m_cPending--;  // Since we're locked, we don't need InterlockedDecrement
            }
        }
Example #47
0
        public int OnReadSample(
            int hrStatus,
            int dwStreamIndex,
            MF_SOURCE_READER_FLAG dwStreamFlags,
            long llTimeStamp,
            IMFSample pSample      // Can be null
            )
        {
            int hr = S_Ok;

            try
            {
                lock (this)
                {
                    if (!IsCapturing())
                    {
                        return S_Ok;
                    }

                    if (Failed(hrStatus))
                    {
                        hr = hrStatus;
                        goto done;
                    }

                    if (pSample != null)
                    {
                        if (m_bFirstSample)
                        {
                            m_llBaseTime = llTimeStamp;
                            m_bFirstSample = false;
                        }

                        // rebase the time stamp
                        llTimeStamp -= m_llBaseTime;

                        hr = pSample.SetSampleTime(llTimeStamp);

                        if (Failed(hr)) { goto done; }

                        hr = m_pWriter.WriteSample(0, pSample);

                        if (Failed(hr)) { goto done; }
                    }

                    // Read another sample.
                    hr = m_pReader.ReadSample(
                        MF_SOURCE_READER_FIRST_VIDEO_STREAM,
                        0,
                        IntPtr.Zero,   // actual
                        IntPtr.Zero,   // flags
                        IntPtr.Zero,   // timestamp
                        IntPtr.Zero    // sample
                        );

                done:
                    if (Failed(hr))
                    {
                        PostMessage(m_hwndEvent, m_iMessageID, new IntPtr(hr), IntPtr.Zero);
                    }
                }
            }
            catch (Exception e)
            {
                hr = Marshal.GetHRForException(e);
            }
            finally
            {
                SafeRelease(pSample);
            }

            return hr;
        }
Example #48
0
        // IMFSourceReaderCallback methods
        //-------------------------------------------------------------------
        // OnReadSample
        //
        // Called when the IMFMediaSource::ReadSample method completes.
        //-------------------------------------------------------------------
        public int OnReadSample(int hrStatus, int dwStreamIndex, MF_SOURCE_READER_FLAG dwStreamFlags, long llTimestamp, IMFSample pSample)
        {
            var hr = hrStatus;
            IMFMediaBuffer pBuffer = null;
            lock (LockSync)
            {
                try
                {
                    if (pSample != null)
                    {
                        // Get the video frame buffer from the sample.
                        if (Succeeded(hr))
                            hr = pSample.GetBufferByIndex(0, out pBuffer);

                        if (Succeeded(hr))
                        {
                            hr = OnFrame(pSample, pBuffer, llTimestamp, snapFormat);
                            snapFormat = string.Empty;
                        }
                    }

                    // Request the next frame.
                    if (Succeeded(hr))
                    {
                        // Read next sample.
                        hr = PReader.ReadSample(
                            (int) MF_SOURCE_READER.FirstVideoStream,
                            0,
                            IntPtr.Zero, // actual
                            IntPtr.Zero, // flags
                            IntPtr.Zero, // time stamp
                            IntPtr.Zero // sample
                            );
                    }

                    if (Failed(hr))
                    {
                        NotifyError(hr);
                    }
                }
                finally
                {
                    SafeRelease(pBuffer);
                    SafeRelease(pSample);
                }
            }

            return hr;
        }
Example #49
0
        protected void ClearDesiredSampleTime(IMFSample pSample)
        {
            if (pSample == null)
            {
                throw new COMException("ClearDesiredSampleTime", E_Pointer);
            }

            IMFDesiredSample pDesired = null;
            object pUnkSwapChain = null;

            // We store some custom attributes on the sample, so we need to cache them
            // and reset them.
            //
            // This works around the fact that IMFDesiredSample::Clear() removes all of the
            // attributes from the sample.

            int counter;
            int hr;

            hr = pSample.GetUINT32(MFSamplePresenter_SampleCounter, out counter);
            MFError.ThrowExceptionForHR(hr);

            try
            {
                Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");
                hr = pSample.GetUnknown(MFSamplePresenter_SampleSwapChain, IID_IUnknown, out pUnkSwapChain);
                MFError.ThrowExceptionForHR(hr);
            }
            catch { }

            pDesired = (IMFDesiredSample)pSample;

            pDesired.Clear();

            hr = pSample.SetUINT32(MFSamplePresenter_SampleCounter, counter);
            MFError.ThrowExceptionForHR(hr);

            if (pUnkSwapChain != null)
            {
                hr = pSample.SetUnknown(MFSamplePresenter_SampleSwapChain, pUnkSwapChain);
                MFError.ThrowExceptionForHR(hr);
            }

            SafeRelease(pUnkSwapChain);
            //SafeRelease(pDesired);
        }
Example #50
0
        //-------------------------------------------------------------------
        // Name: ProcessSample
        // Description: Receives an input sample. [Asynchronous]
        //
        // Note: The client should only give us a sample after we send an
        //       MEStreamSinkRequestSample event.
        //-------------------------------------------------------------------
        public int ProcessSample(IMFSample pSample)
        {
            TRACE("CWavStream::ProcessSample");
            lock (this)
            {
                if (pSample == null)
                {
                    throw new COMException("Null pSample", E_InvalidArgument);
                }

                CheckShutdown();

                // Validate the operation.
                ValidateOperation(CAsyncOperation.StreamOperation.OpProcessSample);

                // Add the sample to the sample queue.
                m_SampleQueue.Enqueue(pSample);

                // Unless we are paused, start an async operation to dispatch the next sample.
                if (m_state != State.Paused)
                {
                    // Queue the operation.
                    QueueAsyncOperation(CAsyncOperation.StreamOperation.OpProcessSample);
                }
            }
            return S_Ok;
        }
Example #51
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
        }
Example #52
0
        // IMFSourceReaderCallback methods
        //-------------------------------------------------------------------
        // OnReadSample
        //
        // Called when the IMFMediaSource::ReadSample method completes.
        //-------------------------------------------------------------------
        public int OnReadSample(int hrStatus, int dwStreamIndex, MF_SOURCE_READER_FLAG dwStreamFlags, long llTimestamp, IMFSample pSample)
        {
            int hr = hrStatus;
            IMFMediaBuffer pBuffer = null;

            lock (this)
            {
                try
                {
                    if (Succeeded(hr))
                    {
                        if (pSample != null)
                        {
                            // Get the video frame buffer from the sample.
                            hr = pSample.GetBufferByIndex(0, out pBuffer);

                            // Draw the frame.

                            if (Succeeded(hr))
                            {
                                hr = m_draw.DrawFrame(pBuffer);
                            }
                        }
                    }

                    // Request the next frame.
                    if (Succeeded(hr))
                    {
                        // Ask for the first sample.
                        hr = m_pReader.ReadSample((int)MF_SOURCE_READER.FirstVideoStream, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
                    }

                    if (Failed(hr))
                    {
                        NotifyError(hr);
                    }
                }
                finally
                {
                    //SafeRelease(pBuffer);
                    SafeRelease(pSample);
                }
            }

            return hr;
        }
Example #53
0
        private void CreateAudioSample(out IMFSample ppSample)
        {
            int hr;
            m_Log.WriteLine("CreateAudioSample");
            ppSample = null;

            IMFMediaBuffer pBuffer = null;
            IMFSample pSample = null;

            int cbBuffer = 0;
            IntPtr pData = IntPtr.Zero;
            long duration = 0;

            // Start with one second of data, rounded up to the nearest block.
            cbBuffer = Utils.AlignUp(m_Riff.Format().nAvgBytesPerSec, m_Riff.Format().nBlockAlign);

            // Don't request any more than what's left.
            cbBuffer = Math.Min(cbBuffer, m_Riff.BytesRemainingInChunk());

            // Create the buffer.
            hr = MFExtern.MFCreateMemoryBuffer(cbBuffer, out pBuffer);
            MFError.ThrowExceptionForHR(hr);

            int a, b;

            // Get a pointer to the buffer memory.
            hr = pBuffer.Lock(out pData, out a, out b);
            MFError.ThrowExceptionForHR(hr);

            try
            {
                // Fill the buffer
                m_Riff.ReadDataFromChunk(pData, cbBuffer);
            }
            finally
            {
                // Unlock the buffer.
                hr = pBuffer.Unlock();
                MFError.ThrowExceptionForHR(hr);
            }

            // Set the size of the valid data in the buffer.
            hr = pBuffer.SetCurrentLength(cbBuffer);
            MFError.ThrowExceptionForHR(hr);

            // Create a new sample and add the buffer to it.
            hr = MFExtern.MFCreateSample(out pSample);
            MFError.ThrowExceptionForHR(hr);

            hr = pSample.AddBuffer(pBuffer);
            MFError.ThrowExceptionForHR(hr);

            // Set the time stamps, duration, and sample flags.
            hr = pSample.SetSampleTime(m_rtCurrentPosition);
            MFError.ThrowExceptionForHR(hr);

            duration = Utils.AudioDurationFromBufferSize(m_Riff.Format(), cbBuffer);
            hr = pSample.SetSampleDuration(duration);
            MFError.ThrowExceptionForHR(hr);

            // Set the discontinuity flag.
            if (m_discontinuity)
            {
                hr = pSample.SetUINT32(MFAttributesClsid.MFSampleExtension_Discontinuity, 1);
                MFError.ThrowExceptionForHR(hr);
            }

            // Update our current position.
            m_rtCurrentPosition += duration;

            // Give the pointer to the caller.
            ppSample = pSample;

            //SAFE_RELEASE(pBuffer);
            //SAFE_RELEASE(pSample);
        }