<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Fooling Around &#187; howto</title>
	<atom:link href="http://alax.info/blog/tag/howto/feed" rel="self" type="application/rss+xml" />
	<link>http://alax.info/blog</link>
	<description>// Software Production Line</description>
	<lastBuildDate>Wed, 02 May 2012 15:42:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Windows Visual PC files and locations</title>
		<link>http://alax.info/blog/1115</link>
		<comments>http://alax.info/blog/1115#comments</comments>
		<pubDate>Sun, 14 Mar 2010 10:20:02 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[.vhd]]></category>
		<category><![CDATA[.vmc]]></category>
		<category><![CDATA[.vmcx]]></category>
		<category><![CDATA[.vud]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[tip]]></category>
		<category><![CDATA[virtual pc]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=1115</guid>
		<description><![CDATA[<a href="http://alax.info/blog/1115" title="Windows Visual PC files and locations"></a>Microsoft Windows Visual PC implements virtual machines and the application holds the entire machine state and virtual hard disk information in files. In a few large files in fact, so a question to move and/or backup the files is a &#8230;<p class="read-more"><a href="http://alax.info/blog/1115">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/1115" title="Windows Visual PC files and locations"></a><p><a href="http://www.microsoft.com/Windows/Virtual-PC/default.aspx">Microsoft Windows Visual PC</a> implements virtual machines and the application holds the entire machine state and virtual hard disk information in files. In a few large files in fact, so a question to move and/or backup the files is a question of periodic interest.</p>
<p>So what are the files it is using? First of all, the primary file a user clicks on to start virtual machine is a <strong>.VMCX</strong> file and it is located in <strong>&#8220;C:\Users\$(UserName)\Virtual Machines&#8221;</strong> directory. It is a shortcut to internal files and is holding very basic information about the machine, its state and location of other files.</p>
<pre>
<pre style="color: #000000; background: none repeat scroll 0% 0% #ffffff;"><span style="color: #004a43;">&lt;?</span><span style="color: #004a43;">xml</span> <span style="color: #004a43;">version</span><span style="color: #808030;">=</span><span style="color: #008c00;">"1.0"</span> <span style="color: #004a43;">encoding</span><span style="color: #808030;">=</span><span style="color: #0000e6;">"UTF-16"</span><span style="color: #004a43;">?&gt;</span>
<span style="color: #696969;">&lt;!--</span><span style="color: #696969;"> Microsoft Virtual Machine Description and Registration Settings </span><span style="color: #696969;">--&gt;</span>
<span style="color: #a65700;">&lt;</span><span style="color: #5f5035;">vm_description</span><span style="color: #a65700;">&gt;</span>
    <span style="color: #a65700;">&lt;</span><span style="color: #5f5035;">ram_size</span> <span style="color: #274796;">type</span><span style="color: #808030;">=</span><span style="color: #0000e6;">"</span><span style="color: #0000e6;">string</span><span style="color: #0000e6;">"</span><span style="color: #a65700;">&gt;</span>512 MB<span style="color: #a65700;">&lt;/</span><span style="color: #5f5035;">ram_size</span><span style="color: #a65700;">&gt;</span>
    <span style="color: #a65700;">&lt;</span><span style="color: #5f5035;">vmstate</span> <span style="color: #274796;">type</span><span style="color: #808030;">=</span><span style="color: #0000e6;">"</span><span style="color: #0000e6;">string</span><span style="color: #0000e6;">"</span><span style="color: #a65700;">&gt;</span>Hibernated<span style="color: #a65700;">&lt;/</span><span style="color: #5f5035;">vmstate</span><span style="color: #a65700;">&gt;</span>
    <span style="color: #a65700;">&lt;</span><span style="color: #5f5035;">primary_disk1</span> <span style="color: #274796;">type</span><span style="color: #808030;">=</span><span style="color: #0000e6;">"</span><span style="color: #0000e6;">string</span><span style="color: #0000e6;">"</span><span style="color: #a65700;">&gt;</span>C:\Users\Roman\AppData\Local\Microsoft\Windows Virtual PC\Virtual Machines\Windows XP Mode.vhd<span style="color: #a65700;">&lt;/</span><span style="color: #5f5035;">primary_disk1</span><span style="color: #a65700;">&gt;</span>
    <span style="color: #a65700;">&lt;</span><span style="color: #5f5035;">secondary_disk1</span> <span style="color: #274796;">type</span><span style="color: #808030;">=</span><span style="color: #0000e6;">"</span><span style="color: #0000e6;">string</span><span style="color: #0000e6;">"</span> <span style="color: #a65700;">/&gt;</span>
    <span style="color: #a65700;">&lt;</span><span style="color: #5f5035;">notes</span> <span style="color: #274796;">type</span><span style="color: #808030;">=</span><span style="color: #0000e6;">"</span><span style="color: #0000e6;">string</span><span style="color: #0000e6;">"</span><span style="color: #a65700;">&gt;</span>Windows XP Professional in "XP Mode"
Username XPMUser, Password XPM User<span style="color: #a65700;">&lt;/</span><span style="color: #5f5035;">notes</span><span style="color: #a65700;">&gt;</span>
    <span style="color: #a65700;">&lt;</span><span style="color: #5f5035;">vmc_path</span> <span style="color: #274796;">type</span><span style="color: #808030;">=</span><span style="color: #0000e6;">"</span><span style="color: #0000e6;">string</span><span style="color: #0000e6;">"</span><span style="color: #a65700;">&gt;</span>C:\Users\Roman\AppData\Local\Microsoft\Windows Virtual PC\Virtual Machines\Windows XP Mode.vmc<span style="color: #a65700;">&lt;/</span><span style="color: #5f5035;">vmc_path</span><span style="color: #a65700;">&gt;</span>
<span style="color: #a65700;">&lt;/</span><span style="color: #5f5035;">vm_description</span><span style="color: #a65700;">&gt;</span></pre>
</pre>
<p>This directory has a special hidden <strong>desktop.ini</strong> file in it, which instruct the shell to treat the directory and the files in a special way, as Virtual PC files. This is also how Windows is providing user a link &#8220;Create virtual machine&#8221;.</p>
<p>The <strong>.VMCX</strong> file is editable (its format is based on XML) and it holds references to <strong>.VHD</strong> virtual disk files and <strong>.VMC</strong> virtual machine configuration files. However, <strong>.VMCX</strong> file is nothing but a shortcut only, and Windows Virtual PC will re-created those files once underlying <strong>.VMC</strong> file is double-clicked to be started, so there is no need to edit <strong>.VMCX</strong> files.</p>
<p><strong>.VMC</strong> file is a virtual machine configuration file and it holds the settings a user provides for the virtual machine through settings dialog. The file is also using XML formatting, and is editable. While the file is small itself, its location is used as a base location for <strong>.VSV</strong> file, where software stores runtime state of virtual machine. The <strong>.VSV</strong> file size is stipulated by amount of RAM granted to the virtual machine, so the file may be pretty large itself and it might be desired to be moved to another location also. To achieve this, the small <strong>.VMC</strong> file needs to be moved to location of interest. A <strong>.VMC</strong> file can be double-clicked itself to start the virtual machine.</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2010/03/14-Image001.png"><img class="alignnone size-medium wp-image-1116" title="Windows Virtual PC Settings Dialog" src="http://alax.info/blog/wp-content/uploads/2010/03/14-Image001-320x214.png" alt="Windows Virtual PC Settings Dialog" width="320" height="214" /><br />
</a></p>
<p><strong>.VHD </strong>are the large files as they store data from virtual hard disks, so moving them may make  sense. Additionally to the files themselves, if &#8220;Create Undo Disks&#8221; option is enabled, software will manage additional <strong>.VUD</strong> file with the name of format &#8220;VirtualPCUndo_$(VirtualMachineName)_$(Token).vud&#8221; file with changes that has not yet been applied. If moved, the <strong>.VUD</strong> files have to be thought of as a part of <strong>.VHD </strong>files.</p>
<p>By default a <strong>.VMC</strong> file holds both absolute and relative path refrences to <strong>.VHD</strong> and <strong>.VUD</strong> files, with relative reference as a priority. So if <strong>.VMC</strong> and <strong>.VHD</strong> (optionally with <strong>.VUD</strong>) files are moved together, no special path update/edit required. Software will be able to locate moved disk file automatically as soon as virtual machine is started. Still it is possible to edit the files manually and have files located in different directories. Also if disk file location is modified via GUI, software offers/attempts to strip undo disk <strong>.VUD</strong> file and cancel unapplied changes. If configuration file is edited manually, it is possible to keep undo disks without canceling the changes.</p>
<p>When moving files to a different location, make sure to check directory security so that Windows Virtual PC has sufficient privileges accessing files in the new location, or otherwise it would show ambiguous error messages &#8220;Could not register the virtual machine&#8221;.</p>
<p>See Also: <a href="http://download.microsoft.com/download/7/D/6/7D686A6A-B0F7-42E5-BB3B-4972A8C42C9F/Windows Virtual PC Tips.pdf">Windows Virtual PC Tips on microsoft.com</a></p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/1115/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MediaTools: How to manually configure filters to render M-JPEG video stream from an IP camera</title>
		<link>http://alax.info/blog/1006</link>
		<comments>http://alax.info/blog/1006#comments</comments>
		<pubDate>Wed, 05 Aug 2009 06:48:46 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[Media Tools]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[camera]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[JPEG]]></category>
		<category><![CDATA[M-JPEG]]></category>
		<category><![CDATA[mediatools]]></category>
		<category><![CDATA[sample]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=1006</guid>
		<description><![CDATA[<a href="http://alax.info/blog/1006" title="MediaTools: How to manually configure filters to render M-JPEG video stream from an IP camera"></a>Media Tools DirectShow Filters can be used to acquire, parse and decoder M-JPEG encoded video stream from an IP camera or a video server, however for a quick start it is necessary to properly register filters on system and create &#8230;<p class="read-more"><a href="http://alax.info/blog/1006">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/1006" title="MediaTools: How to manually configure filters to render M-JPEG video stream from an IP camera"></a><p><a href="http://alax.info/blog/category/utilities/media-tools">Media Tools</a> DirectShow Filters can be used to acquire, parse and decoder M-JPEG encoded video stream from an IP camera or a video server, however for a quick start it is necessary to properly register filters on system and create a DirectShow graph.</p>
<p>To register the filters, it is necessary to download DLLs from <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/MediaTools/_Bin">repository</a>. While Acquisition.dll does not require special prerequisites installed, CodingI.dll is using <a href="http://software.intel.com/en-us/intel-ipp/">Intel Integrated Performance Primitives</a> (IPP) version 6.0.0 internally and requires its [at least] redistributables installed before DLLs are being registered using regsvr32.</p>
<p>Intel went further with new releases of IPP, which are incompatible with the version used to build CodingI.dll, so it is version 6.0.0 (in downloads on  Intel website: version 6.0 build 0) has to be installed. Note that Intel DLLs from <em>C:\Program Files\Intel\IPP\6.0.0.044\ia32\bin</em> (version 6.0.0.062 is known to be also compatible) need to be on system search path, or copied to <em>C:\Windows\system32</em> directory.</p>
<p>Once Intel IPP is prepared, it is required to register CodingI.dll using regsvr32. This registers filters and they are available in GraphEdit and for applications. It is important that on the way of constructing graph which renders video using standard video renderers it is required to specify correct resolution for video, or otherwise graph might fail to start with a message &#8220;The graph could not change state&#8221;, caused by video renderer failure to dynamically change to different (effective) resolution.</p>
<p>To create rendering graph, add Alax.Info HTTP Stream Source Filter from the filter list and provide camera URL in properties, e.g. <a href="http://cam15001.miemasu.net/nphMotionJPEG?Kind=1">http://cam15001.miemasu.net/nphMotionJPEG?Kind=1</a></p>
<p><a href="http://alax.info/blog/wp-content/uploads/2009/08/03-image001.png"><img class="alignnone size-medium wp-image-1007" title="Adding Alax.Info HTTP Stream Source Filter" src="http://alax.info/blog/wp-content/uploads/2009/08/03-image001-320x151.png" alt="Adding Alax.Info HTTP Stream Source Filter" width="320" height="151" /></a></p>
<p><span id="more-1006"></span>Add more filters and provide proper resolution for video:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2009/08/03-image002.png"><img class="alignnone size-medium wp-image-1008" title="Alax.Info JPEG Frame Decoder Filter" src="http://alax.info/blog/wp-content/uploads/2009/08/03-image002-320x151.png" alt="Alax.Info JPEG Frame Decoder Filter" width="320" height="151" /></a></p>
<p>Complete graph construction with resolution set up:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2009/08/03-image003.png"><img class="alignnone size-medium wp-image-1009" title="Render Alax.Info JPEG Decoder Filter output pin" src="http://alax.info/blog/wp-content/uploads/2009/08/03-image003-320x151.png" alt="Render Alax.Info JPEG Decoder Filter output pin" width="320" height="151" /></a></p>
<p>Being run, the graph shows video:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2009/08/03-image004.png"><img class="alignnone size-medium wp-image-1010" title="Video from cam15001.miemasu.net camera through Alax.Info DirectShow filters" src="http://alax.info/blog/wp-content/uploads/2009/08/03-image004-320x151.png" alt="Video from cam15001.miemasu.net camera through Alax.Info DirectShow filters" width="320" height="151" /></a></p>
<p>Dynamic handling of resolution selection, configuration and change is also illustrated in sample application <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/MediaTools/Samples/RenderHttpMjpegVideo01">RenderHttpMjpegVideo01</a>.</p>
<p>NOTE: The constructed graph .GRF file is <a href="http://alax.info/blog/wp-content/uploads/2009/08/cam15001miemasunet.grf">available for download</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/1006/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How To: Save image to BMP file from IBasicVideo or VMR windowless interface</title>
		<link>http://alax.info/blog/602</link>
		<comments>http://alax.info/blog/602#comments</comments>
		<pubDate>Sun, 24 Aug 2008 11:30:29 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[bmp]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[VMR]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=602</guid>
		<description><![CDATA[<a href="http://alax.info/blog/602" title="How To: Save image to BMP file from IBasicVideo or VMR windowless interface"></a>A simple question being asked all over again. Given IBasicVideo, IBasicVideo2, IVMRWindowlessControl or IVMRWindowlessControl9, how to save image to file? It is easy. It is a bit easier with IBasicVideo because it is possible to query this interface directly from &#8230;<p class="read-more"><a href="http://alax.info/blog/602">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/602" title="How To: Save image to BMP file from IBasicVideo or VMR windowless interface"></a><p>A simple question being asked all over again. Given <a href="http://msdn.microsoft.com/en-us/library/ms784633(VS.85).aspx">IBasicVideo</a>, <a href="http://msdn.microsoft.com/en-us/library/ms784613(VS.85).aspx">IBasicVideo2</a>, <a href="http://msdn.microsoft.com/en-us/library/ms787170(VS.85).aspx">IVMRWindowlessControl</a> or <a href="http://msdn.microsoft.com/en-us/library/ms787155(VS.85).aspx">IVMRWindowlessControl9</a>, how to save image to file? It is easy. It is a bit easier with <a href="http://msdn.microsoft.com/en-us/library/ms784633(VS.85).aspx">IBasicVideo</a> because it is possible to query this interface directly from graph&#8217;s interface, such as <a href="http://msdn.microsoft.com/en-us/library/ms785794(VS.85).aspx">IGraphBuilder</a>, and the call will be forwarded to video renderer. This code assumes internal bitmap format is non-paletted, which I believe is always the case.</p>
<pre><span style="color: #603000;">LONG</span> nBufferSize <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: #800080;">;</span>
ATLENSURE_SUCCEEDED<span style="color: #808030;">(</span>pBasicVideo<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>GetCurrentImage<span style="color: #808030;">(</span><span style="color: #808030;">&amp;</span>nBufferSize<span style="color: #808030;">,</span> <span style="color: #7d0045;">NULL</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
CHeapPtr<span style="color: #800080;">&lt;</span><span style="color: #603000;">BITMAPINFO</span><span style="color: #800080;">&gt;</span> pBitmapInfo<span style="color: #800080;">;</span>
ATLENSURE_THROW<span style="color: #808030;">(</span>pBitmapInfo<span style="color: #808030;">.</span>AllocateBytes<span style="color: #808030;">(</span>nBufferSize<span style="color: #808030;">)</span><span style="color: #808030;">,</span> E_OUTOFMEMORY<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLENSURE_SUCCEEDED<span style="color: #808030;">(</span>pBasicVideo<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>GetCurrentImage<span style="color: #808030;">(</span><span style="color: #808030;">&amp;</span>nBufferSize<span style="color: #808030;">,</span> <span style="color: #808030;">(</span><span style="color: #603000;">LONG</span><span style="color: #808030;">*</span><span style="color: #808030;">)</span> <span style="color: #808030;">(</span><span style="color: #603000;">BITMAPINFO</span><span style="color: #808030;">*</span><span style="color: #808030;">)</span> pBitmapInfo<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">BYTE</span><span style="color: #808030;">*</span> pnData <span style="color: #808030;">=</span> <span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">BYTE</span><span style="color: #808030;">*</span><span style="color: #808030;">)</span> <span style="color: #808030;">(</span><span style="color: #808030;">&amp;</span>pBitmapInfo<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>bmiHeader <span style="color: #808030;">+</span> <span style="color: #008c00;">1</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #696969;">// NOTE: You might wish to handle &lt;=8 bpp bitmaps here</span>
ATLASSERT<span style="color: #808030;">(</span>pBitmapInfo<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>bmiHeader<span style="color: #808030;">.</span>biBitCount <span style="color: #808030;">&gt;</span> <span style="color: #008c00;">8</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLASSERT<span style="color: #808030;">(</span>pBitmapInfo<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>bmiHeader<span style="color: #808030;">.</span>biCompression <span style="color: #808030;">=</span><span style="color: #808030;">=</span> BI_RGB<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLASSERT<span style="color: #808030;">(</span>pBitmapInfo<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>bmiHeader<span style="color: #808030;">.</span>biSizeImage<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #603000;">BITMAPFILEHEADER</span> BitmapFileHeader<span style="color: #800080;">;</span>
<span style="color: #400000;">ZeroMemory</span><span style="color: #808030;">(</span><span style="color: #808030;">&amp;</span>BitmapFileHeader<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">sizeof</span> BitmapFileHeader<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
BitmapFileHeader<span style="color: #808030;">.</span>bfType <span style="color: #808030;">=</span> <span style="color: #0000e6;">'MB'</span><span style="color: #800080;">;</span>
BitmapFileHeader<span style="color: #808030;">.</span>bfSize <span style="color: #808030;">=</span> <span style="color: #808030;">(</span><span style="color: #603000;">DWORD</span><span style="color: #808030;">)</span> <span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">sizeof</span> <span style="color: #808030;">(</span><span style="color: #603000;">BITMAPFILEHEADER</span><span style="color: #808030;">)</span> <span style="color: #808030;">+</span> pBitmapInfo<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>bmiHeader<span style="color: #808030;">.</span>biSize <span style="color: #808030;">+</span> pBitmapInfo<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>bmiHeader<span style="color: #808030;">.</span>biSizeImage<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
BitmapFileHeader<span style="color: #808030;">.</span>bfOffBits <span style="color: #808030;">=</span> <span style="color: #808030;">(</span><span style="color: #603000;">DWORD</span><span style="color: #808030;">)</span> <span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">sizeof</span> <span style="color: #808030;">(</span><span style="color: #603000;">BITMAPFILEHEADER</span><span style="color: #808030;">)</span> <span style="color: #808030;">+</span> pBitmapInfo<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>bmiHeader<span style="color: #808030;">.</span>biSize<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLENSURE_SUCCEEDED<span style="color: #808030;">(</span>File<span style="color: #808030;">.</span>Write<span style="color: #808030;">(</span><span style="color: #808030;">&amp;</span>BitmapFileHeader<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">sizeof</span> BitmapFileHeader<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLENSURE_SUCCEEDED<span style="color: #808030;">(</span>File<span style="color: #808030;">.</span>Write<span style="color: #808030;">(</span><span style="color: #808030;">&amp;</span>pBitmapInfo<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>bmiHeader<span style="color: #808030;">,</span> pBitmapInfo<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>bmiHeader<span style="color: #808030;">.</span>biSize<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLENSURE_SUCCEEDED<span style="color: #808030;">(</span>File<span style="color: #808030;">.</span>Write<span style="color: #808030;">(</span>pnData<span style="color: #808030;">,</span> <span style="color: #808030;">(</span><span style="color: #603000;">DWORD</span><span style="color: #808030;">)</span> pBitmapInfo<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>bmiHeader<span style="color: #808030;">.</span>biSizeImage<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span></pre>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/602/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How To: Dump CAtlRegExp regular expression variable on parse error</title>
		<link>http://alax.info/blog/592</link>
		<comments>http://alax.info/blog/592#comments</comments>
		<pubDate>Sat, 23 Aug 2008 07:52:12 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[regexp]]></category>
		<category><![CDATA[regular expressions]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=592</guid>
		<description><![CDATA[<a href="http://alax.info/blog/592" title="How To: Dump CAtlRegExp regular expression variable on parse error"></a>ATL regular expression code adds dump/debug capabilities with ATL_REGEXP_DUMP preprocessor definition defined (undocumented). Dump output is directed to stdout, so if the application is not console, it has to be redirected in advance, e.g. into a $(BinaryPath)$(BinaryName)-atlrx.h file. CAtlRegExp&#60;&#62; Expression; &#8230;<p class="read-more"><a href="http://alax.info/blog/592">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/592" title="How To: Dump CAtlRegExp regular expression variable on parse error"></a><p><a href="http://www.codeplex.com/AtlServe">ATL regular expression code</a> adds dump/debug capabilities with <strong>ATL_REGEXP_DUMP</strong> preprocessor definition defined (undocumented). Dump output is directed to <a href="http://msdn.microsoft.com/en-us/library/40bbyw78.aspx">stdout</a>, so if the application is not console, it has to be redirected in advance, e.g. into a <em>$(BinaryPath)$(BinaryName)-atlrx.h</em> file.</p>
<pre>	CAtlRegExp&lt;&gt; Expression; LPCTSTR pszPattern; BOOL bCaseSensitive;
#if defined(ATL_REGEXP_DUMP)
	REParseError Error = Expression.Parse(pszPattern, bCaseSensitive);
	if(Error != REPARSE_ERROR_OK)
	{
		FILE* pStream = NULL;
		if(!GetStdHandle(STD_OUTPUT_HANDLE))
		{
			TCHAR pszPath[MAX_PATH] = { 0 };
			ATLVERIFY(GetModuleFileName(_AtlBaseModule.GetModuleInstance(), pszPath, _countof(pszPath)));
			RemoveExtension(pszPath); // ATLPath::
			_tcscat_s(pszPath, _countof(pszPath), _T("-atlrx.txt"));
			ATLVERIFY(freopen_s(&amp;pStream, CStringA(pszPath), "w", stdout) == 0);
		}
		_tprintf(_T("Error %d\n"), Error);
		Expression.Dump();
		if(pStream)
			ATLVERIFY(fclose(pStream) == 0);
		ATLASSERT(FALSE); // Break into debugger
	}
#else
	ATLVERIFY(Expression.Parse(pszPattern, bCaseSensitive) == REPARSE_ERROR_OK);
#endif // defined(ATL_REGEXP_DUMP)</pre>
<p>There is also <strong>ATLRX_DEBUG</strong> definition, which enables other debug capabilities. <a href="http://msdn.microsoft.com/en-us/library/k3zs4axe(VS.80).aspx">CAtlRegExp</a> object is given a virtual function OnDebugEvent through which it prints comments on <a href="http://msdn.microsoft.com/en-us/library/s1d10w8z(VS.80).aspx">CAtlRegExp::Match</a> process, which can be also redirected to file similar way.</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/592/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How To: Dump DirectShow media samples</title>
		<link>http://alax.info/blog/574</link>
		<comments>http://alax.info/blog/574#comments</comments>
		<pubDate>Fri, 22 Aug 2008 17:54:22 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Seriously]]></category>
		<category><![CDATA[Source]]></category>
		<category><![CDATA[Utilities]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[howto]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=574</guid>
		<description><![CDATA[<a href="http://alax.info/blog/574" title="How To: Dump DirectShow media samples"></a>Given a DirectShow filter graph, what media samples are being sent through particular graph point? DumpMediaSamples utility gives a fast answer to this question. It prints out connection media type details (with details of VIDEOINFOHEADER, VIDEOINFOHEADER2 and WAVEFORMATEX structures corresponding &#8230;<p class="read-more"><a href="http://alax.info/blog/574">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/574" title="How To: Dump DirectShow media samples"></a><p>Given a <a href="http://msdn.microsoft.com/en-us/library/ms783323(VS.85).aspx">DirectShow</a> filter graph, what media samples are being sent through particular graph point? DumpMediaSamples utility gives a fast answer to this question. It prints out connection media type details (with details of <a href="http://msdn.microsoft.com/en-us/library/ms787915(VS.85).aspx">VIDEOINFOHEADER</a>, <a href="http://msdn.microsoft.com/en-us/library/ms787914(VS.85).aspx">VIDEOINFOHEADER2</a> and <a href="http://msdn.microsoft.com/en-us/library/ms713497.aspx">WAVEFORMATEX</a> structures corresponding to <a href="http://msdn.microsoft.com/en-us/library/ms779120(VS.85).aspx">FORMAT_VideoInfo</a>, <a href="http://msdn.microsoft.com/en-us/library/ms779120(VS.85).aspx">FORMAT_VideoInfo2</a> and <a href="http://msdn.microsoft.com/en-us/library/ms779120(VS.85).aspx">FORMAT_WaveFormatEx</a> format types) and <a href="http://msdn.microsoft.com/en-us/library/ms785991(VS.85).aspx">IMediaSample</a> details obtained through <a href="http://msdn.microsoft.com/en-us/library/ms779269(VS.85).aspx">AM_SAMPLE2_PROPERTIES</a> structure. First of all, it is necessary to create a graph of interest using <a href="http://msdn.microsoft.com/en-us/library/ms787460(VS.85).aspx">GraphEdit</a> utility. At the point of interest it is necessary to insert [an uninitialized] <a href="http://msdn.microsoft.com/en-us/library/ms787594(VS.85).aspx">Sample Grabber Filter</a> with the filter name &#8220;SampleGrabber&#8221; (this is the default name but if you add second filter which will be given a different name and remove first filter then, the utility would fail). The graph may look like this: </p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/08/22-image011.png"><img class="alignnone size-medium wp-image-575" title="Filter Graph with Sample Grabber" src="http://alax.info/blog/wp-content/uploads/2008/08/22-image011-300x106.png" alt="" width="300" height="106" /></a> </p>
<p><span id="more-574"></span> Save the graph into a file and start utility providing filter graph path as a command line argument. The utility will <a href="http://msdn.microsoft.com/en-us/library/ms787251(VS.85).aspx">load the graph</a>, locate the inserted <a href="http://msdn.microsoft.com/en-us/library/ms787594(VS.85).aspx">Sample Grabber Filter</a> and run the graph. Any sample passing through will be printed: </p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/08/22-image012.png"><img class="alignnone size-medium wp-image-576" title="DumpMediaSamples in Action" src="http://alax.info/blog/wp-content/uploads/2008/08/22-image012-300x175.png" alt="" width="300" height="175" /></a></p>
<pre>Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\&gt;DumpMediaSamples Test.grf
Media Type:

majortype {73646976-0000-0010-8000-00AA00389B71}, subtype {44495658-0000-0010-8000-00AA00389B71}, pUnk 0x00000000
bFixedSizeSamples 1, bTemporalCompression 0, lSampleSize 23443
formattype {05589F80-C356-11CE-BF01-00AA0055595A}, cbFormat 88, pbFormat 0x0017a7b0
pbFormat as VIDEOINFOHEADER:
  rcSource { 0, 0, 0, 0 ), rcTarget { 0, 0, 0, 0 }
  dwBitRate 372125, dwBitErrorRate 0, AvgTimePerFrame 400,000.00
  bmiHeader.biSize 40, bmiHeader.biWidth 400, bmiHeader.biHeight 320, bmiHeader.biPlanes 1, bmiHeader.biBitCount 16, bmiHeader.biCom
pression XVID
  bmiHeader.biSizeImage 768000, bmiHeader.biXPelsPerMeter 0, bmiHeader.biYPelsPerMeter 0, bmiHeader.biClrUsed 0, bmiHeader.biClrImpo
rtant 0

Media Samples:

fSampleTime 0.000, .dwTypeSpecificFlags 0x00000000, .dwSampleFlags 0x00000115, .tStart 000000000, .tStop 000400000, .dwStreamId 0
.cbBuffer 23443, .lActual 15621, pbBuffer 00 00 01 B0 F5 00 00 01 B5 09 00 00 01 00 00 00 01 20 08 86 84 00 67 0C 32 10 A0 51 8F 00 00 01 B2 44 69 76 58 35 30 33 62 31 33 39 33 70 00 00

fSampleTime 0.040, .dwTypeSpecificFlags 0x00000000, .dwSampleFlags 0x00000110, .tStart 000400000, .tStop 000800000, .dwStreamId 0
.cbBuffer 23443, .lActual 1, pbBuffer 7F

fSampleTime 0.080, .dwTypeSpecificFlags 0x00000000, .dwSampleFlags 0x00000110, .tStart 000800000, .tStop 001200000, .dwStreamId 0
.cbBuffer 23443, .lActual 1, pbBuffer 7F</pre>
<p>A pre-built binary (<a href="http://www.assembla.com/code/roatl-utilities/subversion/nodes/trunk/DumpMediaSamples/Release/DumpMediaSamples.exe?format=raw">Win32</a>) and reference Visual C++ project source code (will require additional headers to compile) are <a href="http://www.assembla.com/code/roatl-utilities/subversion/nodes/trunk/DumpMediaSamples">available from SVN</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/574/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 5: In-Place Processing)</title>
		<link>http://alax.info/blog/494</link>
		<comments>http://alax.info/blog/494#comments</comments>
		<pubDate>Sat, 26 Jul 2008 13:14:47 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Source]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[WTL]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[DMO]]></category>
		<category><![CDATA[howto]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=494</guid>
		<description><![CDATA[<a href="http://alax.info/blog/494" title="How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 5: In-Place Processing)"></a>Previously on the topic: Part 1: Starting the Project Part 2: Video Processing Part 3: Persistence, Automation and Property Pages Part 4: Merit Due to the nature of the brightness and constract correction processing, it would make sense to combine &#8230;<p class="read-more"><a href="http://alax.info/blog/494">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/494" title="How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 5: In-Place Processing)"></a><p>Previously on the topic:</p>
<ul>
<li><a href="http://alax.info/blog/402">Part 1: Starting the Project</a></li>
<li><a href="http://alax.info/blog/412">Part 2: Video Processing</a></li>
<li><a href="http://alax.info/blog/433">Part 3: Persistence, Automation and Property Pages</a></li>
<li><a href="http://alax.info/blog/481">Part 4: Merit</a></li>
</ul>
<p>Due to the nature of the brightness and constract correction processing, it would make sense to combine and simplify processing to apply correction &#8220;in-place&#8221;, that is without copying data from input to output buffer, but instead processing the same buffer before it is passed further downstream.</p>
<p><a href="http://msdn.microsoft.com/en-us/library/ms783356(VS.85).aspx">DMO API</a> offers additional optional <a href="http://msdn.microsoft.com/en-us/library/ms785945(VS.85).aspx">IMediaObjectInPlace</a> interface to be implemented on the DMO which the hosting object might prefer to regular <a href="http://msdn.microsoft.com/en-us/library/ms785947(VS.85).aspx">IMediaObject</a>.</p>
<p>The interface itself is simple with basically the only Process method to actually handle the processing:</p>
<pre>// IMediaObjectInPlace
	STDMETHOD(Process)(ULONG nSize, BYTE* pnData, REFERENCE_TIME nStartTime, DWORD nFlags)
	STDMETHOD(Clone)(IMediaObjectInPlace** ppMediaObject)
	STDMETHOD(GetLatency)(REFERENCE_TIME* pnLatencyTime)</pre>
<p><span id="more-494"></span></p>
<p>Still the interest in <a href="http://msdn.microsoft.com/en-us/library/ms786499(VS.85).aspx">in-place processing in DMO</a> is more abstract because current <a href="http://msdn.microsoft.com/en-us/library/ms783389(VS.85).aspx">DMO Wrapper Filter</a> implementation does not take advantage of in-place processing and chooses to always work through  <a href="http://msdn.microsoft.com/en-us/library/ms785947(VS.85).aspx">IMediaObject</a>.</p>
<p>However if the object is hosted directly, in-place processing might make sense and be important.</p>
<p>To support in-place processing in the DMO it is required to inherit from interface and add it to the COM map:</p>
<pre>class ATL_NO_VTABLE CBrightnessContrastObject :
	public CComObjectRootEx&lt;CComMultiThreadModel&gt;,
	...
<strong>	public IMediaObjectInPlace
</strong>...
BEGIN_COM_MAP(CBrightnessContrastObject)
	...
<strong>	COM_INTERFACE_ENTRY(IMediaObjectInPlace)
</strong>END_COM_MAP()</pre>
<p>And implement the <a href="http://msdn.microsoft.com/en-us/library/ms785945(VS.85).aspx">IMediaObjectInPlace</a> methods, of which <a href="http://msdn.microsoft.com/en-us/library/ms785946(VS.85).aspx">IMediaObjectInPlace::Process</a> is the essential.</p>
<p>Source code: <a href="http://alax.info/blog/wp-content/uploads/2008/07/dmobrightnesscontrastsample05.zip">DmoBrightnessContrastSample.05.zip</a><a href="../wp-content/uploads/2008/07/dmobrightnesscontrastsample03.zip"></a> (note that Release build binary is included)</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/494/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 4: Merit)</title>
		<link>http://alax.info/blog/481</link>
		<comments>http://alax.info/blog/481#comments</comments>
		<pubDate>Fri, 25 Jul 2008 22:44:46 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Source]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[WTL]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[DMO]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[merit]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=481</guid>
		<description><![CDATA[<a href="http://alax.info/blog/481" title="How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 4: Merit)"></a>Previously on the topic: Part 1: Starting the Project Part 2: Video Processing Part 3: Persistence, Automation and Property Pages The implemented so far filter/DMO shown a problem related to its unexpectedly high &#8220;importance&#8221; in the system with the symptom &#8230;<p class="read-more"><a href="http://alax.info/blog/481">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/481" title="How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 4: Merit)"></a><p>Previously on the topic:</p>
<ul>
<li><a href="http://alax.info/blog/402">Part 1: Starting the Project</a></li>
<li><a href="http://alax.info/blog/412">Part 2: Video Processing</a></li>
<li><a href="http://alax.info/blog/433">Part 3: Persistence, Automation and Property Pages</a></li>
</ul>
<p>The implemented so far filter/DMO shown a problem related to its unexpectedly high &#8220;importance&#8221; in the system with the symptom of &#8220;auto-insertion&#8221; the filter when it is not necessary. For example, let us render an AVI file through <a href="http://msdn.microsoft.com/en-us/library/ms786496(VS.85).aspx">Infinite Tee Pin Filter</a>:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/07/image011.png"><img class="alignnone size-medium wp-image-482" title="Rendering AVI file through Infinite Tee Pin Filter" src="http://alax.info/blog/wp-content/uploads/2008/07/image011-300x78.png" alt="" width="300" height="78" /></a></p>
<p>The problem is that DirectShow auto-inserts our Brightness/Contrast filter into the graph while it is obviously not expected, wanted or necessary:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/07/image012.png"><img class="alignnone size-medium wp-image-483" title="Auto-inserted Brightness/Contrast filter/DMO" src="http://alax.info/blog/wp-content/uploads/2008/07/image012-300x65.png" alt="" width="300" height="65" /></a></p>
<p>The problem is high filter/DMO <a href="http://msdn.microsoft.com/en-us/library/aa920889.aspx">merit</a> value and a popular <a href="http://fourcc.org/yuv.php#YUY2">YUY2</a> video format the filter is advertised to accept on input during DMO registration.</p>
<p><span id="more-481"></span></p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/07/image013.png"><img class="alignnone size-medium wp-image-484" title="Brightness/Contrast filter/DMO merit" src="http://alax.info/blog/wp-content/uploads/2008/07/image013-253x300.png" alt="" width="253" height="300" /></a></p>
<p>The merit is <strong>0&#215;00600800</strong> and defined values are:</p>
<pre>enum
{
    MERIT_PREFERRED     = 0x800000,
<strong>    MERIT_NORMAL        = 0x600000,
</strong>    MERIT_UNLIKELY      = 0x400000,
    MERIT_DO_NOT_USE    = 0x200000,
    MERIT_SW_COMPRESSOR = 0x100000,
    MERIT_HW_COMPRESSOR = 0x100050
};</pre>
<p>So the filter&#8217;s merit is <strong>MERIT_NORMAL</strong> plus <strong>0&#215;800</strong> DMO API adds to give DMOs an advantage over regular filters. If we followed merit choice guidelines (&#8220;<a href="http://msdn.microsoft.com/en-us/library/aa920889.aspx"><em>A filter that should never be considered for ordinary playback should have a  merit of MERIT_DO_NOT_USE or less</em></a>&#8220;), we would have taken <strong>MERIT_DO_NOT_USE</strong> value or <strong>MERIT_UNLIKELY</strong> at the very most, because the nature of this filter is to provide additional processing feature when it is explicitly requested by the graph creator.</p>
<p>So in order to resolve the problem we need to override DMO&#8217;s default merit and review the registration step. To provide our own merit value for the filter, we need to create a <strong>REG_DWORD</strong> Merit value in advance under coclass registry key in <strong>HKEY_CLASSES_ROOT</strong>:</p>
<pre>OLECHAR pszClassIdentifier[64] = { 0 };
ATLVERIFY(StringFromGUID2(GetObjectCLSID(), pszClassIdentifier, _countof(pszClassIdentifier)));
CRegKey Key;
CString sKeyName;
sKeyName.Format(_T("CLSID\\%ls"), pszClassIdentifier);
__C(HRESULT_FROM_WIN32(Key.Create(HKEY_CLASSES_ROOT, sKeyName)));
static const DWORD g_nMerit = MERIT_DO_NOT_USE;
__C(HRESULT_FROM_WIN32(Key.SetDWORDValue(_T("Merit"), g_nMerit)));</pre>
<p>Note that another (even easier) way to pre-create this registry value is putting it into .RGS registration script file (MERIT_DO_NOT_USE = 0&#215;00200000 = 2097152):</p>
<pre>HKCR
{
	...
	NoRemove CLSID
	{
		ForceRemove {334BE85B-9DE4-4405-8EEE-9CBB2650F83D} = s 'BrightnessContrastObject Class'
		{
			...
<strong>			val Merit = d '2097152'
</strong></pre>
<p>Source code: <a href="http://alax.info/blog/wp-content/uploads/2008/07/dmobrightnesscontrastsample04.rename-to-zip">DmoBrightnessContrastSample.04.zip</a> (note that Release build binary is included)</p>
<p>See also:</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/ms787559(VS.85).aspx">Registering a DMO</a></li>
</ul>
<p>Continued by:</p>
<ul>
<li><a href="../494">Part 5: In-Place Processing<br />
</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/481/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 3: Persistence, Automation and Property Pages)</title>
		<link>http://alax.info/blog/433</link>
		<comments>http://alax.info/blog/433#comments</comments>
		<pubDate>Fri, 18 Jul 2008 13:31:35 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Source]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[WTL]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[DMO]]></category>
		<category><![CDATA[howto]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=433</guid>
		<description><![CDATA[<a href="http://alax.info/blog/433" title="How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 3: Persistence, Automation and Property Pages)"></a>Previously on the topic: Part 1: Starting the Project Part 2: Video Processing The principal task of video processing is done but there are still things mandatory for the filter to be usable. First of all, a custom interface is &#8230;<p class="read-more"><a href="http://alax.info/blog/433">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/433" title="How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 3: Persistence, Automation and Property Pages)"></a><p>Previously on the topic:</p>
<ul>
<li><a href="http://alax.info/blog/402">Part 1: Starting the Project</a></li>
<li><a href="http://alax.info/blog/412">Part 2: Video Processing</a></li>
</ul>
<p>The principal task of video processing is done but there are still things mandatory for the filter to be usable. First of all, a custom interface is required to be able to control the filter from higher level application and to adjust brightness and constract correction values on the run time. Additionally, persistence would not hurt at all to be able to store correction settings along with other graph settings in <a href="http://msdn.microsoft.com/en-us/library/ms787460(VS.85).aspx">GraphEdit</a> <a href="http://msdn.microsoft.com/en-us/library/ms787598(VS.85).aspx">graph file</a> or anywhere else. Additionally, it would also be convenient to have a property page for the filter to be able to adjust the correction settings through GUI, both on graph composition and while the graph is running.</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/07/image009.png"><img class="alignnone size-medium wp-image-445" title="Filter/DMO Property Page" src="http://alax.info/blog/wp-content/uploads/2008/07/image009-261x300.png" alt="" width="261" height="300" /></a></p>
<p>All the mentioned tasks are interconnected and <a href="http://msdn.microsoft.com/en-us/library/t9adwcde.aspx">ATL</a> has an answer in implementation of:</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/ms221608(VS.85).aspx">IDispatch</a>-derived automation interface through <a href="http://msdn.microsoft.com/en-us/library/494h01te.aspx">IDispatchImpl</a> class to implement custom interface to be used for external control over the filter/DMO and also to be used to access persistent properties</li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms690091(VS.85).aspx">IPersistStream</a>/<a href="http://msdn.microsoft.com/en-us/library/ms682273(VS.85).aspx">IPersistStreamInit</a> interfaces through <a href="http://msdn.microsoft.com/en-us/library/x2fwwk86.aspx">IPersistStreamInitImpl</a> class and <a href="http://msdn.microsoft.com/en-us/library/y5s333c2.aspx">PROP_MAP</a> macro map to implement persistence capabilities</li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms695217(VS.85).aspx">ISpecifyPropertyPages</a> interface through <a href="http://msdn.microsoft.com/en-us/library/96ww582d.aspx">ISpecifyPropertyPagesImpl</a> class to provide custom property page</li>
</ul>
<p><span id="more-433"></span></p>
<p>Also note that <a href="http://msdn.microsoft.com/en-us/library/ms783383(VS.85).aspx">DMO Minimum Requirements</a> mention <a href="http://msdn.microsoft.com/en-us/library/ms690091(VS.85).aspx">IPersistStream</a> and <a href="http://msdn.microsoft.com/en-us/library/ms695217(VS.85).aspx">ISpecifyPropertyPages</a> as not required but recommended as useful, and these interfaces will be used by DirectShow.</p>
<p>We start with custom <a href="http://msdn.microsoft.com/en-us/library/ms221608(VS.85).aspx">IDispatch</a>-derived interface to be used to control filter and for persistence. ATL Project Wizard already prepared empty IBrightnessContrastObject interface as a part of project creation, where we are adding <strong>Brightness</strong> and <strong>Contrast</strong> properties (in the IDL definition) and adding implementation of corresponding methods to the filter/DMO class:</p>
<pre>interface IBrightnessContrastObject : IDispatch
{
	[propget, id(1)] HRESULT Brightness([out, retval] LONG* pnBrightness);
	[propput, id(1)] HRESULT Brightness([in] LONG nBrightness);
	[propget, id(2)] HRESULT Contrast([out, retval] LONG* pnContrast);
	[propput, id(2)] HRESULT Contrast([in] LONG nContrast);
};</pre>
<pre>// IBrightnessContrastObject
	STDMETHOD(get_Brightness)(LONG* pnBrightness) throw()
	STDMETHOD(put_Brightness)(LONG nBrightness) throw()
	STDMETHOD(get_Contrast)(LONG* pnContrast) throw()
	STDMETHOD(put_Contrast)(LONG nContrast) throw()</pre>
<p>To complete implemetnation of persistence we are to inherit from <a href="http://msdn.microsoft.com/en-us/library/x2fwwk86.aspx">IPersistStreamInitImpl</a> and also add a property map:</p>
<pre>class ATL_NO_VTABLE CBrightnessContrastObject :
	...
	public IPersistStreamInitImpl&lt;CBrightnessContrastObject&gt;,
...
BEGIN_COM_MAP(CBrightnessContrastObject)
	COM_INTERFACE_ENTRY(IPersistStreamInit)
	COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStreamInit)
...
BEGIN_PROP_MAP(CBrightnessContrastObject)
	PROP_ENTRY_TYPE_EX("Brightness", 1, CLSID_NULL, __uuidof(IBrightnessContrastObject), VT_I4)
	PROP_ENTRY_TYPE_EX("Contrast", 2, CLSID_NULL, __uuidof(IBrightnessContrastObject), VT_I4)
END_PROP_MAP()
...
public:
	BOOL m_bRequiresSave;</pre>
<p>In the property map we enumerate the persistent properties using <a href="http://msdn.microsoft.com/en-us/library/ds84x0xt.aspx">PROP_ENTRY_TYPE_EX</a> (a successor of <a href="http://msdn.microsoft.com/en-us/library/ds84x0xt(VS.80).aspx">PROP_ENTRY_EX</a>, which is deprecated starting Visual Studio .NET 2008).</p>
<p>Note that ATL implements <a href="http://msdn.microsoft.com/en-us/library/ms682273(VS.85).aspx">IPersistStreamInit</a>, however <a href="http://msdn.microsoft.com/en-us/library/ms690091(VS.85).aspx">IPersistStream</a> is compatible in method declaration so we can quick-implement this interface through declaring <a href="http://msdn.microsoft.com/en-us/library/dcxf7dhx.aspx">COM_INTERFACE_ENTRY_IID</a> and thus casting <a href="http://msdn.microsoft.com/en-us/library/ms682273(VS.85).aspx">IPersistStreamInit</a> to <a href="http://msdn.microsoft.com/en-us/library/ms690091(VS.85).aspx">IPersistStream</a>.</p>
<p>Note CLSID_NULL which is a class identifier of the corresponding property page, if any, which we will replace with a non-NULL identifier below as soon as property page is ready.</p>
<p>We also need a <strong>m_bRequiresSave</strong> variable which is used by <strong>IPersist*Impl</strong> classes and for this reason it has to be either public or instead we should friend the classes to allow access to the variable.</p>
<p>To ensure automation interface property put accessors are working as expected, let us re-work debug pre-initialization of the correction variables through <strong>FinalConstruct</strong> method:</p>
<pre>#if defined(_DEBUG)
	HRESULT FinalConstruct() throw()
	{
		_ATLTRY
		{
			__C(put_Brightness(-0x0010));
			__C(put_Contrast(0x2000));
		}
		_ATLCATCH(Exception)
		{
			return Exception;
		}
		return S_OK;
	}
#endif // defined(_DEBUG)</pre>
<p>The only things remained is a property page, for which we create a new COM object class CGeneralPropertyPage. Luckily, ATL has a wizard-based creation helper for property pages:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/07/image007.png"><img class="alignnone size-medium wp-image-442" title="Add ATL Class" src="http://alax.info/blog/wp-content/uploads/2008/07/image007-300x194.png" alt="" width="300" height="194" /></a></p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/07/image008.png"><img class="alignnone size-medium wp-image-443" title="ATL Property Page Class Settings" src="http://alax.info/blog/wp-content/uploads/2008/07/image008-300x253.png" alt="" width="300" height="253" /></a></p>
<p>We will start needing <a href="http://wtl.sourceforge.net/">WTL</a> for convenient GUI implementation. Please refer to <a href="http://msdn.microsoft.com/en-us/library/5h66xtbw.aspx">Example: Implementing a Property Page</a> on how property page is implemented. Once implementation is complete, we need to inherit from <a href="http://msdn.microsoft.com/en-us/library/x2fwwk86.aspx">IPersistStreamInitImpl</a> and reference the property page from filter/DMO property map:</p>
<pre>class ATL_NO_VTABLE CBrightnessContrastObject :
	...
	public ISpecifyPropertyPagesImpl&lt;CBrightnessContrastObject&gt;,
...
BEGIN_COM_MAP(CBrightnessContrastObject)
	...
	COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
...
BEGIN_PROP_MAP(CBrightnessContrastObject)
	PROP_PAGE(CLSID_GeneralPropertyPage)</pre>
<p>Filter&#8217;s run time:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/07/image010.png"><img class="alignnone size-medium wp-image-447" title="Runtime" src="http://alax.info/blog/wp-content/uploads/2008/07/image010-300x129.png" alt="" width="300" height="129" /></a></p>
<p>Source code: <a href="http://alax.info/blog/wp-content/uploads/2008/07/dmobrightnesscontrastsample03.zip">DmoBrightnessContrastSample.03.zip</a> (note that Release build binary is included)</p>
<p>Continued by:</p>
<ul>
<li><a href="../481">Part 4: Merit</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/433/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 2: Video Processing)</title>
		<link>http://alax.info/blog/412</link>
		<comments>http://alax.info/blog/412#comments</comments>
		<pubDate>Sat, 12 Jul 2008 07:55:09 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[DMO]]></category>
		<category><![CDATA[howto]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=412</guid>
		<description><![CDATA[<a href="http://alax.info/blog/412" title="How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 2: Video Processing)"></a>Previously on the topic: Part 1: Starting the Project We have the DMO filter project compilable and registered with the system and it is right time to start putting code in that allows connecting the filter to other DirectShow filters, &#8230;<p class="read-more"><a href="http://alax.info/blog/412">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/412" title="How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 2: Video Processing)"></a><p>Previously on the topic:</p>
<ul>
<li><a href="http://alax.info/blog/402">Part 1: Starting the Project</a></li>
</ul>
<p>We have the DMO filter project compilable and registered with the system and it is right time to start putting code in that allows connecting the filter to other DirectShow filters, such as video capture or video file source on the input and video renderer on the output.</p>
<p>IMediaObject implementation includes the following groups of functions:</p>
<ul>
<li>object capabilities:
<pre>STDMETHOD(GetStreamCount)(DWORD* pnInputStreamCount, DWORD* pnOutputStreamCount)
STDMETHOD(GetInputStreamInfo)(DWORD nInputStreamIndex, DWORD* pnFlags)
STDMETHOD(GetOutputStreamInfo)(DWORD nOutputStreamIndex, DWORD* pnFlags)
STDMETHOD(GetInputType)(DWORD nInputStreamIndex, DWORD nTypeIndex, DMO_MEDIA_TYPE* pMediaType)
STDMETHOD(GetOutputType)(DWORD nOutputStreamIndex, DWORD nTypeIndex, DMO_MEDIA_TYPE* pMediaType)</pre>
</li>
<li>current media types:
<pre>STDMETHOD(SetInputType)(DWORD nInputStreamIndex, const DMO_MEDIA_TYPE* pMediaType, DWORD nFlags)
STDMETHOD(SetOutputType)(DWORD nOutputStreamIndex, const DMO_MEDIA_TYPE* pMediaType, DWORD nFlags)
STDMETHOD(GetInputCurrentType)(DWORD nInputStreamIndex, DMO_MEDIA_TYPE* pMediaType)
STDMETHOD(GetOutputCurrentType)(DWORD nOutputStreamIndex, DMO_MEDIA_TYPE* pMediaType)
STDMETHOD(GetInputSizeInfo)(DWORD nInputStreamIndex, DWORD* pnBufferSize, DWORD* pnMaximalLookAheadBufferSize, DWORD* pnAlignment)
STDMETHOD(GetOutputSizeInfo)(DWORD nOutputStreamIndex, DWORD* pnBufferSize, DWORD* pnAlignment)</pre>
</li>
<li>streaming:
<pre>STDMETHOD(GetInputMaxLatency)(DWORD nInputStreamIndex, REFERENCE_TIME* pnMaximalLatency)
STDMETHOD(SetInputMaxLatency)(DWORD nInputStreamIndex, REFERENCE_TIME nMaximalLatency)
STDMETHOD(Flush)()
STDMETHOD(Discontinuity)(DWORD nInputStreamIndex)
STDMETHOD(AllocateStreamingResources)()</pre>
</li>
<li>data processing:
<pre>STDMETHOD(GetInputStatus)(DWORD nInputStreamIndex, DWORD* pnFlags)
STDMETHOD(Lock)(LONG bLock)
STDMETHOD(ProcessInput)(DWORD nInputStreamIndex, IMediaBuffer* pMediaBuffer, DWORD nFlags, REFERENCE_TIME nTime, REFERENCE_TIME nLength)
STDMETHOD(ProcessOutput)(DWORD nFlags, DWORD nOutputBufferCount, DMO_OUTPUT_DATA_BUFFER* pOutputBuffers, DWORD* pnStatus)</pre>
</li>
</ul>
<p><span id="more-412"></span></p>
<p>For a very basic filter/DMO we will need to implement:</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/ms785936(VS.85).aspx">GetStreamCount</a> to indicate number of streams and number of pins on the corresponding filter</li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms785930(VS.85).aspx">GetInputStreamInfo</a> and <a href="http://msdn.microsoft.com/en-us/library/ms785931(VS.85).aspx">GetInputType</a> to indicate acceptable input media type</li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms785934(VS.85).aspx">GetOutputStreamInfo</a> and <a href="http://msdn.microsoft.com/en-us/library/ms785935(VS.85).aspx">GetOutputType</a> to indicate acceptable output media type; we will be ready to suggest output media type as soon as input media type is already agreed since media types should match</li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms785952(VS.85).aspx">SetInputType</a>, <a href="http://msdn.microsoft.com/en-us/library/ms785953(VS.85).aspx">SetOutputType</a>, <a href="http://msdn.microsoft.com/en-us/library/ms785926(VS.85).aspx">GetInputCurrentType</a>, <a href="http://msdn.microsoft.com/en-us/library/ms785932(VS.85).aspx">GetOutputCurrentType</a> are simple get/put accessors with a check on setting current media type to be used</li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms785928(VS.85).aspx">GetInputSizeInfo</a> and <a href="http://msdn.microsoft.com/en-us/library/ms785933(VS.85).aspx">GetOutputSizeInfo</a> will indicate buffer requirements</li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms785929(VS.85).aspx">GetInputStatus</a> and <a href="http://msdn.microsoft.com/en-us/library/ms785949(VS.85).aspx">ProcessInput</a> will deal with accepting input data</li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms785950(VS.85).aspx">ProcessOutput</a> is the method to actually perform brightness and contrast conversion</li>
</ul>
<p>The object will have one input and one output pin with similar fixed side buffers on both ends &#8211; the simplest case possible.</p>
<p>Starting with <a href="http://msdn.microsoft.com/en-us/library/ms785931(VS.85).aspx">GetInputType</a> method we are dealing with <a href="http://msdn.microsoft.com/en-us/library/ms783393(VS.85).aspx">DMO_MEDIA_TYPE</a> structure, which describes format of the data used. It is a struct member twin of DirectShow <a href="http://msdn.microsoft.com/en-us/library/ms779120(VS.85).aspx">AM_MEDIA_TYPE</a> with DMO API management functions <a href="http://msdn.microsoft.com/en-us/library/ms783377(VS.85).aspx">Mo*MediaType</a>. For easy and reliable manipulation with this type we will need a ATL/WTL-like wrapper class <em>&#8220;template &lt; BOOL t_bManaged &gt; class CDmoMediaTypeT&#8221;</em>, which will take care of allocating and freeing the media types.</p>
<p><strong>m_pInputMediaType</strong> and <strong>m_pOutputMediaType</strong> variables will hold media types accepted and agreed for object streams (and thus, filter pins). <strong>m_DataCriticalSection</strong> is a critical section to ensure thread safe operation.</p>
<p><a href="http://msdn.microsoft.com/en-us/library/ms785949(VS.85).aspx">ProcessInput</a> method will be receiving input buffers for further processing, however this method is not expected to write any outputs. The filter/DMO is expected to pre-process the input and copy save pre-processing outputs in member variables or private buffers. Or instead, the filter can leave a reference to the input buffer and perform the entire processing in the following <a href="http://msdn.microsoft.com/en-us/library/ms785950(VS.85).aspx">ProcessOutput</a> call.</p>
<p>Other methods <a href="http://msdn.microsoft.com/en-us/library/ms785952(VS.85).aspx">SetInputType</a>, <a href="http://msdn.microsoft.com/en-us/library/ms785953(VS.85).aspx">SetOutputType</a>, <a href="http://msdn.microsoft.com/en-us/library/ms785924(VS.85).aspx">Flush</a>, <a href="http://msdn.microsoft.com/en-us/library/ms785923(VS.85).aspx">Discontinuity</a> and <a href="http://msdn.microsoft.com/en-us/library/ms785929(VS.85).aspx">GetInputStatus</a> are also dependent on current input status, so to ease further life we are making <strong>CInput</strong> class to hold all input data provided with <a href="http://msdn.microsoft.com/en-us/library/ms785949(VS.85).aspx">ProcessInput</a> call until required by <a href="http://msdn.microsoft.com/en-us/library/ms785950(VS.85).aspx">ProcessOutput</a> and other implementation methods. <strong>m_Input</strong> member variable will hold latest input buffer.</p>
<p><a href="http://msdn.microsoft.com/en-us/library/ms785950(VS.85).aspx">ProcessOutput</a> is the last method to implement and it has the real data processing. The method is called when both streams/pins are connected, media types agreed and the graph is not stopped. At the moment of the call we should have input data already available through a reference to <a href="http://msdn.microsoft.com/en-us/library/ms785866(VS.85).aspx">IMediaBuffer</a> held by <strong>m_Input </strong>variable and received through <a href="http://msdn.microsoft.com/en-us/library/ms785949(VS.85).aspx">ProcessInput</a> call. <a href="http://msdn.microsoft.com/en-us/library/ms785950(VS.85).aspx">ProcessOutput</a> is to full output buffer with processed data.</p>
<p>Initially we decided to use <a href="http://fourcc.org/yuv.php#YUY2">YUY2</a> pixel format for input and output data. The choice of YUV format is stipulated by ease of <a href="http://msdn.microsoft.com/en-us/library/ms798812.aspx">processing in YUV color space</a>. Brightness and contrast correction affects only Y component of the pixel:</p>
<blockquote><p>The following equation summarizes the steps described in the previous paragraph. C is the contrast value and B is the brightness value.<br />
<strong>Y&#8217; = ((Y &#8211; 16) x C) + B + 16</strong></p></blockquote>
<p>YUY2 format has pixels united into macropixel structure, one macropixel for two horizontally neighboring pixels:</p>
<p><img src="http://fourcc.org/images/yuy2.gif" alt="YUY2 Macropixel Format" /></p>
<p>That is, input and output buffers are arrays of macropixels, where we need to update Y component using brightness and contrast correction coefficients. At the very moment we define constant member variables m_nBrightness and m_nContrast and initialize them to predefeined values of -0&#215;0010 and 0&#215;2000 respectively. Let brightness value range be -0x00FF (unbright) through 0x00FF (bright), with a value of 0&#215;0000 leaving original brightness intact. The contrast value range will be 0&#215;0000 (full fade out) through 0xFFFF, with a value of 0&#215;4000 leaving original contrast intact. So taken constants will slightly decrease brightness and apply 50%. contrast reduction. The actual correction for one Y value is performed by function <strong>Adjust</strong>.</p>
<p>It is important to support non-standard video strides in order to be compatible to <a href="http://msdn.microsoft.com/en-us/library/ms787872(VS.85).aspx">Video Mixing Renderer Filter</a>. <a href="http://msdn.microsoft.com/en-us/library/ms787872(VS.85).aspx">Video Mixing Renderer Filter</a> can request an image with extended strides by providing respective media type on the output pin of the <a href="http://msdn.microsoft.com/en-us/library/ms783389(VS.85).aspx">DMO Wrapper Filter</a>, which is passed to the DMO output stream. <a href="http://msdn.microsoft.com/en-us/library/ms785950(VS.85).aspx">ProcessOutput</a> should be prepared to the changed media type and extended strides by checking <strong>biWidth</strong> field of the <a href="http://msdn.microsoft.com/en-us/library/ms532290(VS.85).aspx">BITMAPINFOHEADER</a> structure embedded into media type.</p>
<p>Once the processing is ready, we can easily check the operation using <a href="http://msdn.microsoft.com/en-us/library/ms786496(VS.85).aspx">Infinite Pin Tee Filter</a> duplicating video stream into two streams and rendering the first through designed filter and rendering the other (original) stream as is:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/07/image005.png"><img class="alignnone size-medium wp-image-413" title="Test graph with GraphEdit" src="http://alax.info/blog/wp-content/uploads/2008/07/image005-300x131.png" alt="" width="300" height="131" /></a></p>
<p>Once the graph is started, video renderers pop up their windows:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/07/image006.png"><img class="alignnone size-medium wp-image-414" title="GraphEdit Video Renderers" src="http://alax.info/blog/wp-content/uploads/2008/07/image006-300x158.png" alt="" width="300" height="158" /></a></p>
<p>Source code: <a href="http://alax.info/blog/wp-content/uploads/2008/07/dmobrightnesscontrastsample02.zip">DmoBrightnessContrastSample.02.zip</a> (note that Release build binary is included)</p>
<p>Additional notes:</p>
<ul>
<li><a href="http://www.fourcc.org/yuv.php">YUV Formats</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms798812.aspx">Processing in the 8-bit YUV Color Space</a></li>
<li><a href="http://en.wikipedia.org/wiki/Brightness">Brightness</a> and <a href="http://en.wikipedia.org/wiki/Contrast_(vision)">Contrast</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms787872(VS.85).aspx">Using the Video Mixing Renderer</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms779712(VS.85).aspx">BITMAPINFOHEADER Structure</a> &#8211; see Remarks on calculating stride</li>
</ul>
<p>Continued by:</p>
<ul>
<li><a href="http://alax.info/blog/433">Part 3: Persistence, Automation and Property Pages</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/412/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 1: Starting the Project)</title>
		<link>http://alax.info/blog/402</link>
		<comments>http://alax.info/blog/402#comments</comments>
		<pubDate>Sat, 05 Jul 2008 11:31:11 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[DMO]]></category>
		<category><![CDATA[howto]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=402</guid>
		<description><![CDATA[<a href="http://alax.info/blog/402" title="How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 1: Starting the Project)"></a>This post is starting a step by step tutorial on writing a simple DirectShow filter using a simplified DirectX Media Objects (DMO) API. From the very scratch, the goal is to make a DirectShow/DMO video processing filter which implements video &#8230;<p class="read-more"><a href="http://alax.info/blog/402">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/402" title="How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 1: Starting the Project)"></a><p>This post is starting a step by step tutorial on writing a simple <a href="http://msdn.microsoft.com/en-us/library/ms783323(VS.85).aspx">DirectShow</a> filter using a simplified <a href="http://msdn.microsoft.com/en-us/library/ms783356(VS.85).aspx">DirectX Media Objects (DMO)</a> API. From the very scratch, the goal is to make a DirectShow/DMO video processing filter which implements video brightness and contrast correction.</p>
<p>DirectX Media Objects are <a href="http://www.microsoft.com/com/default.mspx">COM</a>-based components. To implement a COM object we will use <a href="http://msdn.microsoft.com/en-us/vstudio/default.aspx">Visual Studio .NET 2008</a> and <a href="http://msdn.microsoft.com/en-us/library/3ax346b7(VS.80).aspx">Active Template Library (ATL)</a>.</p>
<p>We are starting creating a no thrills ATL DLL project following by adding a no thrills <em>ATL Simple Object Class</em>:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/07/image001.png"><img class="alignnone size-medium wp-image-404" title="image001" src="http://alax.info/blog/wp-content/uploads/2008/07/image001-300x253.png" alt="ATL DLL Project" width="300" height="253" /></a></p>
<p><span id="more-402"></span></p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/07/image002.png"><img class="alignnone size-medium wp-image-405" title="image002" src="http://alax.info/blog/wp-content/uploads/2008/07/image002-300x194.png" alt="ATL Simple Object" width="300" height="194" /></a></p>
<p>The only thing to make sure is to choose &#8220;Both&#8221; Threading Model since DirectX Media Object must function correctly in a free-threaded environment:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/07/image003.png"><img class="alignnone size-medium wp-image-406" title="image003" src="http://alax.info/blog/wp-content/uploads/2008/07/image003-300x253.png" alt="ATL Simple Object Threading Model" width="300" height="253" /></a></p>
<p>Visual Studio wizard creates a class which implements custom IDispatch-derived dual interface. We will not need it until we get to persistence and property pages.</p>
<p>First of all, we need to reference relevant SDK headers to be able to use DirectShow and <a href="http://msdn.microsoft.com/en-us/library/ms783356(VS.85).aspx">DMO API</a>:</p>
<pre>#include &lt; dshow.h &gt;
#include &lt; dmo.h &gt;
#include &lt; dmodshow.h &gt;
...
#pragma comment(lib, "strmiids.lib")
#pragma comment(lib, "dmoguids.lib")
#pragma comment(lib, "msdmo.lib")</pre>
<p>We reference header files and immediately leave a comment to linker to link library files (to avoid specifying them explicitly in project settings.</p>
<p>From the <a href="http://msdn.microsoft.com/en-us/library/ms783383(VS.85).aspx">minimum requirements for every DMO</a> we implemented aggregation (<a href="http://msdn.microsoft.com/en-us/library/t9adwcde.aspx">ATL</a> provides implementation by default) and threading model:</p>
<blockquote><p>Every DMO should meet the following minimum requirements:<br />
- It must support aggregation.<br />
- It must expose the <a href="http://msdn.microsoft.com/en-us/library/ms785947(VS.85).aspx">IMediaObject</a> interface.<br />
- The threading model must be &#8216;both&#8217;. DMOs must function correctly in a free-threaded environment.</p></blockquote>
<p>We yet need to expose <a href="http://msdn.microsoft.com/en-us/library/ms785947(VS.85).aspx">IMediaObject</a> interface and add registration code to expose the object/filter to DirectShow-enabled applications and software components. While registration step is not necessary, it still allows visual graph construction with the filter being developed using <a href="http://msdn.microsoft.com/en-us/library/ms787460(VS.85).aspx">GraphEdit</a> utility.</p>
<p>To implement <a href="http://msdn.microsoft.com/en-us/library/ms785947(VS.85).aspx">IMediaObject</a>, we inherit from it the media object class:</p>
<pre>class ATL_NO_VTABLE CBrightnessContrastObject :
    public CComObjectRootEx&lt; CComMultiThreadModel &gt;,
    public CComCoClass&lt; CBrightnessContrastObject, &amp;CLSID_BrightnessContrastObject &gt;,
    public IDispatchImpl&lt; IBrightnessContrastObject &gt;,
<strong>    public IMediaObject</strong></pre>
<p>then add the interface into COM MAP:</p>
<pre>BEGIN_COM_MAP(CBrightnessContrastObject)
    <strong>COM_INTERFACE_ENTRY(IMediaObject)</strong></pre>
<p>and add <a href="http://msdn.microsoft.com/en-us/library/ms785947(VS.85).aspx">IMediaObject</a> methods to the class.</p>
<p>Since <a href="http://msdn.microsoft.com/en-us/library/ms785947(VS.85).aspx">IMediaObject</a> contains Lock method, it is confused with <a href="http://msdn.microsoft.com/en-us/library/8hzca2fs.aspx">CComObjectRootEx</a>&#8216;s Lock and breaks project from compilation. To resolve this ambiguity, we add another method to the media object class:</p>
<pre>// CComObjectRootEx
    VOID Lock()
    {
        CComObjectRootEx::Lock();
    }</pre>
<p>To enable automatic registration of the media object with DirectShow/DMO infrastructure, we are putting registration as a part of COM registration of the DLL module. This way the object will be automatically exposed to DirectShow software once the DLL is installed and registered with the system.</p>
<p>First of all, we are adding <a href="http://msdn.microsoft.com/en-us/library/24z8966k.aspx">GetObjectFriendlyName</a> method to provide a friendly name for the object, to be used by both ATL to register the class as COM class and the same name will be available to DirectShow software:</p>
<pre>static LPCTSTR GetObjectFriendlyName() throw()
{
    return _T("Alax.Info BrightnessContrast Sample");
}</pre>
<p>To intercept COM registration and register the object as DMO we are overriding UpdateRegistry method. The implementation for this method is added to th class through <a href="http://msdn.microsoft.com/en-us/library/w0ey2be3(VS.80).aspx">DECLARE_REGISTRY_RESOURCEID</a> macro. We comment this out and add implementation for this method explicitly:</p>
<p>Except for default handling through <a href="http://msdn.microsoft.com/en-us/library/fk48ft1t.aspx">CAtlModule::UpdateRegistryFromResource</a>, we will add calls to our <strong>RegisterMediaObject</strong> and <strong>UnregisterMediaObject</strong> functions which in their turn will use <a href="http://msdn.microsoft.com/en-us/library/ms783385(VS.85).aspx">DMORegister</a> and <a href="http://msdn.microsoft.com/en-us/library/ms783388(VS.85).aspx">DMOUnregister</a> API.</p>
<pre>static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()
{
    _ATLTRY
    {
        if(!bRegister)
            UnregisterMediaObject();
        ATLASSERT(_pAtlModule);
        _pAtlModule-&gt;UpdateRegistryFromResource(IDR_BRIGHTNESSCONTRASTOBJECT, bRegister);
        if(bRegister)
            RegisterMediaObject();
    }
    _ATLCATCH(Exception)
    {
        return Exception;
    }
    return S_OK;
}</pre>
<p>Our media object will expose one input and one output stream/pin both with media type MEDIATYPE_Video, <a href="http://msdn.microsoft.com/en-us/library/aa390521.aspx">MEDIASUBTYPE_YUY2</a>.</p>
<p>Once the project is compiled, COM registration is performed as a part of build task and DMO registration is a subtask. So, the object is already exposed to DirectShow software and applications:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/07/image004.png"><img class="alignnone size-medium wp-image-408" title="GraphEdit Availability" src="http://alax.info/blog/wp-content/uploads/2008/07/image004-253x300.png" alt="" width="253" height="300" /></a></p>
<p>The framework part is done, we are ready to add real implementation for <a href="http://msdn.microsoft.com/en-us/library/ms785947(VS.85).aspx">IMediaObject</a> interface and video processing methods.</p>
<p>Source code: <a href="http://alax.info/blog/wp-content/uploads/2008/07/dmobrightnesscontrastsample01.zip">DmoBrightnessContrastSample.01.zip</a></p>
<p>Additional Notes:</p>
<ul>
<li>Platform SDK provides <a href="http://msdn.microsoft.com/en-us/library/ms785938(VS.85).aspx">IMediaObjectImpl</a> template class (dmoimpl.h) to inherit from instead of <a href="http://msdn.microsoft.com/en-us/library/ms785947(VS.85).aspx">IMediaObject</a>, which offer base implementation for <a href="http://msdn.microsoft.com/en-us/library/ms785947(VS.85).aspx">IMediaObject</a> interface.</li>
<li>See also <a href="http://vnet.uh.edu/vrecord_data/vclass/resource/ATL_Tutorial_9219.doc">similar tutorial on vnet.uh.edu</a></li>
</ul>
<p>Continued by:</p>
<ul>
<li><a href="http://alax.info/blog/412">Part 2: Video Processing</a></li>
<li><a href="http://alax.info/blog/433">Part 3: Persistence, Automation and Property Pages</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/402/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

