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"); }
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()); }
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); }