/// <summary>
        ///  Set the value of one member of the IAMStreamConfig format block.
        ///  Helper function for several properties that expose
        ///  video/audio settings from IAMStreamConfig.GetFormat().
        ///  IAMStreamConfig.GetFormat() returns a AMMediaType struct.
        ///  AMMediaType.formatPtr points to a format block structure.
        ///  This format block structure may be one of several 
        ///  types, the type being determined by AMMediaType.formatType.
        /// </summary>
        protected object setStreamConfigSetting(IAMStreamConfig streamConfig, string fieldName, object newValue)
        {
            if (streamConfig == null)
                throw new NotSupportedException();
            assertStopped();
            derenderGraph();

            object returnValue = null;
            IntPtr pmt = IntPtr.Zero;
            AMMediaType mediaType = new AMMediaType();

            try
            {
                // Get the current format info
                int hr = streamConfig.GetFormat(out pmt);
                if (hr != 0)
                    Marshal.ThrowExceptionForHR(hr);
                Marshal.PtrToStructure(pmt, mediaType);

                // The formatPtr member points to different structures
                // dependingon the formatType
                object formatStruct;
                if (mediaType.formatType == FormatType.WaveEx)
                    formatStruct = new WaveFormatEx();
                else if (mediaType.formatType == FormatType.VideoInfo)
                    formatStruct = new VideoInfoHeader();
                else if (mediaType.formatType == FormatType.VideoInfo2)
                    formatStruct = new VideoInfoHeader2();
                else
                    throw new NotSupportedException("This device does not support a recognized format block.");

                // Retrieve the nested structure
                Marshal.PtrToStructure(mediaType.formatPtr, formatStruct);

                // Find the required field
                Type structType = formatStruct.GetType();
                FieldInfo fieldInfo = structType.GetField(fieldName);
                if (fieldInfo == null)
                    throw new NotSupportedException("Unable to find the member '" + fieldName + "' in the format block.");

                // Update the value of the field
                fieldInfo.SetValue(formatStruct, newValue);

                // PtrToStructure copies the data so we need to copy it back
                Marshal.StructureToPtr(formatStruct, mediaType.formatPtr, false);

                // Save the changes
                hr = streamConfig.SetFormat(mediaType);
                if (hr != 0)
                    Marshal.ThrowExceptionForHR(hr);
            }
            finally
            {
                DsUtils.FreeAMMediaType(mediaType);
                Marshal.FreeCoTaskMem(pmt);
            }
            renderGraph();
            startPreviewIfNeeded();

            return (returnValue);
        }
        // --------------------- Private Methods -----------------------
        /// <summary> 
        ///  Create a new filter graph and add filters (devices, compressors, 
        ///  misc), but leave the filters unconnected. Call renderGraph()
        ///  to connect the filters.
        /// </summary>
        /// 
        protected void createGraph()
        {
            Guid cat;
            Guid med;
            int hr;
            Type comType = null;
            object comObj = null;

            // Ensure required properties are set
            if (videoDevice == null && audioDevice == null)
                throw new ArgumentException("The video and/or audio device have not been set. Please set one or both to valid capture devices.\n");

            // Skip if we are already created
            if ((int)graphState < (int)GraphState.Created)
            {
                // Garbage collect, ensure that previous filters are released
                GC.Collect();

                // Make a new filter graph
                graphBuilder = (IGraphBuilder)Activator.CreateInstance(Type.GetTypeFromCLSID(Clsid.FilterGraph, true));

                // Get the Capture Graph Builder
                Guid clsid = Clsid.CaptureGraphBuilder2;
                Guid riid = typeof(ICaptureGraphBuilder2).GUID;
                captureGraphBuilder = (ICaptureGraphBuilder2)DsBugWO.CreateDsInstance(ref clsid, ref riid);

                // Link the CaptureGraphBuilder to the filter graph
                hr = captureGraphBuilder.SetFiltergraph(graphBuilder);
                if (hr < 0) Marshal.ThrowExceptionForHR(hr);

                comType = Type.GetTypeFromCLSID(Clsid.SampleGrabber);
                if (comType == null)
                    throw new NotImplementedException(@"DirectShow SampleGrabber not installed/registered!");
                comObj = Activator.CreateInstance(comType);
                sampGrabber = (ISampleGrabber)comObj; comObj = null;

                baseGrabFlt = (IBaseFilter)sampGrabber;

                // Add the graph to the Running Object Table so it can be
                // viewed with GraphEdit
            #if DEBUG
                DsROT.AddGraphToRot(graphBuilder, out rotCookie);
            #endif

                AMMediaType media = new AMMediaType();
                // Get the video device and add it to the filter graph
                if (VideoDevice != null)
                {
                    videoDeviceFilter = (IBaseFilter)Marshal.BindToMoniker(VideoDevice.MonikerString);
                    hr = graphBuilder.AddFilter(videoDeviceFilter, "Video Capture Device");
                    if (hr < 0) Marshal.ThrowExceptionForHR(hr);

                   //  Console.WriteLine("MediaEnineCheck ==> Inside StartVideoCapture.cs before MediaSudType");
                    media.majorType = MediaType.Video;
                    media.subType = MediaSubType.RGB24; //Rajib
                    media.formatType = FormatType.VideoInfo;		// ???
                    hr = sampGrabber.SetMediaType(media);
                    if (hr < 0)
                        Marshal.ThrowExceptionForHR(hr);

                    hr = graphBuilder.AddFilter(baseGrabFlt, "Ds.NET Grabber");
                    if (hr < 0) Marshal.ThrowExceptionForHR(hr);
                }

                // Get the audio device and add it to the filter graph
                if (AudioDevice != null)
                {
                    audioDeviceFilter = (IBaseFilter)Marshal.BindToMoniker(AudioDevice.MonikerString);
                    hr = graphBuilder.AddFilter(audioDeviceFilter, "Audio Capture Device");
                    if (hr < 0) Marshal.ThrowExceptionForHR(hr);
                }

                // Get the video compressor and add it to the filter graph
                if (VideoCompressor != null)
                {
                    videoCompressorFilter = (IBaseFilter)Marshal.BindToMoniker(VideoCompressor.MonikerString);
                    hr = graphBuilder.AddFilter(videoCompressorFilter, "Video Compressor");
                    if (hr < 0) Marshal.ThrowExceptionForHR(hr);
                }

                // Get the audio compressor and add it to the filter graph
                if (AudioCompressor != null)
                {
                    audioCompressorFilter = (IBaseFilter)Marshal.BindToMoniker(AudioCompressor.MonikerString);
                    hr = graphBuilder.AddFilter(audioCompressorFilter, "Audio Compressor");
                    if (hr < 0) Marshal.ThrowExceptionForHR(hr);
                }

                // Retrieve the stream control interface for the video device
                // FindInterface will also add any required filters
                // (WDM devices in particular may need additional
                // upstream filters to function).

                // Try looking for an interleaved media type
                object o;
                cat = PinCategory.Capture;
                med = MediaType.Interleaved;
                Guid iid = typeof(IAMStreamConfig).GUID;
                hr = captureGraphBuilder.FindInterface(
                    ref cat, ref med, videoDeviceFilter, ref iid, out o);

                if (hr != 0)
                {
                    // If not found, try looking for a video media type
                    med = MediaType.Video;
                    hr = captureGraphBuilder.FindInterface(
                        ref cat, ref med, videoDeviceFilter, ref iid, out o);

                    if (hr != 0)
                        o = null;
                }
                videoStreamConfig = o as IAMStreamConfig;

                // Retrieve the stream control interface for the audio device
                o = null;
                cat = PinCategory.Capture;
                med = MediaType.Audio;
                iid = typeof(IAMStreamConfig).GUID;
                hr = captureGraphBuilder.FindInterface(
                    ref cat, ref med, audioDeviceFilter, ref iid, out o);
                if (hr != 0)
                    o = null;
                audioStreamConfig = o as IAMStreamConfig;

                // Retreive the media control interface (for starting/stopping graph)
                mediaControl = (IMediaControl)graphBuilder;

                // Reload any video crossbars
                if (videoSources != null) videoSources.Dispose(); videoSources = null;

                // Reload any audio crossbars
                if (audioSources != null) audioSources.Dispose(); audioSources = null;

                // Reload any property pages exposed by filters
                if (propertyPages != null) propertyPages.Dispose(); propertyPages = null;

                // Reload capabilities of video device
                videoCaps = null;

                // Reload capabilities of video device
                audioCaps = null;

                // Retrieve TV Tuner if available
                o = null;
                cat = PinCategory.Capture;
                med = MediaType.Interleaved;
                iid = typeof(IAMTVTuner).GUID;
                hr = captureGraphBuilder.FindInterface(
                    ref cat, ref med, videoDeviceFilter, ref iid, out o);
                if (hr != 0)
                {
                    med = MediaType.Video;
                    hr = captureGraphBuilder.FindInterface(
                        ref cat, ref med, videoDeviceFilter, ref iid, out o);
                    if (hr != 0)
                        o = null;
                }
                IAMTVTuner t = o as IAMTVTuner;
                if (t != null)
                    tuner = new Tuner(t);

                videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader));
                Marshal.FreeCoTaskMem(media.formatPtr); media.formatPtr = IntPtr.Zero;
                hr = sampGrabber.SetBufferSamples(false);
                if (hr == 0)
                    hr = sampGrabber.SetOneShot(false);
                if (hr == 0)
                    hr = sampGrabber.SetCallback(new SampleGrabberCallback(), 1);
                if (hr < 0)
                    Marshal.ThrowExceptionForHR(hr);
                // Update the state now that we are done
                graphState = GraphState.Created;

            }
        }
        /// <summary>
        ///  Connects the filters of a previously created graph 
        ///  (created by createGraph()). Once rendered the graph
        ///  is ready to be used. This method may also destroy
        ///  streams if we have streams we no longer want.
        /// </summary>
        protected void renderGraph()
        {
            Guid cat;
            Guid med;
            int hr;
            bool didSomething = false;
            const int WS_CHILD = 0x40000000;
            const int WS_CLIPCHILDREN = 0x02000000;
            const int WS_CLIPSIBLINGS = 0x04000000;

            assertStopped();

            // Ensure required properties set
            if (filename == null)
                throw new ArgumentException("The Filename property has not been set to a file.\n");

            // Stop the graph
            if (mediaControl != null)
                mediaControl.Stop();

            // Create the graph if needed (group should already be created)
            createGraph();

            // Derender the graph if we have a capture or preview stream
            // that we no longer want. We can't derender the capture and
            // preview streams seperately.
            // Notice the second case will leave a capture stream intact
            // even if we no longer want it. This allows the user that is
            // not using the preview to Stop() and Start() without
            // rerendering the graph.
            if (!wantPreviewRendered && isPreviewRendered)
                derenderGraph();
            if (!wantCaptureRendered && isCaptureRendered)
                if (wantPreviewRendered)
                    derenderGraph();

            // Render capture stream (only if necessary)
            if (wantCaptureRendered && !isCaptureRendered)
            {
                // Render the file writer portion of graph (mux -> file)
                Guid mediaSubType = MediaSubType.Avi;
                hr = captureGraphBuilder.SetOutputFileName(ref mediaSubType, Filename, out muxFilter, out fileWriterFilter);
                if (hr < 0) Marshal.ThrowExceptionForHR(hr);

                // Render video (video -> mux)
                if (VideoDevice != null)
                {
                    // Try interleaved first, because if the device supports it,
                    // it's the only way to get audio as well as video
                    cat = PinCategory.Capture;
                    med = MediaType.Interleaved;
                    hr = captureGraphBuilder.RenderStream(ref cat, ref med, videoDeviceFilter, videoCompressorFilter, muxFilter);
                    if (hr < 0)
                    {
                        med = MediaType.Video;

                        hr = captureGraphBuilder.RenderStream(ref cat, ref med, videoDeviceFilter, videoCompressorFilter, muxFilter);
                        if (hr == -2147220969) throw new DeviceInUseException("Video device", hr);
                        if (hr < 0) Marshal.ThrowExceptionForHR(hr);
                    }

                }

                // Render audio (audio -> mux)
                if (AudioDevice != null)
                {
                    cat = PinCategory.Capture;
                    med = MediaType.Audio;
                    hr = captureGraphBuilder.RenderStream(ref cat, ref med, audioDeviceFilter, audioCompressorFilter, muxFilter);
                    if (hr < 0) Marshal.ThrowExceptionForHR(hr);
                }
                isCaptureRendered = true;
                didSomething = true;

                AMMediaType media = new AMMediaType();
                hr = sampGrabber.GetConnectedMediaType(media);
                if (hr < 0)
                    Marshal.ThrowExceptionForHR(hr);
                if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero))
                    throw new NotSupportedException("Unknown Grabber Media Format");

                videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader));
                Marshal.FreeCoTaskMem(media.formatPtr); media.formatPtr = IntPtr.Zero;
            }

            // Render preview stream (only if necessary)
            if (wantPreviewRendered && !isPreviewRendered)
            {
                // Render preview (video -> renderer)
                cat = PinCategory.Preview;
                med = MediaType.Video;
                hr = captureGraphBuilder.RenderStream(ref cat, ref med, videoDeviceFilter, baseGrabFlt, null);
                if (hr < 0) Marshal.ThrowExceptionForHR(hr);

                // Get the IVideoWindow interface
                videoWindow = (IVideoWindow)graphBuilder;

                // Set the video window to be a child of the main window
                hr = videoWindow.put_Owner(previewWindow.Handle);
                if (hr < 0) Marshal.ThrowExceptionForHR(hr);

                // Set video window style
                hr = videoWindow.put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
                if (hr < 0) Marshal.ThrowExceptionForHR(hr);

                // Position video window in client rect of owner window
                previewWindow.Resize += new EventHandler(onPreviewWindowResize);
                onPreviewWindowResize(this, null);

                // Make the video window visible, now that it is properly positioned
                hr = videoWindow.put_Visible(DsHlp.OATRUE);
                if (hr < 0) Marshal.ThrowExceptionForHR(hr);

                isPreviewRendered = true;
                didSomething = true;

                AMMediaType media = new AMMediaType();
                hr = sampGrabber.GetConnectedMediaType(media);
                if (hr < 0)
                    Marshal.ThrowExceptionForHR(hr);
                if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero))
                    throw new NotSupportedException("Unknown Grabber Media Format");

                videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader));
                Marshal.FreeCoTaskMem(media.formatPtr); media.formatPtr = IntPtr.Zero;
            }

            if (didSomething)
                graphState = GraphState.Rendered;
        }
Example #4
0
 public static void FreeAMMediaType(AMMediaType mediaType)
 {
     if (mediaType.formatSize != 0)
     {
         Marshal.FreeCoTaskMem(mediaType.formatPtr);
     }
     if (mediaType.unkPtr != IntPtr.Zero)
     {
         Marshal.Release(mediaType.unkPtr);
     }
     mediaType.formatSize = 0;
     mediaType.formatPtr = IntPtr.Zero;
     mediaType.unkPtr = IntPtr.Zero;
 }