Click here to Skip to main content
15,891,976 members
Articles / Programming Languages / C#

DirectX.Capture Class Library

Rate me:
Please Sign up or sign in to vote.
4.94/5 (227 votes)
29 Mar 2008Public Domain5 min read 4M   72K   598  
A .NET class library for capturing video and audio to AVI files.
// ------------------------------------------------------------------
// DirectX.Capture
//
// History:
//	2003-Jan-24		BL		- created
//
// Copyright (c) 2003 Brian Low
// ------------------------------------------------------------------

using System;
using System.Diagnostics;
using System.Collections;
using System.Runtime.InteropServices;
using DShowNET;

namespace DirectX.Capture
{
	/// <summary>
	///  A collection of available PropertyPages in a DirectShow
	///  filter graph. It is up to the driver manufacturer to implement
	///  a property pages on their drivers. The list of supported 
	///  property pages will vary from driver to driver.
	/// </summary>
	public class PropertyPageCollection : CollectionBase, IDisposable
	{

		// --------------- Constructors / Destructor ----------------

		/// <summary> Initialize collection with no property pages. </summary>
		internal PropertyPageCollection()
		{
			InnerList.Capacity = 1;
		}

		/// <summary> Initialize collection with property pages from existing graph. </summary>
		internal PropertyPageCollection(
			ICaptureGraphBuilder2 graphBuilder, 
			IBaseFilter videoDeviceFilter, IBaseFilter audioDeviceFilter,
			IBaseFilter videoCompressorFilter, IBaseFilter audioCompressorFilter, 
			SourceCollection videoSources, SourceCollection audioSources)
		{
			addFromGraph( graphBuilder, 
				videoDeviceFilter, audioDeviceFilter,
				videoCompressorFilter, audioCompressorFilter,
				videoSources, audioSources );
		}

		/// <summary> Destructor. Release unmanaged resources. </summary>
		~PropertyPageCollection()
		{
			Dispose();
		}



		// ----------------- Public Properties ------------------

		/// <summary> Empty the collection. </summary>
		public new void Clear()
		{
			for ( int c = 0; c < InnerList.Count; c++ )
				this[c].Dispose();
			InnerList.Clear();
		}

		/// <summary> Release unmanaged resources </summary>
		public void Dispose()
		{
			Clear();
			InnerList.Capacity = 1;
		}



		// ---------------- Private Methods --------------------

		/// <summary> Get the filter at the specified index. </summary>
		public PropertyPage this[int index]
		{
			get { return( (PropertyPage) InnerList[index] ); }
		}



		// ------------------ Public Methods --------------------

		/// <summary> Populate the collection by looking for commonly implemented property pages. </summary>
		protected void addFromGraph(
			ICaptureGraphBuilder2 graphBuilder, 
			IBaseFilter videoDeviceFilter, IBaseFilter audioDeviceFilter,
			IBaseFilter videoCompressorFilter, IBaseFilter audioCompressorFilter, 
			SourceCollection videoSources, SourceCollection audioSources)
		{
			object filter = null;
			Guid cat;
			Guid med;
			Guid iid;
			int hr;

			Trace.Assert( graphBuilder != null );

			// 1. the video capture filter
			addIfSupported( videoDeviceFilter, "Video Capture Device" );

			// 2. the video capture pin
			cat = PinCategory.Capture;
			med = MediaType.Interleaved; 
			iid = typeof(IAMStreamConfig).GUID;
			hr = graphBuilder.FindInterface( 
				ref cat, ref med, videoDeviceFilter, ref iid, out filter );
			if ( hr != 0 )
			{
				med = MediaType.Video ;
				hr = graphBuilder.FindInterface( 
					ref cat, ref med, videoDeviceFilter, ref iid, out filter );
				if ( hr != 0 )
					filter = null;
			}
			addIfSupported( filter, "Video Capture Pin" );

			// 3. the video preview pin
			cat = PinCategory.Preview;
			med = MediaType.Interleaved; 
			iid = typeof(IAMStreamConfig).GUID;
			hr = graphBuilder.FindInterface( 
				ref cat, ref med, videoDeviceFilter, ref iid, out filter );
			if ( hr != 0 )
			{
				med = MediaType.Video ;
				hr = graphBuilder.FindInterface( 
					ref cat, ref med, videoDeviceFilter, ref iid, out filter );
				if ( hr != 0 )
					filter = null;
			}
			addIfSupported( filter, "Video Preview Pin" );

			// 4. the video crossbar(s)
			ArrayList crossbars = new ArrayList();
			int num = 1;
			for ( int c = 0; c < videoSources.Count; c++ )
			{
				CrossbarSource s = videoSources[c] as CrossbarSource;
				if ( s != null )
				{
					if ( crossbars.IndexOf( s.Crossbar ) < 0 )
					{
						crossbars.Add( s.Crossbar );
						if ( addIfSupported( s.Crossbar, "Video Crossbar " + ( num==1 ? "" : num.ToString() ) ) )
							num++;
					}
				}
			}
			crossbars.Clear();

			// 5. the video compressor
			addIfSupported( videoCompressorFilter, "Video Compressor" );

			// 6. the video TV tuner
			cat = PinCategory.Capture;
			med = MediaType.Interleaved; 
			iid = typeof(IAMTVTuner).GUID;
			hr = graphBuilder.FindInterface( 
				ref cat, ref med, videoDeviceFilter, ref iid, out filter );
			if ( hr != 0 )
			{
				med = MediaType.Video ;
				hr = graphBuilder.FindInterface( 
					ref cat, ref med, videoDeviceFilter, ref iid, out filter );
				if ( hr != 0 )
					filter = null;
			}
			addIfSupported( filter, "TV Tuner" );

			// 7. the video compressor (VFW)
			IAMVfwCompressDialogs compressDialog = videoCompressorFilter as IAMVfwCompressDialogs;
			if ( compressDialog != null )
			{
				VfwCompressorPropertyPage page = new VfwCompressorPropertyPage( "Video Compressor", compressDialog );
				InnerList.Add( page );
			}

			// 8. the audio capture filter
			addIfSupported( audioDeviceFilter, "Audio Capture Device" );

			// 9. the audio capture pin
			cat = PinCategory.Capture;
			med = MediaType.Audio; 
			iid = typeof(IAMStreamConfig).GUID;
			hr = graphBuilder.FindInterface( 
				ref cat, ref med, audioDeviceFilter, ref iid, out filter );
			if ( hr != 0 )
			{
				filter = null;
			}
			addIfSupported( filter, "Audio Capture Pin" );

			// 9. the audio preview pin
			cat = PinCategory.Preview;
			med = MediaType.Audio; 
			iid = typeof(IAMStreamConfig).GUID;
			hr = graphBuilder.FindInterface( 
				ref cat, ref med, audioDeviceFilter, ref iid, out filter );
			if ( hr != 0 )
			{
				filter = null;
			}
			addIfSupported( filter, "Audio Preview Pin" );

			// 10. the audio crossbar(s)
			num = 1;
			for ( int c = 0; c < audioSources.Count; c++ )
			{
				CrossbarSource s = audioSources[c] as CrossbarSource;
				if ( s != null )
				{
					if ( crossbars.IndexOf( s.Crossbar ) < 0 )
					{
						crossbars.Add( s.Crossbar );
						if ( addIfSupported( s.Crossbar, "Audio Crossbar " + ( num==1 ? "" : num.ToString() ) ) )
							num++;
					}
				}
			}
			crossbars.Clear();

			// 11. the audio compressor
			addIfSupported( audioCompressorFilter, "Audio Compressor" );

		}

		/// <summary> 
		///  Returns the object as an ISpecificPropertyPage
		///  if the object supports the ISpecificPropertyPage
		///  interface and has at least one property page.
		/// </summary>
		protected bool addIfSupported(object o, string name)
		{
			ISpecifyPropertyPages specifyPropertyPages = null;
			DsCAUUID cauuid = new DsCAUUID();
			bool wasAdded = false;

			// Determine if the object supports the interface
			// and has at least 1 property page
			try
			{
				specifyPropertyPages = o as ISpecifyPropertyPages;
				if ( specifyPropertyPages != null )
				{
					int hr = specifyPropertyPages.GetPages( out cauuid );
					if ( ( hr != 0 ) || ( cauuid.cElems <= 0 ) )
						specifyPropertyPages = null;
				}
			}
			finally
			{
				if( cauuid.pElems != IntPtr.Zero )
					Marshal.FreeCoTaskMem( cauuid.pElems );
			}
			
			// Add the page to the internal collection
			if ( specifyPropertyPages != null )
			{
				DirectShowPropertyPage p = new DirectShowPropertyPage( name, specifyPropertyPages );
				InnerList.Add( p );
				wasAdded = true;
			}
			return( wasAdded );
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication


Written By
Web Developer
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions