예제 #1
0
        private void EventProc()
        {
            logger.Debug("EventProc() BEGIN");

            MediaEventGenerator eventGen = null;

            try
            {
                eventGen = encoder.QueryInterface <MediaEventGenerator>();

                while (!closing)
                {
                    MediaEvent mediaEvent = null;
                    try
                    {
                        mediaEvent = eventGen.GetEvent(true);

                        if (closing)
                        {
                            break;
                        }

                        HandleMediaEvent(mediaEvent);
                    }
                    catch (Exception ex)
                    {
                        logger.Error(ex);

                        Thread.Sleep(10);
                    }
                    finally
                    {
                        if (mediaEvent != null)
                        {
                            mediaEvent.Dispose();
                            mediaEvent = null;
                        }
                    }
                }
            }
            finally
            {
                using (var shutdown = eventGen.QueryInterface <Shutdownable>())
                {
                    shutdown.Shutdown();
                }

                eventGen?.Dispose();
                Close();
            }

            logger.Debug("EventProc() END");
        }
예제 #2
0
        public void Close()
        {
            logger.Debug("MfEncoderAsync::Close()");

            closing = true;


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

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

            if (encoder != null)
            {
                //using (var shutdown = encoder.QueryInterface<Shutdownable>())
                //{
                //    shutdown.Shutdown();
                //    //while(shutdown.ShutdownStatus != ShutdownStatus.Completed)
                //    //{
                //    //    logger.Warn("shutdown.ShutdownStatus " + shutdown.ShutdownStatus);
                //    //    Thread.Sleep(100);

                //    //}
                //}

                encoder.Dispose();
                encoder = null;
            }

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

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


            if (eventHandler != null)
            {
                eventHandler.EventReceived -= HandleMediaEvent;
                eventHandler.Dispose();
                eventHandler = null;
            }

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



            // logger.Info(SharpDX.Diagnostics.ObjectTracker.ReportActiveObjects());
        }
예제 #3
0
        private void SetupEncoder(MfVideoArgs args)
        {
            logger.Debug("SetupEncoder(...)");


            var width  = args.Width;
            var height = args.Height;

            var frameRate   = args.FrameRate;
            int avgBitrate  = args.AvgBitrate;
            int maxBitrate  = args.MaxBitrate;
            int mpegProfile = (int)args.Profile;

            long pixelAspectRatio = args.AspectRatio;

            //var inputFormat = VideoFormatGuids.Argb32;//VideoFormatGuids.NV12;
            var inputFormat = args.Format;

            logger.Info("Encoder input params: " + width + "x" + height + " fps=" + frameRate + " {" + inputFormat + "}");
            using (var attr = encoder.Attributes)
            {
                // TODO:
                // log pref

                try
                {
                    syncMode = !(attr.Get(TransformAttributeKeys.TransformAsync) == 1);
                }
                catch (SharpDX.SharpDXException ex)
                {
                    syncMode = true;
                }


                if (!syncMode)
                {
                    //var transformAsync = (attr.Get(TransformAttributeKeys.TransformAsync) == 1);
                    //if (transformAsync)
                    //{
                    attr.Set(TransformAttributeKeys.TransformAsyncUnlock, 1);
                    attr.Set(TransformAttributeKeys.MftSupportDynamicFormatChange, true);

                    bool d3d11Aware = attr.Get(TransformAttributeKeys.D3D11Aware);
                    if (d3d11Aware)
                    {
                        using (var devMan = new DXGIDeviceManager())
                        {
                            devMan.ResetDevice(device);
                            encoder.ProcessMessage(TMessageType.SetD3DManager, devMan.NativePointer);
                        }
                    }
                    //}
                }

                attr.Set(CodecApiPropertyKeys.AVLowLatencyMode, args.LowLatency);
                attr.Set(CodecApiPropertyKeys.AVEncCommonRateControlMode, args.BitrateMode);
                attr.Set(CodecApiPropertyKeys.AVEncCommonQuality, args.Quality);

                attr.Set(CodecApiPropertyKeys.AVEncMPVGOPSize, args.GopSize);

                // отключаем B-фреймы
                attr.Set(CodecApiPropertyKeys.AVEncMPVDefaultBPictureCount, 0);


                //attr.Set(CodecApiPropertyKeys.AVEncNumWorkerThreads, 4);

                var attrLog = MfTool.LogMediaAttributes(attr);

                logger.Debug("\r\nMFT:\r\n-----------------\r\n" + attrLog);
            }


            int inputStreamCount   = -1;
            int outputStreamsCount = -1;

            encoder.GetStreamCount(out inputStreamCount, out outputStreamsCount);
            int[] inputStreamIDs  = new int[inputStreamCount];
            int[] outputStreamIDs = new int[outputStreamsCount];

            bool res = encoder.TryGetStreamIDs(inputStreamIDs, outputStreamIDs);

            if (res)
            {
                inputStreamId  = inputStreamIDs[0];
                outputStreamId = outputStreamIDs[0];
            }
            else
            {
                inputStreamId  = 0;
                outputStreamId = 0;
            }


            for (int i = 0; ; i++)
            {
                if (!encoder.TryGetOutputAvailableType(outputStreamId, i, out MediaType mediaType))
                {
                    //
                    logger.Warn("NoMoreOutputTypes");
                    break;
                }
                //var log = MfTool.LogMediaType(mediaType);
                //logger.Warn(log);

                mediaType.Set(MediaTypeAttributeKeys.InterlaceMode, (int)VideoInterlaceMode.Progressive);
                mediaType.Set(MediaTypeAttributeKeys.FrameSize, MfTool.PackToLong(width, height));
                mediaType.Set(MediaTypeAttributeKeys.FrameRate, frameRate);
                mediaType.Set(MediaTypeAttributeKeys.AllSamplesIndependent, 1);

                mediaType.Set(MediaTypeAttributeKeys.Mpeg2Profile, mpegProfile);
                mediaType.Set(MediaTypeAttributeKeys.AvgBitrate, avgBitrate);
                mediaType.Set(CodecApiPropertyKeys.AVEncCommonMaxBitRate, maxBitrate);

                mediaType.Set(MediaTypeAttributeKeys.PixelAspectRatio, pixelAspectRatio);

                encoder.SetOutputType(outputStreamId, mediaType, 0);

                OutputMediaType = mediaType;

                var _mediaLog = MfTool.LogMediaType(mediaType);
                logger.Debug("\r\nOutputMediaType:\r\n-----------------\r\n" + _mediaLog);

                //logger.Debug("\r\n" + i + ". AvailableOutputMediaType:\r\n-----------------\r\n" + mediaLog);
                //mediaType.Dispose();
                //mediaType = null;
                break;
            }

            if (OutputMediaType == null)
            {
                //...
            }

            for (int i = 0; ; i++)
            {
                try
                {
                    encoder.GetInputAvailableType(0, i, out MediaType availableType);

                    //var log = MfTool.LogMediaType(availableType);
                    //logger.Debug("\r\n" + i + ". AvalibleInputMediaType:\r\n-----------------\r\n" + log);

                    var formatId = availableType.Get(MediaTypeAttributeKeys.Subtype);
                    if (formatId == inputFormat)
                    {
                        InputMediaType = availableType;
                        availableType  = null;
                        //logger.Debug("inputFormat " + inputFormat);
                        break;
                    }

                    if (availableType != null)
                    {
                        availableType.Dispose();
                        availableType = null;
                    }
                }
                catch (SharpDX.SharpDXException ex)
                {
                    if (ex.ResultCode != SharpDX.MediaFoundation.ResultCode.NoMoreTypes)
                    {
                        throw;
                    }
                    break;
                }
            }

            if (InputMediaType == null)
            {
                throw new FormatException("Unsuported input format: " + MfTool.GetMediaTypeName(inputFormat));
            }

            //InputMediaType.Set(MediaTypeAttributeKeys.MajorType, MediaTypeGuids.Video);
            //InputMediaType.Set(MediaTypeAttributeKeys.Subtype, VideoFormatGuids.NV12);
            InputMediaType.Set(MediaTypeAttributeKeys.FrameSize, MfTool.PackToLong(width, height));
            InputMediaType.Set(MediaTypeAttributeKeys.FrameRate, frameRate);

            InputMediaType.Set(MediaTypeAttributeKeys.InterlaceMode, (int)VideoInterlaceMode.Progressive);
            InputMediaType.Set(MediaTypeAttributeKeys.AllSamplesIndependent, 1);
            encoder.SetInputType(inputStreamId, InputMediaType, 0);

            var mediaLog = MfTool.LogMediaType(InputMediaType);

            logger.Debug("\r\nInputMediaType:\r\n-----------------\r\n" + mediaLog);


            if (!syncMode)
            {
                mediaEventGenerator         = encoder.QueryInterface <MediaEventGenerator>();
                eventHandler                = new MediaEventHandler(mediaEventGenerator);
                eventHandler.EventReceived += HandleMediaEvent;
            }



            //encoder.GetInputStreamInfo(0, out TInputStreamInformation inputStreamInfo);
            //var inputInfoFlags = (MftInputStreamInformationFlags)inputStreamInfo.DwFlags;
            //logger.Debug(MfTool.LogEnumFlags(inputInfoFlags));

            //encoder.GetOutputStreamInfo(0, out TOutputStreamInformation outputStreamInfo);
            //var outputInfoFlags = (MftOutputStreamInformationFlags)outputStreamInfo.DwFlags;
            //logger.Debug(MfTool.LogEnumFlags(outputInfoFlags));


            //var guid = new Guid("901db4c7-31ce-41a2-85dc-8fa0bf41b8da");
            //encoder.QueryInterface(guid, out var pUnk);

            //var codecApi = (NativeAPIs.DShow.ICodecAPI)Marshal.GetObjectForIUnknown(pUnk);
            ////var code = codecApi.GetParameterRange(CodecApiPropertyKeys.AVEncMPVDefaultBPictureCount.Guid, out var valMin, out var valMax, out var sDelta);
            //var code = codecApi.GetValue(CodecApiPropertyKeys.AVEncMPVDefaultBPictureCount.Guid, out var val);
        }