Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
Capture.cs
Package: capsample_src.zip [view]
Upload User: wuming6209
Upload Date: 2013-06-06
Package Size: 161k
Code Size: 69k
Category:
Video Capture
Development Platform:
Visual C++
- // ------------------------------------------------------------------
- // DirectX.Capture
- //
- // History:
- // 2003-Jan-24 BL - created
- // 2003-Aug-06 DB - modified
- //
- // Copyright (c) 2003 Brian Low
- // ------------------------------------------------------------------
- using System;
- using System.Diagnostics;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Collections;
- using System.IO;
- using System.Reflection;
- using System.Runtime.InteropServices;
- using System.Threading;
- using System.Windows.Forms;
- using System.Data;
- using System.ComponentModel;
- using DShowNET;
- using DShowNET.Device;
- namespace DirectX.Capture
- {
- /// <summary>
- /// Use the Capture class to capture audio and video to AVI files.
- /// </summary>
- /// <remarks>
- /// This is the core class of the Capture Class Library. The following
- /// sections introduce the Capture class and how to use this library.
- ///
- /// <br/><br/>
- /// <para><b>Basic Usage</b></para>
- ///
- /// <para>
- /// The Capture class only requires a video device and/or audio device
- /// to begin capturing. The <see cref="Filters"/> class provides
- /// lists of the installed video and audio devices.
- /// </para>
- /// <code><div style="background-color:whitesmoke;">
- /// // Remember to add a reference to DirectX.Capture.dll
- /// using DirectX.Capture
- /// ...
- /// Capture capture = new Capture( Filters.VideoInputDevices[0],
- /// Filters.AudioInputDevices[0] );
- /// capture.Start();
- /// ...
- /// capture.Stop();
- /// </div></code>
- /// <para>
- /// This will capture video and audio using the first video and audio devices
- /// installed on the system. To capture video only, pass a null as the second
- /// parameter of the constructor.
- /// </para>
- /// <para>
- /// The class is initialized to a valid temporary file in the Windows temp
- /// folder. To capture to a different file, set the
- /// <see cref="Capture.Filename"/> property before you begin
- /// capturing. Remember to add DirectX.Capture.dll to
- /// your project references.
- /// </para>
- ///
- /// <br/>
- /// <para><b>Setting Common Properties</b></para>
- ///
- /// <para>
- /// The example below shows how to change video and audio settings.
- /// Properties such as <see cref="Capture.FrameRate"/> and
- /// <see cref="AudioSampleSize"/> allow you to programmatically adjust
- /// the capture. Use <see cref="Capture.VideoCaps"/> and
- /// <see cref="Capture.AudioCaps"/> to determine valid values for these
- /// properties.
- /// </para>
- /// <code><div style="background-color:whitesmoke;">
- /// Capture capture = new Capture( Filters.VideoInputDevices[0],
- /// Filters.AudioInputDevices[1] );
- /// capture.VideoCompressor = Filters.VideoCompressors[0];
- /// capture.AudioCompressor = Filters.AudioCompressors[0];
- /// capture.FrameRate = 29.997;
- /// capture.FrameSize = new Size( 640, 480 );
- /// capture.AudioSamplingRate = 44100;
- /// capture.AudioSampleSize = 16;
- /// capture.Filename = "C:MyVideo.avi";
- /// capture.Start();
- /// ...
- /// capture.Stop();
- /// </div></code>
- /// <para>
- /// The example above also shows the use of video and audio compressors. In most
- /// cases you will want to use compressors. Uncompressed video can easily
- /// consume over a 1GB of disk space per minute. Whenever possible, set
- /// the <see cref="Capture.VideoCompressor"/> and <see cref="Capture.AudioCompressor"/>
- /// properties as early as possible. Changing them requires the internal filter
- /// graph to be rebuilt which often causes most of the other properties to
- /// be reset to default values.
- /// </para>
- ///
- /// <br/>
- /// <para><b>Listing Devices</b></para>
- ///
- /// <para>
- /// Use the <see cref="Filters.VideoInputDevices"/> collection to list
- /// video capture devices installed on the system.
- /// </para>
- /// <code><div style="background-color:whitesmoke;">
- /// foreach ( Filter f in Filters.VideoInputDevices )
- /// {
- /// Debug.WriteLine( f.Name );
- /// }
- /// </div></code>
- /// The <see cref="Filters"/> class also provides collections for audio
- /// capture devices, video compressors and audio compressors.
- ///
- /// <br/>
- /// <para><b>Preview</b></para>
- ///
- /// <para>
- /// Video preview is controled with the <see cref="Capture.PreviewWindow"/>
- /// property. Setting this property to a visible control will immediately
- /// begin preview. Set to null to stop the preview.
- /// </para>
- /// <code><div style="background-color:whitesmoke;">
- /// // Enable preview
- /// capture.PreviewWindow = myPanel;
- /// // Disable preview
- /// capture.PreviewWindow = null;
- /// </div></code>
- /// <para>
- /// The control used must have a window handle (HWND), good controls to
- /// use are the Panel or the form itself.
- /// </para>
- /// <para>
- /// Retrieving or changing video/audio settings such as FrameRate,
- /// FrameSize, AudioSamplingRate, and AudioSampleSize will cause
- /// the preview window to flash. This is beacuse the preview must be
- /// temporarily stopped. Disable the preview if you need to access
- /// several properties at the same time.
- /// </para>
- ///
- /// <br/>
- /// <para><b>Property Pages</b></para>
- ///
- /// <para>
- /// Property pages exposed by the devices and compressors are
- /// available through the <see cref="Capture.PropertyPages"/>
- /// collection.
- /// </para>
- /// <code><div style="background-color:whitesmoke;">
- /// // Display the first property page
- /// capture.PropertyPages[0].Show();
- /// </div></code>
- /// <para>
- /// The property pages will often expose more settings than
- /// the Capture class does directly. Some examples are brightness,
- /// color space, audio balance and bass boost. The disadvantage
- /// to using the property pages is the user's choices cannot be
- /// saved and later restored. The exception to this is the video
- /// and audio compressor property pages. Most compressors support
- /// the saving and restoring state, see the
- /// <see cref="PropertyPage.State"/> property for more information.
- /// </para>
- /// <para>
- /// Changes made in the property page will be reflected
- /// immediately in the Capture class properties (e.g. Capture.FrameSize).
- /// However, the reverse is not always true. A change made directly to
- /// FrameSize, for example, may not be reflected in the associated
- /// property page. Fortunately, the filter will use requested FrameSize
- /// even though the property page shows otherwise.
- /// </para>
- ///
- /// <br/>
- /// <para><b>Saving and Restoring Settings</b></para>
- ///
- /// <para>
- /// To save the user's choice of devices and compressors,
- /// save <see cref="Filter.MonikerString"/> and user it later
- /// to recreate the Filter object.
- /// </para>
- /// <para>
- /// To save a user's choices from a property page use
- /// <see cref="PropertyPage.State"/>. However, only the audio
- /// and video compressor property pages support this.
- /// </para>
- /// <para>
- /// The last items to save are the video and audio settings such
- /// as FrameSize and AudioSamplingRate. When restoring, remember
- /// to restore these properties after setting the video and audio
- /// compressors.
- /// </para>
- /// <code><div style="background-color:whitesmoke;">
- /// // Disable preview
- /// capture.PreviewWindow = null;
- ///
- /// // Save settings
- /// string videoDevice = capture.VideoDevice.MonikerString;
- /// string audioDevice = capture.AudioDevice.MonikerString;
- /// string videoCompressor = capture.VideoCompressor.MonikerString;
- /// string audioCompressor = capture.AudioCompressor.MonikerString;
- /// double frameRate = capture.FrameRate;
- /// Size frameSize = capture.FrameSize;
- /// short audioChannels = capture.AudioChannels;
- /// short audioSampleSize = capture.AudioSampleSize;
- /// int audioSamplingRate = capture.AudioSamplingRate;
- /// ArrayList pages = new ArrayList();
- /// foreach ( PropertyPage p in capture.PropertyPages )
- /// {
- /// if ( p.SupportsPersisting )
- /// pages.Add( p.State );
- /// }
- ///
- ///
- /// // Restore settings
- /// Capture capture = new Capture( new Filter( videoDevice),
- /// new Filter( audioDevice) );
- /// capture.VideoCompressor = new Filter( videoCompressor );
- /// capture.AudioCompressor = new Filter( audioCompressor );
- /// capture.FrameRate = frameRate;
- /// capture.FrameSize = frameSize;
- /// capture.AudioChannels = audioChannels;
- /// capture.AudioSampleSize = audioSampleSize;
- /// capture.AudioSamplingRate = audioSamplingRate;
- /// foreach ( PropertyPage p in capture.PropertyPages )
- /// {
- /// if ( p.SupportsPersisting )
- /// {
- /// p.State = (byte[]) pages[0]
- /// pages.RemoveAt( 0 );
- /// }
- /// }
- /// // Enable preview
- /// capture.PreviewWindow = myPanel;
- /// </div></code>
- ///
- /// <br/>
- /// <para><b>TV Tuner</b></para>
- ///
- /// <para>
- /// To access the TV Tuner, use the <see cref="Capture.Tuner"/> property.
- /// If the device does not have a TV tuner, this property will be null.
- /// See <see cref="DirectX.Capture.Tuner.Channel"/>,
- /// <see cref="DirectX.Capture.Tuner.InputType"/> and
- /// <see cref="DirectX.Capture.Tuner.SignalPresent"/>
- /// for more information.
- /// </para>
- /// <code><div style="background-color:whitesmoke;">
- /// // Change to channel 5
- /// capture.Tuner.Channel = 5;
- /// </div></code>
- ///
- /// <br/>
- /// <para><b>Troubleshooting</b></para>
- ///
- /// <para>
- /// This class library uses COM Interop to access the full
- /// capabilities of DirectShow, so if there is another
- /// application that can successfully use a hardware device
- /// then it should be possible to modify this class library
- /// to use the device.
- /// </para>
- /// <para>
- /// Try the <b>AMCap</b> sample from the DirectX SDK
- /// (DX9SamplesC++DirectShowBinAMCap.exe) or
- /// <b>Virtual VCR</b> from http://www.DigTV.ws
- /// </para>
- ///
- /// <br/>
- /// <para><b>Credits</b></para>
- ///
- /// <para>
- /// This class library would not be possible without the
- /// DShowNET project by NETMaster:
- /// http://www.codeproject.com/useritems/directshownet.asp
- /// </para>
- /// <para>
- /// Documentation is generated by nDoc available at
- /// http://ndoc.sourceforge.net
- /// </para>
- ///
- /// <br/>
- /// <para><b>Feedback</b></para>
- ///
- /// Feel free to send comments and questions to me at
- /// mportobello@hotmail.com. If the the topic may be of interest
- /// to others, post your question on the www.codeproject.com
- /// page for DirectX.Capture.
- /// </remarks>
- public class Capture : System.Windows.Forms.Form, ISampleGrabberCB
- {
- // ------------------ Private Enumerations --------------------
- /// <summary> Possible states of the interal filter graph </summary>
- protected enum GraphState
- {
- Null, // No filter graph at all
- Created, // Filter graph created with device filters added
- Rendered, // Filter complete built, ready to run (possibly previewing)
- Capturing // Filter is capturing
- }
- // ------------------ Public Properties --------------------
- /// <summary> Is the class currently capturing. Read-only. </summary>
- public bool Capturing { get { return( graphState==GraphState.Capturing ); } }
- /// <summary> Has the class been cued to begin capturing. Read-only. </summary>
- public bool Cued { get { return( isCaptureRendered && graphState==GraphState.Rendered ); } }
- /// <summary> Is the class currently stopped. Read-only. </summary>
- public bool Stopped { get { return( graphState!=GraphState.Capturing ); } }
- /// <summary>
- /// Name of file to capture to. Initially set to
- /// a valid temporary file.
- /// </summary>
- /// <remarks>
- /// If the file does not exist, it will be created. If it does
- /// exist, it will be overwritten. An overwritten file will
- /// not be shortened if the captured data is smaller than the
- /// original file. The file will be valid, it will just contain
- /// extra, unused, data after the audio/video data.
- ///
- /// <para>
- /// A future version of this class will provide a method to copy
- /// only the valid audio/video data to a new file. </para>
- ///
- /// <para>
- /// This property cannot be changed while capturing or cued. </para>
- /// </remarks>
- public string Filename
- {
- get { return( filename ); }
- set
- {
- assertStopped();
- if ( Cued )
- throw new InvalidOperationException( "The Filename cannot be changed once cued. Use Stop() before changing the filename." );
- filename = value;
- if ( fileWriterFilter != null )
- {
- string s;
- AMMediaType mt = new AMMediaType();
- int hr = fileWriterFilter.GetCurFile( out s, mt );
- if( hr < 0 ) Marshal.ThrowExceptionForHR( hr );
- if ( mt.formatSize > 0 )
- Marshal.FreeCoTaskMem( mt.formatPtr );
- hr = fileWriterFilter.SetFileName( filename, mt );
- if( hr < 0 ) Marshal.ThrowExceptionForHR( hr );
- }
- }
- }
- /// <summary>
- /// The control that will host the preview window.
- /// </summary>
- /// <remarks>
- /// Setting this property will begin video preview
- /// immediately. Set this property after setting all
- /// other properties to avoid unnecessary changes
- /// to the internal filter graph (some properties like
- /// FrameSize require the internal filter graph to be
- /// stopped and disconnected before the property
- /// can be retrieved or set).
- ///
- /// <para>
- /// To stop video preview, set this property to null. </para>
- /// </remarks>
- public Control PreviewWindow
- {
- get { return( previewWindow ); }
- set
- {
- assertStopped();
- derenderGraph();
- previewWindow = value;
- wantPreviewRendered = ( ( previewWindow != null ) && ( videoDevice != null ) );
- renderStream = false;
- renderGraph();
- startPreviewIfNeeded();
- }
- }
- /// <summary>
- /// The capabilities of the video device.
- /// </summary>
- /// <remarks>
- /// It may be required to cue the capture (see <see cref="Cue"/>)
- /// before all capabilities are correctly reported. If you
- /// have such a device, the developer would be interested to
- /// hear from you.
- ///
- /// <para>
- /// The information contained in this property is retrieved and
- /// cached the first time this property is accessed. Future
- /// calls to this property use the cached results. This was done
- /// for performance. </para>
- ///
- /// <para>
- /// However, this means <b>you may get different results depending
- /// on when you access this property first</b>. If you are experiencing
- /// problems, try accessing the property immediately after creating
- /// the Capture class or immediately after setting the video and
- /// audio compressors. Also, inform the developer. </para>
- /// </remarks>
- public VideoCapabilities VideoCaps
- {
- get
- {
- if ( videoCaps == null )
- {
- if ( videoStreamConfig != null )
- {
- try
- {
- videoCaps = new VideoCapabilities( videoStreamConfig );
- }
- catch ( Exception ex ) { Debug.WriteLine( "VideoCaps: unable to create videoCaps." + ex.ToString() ); }
- }
- }
- return( videoCaps );
- }
- }
- /// <summary>
- /// The capabilities of the audio device.
- /// </summary>
- /// <remarks>
- /// It may be required to cue the capture (see <see cref="Cue"/>)
- /// before all capabilities are correctly reported. If you
- /// have such a device, the developer would be interested to
- /// hear from you.
- ///
- /// <para>
- /// The information contained in this property is retrieved and
- /// cached the first time this property is accessed. Future
- /// calls to this property use the cached results. This was done
- /// for performance. </para>
- ///
- /// <para>
- /// However, this means <b>you may get different results depending
- /// on when you access this property first</b>. If you are experiencing
- /// problems, try accessing the property immediately after creating
- /// the Capture class or immediately after setting the video and
- /// audio compressors. Also, inform the developer. </para>
- /// </remarks>
- public AudioCapabilities AudioCaps
- {
- get
- {
- if ( audioCaps == null )
- {
- if ( audioStreamConfig != null )
- {
- try
- {
- audioCaps = new AudioCapabilities( audioStreamConfig );
- }
- catch ( Exception ex ) { Debug.WriteLine( "AudioCaps: unable to create audioCaps." + ex.ToString() ); }
- }
- }
- return( audioCaps );
- }
- }
- /// <summary>
- /// The video capture device filter. Read-only. To use a different
- /// device, dispose of the current Capture instance and create a new
- /// instance with the desired device.
- /// </summary>
- public Filter VideoDevice { get { return( videoDevice ); } }
- /// <summary>
- /// The audio capture device filter. Read-only. To use a different
- /// device, dispose of the current Capture instance and create a new
- /// instance with the desired device.
- /// </summary>
- public Filter AudioDevice { get { return( audioDevice ); } }
- /// <summary>
- /// The video compression filter. When this property is changed
- /// the internal filter graph is rebuilt. This means that some properties
- /// will be reset. Set this property as early as possible to avoid losing
- /// changes. This property cannot be changed while capturing.
- /// </summary>
- public Filter VideoCompressor
- {
- get { return( videoCompressor ); }
- set
- {
- assertStopped();
- destroyGraph();
- videoCompressor = value;
- renderGraph();
- startPreviewIfNeeded();
- }
- }
- /// <summary>
- /// The audio compression filter.
- /// </summary>
- /// <remarks>
- /// When this property is changed
- /// the internal filter graph is rebuilt. This means that some properties
- /// will be reset. Set this property as early as possible to avoid losing
- /// changes. This property cannot be changed while capturing.
- /// </remarks>
- public Filter AudioCompressor
- {
- get { return( audioCompressor ); }
- set
- {
- assertStopped();
- destroyGraph();
- audioCompressor = value;
- renderGraph();
- startPreviewIfNeeded();
- }
- }
- /// <summary>
- /// The current video source. Use Capture.VideoSources to
- /// list available sources. Set to null to disable all
- /// sources (mute).
- /// </summary>
- public Source VideoSource
- {
- get { return( VideoSources.CurrentSource ); }
- set { VideoSources.CurrentSource = value; }
- }
- /// <summary>
- /// The current audio source. Use Capture.AudioSources to
- /// list available sources. Set to null to disable all
- /// sources (mute).
- /// </summary>
- public Source AudioSource
- {
- get { return( AudioSources.CurrentSource ); }
- set { AudioSources.CurrentSource = value; }
- }
- /// <summary>
- /// Collection of available video sources/physical connectors
- /// on the current video device.
- /// </summary>
- /// <remarks>
- /// In most cases, if the device has only one source,
- /// this collection will be empty.
- ///
- /// <para>
- /// The information contained in this property is retrieved and
- /// cached the first time this property is accessed. Future
- /// calls to this property use the cached results. This was done
- /// for performance. </para>
- ///
- /// <para>
- /// However, this means <b>you may get different results depending
- /// on when you access this property first</b>. If you are experiencing
- /// problems, try accessing the property immediately after creating
- /// the Capture class or immediately after setting the video and
- /// audio compressors. Also, inform the developer. </para>
- /// </remarks>
- public SourceCollection VideoSources
- {
- get
- {
- if ( videoSources == null )
- {
- try
- {
- if ( videoDevice != null )
- videoSources = new SourceCollection( captureGraphBuilder, videoDeviceFilter, true );
- else
- videoSources = new SourceCollection();
- }
- catch ( Exception ex ) { Debug.WriteLine( "VideoSources: unable to create VideoSources." + ex.ToString() ); }
- }
- return ( videoSources );
- }
- }
- /// <summary>
- /// Collection of available audio sources/physical connectors
- /// on the current audio device.
- /// </summary>
- /// <remarks>
- /// In most cases, if the device has only one source,
- /// this collection will be empty. For audio
- /// there are 2 different methods for enumerating audio sources
- /// an audio crossbar (usually TV tuners?) or an audio mixer
- /// (usually sound cards?). This class will first look for an
- /// audio crossbar. If no sources or only one source is available
- /// on the crossbar, this class will then look for an audio mixer.
- /// This class does not support both methods.
- ///
- /// <para>
- /// The information contained in this property is retrieved and
- /// cached the first time this property is accessed. Future
- /// calls to this property use the cached results. This was done
- /// for performance. </para>
- ///
- /// <para>
- /// However, this means <b>you may get different results depending
- /// on when you access this property first</b>. If you are experiencing
- /// problems, try accessing the property immediately after creating
- /// the Capture class or immediately after setting the video and
- /// audio compressors. Also, inform the developer. </para>
- /// </remarks>
- public SourceCollection AudioSources
- {
- get
- {
- if ( audioSources == null )
- {
- try
- {
- if ( audioDevice != null )
- audioSources = new SourceCollection( captureGraphBuilder, audioDeviceFilter, false );
- else
- audioSources = new SourceCollection();
- }
- catch ( Exception ex ) { Debug.WriteLine( "AudioSources: unable to create AudioSources." + ex.ToString() ); }
- }
- return ( audioSources );
- }
- }
- /// <summary>
- /// Available property pages.
- /// </summary>
- /// <remarks>
- /// These are property pages exposed by the DirectShow filters.
- /// These property pages allow users modify settings on the
- /// filters directly.
- ///
- /// <para>
- /// The information contained in this property is retrieved and
- /// cached the first time this property is accessed. Future
- /// calls to this property use the cached results. This was done
- /// for performance. </para>
- ///
- /// <para>
- /// However, this means <b>you may get different results depending
- /// on when you access this property first</b>. If you are experiencing
- /// problems, try accessing the property immediately after creating
- /// the Capture class or immediately after setting the video and
- /// audio compressors. Also, inform the developer. </para>
- /// </remarks>
- public PropertyPageCollection PropertyPages
- {
- get
- {
- if ( propertyPages == null )
- {
- try
- {
- propertyPages = new PropertyPageCollection(
- captureGraphBuilder,
- videoDeviceFilter, audioDeviceFilter,
- videoCompressorFilter, audioCompressorFilter,
- VideoSources, AudioSources );
- }
- catch ( Exception ex ) { Debug.WriteLine( "PropertyPages: unable to get property pages." + ex.ToString() ); }
- }
- return( propertyPages );
- }
- }
- /// <summary>
- /// The TV Tuner or null if the current video device
- /// does not have a TV Tuner.
- /// </summary>
- public Tuner Tuner { get { return( tuner ); } }
- /// <summary>
- /// Gets and sets the frame rate used to capture video.
- /// </summary>
- /// <remarks>
- /// Common frame rates: 24 fps for film, 25 for PAL, 29.997
- /// for NTSC. Not all NTSC capture cards can capture at
- /// exactly 29.997 fps. Not all frame rates are supported.
- /// When changing the frame rate, the closest supported
- /// frame rate will be used.
- ///
- /// <para>
- /// Not all devices support getting/setting this property.
- /// If this property is not supported, accessing it will
- /// throw and exception. </para>
- ///
- /// <para>
- /// This property cannot be changed while capturing. Changing
- /// this property while preview is enabled will cause some
- /// fickering while the internal filter graph is partially
- /// rebuilt. Changing this property while cued will cancel the
- /// cue. Call Cue() again to re-cue the capture. </para>
- /// </remarks>
- public double FrameRate
- {
- get
- {
- long avgTimePerFrame = (long) getStreamConfigSetting( videoStreamConfig, "AvgTimePerFrame" );
- return( (double) 10000000 / avgTimePerFrame );
- }
- set
- {
- long avgTimePerFrame = (long) ( 10000000 / value );
- setStreamConfigSetting( videoStreamConfig, "AvgTimePerFrame", avgTimePerFrame );
- }
- }
- /// <summary>
- /// Gets and sets the frame size used to capture video.
- /// </summary>
- /// <remarks>
- /// To change the frame size, assign a new Size object
- /// to this property <code>capture.Size = new Size( w, h );</code>
- /// rather than modifying the size in place
- /// (capture.Size.Width = w;). Not all frame
- /// rates are supported.
- ///
- /// <para>
- /// Not all devices support getting/setting this property.
- /// If this property is not supported, accessing it will
- /// throw and exception. </para>
- ///
- /// <para>
- /// This property cannot be changed while capturing. Changing
- /// this property while preview is enabled will cause some
- /// fickering while the internal filter graph is partially
- /// rebuilt. Changing this property while cued will cancel the
- /// cue. Call Cue() again to re-cue the capture. </para>
- /// </remarks>
- public Size FrameSize
- {
- get
- {
- BitmapInfoHeader bmiHeader;
- bmiHeader = (BitmapInfoHeader) getStreamConfigSetting( videoStreamConfig, "BmiHeader" );
- Size size = new Size( bmiHeader.Width, bmiHeader.Height );
- return( size );
- }
- set
- {
- BitmapInfoHeader bmiHeader;
- bmiHeader = (BitmapInfoHeader) getStreamConfigSetting( videoStreamConfig, "BmiHeader" );
- bmiHeader.Width = value.Width;
- bmiHeader.Height = value.Height;
- setStreamConfigSetting( videoStreamConfig, "BmiHeader", bmiHeader );
- }
- }
- /// <summary>
- /// Get or set the number of channels in the waveform-audio data.
- /// </summary>
- /// <remarks>
- /// Monaural data uses one channel and stereo data uses two channels.
- ///
- /// <para>
- /// Not all devices support getting/setting this property.
- /// If this property is not supported, accessing it will
- /// throw and exception. </para>
- ///
- /// <para>
- /// This property cannot be changed while capturing. Changing
- /// this property while preview is enabled will cause some
- /// fickering while the internal filter graph is partially
- /// rebuilt. Changing this property while cued will cancel the
- /// cue. Call Cue() again to re-cue the capture. </para>
- /// </remarks>
- public short AudioChannels
- {
- get
- {
- short audioChannels = (short) getStreamConfigSetting( audioStreamConfig, "nChannels" );
- return( audioChannels );
- }
- set
- {
- setStreamConfigSetting( audioStreamConfig, "nChannels", value );
- }
- }
- /// <summary>
- /// Get or set the number of audio samples taken per second.
- /// </summary>
- /// <remarks>
- /// Common sampling rates are 8.0 kHz, 11.025 kHz, 22.05 kHz, and
- /// 44.1 kHz. Not all sampling rates are supported.
- ///
- /// <para>
- /// Not all devices support getting/setting this property.
- /// If this property is not supported, accessing it will
- /// throw and exception. </para>
- ///
- /// <para>
- /// This property cannot be changed while capturing. Changing
- /// this property while preview is enabled will cause some
- /// fickering while the internal filter graph is partially
- /// rebuilt. Changing this property while cued will cancel the
- /// cue. Call Cue() again to re-cue the capture. </para>
- /// </remarks>
- public int AudioSamplingRate
- {
- get
- {
- int samplingRate = (int) getStreamConfigSetting( audioStreamConfig, "nSamplesPerSec" );
- return( samplingRate );
- }
- set
- {
- setStreamConfigSetting( audioStreamConfig, "nSamplesPerSec", value );
- }
- }
- /// <summary>
- /// Get or set the number of bits recorded per sample.
- /// </summary>
- /// <remarks>
- /// Common sample sizes are 8 bit and 16 bit. Not all
- /// samples sizes are supported.
- ///
- /// <para>
- /// Not all devices support getting/setting this property.
- /// If this property is not supported, accessing it will
- /// throw and exception. </para>
- ///
- /// <para>
- /// This property cannot be changed while capturing. Changing
- /// this property while preview is enabled will cause some
- /// fickering while the internal filter graph is partially
- /// rebuilt. Changing this property while cued will cancel the
- /// cue. Call Cue() again to re-cue the capture. </para>
- /// </remarks>
- public short AudioSampleSize
- {
- get
- {
- short sampleSize = (short) getStreamConfigSetting( audioStreamConfig, "wBitsPerSample" );
- return( sampleSize );
- }
- set
- {
- setStreamConfigSetting( audioStreamConfig, "wBitsPerSample", value );
- }
- }
- /// <summary>
- /// Necesario para poder hacer una identificaci髇 cuando se lance el evento CaptureFrameCompleted
- /// </summary>
- /*public int Id
- {
- get
- {
- return id;
- }
- set
- {
- id = value;
- }
- }*/
- // --------------------- Events ----------------------
- /// <summary> Fired when a capture is completed (manually or automatically). </summary>
- public event EventHandler CaptureComplete;
- /// <summary> Fired when a frame was captured. </summary>
- public delegate void FrameCapHandler(System.Windows.Forms.PictureBox Frame);
- //public static event FrameCapHandler FrameCaptureComplete;
- public event FrameCapHandler FrameCaptureComplete;
- // ------------- Protected/private Properties --------------
- protected GraphState graphState = GraphState.Null; // State of the internal filter graph
- protected bool isPreviewRendered = false; // When graphState==Rendered, have we rendered the preview stream?
- protected bool isCaptureRendered = false; // When graphState==Rendered, have we rendered the capture stream?
- protected bool wantPreviewRendered = false; // Do we need the preview stream rendered (VideoDevice and PreviewWindow != null)
- protected bool wantCaptureRendered = false; // Do we need the capture stream rendered
- protected bool wantCaptureFrame = false;
- protected int rotCookie = 0; // Cookie into the Running Object Table
- protected Filter videoDevice = null; // Property Backer: Video capture device filter
- protected Filter audioDevice = null; // Property Backer: Audio capture device filter
- protected Filter videoCompressor = null; // Property Backer: Video compression filter
- protected Filter audioCompressor = null; // Property Backer: Audio compression filter
- protected string filename = ""; // Property Backer: Name of file to capture to
- protected Control previewWindow = null; // Property Backer: Owner control for preview
- protected VideoCapabilities videoCaps = null; // Property Backer: capabilities of video device
- protected AudioCapabilities audioCaps = null; // Property Backer: capabilities of audio device
- protected SourceCollection videoSources = null; // Property Backer: list of physical video sources
- protected SourceCollection audioSources = null; // Property Backer: list of physical audio sources
- protected PropertyPageCollection propertyPages = null; // Property Backer: list of property pages exposed by filters
- protected Tuner tuner = null; // Property Backer: TV Tuner
- protected IGraphBuilder graphBuilder; // DShow Filter: Graph builder
- protected IMediaControl mediaControl; // DShow Filter: Start/Stop the filter graph -> copy of graphBuilder
- protected IVideoWindow videoWindow; // DShow Filter: Control preview window -> copy of graphBuilder
- protected ICaptureGraphBuilder2 captureGraphBuilder = null; // DShow Filter: building graphs for capturing video
- protected ISampleGrabber sampGrabber = null;
- protected IAMStreamConfig videoStreamConfig = null; // DShow Filter: configure frame rate, size
- protected IAMStreamConfig audioStreamConfig = null; // DShow Filter: configure sample rate, sample size
- protected IBaseFilter videoDeviceFilter = null; // DShow Filter: selected video device
- protected IBaseFilter videoCompressorFilter = null; // DShow Filter: selected video compressor
- protected IBaseFilter audioDeviceFilter = null; // DShow Filter: selected audio device
- protected IBaseFilter audioCompressorFilter = null; // DShow Filter: selected audio compressor
- protected IBaseFilter muxFilter = null; // DShow Filter: multiplexor (combine video and audio streams)
- protected IBaseFilter baseGrabFlt = null;
- protected IFileSinkFilter fileWriterFilter = null; // DShow Filter: file writer
- protected VideoInfoHeader videoInfoHeader;
- protected byte[] savedArray;
- protected bool capturedFrame = false;
- protected int bufferedSize;
- protected bool captured = true;
- protected bool firstFrame = true;
- protected bool renderStream = false;
- //protected int id; //Almacena un n鷐ero que identifica a la c醡ara
- //protected CTee InfTee;
- /// <summary> event when callback has finished (ISampleGrabberCB.BufferCB). </summary>
- private delegate void CaptureDone();
- private const int WM_GRAPHNOTIFY = 0x00008001; // message from graph
- private IMediaEventEx mediaEvt; // event interface
- protected System.Windows.Forms.PictureBox ImageCaptured;
- // ------------- Constructors/Destructors --------------
- /// <summary>
- /// Create a new Capture object.
- /// videoDevice and audioDevice can be null if you do not
- /// wish to capture both audio and video. However at least
- /// one must be a valid device. Use the <see cref="Filters"/>
- /// class to list available devices.
- /// </summary>
- public Capture(Filter videoDevice, Filter audioDevice)
- {
- if ( videoDevice == null && audioDevice == null)
- throw new ArgumentException( "The videoDevice and/or the audioDevice parameter must be set to a valid Filter.n" );
- this.videoDevice = videoDevice;
- this.audioDevice = audioDevice;
- this.Filename = getTempFilename();
- this.ImageCaptured = new System.Windows.Forms.PictureBox();
- createGraph();
- }
- /// <summary> Destructor. Dispose of resources. </summary>
- ~Capture()
- {
- Dispose();
- }
- // --------------------- Public Methods -----------------------
- /// <summary>
- /// Prepare for capturing. Use this method when capturing
- /// must begin as quickly as possible.
- /// </summary>
- /// <remarks>
- /// This will create/overwrite a zero byte file with
- /// the name set in the Filename property.
- ///
- /// <para>
- /// This will disable preview. Preview will resume
- /// once capture begins. This problem can be fixed
- /// if someone is willing to make the change. </para>
- ///
- /// <para>
- /// This method is optional. If Cue() is not called,
- /// Start() will call it before capturing. This method
- /// cannot be called while capturing. </para>
- /// </remarks>
- public void Cue()
- {
- assertStopped();
- // We want the capture stream rendered
- wantCaptureRendered = true;
- // Re-render the graph (if necessary)
- renderGraph();
- // Pause the graph
- int hr = mediaControl.Pause();
- if ( hr != 0 ) Marshal.ThrowExceptionForHR( hr );
- }
- /// <summary> Begin capturing. </summary>
- public void Start()
- {
- Stop();
- // Para que cuando estemos capturando un video podamos capturar frames
- firstFrame = false;
- assertStopped();
- // We want the capture stream rendered
- wantCaptureRendered = true;
- // Re-render the graph (if necessary)
- renderStream = true;
- renderGraph();
- // Start the filter graph: begin capturing
- int hr = mediaControl.Run();
- if ( hr != 0 ) Marshal.ThrowExceptionForHR( hr );
- // Update the state
- graphState = GraphState.Capturing;
- }
- /// <summary>
- /// Stop the current capture capture. If there is no
- /// current capture, this method will succeed.
- /// </summary>
- public void Stop()
- {
- // Stop the graph if it is running
- // If we have a preview running we should only stop the
- // capture stream. However, if we have a preview stream
- // we need to re-render the graph anyways because we
- // need to get rid of the capture stream. To re-render
- // we need to stop the entire graph
- if ( mediaControl != null )
- {
- mediaControl.Stop();
- }
- // Config is true when the parametres of the device are to be changed
- wantCaptureRendered = false;
- wantPreviewRendered = true;
- // Update the state
- if ( graphState == GraphState.Capturing )
- {
- graphState = GraphState.Rendered;
- if ( CaptureComplete != null )
- CaptureComplete( this, null );
- }
- // Para que cuando volvamos a capturar frames no haya problemas
- firstFrame = true;
- // So we destroy the capture stream IF
- // we need a preview stream. If we don't
- // this will leave the graph as it is.
- renderStream = false;
- try { renderGraph(); }
- catch {}
- try { startPreviewIfNeeded(); }
- catch {}
- }
- /// <summary>
- /// Calls Stop, releases all references. If a capture is in progress
- /// it will be stopped, but the CaptureComplete event will NOT fire.
- /// </summary>
- public void DisposeCapture()
- {
- wantPreviewRendered = false;
- wantCaptureRendered = false;
- CaptureComplete = null;
- try { destroyGraph(); }
- catch {}
- if ( videoSources != null )
- videoSources.Dispose(); videoSources = null;
- if ( audioSources != null )
- audioSources.Dispose(); audioSources = null;
- }
- [STAThread]
- public void CaptureFrame()
- {
- int hr;
- if(firstFrame)
- {
- assertStopped();
- // Re-render the graph (if necessary)
- renderStream = true;
- renderGraph();
- // Start the filter graph: begin capturing
- hr = mediaControl.Run();
- if ( hr != 0 ) Marshal.ThrowExceptionForHR( hr );
- firstFrame = false;
- }
- captured = false;
- if(savedArray == null )
- {
- int size = videoInfoHeader.BmiHeader.ImageSize;
- if( (size<1000) || (size > 16000000) )
- return;
- savedArray = new byte[ size + 64000];
- }
- hr = sampGrabber.SetCallback( this, 1 );
- }
- /// <summary>
- /// Esta funci髇 har