Пример #1
0
        /// <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 TOutputDataBuffer[1];

            // we have to create our own for
            using var sample  = MediaFactory.CreateSample();
            using var pBuffer = MediaFactory.CreateMemoryBuffer(outputBuffer.Length);
            sample.AddBuffer(pBuffer);
            sample.SampleTime           = outputPosition; // hopefully this is not needed
            outputDataBuffer[0].PSample = sample;         //.NativePointer;

            var needsMoreInput = transform.ProcessOutput(TransformProcessOutputFlags.None, outputDataBuffer, out TransformProcessOutputStatus status);

            // **** BUG in SharpDX Transform.ProcessOutput - returns the opposite of what you expect
            if (!needsMoreInput)
            {
                // nothing to read
                return(0);
            }

            using var outputMediaBuffer = sample.ConvertToContiguousBuffer();
            //outputDataBuffer[0].PSample.ConvertToContiguousBuffer(out outputMediaBuffer);

            IntPtr pOutputBuffer = outputMediaBuffer.Lock(out int maxSize, out int 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
            return(outputBufferLength);
        }
Пример #2
0
        private void Drain()
        {
            encoder.GetOutputStreamInfo(0, out TOutputStreamInformation streamInfo);

            MftOutputStreamInformationFlags flags = (MftOutputStreamInformationFlags)streamInfo.DwFlags;
            bool createSample = !flags.HasFlag(MftOutputStreamInformationFlags.MftOutputStreamProvidesSamples);

            bool drain = true;

            do
            {
                Sample outputSample = null;
                try
                {
                    if (createSample)
                    {
                        outputSample                = MediaFactory.CreateSample();
                        outputSample.SampleTime     = 0;
                        outputSample.SampleDuration = 0;

                        using (var mediaBuffer = MediaFactory.CreateMemoryBuffer(streamInfo.CbSize))
                        {
                            outputSample.AddBuffer(mediaBuffer);
                        }
                    }

                    TOutputDataBuffer[] outputDataBuffer = new TOutputDataBuffer[1];

                    var data = new TOutputDataBuffer
                    {
                        DwStatus   = 0,
                        DwStreamID = 0,
                        PSample    = outputSample,
                        PEvents    = null,
                    };
                    outputDataBuffer[0] = data;

                    var res = encoder.TryProcessOutput(TransformProcessOutputFlags.None, outputDataBuffer, out var status);

                    drain = res.Success; //(res != SharpDX.MediaFoundation.ResultCode.TransformNeedMoreInput);
                }
                finally
                {
                    outputSample?.Dispose();
                }
            }while (drain);
        }
Пример #3
0
        public bool ProcessSample(Sample inputSample, Action <Sample> OnSampleDecoded, Action <MediaType> OnMediaTypeChanged = null)
        {
            bool Result = false;


            if (inputSample == null)
            {
                return(false);
            }

            decoder.ProcessInput(0, inputSample, 0);

            //if (decoder.OutputStatus == (int)MftOutputStatusFlags.MftOutputStatusSampleReady)
            {
                decoder.GetOutputStreamInfo(0, out TOutputStreamInformation streamInfo);

                MftOutputStreamInformationFlags flags = (MftOutputStreamInformationFlags)streamInfo.DwFlags;
                bool createSample = !flags.HasFlag(MftOutputStreamInformationFlags.MftOutputStreamProvidesSamples);

                do
                {
                    Sample pSample = null;
                    // Create output sample
                    if (createSample)
                    {
                        pSample                = MediaFactory.CreateSample();
                        pSample.SampleTime     = inputSample.SampleTime;
                        pSample.SampleDuration = inputSample.SampleDuration;
                        pSample.SampleFlags    = inputSample.SampleFlags;
                        //logger.Debug("CreateSample: " + inputSample.SampleTime);

                        using (var mediaBuffer = MediaFactory.CreateMemoryBuffer(streamInfo.CbSize))
                        {
                            pSample.AddBuffer(mediaBuffer);
                        }
                    }

                    TOutputDataBuffer[] outputBuffers = new TOutputDataBuffer[1];

                    var outputBuffer = new TOutputDataBuffer
                    {
                        DwStatus   = 0,
                        DwStreamID = 0,
                        PSample    = pSample,
                        PEvents    = null,
                    };
                    outputBuffers[0] = outputBuffer;


                    var res = decoder.TryProcessOutput(TransformProcessOutputFlags.None, outputBuffers, out TransformProcessOutputStatus status);

                    //logger.Info("TryProcessOutput(...) " + res + " " + outputDataBuffer[0].DwStatus);

                    if (res == SharpDX.Result.Ok)
                    {
                        var buf = outputBuffers[0];

                        var outputSample = buf.PSample;

                        var pEvents = buf.PEvents;
                        if (pEvents != null)
                        {
                            var eventsCount = pEvents.ElementCount;

                            Debug.Assert(eventsCount == 0, "eventsCount == 0");

                            if (eventsCount > 0)
                            {
                                for (int i = 0; i < eventsCount; i++)
                                {
                                    var e = pEvents.GetElement(i);
                                    if (e != null)
                                    {
                                        e.Dispose();
                                        e = null;
                                    }
                                }
                            }
                        }


                        Debug.Assert(outputSample != null, "res.Success && outputSample != null");

                        OnSampleDecoded?.Invoke(outputSample);
                        Result = true;
                        //continue;
                    }
                    else if (res == SharpDX.MediaFoundation.ResultCode.TransformNeedMoreInput)
                    {
                        //logger.Info("-------------------------");

                        if (pSample != null)
                        {
                            pSample.Dispose();
                            pSample = null;
                        }

                        Result = true;

                        break;
                    }
                    else if (res == SharpDX.MediaFoundation.ResultCode.TransformStreamChange)
                    {
                        logger.Warn(res.ToString() + " TransformStreamChange");

                        MediaType newOutputType = null;
                        try
                        {
                            decoder.TryGetOutputAvailableType(outputStreamId, 0, out newOutputType);
                            decoder.SetOutputType(outputStreamId, newOutputType, 0);

                            if (OutputMediaType != null)
                            {
                                OutputMediaType.Dispose();
                                OutputMediaType = null;
                            }
                            OutputMediaType = newOutputType;

                            logger.Info("============== NEW OUTPUT TYPE==================");
                            logger.Info(MfTool.LogMediaType(OutputMediaType));


                            OnMediaTypeChanged?.Invoke(OutputMediaType);
                        }
                        finally
                        {
                            //newOutputType?.Dispose();
                            //newOutputType = null;
                        }
                    }
                    else
                    {
                        res.CheckError();

                        Result = false;
                        break;
                    }
                }while (true);
            }

            return(Result);
        }
Пример #4
0
        /// <summary>
        /// Generates output from the current input data.
        /// </summary>
        /// <param name="dwFlags">Bitwise OR of zero or more flags from the <strong><see cref="SharpDX.MediaFoundation.TransformProcessOutputFlags" /></strong> enumeration.</param>
        /// <param name="outputSamplesRef">Pointer to an array of <strong><see cref="SharpDX.MediaFoundation.TOutputDataBuffer" /></strong> structures, allocated by the caller. The MFT uses this array to return output data to the caller.</param>
        /// <param name="dwStatusRef">Receives a bitwise OR of zero or more flags from the <strong><see cref="SharpDX.MediaFoundation.TransformProcessOutputStatus" /></strong> enumeration.</param>
        /// <returns><c>true</c> if the transform cannot produce output data until it receives more input data, <c>false</c> otherwise</returns>
        /// <msdn-id>ms704014</msdn-id>	
        /// <unmanaged>HRESULT IMFTransform::ProcessOutput([In] _MFT_PROCESS_OUTPUT_FLAGS dwFlags,[In] unsigned int cOutputBufferCount,[In] MFT_OUTPUT_DATA_BUFFER* pOutputSamples,[Out] _MFT_PROCESS_OUTPUT_STATUS* pdwStatus)</unmanaged>	
        /// <unmanaged-short>IMFTransform::ProcessOutput</unmanaged-short>	
        public bool ProcessOutput(TransformProcessOutputFlags dwFlags, TOutputDataBuffer[] outputSamplesRef, out TransformProcessOutputStatus dwStatusRef)
        {
            bool needMoreInput = false;
            var result = ProcessOutput(dwFlags, outputSamplesRef.Length, outputSamplesRef[0], out dwStatusRef);

            // Check if it needs more input
            if (result== ResultCode.TransformNeedMoreInput)
            {
                needMoreInput = true;
            }
            else
            {
                result.CheckError();
            }

            return needMoreInput;
        }
Пример #5
0
        public bool EncodeSample(Sample inputSample, out Sample outputSample)
        {
            bool Result = false;

            outputSample = null;

            if (inputSample == null)
            {
                return(false);
            }

            encoder.ProcessInput(0, inputSample, 0);

            //if (processor.OutputStatus == (int)MftOutputStatusFlags.MftOutputStatusSampleReady)
            {
                encoder.GetOutputStreamInfo(0, out TOutputStreamInformation streamInfo);

                MftOutputStreamInformationFlags flags = (MftOutputStreamInformationFlags)streamInfo.DwFlags;
                bool createSample = !flags.HasFlag(MftOutputStreamInformationFlags.MftOutputStreamProvidesSamples);

                if (createSample)
                {
                    outputSample = MediaFactory.CreateSample();

                    outputSample.SampleTime     = inputSample.SampleTime;
                    outputSample.SampleDuration = inputSample.SampleDuration;
                    outputSample.SampleFlags    = inputSample.SampleFlags;

                    using (var mediaBuffer = MediaFactory.CreateMemoryBuffer(streamInfo.CbSize))
                    {
                        outputSample.AddBuffer(mediaBuffer);
                    }
                }

                TOutputDataBuffer[] outputDataBuffer = new TOutputDataBuffer[1];

                var data = new TOutputDataBuffer
                {
                    DwStatus   = 0,
                    DwStreamID = 0,
                    PSample    = outputSample,
                    PEvents    = null,
                };
                outputDataBuffer[0] = data;

                var res = encoder.TryProcessOutput(TransformProcessOutputFlags.None, outputDataBuffer, out TransformProcessOutputStatus status);
                if (res == SharpDX.Result.Ok)
                {
                    if (outputSample == null)
                    {
                        outputSample = outputDataBuffer[0].PSample;
                    }

                    Debug.Assert(outputSample != null, "res.Success && outputSample != null");

                    Result = true;
                }
                else if (res == SharpDX.MediaFoundation.ResultCode.TransformNeedMoreInput)
                {
                    logger.Warn(res.ToString() + " TransformNeedMoreInput");

                    Result = true;
                }
                else if (res == SharpDX.MediaFoundation.ResultCode.TransformStreamChange)
                {
                    logger.Warn(res.ToString() + " TransformStreamChange");

                    MediaType newOutputType = null;
                    try
                    {
                        encoder.TryGetOutputAvailableType(outputStreamId, 0, out newOutputType);
                        encoder.SetOutputType(outputStreamId, newOutputType, 0);

                        if (OutputMediaType != null)
                        {
                            OutputMediaType.Dispose();
                            OutputMediaType = null;
                        }
                        OutputMediaType = newOutputType;

                        logger.Info("============== NEW OUTPUT TYPE==================");
                        logger.Info(MfTool.LogMediaType(OutputMediaType));
                    }
                    finally
                    {
                        newOutputType?.Dispose();
                        newOutputType = null;
                    }
                }
                else
                {
                    res.CheckError();
                }
            }

            return(Result);
        }
Пример #6
0
        private void ProcessOutput()
        {
            if (stopping)
            {
                logger.Warn("ProcessOutput() stopping...");
            }

            if (closing)
            {
                logger.Warn("ProcessOutput() closing...");
                return;
            }

            encoder.GetOutputStreamInfo(0, out TOutputStreamInformation streamInfo);

            MftOutputStreamInformationFlags flags = (MftOutputStreamInformationFlags)streamInfo.DwFlags;
            bool createSample = !flags.HasFlag(MftOutputStreamInformationFlags.MftOutputStreamProvidesSamples);

            // Create output sample
            Sample outputSample = null;

            try
            {
                if (createSample)
                {
                    Debug.Assert(streamInfo.CbSize > 0, "streamInfo.CbSize > 0");

                    outputSample = MediaFactory.CreateSample();
                    using (var mediaBuffer = MediaFactory.CreateMemoryBuffer(streamInfo.CbSize))
                    {
                        outputSample.AddBuffer(mediaBuffer);
                    }
                }

                TOutputDataBuffer[] outputDataBuffer = new TOutputDataBuffer[1];

                var data = new TOutputDataBuffer
                {
                    DwStatus   = 0,
                    DwStreamID = 0,
                    PSample    = outputSample,
                    PEvents    = null,
                };
                outputDataBuffer[0] = data;

                var res = encoder.TryProcessOutput(TransformProcessOutputFlags.None, outputDataBuffer, out TransformProcessOutputStatus status);

                if (res == SharpDX.Result.Ok)
                {
                    if (outputSample == null)
                    {
                        outputSample = outputDataBuffer[0].PSample;
                    }

                    Debug.Assert(outputSample != null, "res.Success && outputSample != null");
                    FinalizeSample(outputSample);
                    // SampleReady?.Invoke(outputSample);
                }
                else if (res == SharpDX.MediaFoundation.ResultCode.TransformNeedMoreInput)
                {
                    //logger.Debug(res.ToString() + " TransformNeedMoreInput");
                    //Result = true;
                }
                else if (res == SharpDX.MediaFoundation.ResultCode.TransformStreamChange)
                {// не должны приходить для энкодера...
                    // но приходят для Intel MFT !!!
                    logger.Warn(res.ToString() + " TransformStreamChange");

                    MediaType newOutputType = null;
                    try
                    {
                        encoder.TryGetOutputAvailableType(outputStreamId, 0, out newOutputType);
                        encoder.SetOutputType(outputStreamId, newOutputType, 0);

                        if (OutputMediaType != null)
                        {
                            OutputMediaType.Dispose();
                            OutputMediaType = null;
                        }
                        OutputMediaType = newOutputType;

                        logger.Info("============== NEW OUTPUT TYPE==================");
                        logger.Info(MfTool.LogMediaType(OutputMediaType));
                    }
                    finally
                    {
                        newOutputType?.Dispose();
                        newOutputType = null;
                    }
                }
                else
                {
                    res.CheckError();
                }
            }
            finally
            {
                if (outputSample != null)
                {
                    outputSample.Dispose();
                    outputSample = null;
                }
            }
        }
Пример #7
0
 public Result ProcessOutput(TransformProcessOutputFlags dwFlags, TOutputDataBuffer outputSampleRef, out TransformProcessOutputStatus dwStatusRef)
 {
     return(_ProcessOutput(dwFlags, 1, ref outputSampleRef, out dwStatusRef));
 }
Пример #8
0
        public unsafe SharpDX.Result _ProcessOutput(TransformProcessOutputFlags dwFlags, int cOutputBufferCount, ref TOutputDataBuffer outputSamplesRef, out TransformProcessOutputStatus dwStatusRef)
        {
            SharpDX.MediaFoundation.TOutputDataBuffer.__Native outputSamplesRef_ = default(SharpDX.MediaFoundation.TOutputDataBuffer.__Native);
            SharpDX.Result __result__;
            outputSamplesRef.__MarshalTo(ref outputSamplesRef_);

            fixed(void *dwStatusRef_ = &dwStatusRef)
            {
                __result__ = SharpDX.MediaFoundation.LocalInterop.CalliStdCallint(this._nativePointer,
                                                                                  unchecked ((System.Int32)dwFlags), cOutputBufferCount, &outputSamplesRef_, dwStatusRef_,
                                                                                  (*(void ***)this._nativePointer)[25]);
            }

            outputSamplesRef.__MarshalFrom(ref outputSamplesRef_); //<--!!!
            outputSamplesRef.__MarshalFree(ref outputSamplesRef_);
            return(__result__);
        }