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); }
//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); }
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); }
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; } } } }