private void SetupGraphInternal(DsDevice dev, SystemCodecEntry compressor, VideoFormatHelper.SupportedVideoFormat selectedFormat, ref float iFrameRate, ref int iWidth, ref int iHeight, string fileName) { filterGraph = (IFilterGraph2) new FilterGraph(); mediaCtrl = filterGraph as IMediaControl; capBuilder = (ICaptureGraphBuilder2) new CaptureGraphBuilder2(); samplGrabber = (ISampleGrabber) new SampleGrabber(); int hr = capBuilder.SetFiltergraph(filterGraph); DsError.ThrowExceptionForHR(hr); if (rot != null) { rot.Dispose(); rot = null; } rot = new DsROTEntry(filterGraph); if (fileName != null) { deviceFilter = BuildFileCaptureGraph(dev, compressor.Device, selectedFormat, fileName, ref iFrameRate, ref iWidth, ref iHeight); } else { deviceFilter = BuildPreviewOnlyCaptureGraph(dev, selectedFormat, ref iFrameRate, ref iWidth, ref iHeight); } // Now that sizes are fixed/known, store the sizes SaveSizeInfo(samplGrabber); }
private IBaseFilter BuildPreviewOnlyCaptureGraph(DsDevice dev, VideoFormatHelper.SupportedVideoFormat selectedFormat, ref float iFrameRate, ref int iWidth, ref int iHeight) { // Capture Source (Capture/Video) --> (Input) Sample Grabber (Output) --> (In) Null Renderer IBaseFilter nullRenderer = null; try { IBaseFilter capFilter; // Add the video device int hr = filterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out capFilter); DsError.ThrowExceptionForHR(hr); if (capFilter != null) { SetConfigParms(capBuilder, capFilter, selectedFormat, ref iFrameRate, ref iWidth, ref iHeight); } IBaseFilter baseGrabFlt = (IBaseFilter)samplGrabber; ConfigureSampleGrabber(samplGrabber); hr = filterGraph.AddFilter(baseGrabFlt, "ASCOM Video Grabber"); DsError.ThrowExceptionForHR(hr); // Connect the video device output to the sample grabber IPin videoCaptureOutputPin = FindPin(capFilter, PinDirection.Output, MediaType.Video, PinCategory.Capture, "Capture"); IPin grabberInputPin = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); hr = filterGraph.Connect(videoCaptureOutputPin, grabberInputPin); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(videoCaptureOutputPin); Marshal.ReleaseComObject(grabberInputPin); // Add the frame grabber to the graph nullRenderer = (IBaseFilter) new NullRenderer(); hr = filterGraph.AddFilter(nullRenderer, "ASCOM Video Null Renderer"); DsError.ThrowExceptionForHR(hr); // Connect the sample grabber to the null renderer (so frame samples will be coming through) IPin grabberOutputPin = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0); IPin renderedInputPin = DsFindPin.ByDirection(nullRenderer, PinDirection.Input, 0); hr = filterGraph.Connect(grabberOutputPin, renderedInputPin); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(grabberOutputPin); Marshal.ReleaseComObject(renderedInputPin); return(capFilter); } finally { if (nullRenderer != null) { Marshal.ReleaseComObject(nullRenderer); } } }
public void SetupPreviewOnlyGraph(DsDevice dev, VideoFormatHelper.SupportedVideoFormat selectedFormat, ref float iFrameRate, ref int iWidth, ref int iHeight) { try { SetupGraphInternal(dev, null, selectedFormat, ref iFrameRate, ref iWidth, ref iHeight, null); latestBitmap = new Bitmap(iWidth, iHeight, PixelFormat.Format24bppRgb); fullRect = new Rectangle(0, 0, latestBitmap.Width, latestBitmap.Height); } catch { CloseResources(); throw; } }
public void SetupFileRecorderGraph(DsDevice dev, SystemCodecEntry compressor, VideoFormatHelper.SupportedVideoFormat selectedFormat, ref float iFrameRate, ref int iWidth, ref int iHeight, string fileName) { try { SetupGraphInternal(dev, compressor, selectedFormat, ref iFrameRate, ref iWidth, ref iHeight, fileName); latestBitmap = new Bitmap(iWidth, iHeight, PixelFormat.Format24bppRgb); fullRect = new Rectangle(0, 0, latestBitmap.Width, latestBitmap.Height); } catch { CloseResources(); throw; } }
private void SetConfigParms(ICaptureGraphBuilder2 capBuilder, IBaseFilter capFilter, VideoFormatHelper.SupportedVideoFormat selectedFormat, ref float iFrameRate, ref int iWidth, ref int iHeight) { object o; IAMStreamConfig videoStreamConfig; IAMVideoControl videoControl = capFilter as IAMVideoControl; int hr = capBuilder.FindInterface(PinCategory.Capture, MediaType.Video, capFilter, typeof(IAMStreamConfig).GUID, out o); videoStreamConfig = o as IAMStreamConfig; try { if (videoStreamConfig == null) { throw new Exception("Failed to get IAMStreamConfig"); } int iCount = 0, iSize = 0; hr = videoStreamConfig.GetNumberOfCapabilities(out iCount, out iSize); DsError.ThrowExceptionForHR(hr); VideoInfoHeader vMatching = null; VideoFormatHelper.SupportedVideoFormat entry = null; IntPtr taskMemPointer = Marshal.AllocCoTaskMem(iSize); AMMediaType pmtConfig = null; for (int iFormat = 0; iFormat < iCount; iFormat++) { IntPtr ptr = IntPtr.Zero; hr = videoStreamConfig.GetStreamCaps(iFormat, out pmtConfig, taskMemPointer); DsError.ThrowExceptionForHR(hr); vMatching = (VideoInfoHeader)Marshal.PtrToStructure(pmtConfig.formatPtr, typeof(VideoInfoHeader)); if (vMatching.BmiHeader.BitCount > 0) { entry = new VideoFormatHelper.SupportedVideoFormat() { Width = vMatching.BmiHeader.Width, Height = vMatching.BmiHeader.Height, BitCount = vMatching.BmiHeader.BitCount, FrameRate = 10000000.0 / vMatching.AvgTimePerFrame }; if (entry.Matches(selectedFormat)) { // WE FOUND IT !!! break; } } vMatching = null; } if (vMatching != null) { hr = videoStreamConfig.SetFormat(pmtConfig); DsError.ThrowExceptionForHR(hr); iFrameRate = 10000000 / vMatching.AvgTimePerFrame; iWidth = vMatching.BmiHeader.Width; iHeight = vMatching.BmiHeader.Height; } else { AMMediaType media; hr = videoStreamConfig.GetFormat(out media); DsError.ThrowExceptionForHR(hr); // Copy out the videoinfoheader VideoInfoHeader v = new VideoInfoHeader(); Marshal.PtrToStructure(media.formatPtr, v); // If overriding the framerate, set the frame rate if (iFrameRate > 0) { v.AvgTimePerFrame = (int)Math.Round(10000000 / iFrameRate); } else { iFrameRate = 10000000 / v.AvgTimePerFrame; } // If overriding the width, set the width if (iWidth > 0) { v.BmiHeader.Width = iWidth; } else { iWidth = v.BmiHeader.Width; } // If overriding the Height, set the Height if (iHeight > 0) { v.BmiHeader.Height = iHeight; } else { iHeight = v.BmiHeader.Height; } // Copy the media structure back Marshal.StructureToPtr(v, media.formatPtr, false); // Set the new format hr = videoStreamConfig.SetFormat(media); DsError.ThrowExceptionForHR(hr); DsUtils.FreeAMMediaType(media); media = null; } Marshal.FreeCoTaskMem(taskMemPointer); DsUtils.FreeAMMediaType(pmtConfig); pmtConfig = null; } finally { Marshal.ReleaseComObject(videoStreamConfig); } }
private IBaseFilter BuildFileCaptureGraph(DsDevice dev, DsDevice compressor, VideoFormatHelper.SupportedVideoFormat selectedFormat, string fileName, ref float iFrameRate, ref int iWidth, ref int iHeight) { // Capture Source (Capture/Video) --> (Input) Sample Grabber (Output) --> (Input) Video Compressor (Output) --> (Input 01/Video/) AVI Mux (Output) --> (In) FileSink IBaseFilter muxFilter = null; IFileSinkFilter fileWriterFilter = null; IBaseFilter compressorFilter = null; try { IBaseFilter capFilter; // Add the video device int hr = filterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out capFilter); DsError.ThrowExceptionForHR(hr); if (capFilter != null) { SetConfigParms(capBuilder, capFilter, selectedFormat, ref iFrameRate, ref iWidth, ref iHeight); } IBaseFilter baseGrabFlt = (IBaseFilter)samplGrabber; ConfigureSampleGrabber(samplGrabber); hr = filterGraph.AddFilter(baseGrabFlt, "ASCOM Video Grabber"); DsError.ThrowExceptionForHR(hr); // Connect the video device output to the sample grabber IPin videoCaptureOutputPin = FindPin(capFilter, PinDirection.Output, MediaType.Video, Guid.Empty, "Capture"); IPin smartTeeInputPin = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); hr = filterGraph.Connect(videoCaptureOutputPin, smartTeeInputPin); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(videoCaptureOutputPin); Marshal.ReleaseComObject(smartTeeInputPin); // Create the file writer and AVI Mux (already connected to each other) hr = capBuilder.SetOutputFileName(MediaSubType.Avi, fileName, out muxFilter, out fileWriterFilter); DsError.ThrowExceptionForHR(hr); if (compressor != null) { // Create the compressor compressorFilter = CreateFilter(FilterCategory.VideoCompressorCategory, compressor.Name); } if (compressorFilter != null) { hr = filterGraph.AddFilter(compressorFilter, "ASCOM Video Compressor"); DsError.ThrowExceptionForHR(hr); // Connect the sample grabber Output pin to the compressor IPin grabberOutputPin = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0); IPin compressorInputPin = DsFindPin.ByDirection(compressorFilter, PinDirection.Input, 0); hr = filterGraph.Connect(grabberOutputPin, compressorInputPin); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(grabberOutputPin); Marshal.ReleaseComObject(compressorInputPin); // Connect the compressor output to the AVI Mux IPin compressorOutputPin = DsFindPin.ByDirection(compressorFilter, PinDirection.Output, 0); IPin aviMuxVideoInputPin = DsFindPin.ByDirection(muxFilter, PinDirection.Input, 0); hr = filterGraph.Connect(compressorOutputPin, aviMuxVideoInputPin); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(compressorOutputPin); Marshal.ReleaseComObject(aviMuxVideoInputPin); } else { // Connect the sample grabber Output pin to the AVI Mux IPin grabberOutputPin = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0); IPin aviMuxVideoInputPin = DsFindPin.ByDirection(muxFilter, PinDirection.Input, 0); hr = filterGraph.Connect(grabberOutputPin, aviMuxVideoInputPin); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(grabberOutputPin); Marshal.ReleaseComObject(aviMuxVideoInputPin); } return(capFilter); } finally { if (fileWriterFilter != null) { Marshal.ReleaseComObject(fileWriterFilter); } if (muxFilter != null) { Marshal.ReleaseComObject(muxFilter); } if (compressorFilter != null) { Marshal.ReleaseComObject(compressorFilter); } } }