예제 #1
0
            internal IMFSample ProcessOutput()
            {
                MFT_OUTPUT_DATA_BUFFER buffer = new MFT_OUTPUT_DATA_BUFFER()
                {
                    dwStreamID = 0, pSample = null, dwStatus = 0, pEvents = null
                };
                uint status = 0;

                _mft.ProcessOutput(0, 1, buffer, out status);
                return(buffer.pSample);
            }
        /// <summary>
        /// Attempts to read from the transform
        /// Some useful info here:
        /// http://msdn.microsoft.com/en-gb/library/windows/desktop/aa965264%28v=vs.85%29.aspx#process_data
        /// </summary>
        /// <returns></returns>
        private int ReadFromTransform()
        {
            var outputDataBuffer = new MFT_OUTPUT_DATA_BUFFER[1];
            // we have to create our own for
            var sample  = MediaFoundationApi.CreateSample();
            var pBuffer = MediaFoundationApi.CreateMemoryBuffer(outputBuffer.Length);

            sample.AddBuffer(pBuffer);
            sample.SetSampleTime(outputPosition); // hopefully this is not needed
            outputDataBuffer[0].pSample = sample;

            _MFT_PROCESS_OUTPUT_STATUS status;
            var hr = transform.ProcessOutput(_MFT_PROCESS_OUTPUT_FLAGS.None,
                                             1, outputDataBuffer, out status);

            if (hr == MediaFoundationErrors.MF_E_TRANSFORM_NEED_MORE_INPUT)
            {
                Marshal.ReleaseComObject(pBuffer);
                Marshal.ReleaseComObject(sample);
                // nothing to read
                return(0);
            }
            else if (hr != 0)
            {
                Marshal.ThrowExceptionForHR(hr);
            }

            IMFMediaBuffer outputMediaBuffer;

            outputDataBuffer[0].pSample.ConvertToContiguousBuffer(out outputMediaBuffer);
            IntPtr pOutputBuffer;
            int    outputBufferLength;
            int    maxSize;

            outputMediaBuffer.Lock(out pOutputBuffer, out maxSize, out outputBufferLength);
            outputBuffer = BufferHelpers.Ensure(outputBuffer, outputBufferLength);
            Marshal.Copy(pOutputBuffer, outputBuffer, 0, outputBufferLength);
            outputBufferOffset = 0;
            outputBufferCount  = outputBufferLength;
            outputMediaBuffer.Unlock();
            outputPosition += BytesToNsPosition(outputBufferCount, WaveFormat); // hopefully not needed
            Marshal.ReleaseComObject(pBuffer);
            sample.RemoveAllBuffers();                                          // needed to fix memory leak in some cases
            Marshal.ReleaseComObject(sample);
            Marshal.ReleaseComObject(outputMediaBuffer);
            return(outputBufferLength);
        }
예제 #3
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);
        }
예제 #4
0
        public HResult DecodeSample(byte[] inbuffer, int insize, out byte[] outbuff, out int outsize)
        {
            // Process Input.
            MFTOutputDataBuffer outputDataBuffer;
            ProcessOutputStatus processOutputStatus = 0;
            IMFSample           srcVideoSample;
            HResult             mftProcessOutput;
            MFTOutputStreamInfo StreamInfo;
            IMFSample           mftOutSample;
            IMFMediaBuffer      pBuffer, srcBuffer;


            Debug.WriteLine("Process sample...");
            outbuff = null;
            outsize = 0;

            MFExtern.MFCreateSample(out srcVideoSample);
            MFExtern.MFCreateMemoryBuffer(insize, out srcBuffer);
            srcVideoSample.AddBuffer(srcBuffer);

            IntPtr inputdata        = IntPtr.Zero;
            int    reconBuffCurrLen = 0;
            int    reconBuffMaxLen  = 0;

            Debug.WriteLine("CONTINUE...1");

            // move input data to decoder
            srcBuffer.Lock(out inputdata, out reconBuffMaxLen, out reconBuffCurrLen);
            Marshal.Copy(inbuffer, 0, inputdata, insize);
            srcBuffer.Unlock();

            srcBuffer.SetCurrentLength(insize);

            decodertransform.ProcessInput(0, srcVideoSample, 0);

            decodertransform.GetOutputStreamInfo(0, out StreamInfo);

            while (true)
            {
                MFExtern.MFCreateSample(out mftOutSample);
                MFExtern.MFCreateMemoryBuffer(StreamInfo.cbSize, out pBuffer);
                mftOutSample.AddBuffer(pBuffer);

                outputDataBuffer.dwStreamID = 0;
                outputDataBuffer.dwStatus   = MFTOutputDataBufferFlags.None;
                outputDataBuffer.pEvents    = null;
                outputDataBuffer.pSample    = Marshal.GetIUnknownForObject(mftOutSample);

                MFTOutputDataBuffer[] odbs = { outputDataBuffer };

                mftProcessOutput = decodertransform.ProcessOutput(MFTProcessOutputFlags.None, 1, odbs, out processOutputStatus);

                if (mftProcessOutput != HResult.MF_E_TRANSFORM_NEED_MORE_INPUT)
                {
                    IMFMediaBuffer buf;
                    int            bufLength;
                    mftOutSample.ConvertToContiguousBuffer(out buf);
                    buf.GetCurrentLength(out bufLength);

                    IntPtr poutputData = IntPtr.Zero;
                    int    buffCurrLen = 0;
                    int    buffMaxLen  = 0;

                    // get output data from decoder
                    buf.Lock(out poutputData, out buffMaxLen, out buffCurrLen);
                    outbuff = new byte[buffMaxLen];
                    Marshal.Copy(poutputData, outbuff, 0, buffCurrLen);
                    buf.Unlock();

                    outsize = buffCurrLen;
                    Debug.WriteLine("out put size: " + outsize + "\n");

                    Marshal.ReleaseComObject(buf);
                    Marshal.ReleaseComObject(mftOutSample);
                }
                else
                {
                    break;
                }

                return(mftProcessOutput);
            }

            return(mftProcessOutput);
        }
예제 #5
0
        private void CaptureStillImages(MediaItem item)
        {
            using (var releaser = new ComReleaser())
            {
                MF.CreateVideoDeviceSource(item.DeviceItem.SymLink, out IMFMediaSource source);
                releaser.Add(source);
                source.CreatePresentationDescriptor(out IMFPresentationDescriptor presDesc);
                releaser.Add(presDesc);
                presDesc.GetStreamDescriptorByIndex(item.DescIndex, out bool selected, out IMFStreamDescriptor strmDesc);
                releaser.Add(strmDesc);
                strmDesc.GetMediaTypeHandler(out IMFMediaTypeHandler handler);
                releaser.Add(handler);
                handler.GetMediaTypeByIndex(item.TypeIndex, out IMFMediaType type);
                handler.SetCurrentMediaType(type);

                MF.CreateSourceReaderFromMediaSource(source, out IMFSourceReader reader);
                if (reader == null)
                {
                    return;
                }
                releaser.Add(reader);

                IMFTransform          transform      = null;
                MFTOutputDataBuffer[] outSamples     = null;
                IMFSample             outRgb24Sample = null;
                IMFMediaBuffer        outRgb24Buffer = null;

                int rgbSize = item.Width * item.Height * 3;

                var needToConvert = item.SubType != MFMediaType.RGB24;
                if (needToConvert)
                {
                    var processor = new VideoProcessorMFT();
                    releaser.Add(processor);
                    transform = (IMFTransform)processor;
                    HR(transform.SetInputType(0, type, MFTSetTypeFlags.None));
                    var rgbMediaType = MF.CreateMediaType();
                    releaser.Add(rgbMediaType);
                    HR(type.CopyAllItems(rgbMediaType));
                    HR(rgbMediaType.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, MFMediaType.RGB24));
                    HR(rgbMediaType.SetUINT32(MFAttributesClsid.MF_MT_DEFAULT_STRIDE, 3 * item.Width));
                    HR(rgbMediaType.SetUINT32(MFAttributesClsid.MF_MT_SAMPLE_SIZE, rgbSize));
                    HR(transform.SetOutputType(0, rgbMediaType, MFTSetTypeFlags.None));

                    outSamples     = new MFTOutputDataBuffer[1];
                    outSamples[0]  = new MFTOutputDataBuffer();
                    outRgb24Sample = MF.CreateSample();
                    releaser.Add(outRgb24Sample);
                    outRgb24Buffer = MF.CreateMemoryBuffer(rgbSize);
                    releaser.Add(outRgb24Buffer);
                    outRgb24Sample.AddBuffer(outRgb24Buffer);
                    outSamples[0].pSample = Marshal.GetIUnknownForObject(outRgb24Sample);
                }

                while (true)
                {
                    int frames = 0;
                    var hrRS   = reader.ReadSample(
                        (int)MF_SOURCE_READER.AnyStream,
                        MF_SOURCE_READER_CONTROL_FLAG.None,
                        out int streamIndex,
                        out MF_SOURCE_READER_FLAG flags,
                        out long timeStamp,
                        out IMFSample sample
                        );

                    if (sample != null)
                    {
                        try
                        {
                            IMFSample rgbSample = sample;

                            if (transform != null)
                            {
                                transform.ProcessInput(0, sample, 0);
                                while (true)
                                {
                                    var hrPO = transform.ProcessOutput(
                                        MFTProcessOutputFlags.None,
                                        1,
                                        outSamples,
                                        out ProcessOutputStatus status
                                        );
                                    if (hrPO.Succeeded())
                                    {
                                        ConsumeBuffer(outRgb24Buffer, item);
                                        frames++;
                                        Marshal.ReleaseComObject(sample);
                                        return;
                                        //break;
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                                //var hrPI = transform.ProcessInput(0, sample, 0);
                                continue;
                            }

                            rgbSample.GetBufferByIndex(0, out IMFMediaBuffer buff);
                            if (ConsumeBuffer(buff, item))
                            {
                                frames++;
                            }
                            else
                            {
                                return;
                            }
                        }
                        finally
                        {
                            Marshal.ReleaseComObject(sample);
                        }
                        break;
                    }
                }
            }
        }