Example #1
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 #2
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 #3
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 #4
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 #5
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 #6
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 #7
0
        private int ReadFromTransform()
        {
            MFT_OUTPUT_DATA_BUFFER[] array = new MFT_OUTPUT_DATA_BUFFER[1];
            IMFSample      iMFSample       = MediaFoundationApi.CreateSample();
            IMFMediaBuffer iMFMediaBuffer  = MediaFoundationApi.CreateMemoryBuffer(this.outputBuffer.Length);

            iMFSample.AddBuffer(iMFMediaBuffer);
            iMFSample.SetSampleTime(this.outputPosition);
            array[0].pSample = iMFSample;
            _MFT_PROCESS_OUTPUT_STATUS mFT_PROCESS_OUTPUT_STATUS;
            int num = this.transform.ProcessOutput(_MFT_PROCESS_OUTPUT_FLAGS.None, 1, array, out mFT_PROCESS_OUTPUT_STATUS);

            if (num == -1072861838)
            {
                Marshal.ReleaseComObject(iMFMediaBuffer);
                Marshal.ReleaseComObject(iMFSample);
                return(0);
            }
            if (num != 0)
            {
                Marshal.ThrowExceptionForHR(num);
            }
            IMFMediaBuffer iMFMediaBuffer2;

            array[0].pSample.ConvertToContiguousBuffer(out iMFMediaBuffer2);
            IntPtr source;
            int    num2;
            int    num3;

            iMFMediaBuffer2.Lock(out source, out num2, out num3);
            this.outputBuffer = BufferHelpers.Ensure(this.outputBuffer, num3);
            Marshal.Copy(source, this.outputBuffer, 0, num3);
            this.outputBufferOffset = 0;
            this.outputBufferCount  = num3;
            iMFMediaBuffer2.Unlock();
            this.outputPosition += MediaFoundationTransform.BytesToNsPosition(this.outputBufferCount, this.WaveFormat);
            Marshal.ReleaseComObject(iMFMediaBuffer);
            iMFSample.RemoveAllBuffers();
            Marshal.ReleaseComObject(iMFSample);
            Marshal.ReleaseComObject(iMFMediaBuffer2);
            return(num3);
        }
Example #8
0
        private void SetSampleAttributes(StspSampleHeader sampleHeader, IMFSample sample)
        {
            ThrowIfError(sample.SetSampleTime(sampleHeader.ullTimestamp));
            ThrowIfError(sample.SetSampleDuration(sampleHeader.ullDuration));

            SET_SAMPLE_ATTRIBUTE(sampleHeader, sample, MFSampleExtension_BottomFieldFirst, StspSampleFlags.StspSampleFlag_BottomFieldFirst);
            SET_SAMPLE_ATTRIBUTE(sampleHeader, sample, MFSampleExtension_CleanPoint, StspSampleFlags.StspSampleFlag_CleanPoint);
            SET_SAMPLE_ATTRIBUTE(sampleHeader, sample, MFSampleExtension_DerivedFromTopField, StspSampleFlags.StspSampleFlag_DerivedFromTopField);
            SET_SAMPLE_ATTRIBUTE(sampleHeader, sample, MFSampleExtension_Discontinuity, StspSampleFlags.StspSampleFlag_Discontinuity);
            SET_SAMPLE_ATTRIBUTE(sampleHeader, sample, MFSampleExtension_Interlaced, StspSampleFlags.StspSampleFlag_Interlaced);
            SET_SAMPLE_ATTRIBUTE(sampleHeader, sample, MFSampleExtension_RepeatFirstField, StspSampleFlags.StspSampleFlag_RepeatFirstField);
            SET_SAMPLE_ATTRIBUTE(sampleHeader, sample, MFSampleExtension_SingleField, StspSampleFlags.StspSampleFlag_SingleField);

            /* show debug info...
             * int cbTotalLen;
             * sample.GetTotalLength(out cbTotalLen);
             * var isKeyFrame = Convert.ToBoolean(sampleHeader.dwFlags & (int)StspSampleFlags.StspSampleFlag_CleanPoint);
             * Debug.WriteLine($"{DateTime.Now.ToString()} Received sample {sampleHeader.ullTimestamp} Duration-{sampleHeader.ullDuration} Length-{cbTotalLen} " + (isKeyFrame ? "key frame" : ""));
             */
        }
Example #9
0
        /// <summary>Generates the "tail" of the audio effect.</summary>
        /// <param name="InputMessageNumber">Message number to use with OutputSample.</param>
        /// <remarks>
        /// Generates the "tail" of the audio effect. The tail is the portion
        /// of the delay effect that is heard after the input stream ends.
        ///
        /// To generate the tail, the client must drain the MFT by sending
        /// the MFT_MESSAGE_COMMAND_DRAIN message and then call ProcessOutput
        /// to get the tail samples.
        /// </remarks>
        private void ProcessEffectTail(int InputMessageNumber)
        {
            IMFMediaBuffer pOutputBuffer = null;

            MFError throwonhr;
            IntPtr  pbOutputData     = IntPtr.Zero; // Pointer to the memory in the output buffer.
            int     cbOutputLength   = 0;           // Size of the output buffer.
            int     cbBytesProcessed = 0;           // How much data we processed.

            IMFSample pOutSample = null;

            // Allocate an output buffer.
            throwonhr = MFExtern.MFCreateMemoryBuffer(m_cbTailSamples, out pOutputBuffer);

            try
            {
                throwonhr = MFExtern.MFCreateSample(out pOutSample);
                throwonhr = pOutSample.AddBuffer(pOutputBuffer);

                // Lock the output buffer.
                int cb;
                throwonhr = pOutputBuffer.Lock(out pbOutputData, out cbOutputLength, out cb);

                // Calculate how many audio samples we can process.
                cbBytesProcessed = Math.Min(m_cbTailSamples, cbOutputLength);

                // Round to the next lowest multiple of nBlockAlign.
                cbBytesProcessed -= (cbBytesProcessed % m_Alignment);

                // Fill the output buffer with silence, because we are also using it as the input buffer.
                FillBufferWithSilence(pbOutputData, cbBytesProcessed);

                // Process the data.
                ProcessAudio(pbOutputData, pbOutputData, cbBytesProcessed / m_Alignment);

                // Set the data length on the output buffer.
                throwonhr = pOutputBuffer.SetCurrentLength(cbBytesProcessed);

                if (m_rtTimestamp >= 0)
                {
                    long hnsDuration = (cbBytesProcessed / m_AvgBytesPerSec) * UNITS;

                    // Set the time stamp and duration on the output sample.
                    throwonhr = pOutSample.SetSampleTime(m_rtTimestamp);
                    throwonhr = pOutSample.SetSampleDuration(hnsDuration);
                }

                // Done.
                m_cbTailSamples = 0;

                OutputSample(pOutSample, InputMessageNumber);
            }
            catch
            {
                SafeRelease(pOutSample);
                throw;
            }
            finally
            {
                if (pbOutputData != IntPtr.Zero)
                {
                    pOutputBuffer.Unlock();
                }
                SafeRelease(pOutputBuffer);
            }
        }
Example #10
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 #11
0
        /// <summary>
        /// This is the routine that performs the transform. Unless the sinkWriter object
        /// is set all we do is pass the sample on. If the sink writer object is set
        /// we give the sample to it for writing. There are two modes - one where we just
        /// give the sinkwriter the input sample and the other where we clone the input
        /// sample and rebase the timestamps.
        ///
        /// An override of the abstract version in MFTBase_Sync.
        /// </summary>
        /// <param name="pOutputSamples">The structure to populate with output values.</param>
        /// <returns>S_Ok unless error.</returns>
        protected override HResult OnProcessOutput(ref MFTOutputDataBuffer outputSampleDataStruct)
        {
            HResult        hr = HResult.S_OK;
            IMFMediaBuffer inputMediaBuffer = null;
            IMFSample      sinkWriterSample = null;
            IMFAttributes  sampleAttributes;

            // in this MFT we are processing in place, the input sample is the output sample, the media buffer of the
            // input sample is the media buffer of the output sample. Thats for the pipeline. If a sink writer exists
            // we also write the sample data out to the sink writer. This provides the effect of displaying on the
            // screen and simultaneously recording.
            // There are two ways the sink writer can be given the media sample data. It can just be given the
            // input sample directly or a copy of the sample can be made and that copy given to the sink writer.
            // There is also an additional complication - the sample has a timestamp and video cameras tend
            // to just use the current date and time as a timestamp. There are several reports that MP4 files
            // need to have their first frame starting at zero and then every subsequent frame adjusted to that
            // new base time. Certainly the Microsoft supplied example code (and see the
            // CaptureToFileViaReaderWriter also) take great care to do this. This requirement does not
            // seem to exist - my tests indicate it is not necessary to start from 0 in the mp4 file. Maybe the
            // Sink Writer has been improved and now does this automatically. For demonstration purposes
            // the timebase-rebase functionality has been included and choosing that mode copies the sample
            // and resets the time. If the user does not rebase the time we simply send the input sample
            // to the Sink Writer as-is.
            try
            {
                // Set status flags.
                outputSampleDataStruct.dwStatus = MFTOutputDataBufferFlags.None;
                // The output sample is the input sample. We get a new IUnknown for the Input
                // sample since we are going to release it below. The client will release this
                // new IUnknown
                outputSampleDataStruct.pSample = Marshal.GetIUnknownForObject(InputSample);
                // are we recording?
                if (workingSinkWriter != null)
                {
                    // we do everything in a lock
                    lock (sinkWriterLockObject)
                    {
                        // are we in timebase rebase mode?
                        if (wantTimebaseRebase == false)
                        {
                            // we are not. Just give the input sample to the Sink Writer which will
                            // write it out.
                            hr = workingSinkWriter.WriteSample(sinkWriterVideoStreamId, InputSample);
                            if (hr != HResult.S_OK)
                            {
                                throw new Exception("OnProcessOutput call to WriteSample(a) failed. Err=" + hr.ToString());
                            }
                        }
                        else
                        {
                            // the timebase rebase option has been chosen. We need to create a copy of the input sample
                            // so we can adjust the time on it.
                            // Get the data buffer from the input sample. If the sample contains more than one buffer,
                            // this method copies the data from the original buffers into a new buffer, and replaces
                            // the original buffer list with the new buffer. The new buffer is returned in the inputMediaBuffer parameter.
                            // If the sample contains a single buffer, this method returns a pointer to the original buffer.
                            // In typical use, most samples do not contain multiple buffers.
                            hr = InputSample.ConvertToContiguousBuffer(out inputMediaBuffer);
                            if (hr != HResult.S_OK)
                            {
                                throw new Exception("OnProcessOutput call to InputSample.ConvertToContiguousBuffer failed. Err=" + hr.ToString());
                            }
                            // get some other things from the input sample
                            hr = InputSample.GetSampleDuration(out long sampleDuration);
                            if (hr != HResult.S_OK)
                            {
                                throw new Exception("OnProcessOutput call to InputSample.GetSampleDuration failed. Err=" + hr.ToString());
                            }
                            hr = InputSample.GetTotalLength(out int sampleSize);
                            if (hr != HResult.S_OK)
                            {
                                throw new Exception("OnProcessOutput call to InputSample.GetTotalLength failed. Err=" + hr.ToString());
                            }
                            hr = InputSample.GetSampleTime(out long sampleTimeStamp);
                            if (hr != HResult.S_OK)
                            {
                                throw new Exception("OnProcessOutput call to InputSample.GetSampleTime failed. Err=" + hr.ToString());
                            }
                            // get the attributes from the input sample
                            if (InputSample is IMFAttributes)
                            {
                                sampleAttributes = (InputSample as IMFAttributes);
                            }
                            else
                            {
                                sampleAttributes = null;
                            }
                            // we have all the information we need to create a new output sample
                            sinkWriterSample = WMFUtils.CreateMediaSampleFromBuffer(sampleTimeStamp, sampleDuration, inputMediaBuffer, sampleSize, sampleAttributes);
                            if (sinkWriterSample == null)
                            {
                                throw new Exception("OnProcessOutput, Error on call to CreateMediaSampleFromBuffer sinkWriterSample == null");
                            }
                            // we have a sample, if so is it the first non null one?
                            if (isFirstSample)
                            {
                                // yes it is set up our timestamp
                                firstSampleBaseTime = sampleTimeStamp;
                                isFirstSample       = false;
                            }
                            // rebase the time stamp
                            sampleTimeStamp -= firstSampleBaseTime;
                            hr = sinkWriterSample.SetSampleTime(sampleTimeStamp);
                            if (hr != HResult.S_OK)
                            {
                                throw new Exception("OnProcessOutput call to InputSample.SetSampleTime failed. Err=" + hr.ToString());
                            }
                            // write the sample out
                            hr = workingSinkWriter.WriteSample(sinkWriterVideoStreamId, sinkWriterSample);
                            if (hr != HResult.S_OK)
                            {
                                throw new Exception("OnProcessOutput call to WriteSample(b) failed. Err=" + hr.ToString());
                            }
                        }
                    }
                }
            }
            finally
            {
                // clean up
                if (inputMediaBuffer != null)
                {
                    Marshal.ReleaseComObject(inputMediaBuffer);
                }
                if (sinkWriterSample != null)
                {
                    Marshal.ReleaseComObject(sinkWriterSample);
                }
                // Release the current input sample so we can get another one.
                // the act of setting it to null releases it because the property
                // is coded that way
                InputSample = null;
            }
            return(HResult.S_OK);
        }
Example #12
0
        override protected HResult OnProcessOutput(ref MFTOutputDataBuffer pOutputSamples)
        {
            HResult hr = HResult.S_OK;
            MFError throwonhr;

            // Since we don't specify MFTOutputStreamInfoFlags.ProvidesSamples, this can't be null.
            if (pOutputSamples.pSample != IntPtr.Zero)
            {
                long hnsDuration;
                long hnsTime;

                IMFMediaBuffer pInput     = null;
                IMFMediaBuffer pOutput    = null;
                IMFSample      pOutSample = null;

                try
                {
                    // Get the data buffer from the input sample.  If the sample has
                    // multiple buffers, you might be able to get (slightly) better
                    // performance processing each buffer in turn rather than forcing
                    // a new, full-sized buffer to get created.
                    throwonhr = InputSample.ConvertToContiguousBuffer(out pInput);

                    // Turn pointer to interface
                    pOutSample = Marshal.GetUniqueObjectForIUnknown(pOutputSamples.pSample) as IMFSample;

                    // Get the output buffer.
                    throwonhr = pOutSample.ConvertToContiguousBuffer(out pOutput);

                    OnProcessOutput(pInput, pOutput);

                    // Set status flags.
                    pOutputSamples.dwStatus = MFTOutputDataBufferFlags.None;

                    // Copy the duration and time stamp from the input sample,
                    // if present.

                    hr = InputSample.GetSampleDuration(out hnsDuration);
                    if (Succeeded(hr))
                    {
                        throwonhr = pOutSample.SetSampleDuration(hnsDuration);
                    }

                    hr = InputSample.GetSampleTime(out hnsTime);
                    if (Succeeded(hr))
                    {
                        throwonhr = pOutSample.SetSampleTime(hnsTime);
                    }
                }
                finally
                {
                    SafeRelease(pInput);
                    SafeRelease(pOutput);
                    SafeRelease(pOutSample);

                    // Release the current input sample so we can get another one.
                    InputSample = null;
                }
            }
            else
            {
                return(HResult.E_INVALIDARG);
            }

            return(HResult.S_OK);
        }
Example #13
0
        public HResult OnReadSample(
            HResult hrStatus,
            int dwStreamIndex,
            MF_SOURCE_READER_FLAG dwStreamFlags,
            long llTimeStamp,
            IMFSample pSample      // Can be null
            )
        {
            HResult hr = HResult.S_OK;

            try
            {
                lock (this)
                {
                    if (!IsCapturing())
                    {
                        return(HResult.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((int)hr), IntPtr.Zero);
                    }
                }
            }
            catch (Exception e)
            {
                hr = (HResult)Marshal.GetHRForException(e);
            }
            finally
            {
                SafeRelease(pSample);
            }

            return(hr);
        }
Example #14
0
 private void SetSampleAttributes(StspSampleHeader sampleHeader, IMFSample sample)
 {
     ThrowIfError(sample.SetSampleTime(sampleHeader.ullTimestamp));
     ThrowIfError(sample.SetSampleDuration(sampleHeader.ullDuration));
 }
Example #15
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 #16
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);
                            }

                            if (Succeeded(hr))
                            {
                                if (m_bFirstSample)
                                {
                                    m_llBaseTime = llTimestamp;
                                    m_bFirstSample = false;
                                }

                                // rebase the time stamp
                                llTimestamp -= m_llBaseTime;

                                hr = pSample.SetSampleTime(llTimestamp);

                                if (Succeeded(hr))
                                {
                                    hr = m_pWriter.WriteSample(0, pSample);
                                }
                            }
                        }
                    }

                    // 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 #17
0
        // IMFSourceReaderCallback methods

        //-------------------------------------------------------------------
        // OnReadSample
        //
        // Called when the IMFMediaSource::ReadSample method completes.
        //-------------------------------------------------------------------
        public HResult OnReadSample(HResult hrStatus, int dwStreamIndex, MF_SOURCE_READER_FLAG dwStreamFlags, long llTimestamp, IMFSample pSample)
        {
            HResult        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);
                            }

                            if (Succeeded(hr))
                            {
                                if (m_bFirstSample)
                                {
                                    m_llBaseTime   = llTimestamp;
                                    m_bFirstSample = false;
                                }

                                // rebase the time stamp
                                llTimestamp -= m_llBaseTime;

                                hr = pSample.SetSampleTime(llTimestamp);

                                if (Succeeded(hr))
                                {
                                    hr = m_pWriter.WriteSample(0, pSample);
                                }
                            }
                        }
                    }

                    // 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 #18
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// This is the routine that performs the transform. Assumes InputSample is set.
        ///
        /// An override of the abstract version in TantaMFTBase_Sync.
        /// </summary>
        /// <param name="outputSampleDataStruct">The structure to populate with output data.</param>
        /// <returns>S_Ok unless error.</returns>
        /// <history>
        ///    01 Nov 18  Cynic - Ported In
        /// </history>
        protected override HResult OnProcessOutput(ref MFTOutputDataBuffer outputSampleDataStruct)
        {
            long           hnsDuration;
            long           hnsTime;
            HResult        hr = HResult.S_OK;
            IMFMediaBuffer inputMediaBuffer  = null;
            IMFMediaBuffer outputMediaBuffer = null;
            IMFSample      outputSample      = null;

            // Since we don't specify MFTOutputStreamInfoFlags.ProvidesSamples, this can't be null.
            // we expect the caller to have allocated the memory for this
            if (outputSampleDataStruct.pSample == IntPtr.Zero)
            {
                return(HResult.E_INVALIDARG);
            }

            try
            {
                // Get the data buffer from the input sample. If the sample contains more than one buffer,
                // this method copies the data from the original buffers into a new buffer, and replaces
                // the original buffer list with the new buffer. The new buffer is returned in the inputMediaBuffer parameter.
                // If the sample contains a single buffer, this method returns a pointer to the original buffer.
                // In typical use, most samples do not contain multiple buffers.
                hr = InputSample.ConvertToContiguousBuffer(out inputMediaBuffer);
                if (hr != HResult.S_OK)
                {
                    throw new Exception("OnProcessOutput call to InputSample.ConvertToContiguousBuffer failed. Err=" + hr.ToString());
                }

                // Turn pointer into an interface. The GetUniqueObjectForIUnknown method ensures that we
                // receive a unique Runtime Callable Wrapper, because it does not match an IUnknown pointer
                // to an existing object. Use this method when you have to create a unique RCW that is not
                // impacted by other code that calls the ReleaseComObject method.
                outputSample = Marshal.GetUniqueObjectForIUnknown(outputSampleDataStruct.pSample) as IMFSample;
                if (outputSample == null)
                {
                    throw new Exception("OnProcessOutput call to GetUniqueObjectForIUnknown failed. outputSample ==  null");
                }

                // Now get the output buffer. A media sample contains zero or more buffers. Each buffer manages a block of
                // memory, and is represented by the IMFMediaBuffer interface. A sample can have multiple buffers.
                // The buffers are kept in an ordered list and accessed by index value. This call gets us a single
                // pointer to a single contigous buffer which is much more useful.
                hr = outputSample.ConvertToContiguousBuffer(out outputMediaBuffer);
                if (hr != HResult.S_OK)
                {
                    throw new Exception("OnProcessOutput call to InputSample.ConvertToContiguousBuffer failed. Err=" + hr.ToString());
                }

                // now that we have an input and output buffer, do the work to convert them to grayscale.
                // Writing into outputMediaBuffer will write to the approprate location in the outputSample
                // since we took care to Marshal it that way
                ConvertMediaBufferToGrayscale(inputMediaBuffer, outputMediaBuffer);

                // Set status flags.
                outputSampleDataStruct.dwStatus = MFTOutputDataBufferFlags.None;

                // Copy the duration from the input sample, if present. The
                // Media Session needs these in order to keep everything sync'ed
                hr = InputSample.GetSampleDuration(out hnsDuration);
                if (hr == HResult.S_OK)
                {
                    hr = outputSample.SetSampleDuration(hnsDuration);
                    if (hr != HResult.S_OK)
                    {
                        throw new Exception("OnProcessOutput call to OutSample.SetSampleDuration failed. Err=" + hr.ToString());
                    }
                }

                // Copy the time stamp from the input sample, if present.
                hr = InputSample.GetSampleTime(out hnsTime);
                if (hr == HResult.S_OK)
                {
                    hr = outputSample.SetSampleTime(hnsTime);
                    if (hr != HResult.S_OK)
                    {
                        throw new Exception("OnProcessOutput call to OutSample.SetSampleTime failed. Err=" + hr.ToString());
                    }
                }
            }
            finally
            {
                // clean up
                SafeRelease(inputMediaBuffer);
                SafeRelease(outputMediaBuffer);
                SafeRelease(outputSample);

                // Release the current input sample so we can get another one.
                // the act of setting it to null releases it because the property
                // is coded that way
                InputSample = null;
            }

            return(HResult.S_OK);
        }