<?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; memory</title>
	<atom:link href="http://alax.info/blog/tag/memory/feed" rel="self" type="application/rss+xml" />
	<link>http://alax.info/blog</link>
	<description>// Software Production Line</description>
	<lastBuildDate>Fri, 03 Feb 2012 22:49:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Hardware assisted memory corruption detection</title>
		<link>http://alax.info/blog/1319</link>
		<comments>http://alax.info/blog/1319#comments</comments>
		<pubDate>Sat, 19 Nov 2011 17:26:25 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Seriously]]></category>
		<category><![CDATA[Source]]></category>
		<category><![CDATA[corruption]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[detection]]></category>
		<category><![CDATA[exception]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[protection]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=1319</guid>
		<description><![CDATA[<a href="http://alax.info/blog/1319" title="Hardware assisted memory corruption detection"></a>So you got a memory corruption issue with a piece of software. It comes in a unique scenario along the line of having a huge pile of weird code running well most of the time and then, right out of &#8230;<p class="read-more"><a href="http://alax.info/blog/1319">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/1319" title="Hardware assisted memory corruption detection"></a><p>So you got a memory corruption issue with a piece of software. It comes in a unique scenario along the line of having a huge pile of weird code running well most of the time and then, right out of the blue, a corruption takes place followed by unexpected code execution and unstable software state in general.</p>
<p>The biggest problem with memory corruption is that a fragment of code is modifying a memory block which it does not own, and it has no idea who actually is the owner of the block, while the real owner has no timely way to detect the modification. You only face the consequences being unable to capture the modification moment in first place.</p>
<p>To get back to the original cause, an engineer has to drop into a time machine, turn back time and step back to where the trouble took originally place. As developers are not actually given state-of-the-art time machines, the time turning step is speculative.</p>
<h4>CVirtualHeapPtr Class: Memory with Exception-on-Write access mode</h4>
<p>At the same time a Windows platform developer is or might be aware of <a href="http://msdn.microsoft.com/en-us/library/ms810627.aspx">virtual memory API</a> which among other things provides user mode application with capabilities to define memory protection modes. Having this on hands opens unique opportunity to apply read-only protection (PAGE_READONLY) onto a memory block and have exception raised at the very moment of unexpected memory modification, having call stack showing up a source of the problem. I refer to this mode of operation as &#8220;hardware assisted&#8221; because the access violation exception/condition would be generated purely in hardware without any need to additionally do any address comparison in code.</p>
<p>Needless to say that this way is completely convenient for the developer as he does not need to patch the monstrous application all around in order to compare access addresses against read-only fragment. Instead, a block defined as read-only will be immediately available as such for the whole process almost without any performance overhead.</p>
<p>As ATL provides a set of memory allocator templates (<a href="http://msdn.microsoft.com/en-us/library/3by29yh0%28v=vs.80%29.aspx">CHeapPtr</a> for heap backed memory blocks, allocated with <em>CCRTAllocator</em>, alternate options include <a href="http://msdn.microsoft.com/en-us/library/80zw33a6%28v=vs.80%29.aspx">CComHeapPtr</a> with <em>CComAllocator</em> wrapping <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms692727%28v=vs.85%29.aspx">CoTaskMemAlloc</a>/<em>CoTaskMemFree</em> API), let us make an alternate allocator option that mimic well-known class interface and would facilitate corruption detection.</p>
<p>Because virtual memory allocation unit is a page, and protection mode is defined for the whole page, this would be the allocation granularity. For a single allocated byte we would need to request <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms724958%28v=vs.85%29.aspx">SYSTEM_INFO::dwPageSize</a> bytes of virtual memory. Unlike normal memory heap manager, we have no way to share pages between allocations as we would be unable to effectively apply protection modes. This would definitely increase application pressure onto virtual memory, but is still acceptable for the sacred task of troubleshooting.</p>
<p>We define a <em>CVirtualAllocator</em> class to be compatible with ATL&#8217;s <em>CCRTAllocator</em>, however based on <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa366887%28v=vs.85%29.aspx">VirtualAlloc</a>/<em>VirtualFree</em> API. The smart pointer class over memory pointer would be defined as follows:</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #800000; font-weight: bold;">template</span> <span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">typename</span> T<span style="color: #800080;">&gt;</span>
<span style="color: #800000; font-weight: bold;">class</span> CVirtualHeapPtr <span style="color: #800080;">:</span>
    <span style="color: #800000; font-weight: bold;">public</span> CHeapPtr<span style="color: #800080;">&lt;</span>T<span style="color: #808030;">,</span> CVirtualAllocator<span style="color: #800080;">&gt;</span>
<span style="color: #800080;">{</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
<span style="color: #696969;">// CVirtualHeapPtr</span>
    CVirtualHeapPtr<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">throw</span><span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">explicit</span> CVirtualHeapPtr<span style="color: #808030;">(</span>_In_ T<span style="color: #808030;">*</span> pData<span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">throw</span><span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #603000;">VOID</span> SetProtection<span style="color: #808030;">(</span><span style="color: #603000;">DWORD</span> nProtection<span style="color: #808030;">)</span>
    <span style="color: #800080;">{</span>
        <span style="color: #696969;">// </span><span style="color: #ffffff; background: #808000;">TODO: ...</span>
    <span style="color: #800080;">}</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span></pre>
<p>The <em>SetProtection</em> method is to define memory protection for the memory block. Full code for the classes <a href="http://www.alax.info/trac/public/browser/trunk/Utilities/VirtualHeapPtr/VirtualHeapPtr.h#L9">is available on Trac here</a> (lines 9-132):</p>
<ul>
<li><em>CGlobalVirtualAllocator</em> class is a singleton querying operating system for virtual memory page size, and provides alignment method</li>
<li><em>CVirtualAllocator</em> class is a <em>CCRTAllocator</em>-compatible allocator class</li>
<li><em>CVirtualHeapPtr</em> class is smart template class wrapping a pointer to allocated memory</li>
</ul>
<p>Use case code will be as follows. &#8220;SetProtection(PAGE_READONLY)&#8221; enables protection on memory block and turns on exception generation at the moment memory block modification attempt. &#8220;SetProtection(PAGE_READWRITE)&#8221; would restore normal mode of memory operation.</p>
<pre style="color: #000000; background: #ffffff;">CVirtualHeapPtr<span style="color: #800080;">&lt;</span><span style="color: #603000;">BYTE</span><span style="color: #800080;">&gt;</span> p<span style="color: #800080;">;</span>
p<span style="color: #808030;">.</span>Allocate<span style="color: #808030;">(</span><span style="color: #008c00;">2</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
p<span style="color: #808030;">[</span><span style="color: #008c00;">1</span><span style="color: #808030;">]</span> <span style="color: #808030;">=</span> <span style="color: #008000;">0x01</span><span style="color: #800080;">;</span>
p<span style="color: #808030;">.</span>SetProtection<span style="color: #808030;">(</span>PAGE_READONLY<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #696969;">// NOTE: Compile with /EHa on order to catch the exception</span>
_ATLTRY
<span style="color: #800080;">{</span>
    p<span style="color: #808030;">[</span><span style="color: #008c00;">1</span><span style="color: #808030;">]</span> <span style="color: #808030;">=</span> <span style="color: #008000;">0x02</span><span style="color: #800080;">;</span>
    <span style="color: #696969;">// NOTE: We never reach here due to exception</span>
<span style="color: #800080;">}</span>
_ATLCATCHALL<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    <span style="color: #696969;">// NOTE: Catching the access violation for now to be able to continue execution</span>
<span style="color: #800080;">}</span>
p<span style="color: #808030;">.</span>SetProtection<span style="color: #808030;">(</span>PAGE_READWRITE<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
p<span style="color: #808030;">[</span><span style="color: #008c00;">1</span><span style="color: #808030;">]</span> <span style="color: #808030;">=</span> <span style="color: #008000;">0x03</span><span style="color: #800080;">;</span></pre>
<p>Given the information what data gets corrupt, the pointer allocator provides an efficient opportunity to detect the violation attempt. The only thing remained is to keep memory read-only, and temporarily revert to write access when the &#8220;legal&#8221; memory modification code is about to be executed.</p>
<p><span id="more-1319"></span></p>
<h5>One-shot Read/Write Protection with Guard Pages</h5>
<p>Another option granted by memory protection modes is brought by PAGE_GUARD flag. MSDN says:</p>
<blockquote><p>A guard page provides a one-shot alarm for memory page access. This can be useful for an application that needs to monitor the growth of large dynamic data structures. For example, there are operating systems that use guard pages to implement automatic stack checking.</p></blockquote>
<p>Setting a guard page mode provides an additional option to trigger an exception with even read access to a protected memory block.</p>
<pre style="color: #000000; background: #ffffff;">p<span style="color: #808030;">.</span>SetProtection<span style="color: #808030;">(</span>PAGE_READWRITE <span style="color: #808030;">|</span> PAGE_GUARD<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #603000;">BYTE</span> n <span style="color: #808030;">=</span> p<span style="color: #808030;">[</span><span style="color: #008c00;">0</span><span style="color: #808030;">]</span><span style="color: #800080;">;</span></pre>
<h4>CDebugHeapPtr Class: More Options to Catch Memory Corruption Conditions</h4>
<p>While setting memory protection attributes on a memory block of interest provides unique troubleshooting opportunities, it still does not cover important typical problems with memory misuse scenarios. Those are writing immediately before the allocated block, and writing immediately after. Having array of N items, this would be writing to indices -1 and N respectively.</p>
<p>To address this scenarios of misuse we can extend CVirtualHeapPtr class so that it could additionally provide &#8220;sanity pages&#8221; with PAGE_NOACCESS protection at the boundary of allocation. Because virtual memory allocation is granular, we will have to have padding bytes that extend our block to the page boundary, however we have an option to put the padding bytes before or after the payload data block in order to capture after or before memory block writes respectively.</p>
<p>The figure below shows memory layout for the data:</p>
<p><img class="alignnone size-full wp-image-1320" title="CDebugHeapPtr Memory Layout" src="http://alax.info/blog/wp-content/uploads/2011/11/image.png" alt="" width="509" height="541" /></p>
<p>Source code for the <em>CDebugHeapPtr</em> class <a href="http://www.alax.info/trac/public/browser/trunk/Utilities/VirtualHeapPtr/VirtualHeapPtr.h#L155">is available on Trac</a> (lines 155-). The sanity pages create a block of inaccessible addresses which immediately cause access violation exception on either read of write access attempt. Under debugger, those are shows with question marks:</p>
<p><img class="alignnone size-full wp-image-1321" title="PAGE_NOACCESS Data" src="http://alax.info/blog/wp-content/uploads/2011/11/Image0011.png" alt="" width="673" height="288" /></p>
<p>The padding space is pre-initialized with hardcoded value 0&#215;77, and the space is checked for integrity at release of memory block call.</p>
<h4>Catching the Exceptions</h4>
<p>Having the exceptions generated on run-time, they immediately alter application execution code path and are easy to track and catch. There is no need to bring the feature rich debugger, such as Visual Studio to the production site in order to catch the exception and environment, instead a way simpler tool such as <a href="http://alax.info/blog/1248">LogProcessExceptions</a> would be able to create a minidump file and write the state of the application. The minidump can be transferred into debugger-enabled environment for detailed check.</p>
<p>Visual C++ .NET 2010 <a href="http://www.alax.info/trac/public/browser/trunk/Utilities/VirtualHeapPtr">source code</a> is available from SVN.</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/1319/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DirectShow Spy: Intelligent Connect Trace, Selective Process Black Listing</title>
		<link>http://alax.info/blog/1253</link>
		<comments>http://alax.info/blog/1253#comments</comments>
		<pubDate>Sun, 24 Jul 2011 18:55:47 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[Utilities]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[hook]]></category>
		<category><![CDATA[intelligent connect]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[spy]]></category>
		<category><![CDATA[trace]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=1253</guid>
		<description><![CDATA[<a href="http://alax.info/blog/1253" title="DirectShow Spy: Intelligent Connect Trace, Selective Process Black Listing"></a>DirectShow Spy is updated with a few new features: retroactive Intelligent Connect trace log output for IAMGraphBuilderCallback-related activity process name based black list to selectively exclude processes from spying Intelligent Connect Trace The utility received a capability to read back &#8230;<p class="read-more"><a href="http://alax.info/blog/1253">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/1253" title="DirectShow Spy: Intelligent Connect Trace, Selective Process Black Listing"></a><p>DirectShow Spy is updated with a few new features:</p>
<ul>
<li>retroactive Intelligent Connect trace</li>
<li>log output for IAMGraphBuilderCallback-related activity</li>
<li>process name based black list to selectively exclude processes from spying</li>
</ul>
<h4>Intelligent Connect Trace</h4>
<p>The utility received a capability to read back from its own log file (DirectShowSpy.log, located typically in C:\ProgramData directory) and reconstruct graph building sequence, including steps taken by DirectShow <a href="http://msdn.microsoft.com/en-us/library/dd390342%28VS.85%29.aspx">Intelligent Connect</a>.</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2011/07/Image0012.png"><img class="alignnone size-large wp-image-1254" title="Intelligent Connect Trace" src="http://alax.info/blog/wp-content/uploads/2011/07/Image0012-582x600.png" alt="" width="582" height="600" /></a></p>
<p>In order to activate the Intelligent Connect Trace property sheet, one needs to call exported function &#8220;<em>DoGraphBuilderCallbackPropertySheetModal</em>&#8220;, such as using <em>runndll32</em> tool:</p>
<p style="text-align: left; padding-left: 30px;">C:\DirectShowSpy&gt;rundll32 DirectShowSpy.dll,DoGraphBuilderCallbackPropertySheetModal</p>
<p style="text-align: left;">The upper part of the property page displays recently created DirectShow fitler graphs, newest to older. For a selected graph, the lower part displays events in chronological order. The events include:</p>
<ul>
<li>Adding a filter, at <a href="http://msdn.microsoft.com/en-us/library/dd390016%28VS.85%29.aspx">IFilterGraph2::AddFilter</a> method</li>
<li>Removing a filter, at <a href="http://msdn.microsoft.com/en-us/library/dd390022%28VS.85%29.aspx">IFilterGraph2::RemoveFilter</a> method</li>
<li>Selecting a filter, at Intelligent Connect&#8217;s callback at <a href="http://msdn.microsoft.com/en-us/library/dd389378%28VS.85%29.aspx">IAMGraphBuilderCallback::SelectedFilter</a></li>
<li>Creating a filter, at <a href="http://msdn.microsoft.com/en-us/library/dd389377%28VS.85%29.aspx">IAMGraphBuilderCallback::CreatedFilter</a></li>
</ul>
<p>The latter two methods also show &#8220;Application Result&#8221; column and values, which are HRESULT values returned by IAMGraphBuilderCallback callback provided by the application. Typically, a failure HRESULT code indicates that the application rejected the filter.</p>
<p>The trace log is good to expose all DirectShow junk installed in the system. For example,</p>
<p><span id="more-1253"></span><a href="http://alax.info/blog/wp-content/uploads/2011/07/Image0022.png"><img class="alignnone size-large wp-image-1255" title="Junk: ffdshowBC.ax" src="http://alax.info/blog/wp-content/uploads/2011/07/Image0022-800x496.png" alt="" width="620" height="384" /></a></p>
<p>In an attempt to build graph to decode FourCC &#8216;LXH4&#8242; video (which is a private alias for H.264 media type), Filter Graph Manager tried to apply &#8216;ffdshow Video Decoder&#8217; filter, which is unable to process the feed, but is registered at an extremely high merit and violating the guidelines.</p>
<p>The tool shows that the file hosting the filter is &#8220;<em>ffdshowBC.ax</em>&#8221; and shows its location. The application however appears to be aware of this piece of trash, and returned E_FAIL (0&#215;80004005) rejecting the filter.</p>
<p>How comes the garbage is hooking into place where it is not supposed to be, yet is sophisticated enough to reach such internals of operating system? This module is a clone/branch of well-known <a href="http://www.google.com/search?q=ffdshow">ffdshow</a> software, which by default registers itself with abnormally high merit &#8220;with good intentions in mind&#8221;. A short-sighted manufacturer of cheap stuff IP camera duplicated the project, changed the GUIDs, packaged the pathetic crap into ActiveX control cabinet and started distributing it over clean and virgin workstations around the globe.</p>
<p>Going further with the the trace being checked, there are more things to enjoy:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2011/07/Image0033.png"><img class="alignnone size-large wp-image-1256" title="Junk: MainConcept Showcase" src="http://alax.info/blog/wp-content/uploads/2011/07/Image0033-800x553.png" alt="" width="620" height="428" /></a></p>
<p>Trying to decode the same H.264 video feed, the Filter Graph Manager mounting three demultiplexers made  by MainConcept in a row, for MP4, MPEG and MXF containers. The utility immediately indicates that this trash contribution was brought by <a href="http://www.mainconcept.com/products/sdks/others/showcase.html">MainConcept Showcase</a> 8.7.0.28412. One might wanted to install it for a purpose, and it started killing other DirectShow software it shares workstation with.</p>
<p>The good news is that the method is friendly for production environment and only requires to register spy and collect log file. You don&#8217;t eve need to check the UI at the same computer, it is possible to transfer the log file into development environment and have spy read the log there.</p>
<p>The &#8220;Copy to Clipboard&#8221; link is a convenient option to transfer the findings into tab-separated values format, such as to paste into Microsoft Excel:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2011/07/Image0042.png"><img class="alignnone size-large wp-image-1257" title="Data Transfered to Microsoft Excel" src="http://alax.info/blog/wp-content/uploads/2011/07/Image0042-800x394.png" alt="" width="620" height="305" /></a></p>
<h4>Process Black Listing</h4>
<p>The utility received a capability to selectively not load into specific processes. DirectShowSpy is a developer tool and is not intended for production environment, nor it is guaranteed to be issue-free. So in case of specific conflict it is possible to exclude specific process from applying a spy using registry:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2011/07/Image0051.png"><img class="alignnone size-large wp-image-1258" title="Black List Registry" src="http://alax.info/blog/wp-content/uploads/2011/07/Image0051-800x424.png" alt="" width="620" height="328" /></a></p>
<p>The values are under <em>HKLM, SOFTWARE\[Wow6432Node\]Alax.Info\Utilities\DirectShowSpy</em> key, and there are three values defined:</p>
<ul>
<li>CFilterMapperSpy Black List &#8211; defines exclusion for filter mapper spying</li>
<li>CSpy Black List &#8211; defines exclusion for filter graph spy (effective for most applications)</li>
<li>CNoThreadSpy Black List &#8211; defines exclusion for filter graphs created with <a href="http://msdn.microsoft.com/en-us/library/dd375786%28VS.85%29.aspx">CLSID_FilterGraphNoThread</a></li>
</ul>
<p>The exclusion value is a comma-separated list of process names, exact case-insensitive match for executable file names without directory and extension.</p>
<p>It is recommended that filter mapper spy has at least as rich exclusion list as the filter graph spy entires (otherwise, it is possible that spy might raise unexpected exceptions).</p>
<p>Partial Visual C++ .NET 2008 source code is <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/FilterGraphSpy">available from SVN</a>, release binary included (<a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/FilterGraphSpy/Release%20Trace/Win32/DirectShowSpy.dll?format=raw">Win32</a>, <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/FilterGraphSpy/Release%20Trace/x64/DirectShowSpy.dll?format=raw">x64</a>); installation instructions are in <a href="../777">another post</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/1253/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DirectShow Spy: Memory Allocator Properties</title>
		<link>http://alax.info/blog/1168</link>
		<comments>http://alax.info/blog/1168#comments</comments>
		<pubDate>Sat, 05 Mar 2011 10:15:42 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[Utilities]]></category>
		<category><![CDATA[allocator]]></category>
		<category><![CDATA[buffer]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[hook]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[spy]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=1168</guid>
		<description><![CDATA[<a href="http://alax.info/blog/1168" title="DirectShow Spy: Memory Allocator Properties"></a>A small update to the DirectShow Spy today: DirectShow Filter Graph Spy prints memory allocator properties as a part of graph topology trace on transition to running state. Why is that and what it is for? Filters normally agree on &#8230;<p class="read-more"><a href="http://alax.info/blog/1168">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/1168" title="DirectShow Spy: Memory Allocator Properties"></a><p>A small update to the DirectShow Spy today: <a href="http://alax.info/blog/777">DirectShow Filter Graph Spy</a> prints memory allocator properties as a part of graph topology trace on transition to running state. Why is that and what it is for? Filters normally agree on allocator properties (<a href="http://msdn.microsoft.com/en-us/library/dd373419%28VS.85%29.aspx">ALLOCATOR_PROPERTIES</a>, obtained from <a href="http://msdn.microsoft.com/en-us/library/dd407061%28VS.85%29.aspx">IMemAllocator</a>, obtained from <a href="http://msdn.microsoft.com/en-us/library/dd407073%28VS.85%29.aspx">IMemInputPin</a>) themselves without interference from controlling application. Sometimes an undesired choice of buffers can cause sick runtime behavior, including but not limited to the following:</p>
<ol>
<li>live audio capture buffers are too long, and introduce significant latency, including from live video capture stream taking place in parallel; controlling application might need to take advantage of <a href="http://msdn.microsoft.com/en-us/library/dd389144%28VS.85%29.aspx">IAMBufferNegotiation::SuggestAllocatorProperties</a> and request shorter buffers.</li>
<li>a filter, such as for example DMO Wrapper Filter, may default to 1 buffer on allocator, which means that if a buffer reference is for some reason held for future reference (e.g. a video filter might be holding a reference to be able to re-push a video sample if an application is requesting video update), the entire streaming might lock.</li>
<li>some filters are requesting unreasonably many/large buffers and consume vast spaces of RAM, such as MainConcept MXF Demultiplexer requesting 200 buffers x 640 kilobytes each (128 MB in total out of sudden)</li>
<li>some filters are requesting unreasonably few/small buffers resulting in inability to pre-buffer data</li>
</ol>
<p>In a chase for answers to questions &#8220;Where is my memory?&#8221;, &#8220;Why is it so choppy?&#8221;, &#8220;I would really appreciate a nice lipsync&#8221; and to troubleshoot the mentioned scenarios it is helpful to understand buffering configuration. DirectShow Filter Spy is here to deliver this information. Once the graph is put into running state, spy prints out topology data into log file (which is in most cases C:\ProgramData\DirectShowSpy.log):</p>
<pre>Pin 2: Name "Input 01", Direction "Input", Peer "Tee 0x087A5AF0.Output2"
 Connection media type:
 majortype {73646976-0000-0010-8000-00AA00389B71}, subtype {31435641-0000-0010-8000-00AA00389B71}, pUnk 0x00000000
 bFixedSizeSamples 0, bTemporalCompression 0, lSampleSize 1
 formattype {E06D80E3-DB46-11CF-B4D1-00805F6CBBEA}, cbFormat 170, pbFormat 0x07c46fc0
pbFormat as MPEG2VIDEOINFO:
 rcSource { 0, 0, 0, 0 ), rcTarget { 0, 0, 0, 0 }
 dwBitRate 0, dwBitErrorRate 0, AvgTimePerFrame 0
 dwInterlaceFlags 0x0, dwCopyProtectFlags 0x0, dwPictAspectRatioX 16, dwPictAspectRatioY 9, dwControlFlags 0x0
 bmiHeader.biSize 40, bmiHeader.biWidth 1280, bmiHeader.biHeight 720, bmiHeader.biPlanes 1, bmiHeader.biBitCount 24, bmiHeader.biCompression avc1
 bmiHeader.biSizeImage 0, bmiHeader.biXPelsPerMeter 1, bmiHeader.biYPelsPerMeter 1, bmiHeader.biClrUsed 0, bmiHeader.biClrImportant 0
 dwStartTimeCode 0x00000000, cbSequenceHeader 38, dwProfile 100, dwLevel 31, dwFlags 0x4
 [0x0000] 00 1D 67 64 00 1F AC 24 88 05 00 5B BF F0 00 10
 [0x0010] 00 11 00 00 03 03 E8 00 00 E9 BA 0F 18 32 A0 00
 [0x0020] 05 68 EE 32 C8 B0
<strong><span style="text-decoration: underline;"> Memory Allocator: 1 buffers, 1,024 bytes each (1,024 bytes total), align 1, prefix 0</span></strong></pre>
<p>Partial Visual C++ .NET 2008 source code is <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/FilterGraphSpy">available  from SVN</a>, release binary included (<a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/FilterGraphSpy/Release%20Trace/Win32/DirectShowSpy.dll?format=raw">Win32</a>,  <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/FilterGraphSpy/Release%20Trace/x64/DirectShowSpy.dll?format=raw">x64</a>);  installation instructions are in <a href="http://alax.info/blog/777">another post</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/1168/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Sharing Memory Allocators while at the same time Handling Dynamic Media Type Changes</title>
		<link>http://alax.info/blog/981</link>
		<comments>http://alax.info/blog/981#comments</comments>
		<pubDate>Thu, 16 Jul 2009 06:09:57 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[Seriously]]></category>
		<category><![CDATA[allocation]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[IMemAllocator]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[sharing]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=981</guid>
		<description><![CDATA[<a href="http://alax.info/blog/981" title="Sharing Memory Allocators while at the same time Handling Dynamic Media Type Changes"></a>Sharing memory allocators between input and output pins is an important concept to keep performance of filter graph. Unlike more frequent scenario with different allocators, a filter (referred to as &#8220;middle filter&#8221; below) which has equal media types on input &#8230;<p class="read-more"><a href="http://alax.info/blog/981">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/981" title="Sharing Memory Allocators while at the same time Handling Dynamic Media Type Changes"></a><p>Sharing memory allocators between input and output pins is an important concept to keep performance of filter graph. Unlike more frequent scenario with different allocators, a filter (referred to as &#8220;middle filter&#8221; below) which has equal media types on input and output pins has an advantage to avoid memory-to-memory copy operation for every frame processed, by delivering downstream the buffer obtained from an upstream filter. With a high resolution video, at high rate, multiple streams running simultaneously this is the expense one would try to avoid for performance reasons.</p>
<p>Memory allocators are (or can be) shared by well known filters, such as <a href="http://msdn.microsoft.com/en-us/library/dd377544%28VS.85%29.aspx">Sample Grabber Filter</a>, <a href="http://msdn.microsoft.com/en-us/library/dd390336%28VS.85%29.aspx">Infinite Tee Pin Filter</a> and in-place transformation base filters (<a href="http://msdn.microsoft.com/en-us/library/dd388191%28VS.85%29.aspx">CTransInPlaceFilter Class</a>).</p>
<p>Still handling <a href="http://msdn.microsoft.com/en-us/library/dd388799%28VS.85%29.aspx">Dynamic Format Changes</a> (not only from video renderer filter) filters that share memory allocators may run into the problem of being notified of media type change. Because allocator are typically owned by another filter (e.g. <a href="http://msdn.microsoft.com/en-us/library/dd407343%28VS.85%29.aspx">Video Mixing Renderer Filter</a>) and originally its buffer is queried by an upstream filter, the upstream filter obtains allocated buffer independently from the middle filter that shares memory allocators. If the upstream filter decides to never deliver this buffer, however the buffer has a media type attached (see <a href="http://msdn.microsoft.com/en-us/library/dd373499%28VS.85%29.aspx">AM_SAMPLE2_PROPERTIES::pMediaType</a>), there is no way for the middle filter to learn about dynamic format change completed.</p>
<p>As a workaround for handling <a href="http://msdn.microsoft.com/en-us/library/dd388901%28VS.85%29.aspx">Format Changes from the Video Renderer</a>, when resolution is not changed and it is only stride which might be extended, middle filter might be checking data size in lActual field and learn about the change from an increase in this value.</p>
<p>To be reliably notified on media type change the middle filter is to take extra measures while sharing the allocator. Instead using raw allocator obtained from one pin on another pin (typically output pin&#8217;s allocator to be used on an input pin), middle filter may be using an internal proxy object, which implements <a href="http://msdn.microsoft.com/en-us/library/dd407061%28VS.85%29.aspx">IMemAllocator</a> interface and forward calls to internal IMemAllocator, obtained originally. Additionally to that, the proxy can check for attached media types on every buffer taken from the allocator, and once the change is noticed &#8211; at the moment upstream filter is requesting the buffer &#8211; the proxy has a timely chance to remember the new media type so that in the following <a href="http://msdn.microsoft.com/en-us/library/dd407077%28VS.85%29.aspx">IMemInputPin::Receive</a> call this media type can be checked for the case upstream buffer decided to not deliver the buffer with attached media type.</p>
<pre><span style="color: #800000; font-weight: bold;">if</span><span style="color: #808030;">(</span>IsSharingMemAllocators<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    <span style="color: #696969;">// ...</span>
    ATLASSERT<span style="color: #808030;">(</span><span style="color: #808030;">(</span>InputMediaSampleProperties<span style="color: #808030;">.</span>pMediaType <span style="color: #808030;">!</span><span style="color: #808030;">=</span> <span style="color: #7d0045;">NULL</span><span style="color: #808030;">)</span> <span style="color: #808030;">^</span> <span style="color: #808030;">!</span><span style="color: #808030;">(</span>InputMediaSampleProperties<span style="color: #808030;">.</span>dwSampleFlags <span style="color: #808030;">&amp;</span> AM_SAMPLE_TYPECHANGED<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800080;">{</span>
        CRoCriticalSectionLock DataLock<span style="color: #808030;">(</span>GetDataCriticalSection<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        <span style="color: #800000; font-weight: bold;">const</span> CObjectPtr<span style="color: #800080;">&lt;</span>CProxyMemAllocator<span style="color: #800080;">&gt;</span><span style="color: #808030;">&amp;</span> pInputProxyMemAllocator <span style="color: #808030;">=</span> m_pInputPin<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>GetProxyMemAllocatorReference<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        CMediaType pMediaType<span style="color: #800080;">;</span>
        <span style="color: #800000; font-weight: bold;">if</span><span style="color: #808030;">(</span>pInputProxyMemAllocator <span style="color: #808030;">&amp;</span><span style="color: #808030;">&amp;</span> pInputProxyMemAllocator<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>GetDynamicallyChangedMediaType<span style="color: #808030;">(</span>pMediaType<span style="color: #808030;">,</span> TRUE<span style="color: #808030;">)</span><span style="color: #808030;">)</span>
        <span style="color: #800080;">{</span>
            m_pInputPin<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>SetMediaType<span style="color: #808030;">(</span>pMediaType<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
            m_pOutputPin<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>SetMediaType<span style="color: #808030;">(</span>pMediaType<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
            <span style="color: #696969;">// ...</span>
        <span style="color: #800080;">}</span>
    <span style="color: #800080;">}</span>
    <span style="color: #800000; font-weight: bold;">if</span><span style="color: #808030;">(</span>InputMediaSampleProperties<span style="color: #808030;">.</span>pMediaType<span style="color: #808030;">)</span>
    <span style="color: #800080;">{</span>
        m_pInputPin<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>SetMediaType<span style="color: #808030;">(</span>InputMediaSampleProperties<span style="color: #808030;">.</span>pMediaType<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        m_pOutputPin<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>SetMediaType<span style="color: #808030;">(</span>InputMediaSampleProperties<span style="color: #808030;">.</span>pMediaType<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        <span style="color: #696969;">// ...</span>
    <span style="color: #800080;">}</span>
    DeliverMediaSample<span style="color: #808030;">(</span>pMemInputPin<span style="color: #808030;">,</span> pInputMediaSample<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span></pre>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/981/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ahead Nero&#8217;s NeResize DirectShow Filter</title>
		<link>http://alax.info/blog/967</link>
		<comments>http://alax.info/blog/967#comments</comments>
		<pubDate>Mon, 29 Jun 2009 22:34:26 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[Seriously]]></category>
		<category><![CDATA[access violation]]></category>
		<category><![CDATA[ahead]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[crap]]></category>
		<category><![CDATA[crash]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[debugger]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[NeResize]]></category>
		<category><![CDATA[nero]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=967</guid>
		<description><![CDATA[<a href="http://alax.info/blog/967" title="Ahead Nero&#039;s NeResize DirectShow Filter"></a>Another example of a negligence with a cost of incompatibility and enormous amount of support time. Ahead Nero installs a number of DirectShow filters into $(Program Files)\Common Files\Ahead\DSFilter directory. One of the files is NeResize.ax and it hosts a Nero &#8230;<p class="read-more"><a href="http://alax.info/blog/967">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/967" title="Ahead Nero&#039;s NeResize DirectShow Filter"></a><p>Another example of a negligence with a cost of incompatibility and enormous amount of support time. Ahead Nero installs a number of DirectShow filters into <em>$(Program Files)\Common Files\Ahead\DSFilter</em> directory. One of the files is <em>NeResize.ax</em> and it hosts a <em>Nero Resize</em> filter. Let us take a closer look:</p>
<p>CLSID: <strong>{30002E0C-C574-481E-A5DE-90AE54A79E10}</strong> (note that Nero 8 ships the same buggy stuff with new CLSID of <strong>{3D0A27C9-B4D6-487B-AFE4-E3CABD4B81F9}</strong><em> &#8211; 11.05.2010</em>)<br />
Merit: <strong>0&#215;00400000</strong> (<a href="http://msdn.microsoft.com/en-us/library/dd388793(VS.85).aspx">MERIT_UNLIKELY</a>)<br />
Input Pin&#8217;s Media Type: major type GUID_NULL, subtype GUID_NULL<br />
Output Pin&#8217;s Media Type: major type GUID_NULL, subtype GUID_NULL</p>
<p>The filter is clearly a video filter:</p>
<p><img class="alignnone size-full wp-image-969" title="Ahead Nero Resize Filter's Property Page" src="http://alax.info/blog/wp-content/uploads/2009/06/29-image001.png" alt="Ahead Nero Resize Filter's Property Page" width="376" height="292" /></p>
<p>So the filter register itself under a merit that allows taking it during <a href="http://msdn.microsoft.com/en-us/library/dd390342(VS.85).aspx">Intelligent Connect</a>, it registers using media type wildcard which is clearly widely than the filter can affectively operate with and the most interesting part is: with certain video media types the filter crashes (memory access violation) during pin connection negotiation process. That is, inaccurate filter <span style="text-decoration: underline;">may be crashing third party software it has nothing to deal with at all</span>.</p>
<pre>*** Unhandled Exception
Process: 0x000001d4, Thread: 0x00000ce4, Date: 6/29/2009, Time: 11:20:56 AM, Application: C:\Program Files\...
Module: C:\..., Product Version: 1.7.1.1, File Version: 1.7.1.20014, File Time: 23.06.2009, 19:02
Code: 0xc0000005, Flags: 0x00000000, Address: 0x05fc6c65
Parameters: 0x00000001, 0x15be9030

** Call Stack
NeResize!05fc6c65 DllUnregisterServer +21909 @05fc0000
NeResize!05fc7888 DllUnregisterServer +25016 @05fc0000
NeResize!05fc7204 DllUnregisterServer +23348 @05fc0000</pre>
<p>Additionally to that the filter does not allow its insertion in debugging environment, and it seems even with Visual Studio running without a debugging session active. Which means that developer may be unaware of issues until incompatibility comes up at a later stage such as testing, or at production site.</p>
<p>It is not the first Nero filter which is bringing real problems. Basically any user who want to keep his system far from issues while still having Nero installed, needs to do find <em>$(Program Files)\Common Files\Ahead\DSFilter</em> directory and immediately rename it to some <em>~DSFilter</em> in order to invalidate all Nero filters registration.</p>
<p>A few quotes from <a href="http://msdn.microsoft.com/en-us/library/dd388793(VS.85).aspx">Guidelines for Registering Filters</a>:</p>
<p style="padding-left: 30px;">Avoid specifying MEDIATYPE_None, MEDIASUBTYPE_None, or GUID_NULL in the <a id="ctl00_MTContentSelector1_mainContentContainer_ctl04" onclick="javascript:Track('ctl00_MTContentSelector1_mainContentContainer_ctl00|ctl00_MTContentSelector1_mainContentContainer_ctl04',this);" href="http://msdn.microsoft.com/en-us/library/dd373438%28VS.85%29.aspx"><strong>AMOVIESETUP_MEDIATYPE</strong></a> information for a pin. <strong>IFilterMapper2</strong> treats these as wildcards, which can slow the graph-building process.</p>
<p>Nero Resize does specify and obviously slows the system down.</p>
<p style="padding-left: 30px;">Choose the lowest merit value possible. Here are some guidelines:<br />
&#8230;<br />
Special purpose filter; any filter that is created directly by the application: MERIT_DO_NOT_USE</p>
<p>Nero Resize uses higher value and thus affects proper applications.</p>
<p>Software developers will be safer to prevent from <a href="http://msdn.microsoft.com/en-us/library/dd373399(VS.85).aspx">DirectShow Filter Graph Manager</a> considering the buggy filter to be used during <a href="http://msdn.microsoft.com/en-us/library/dd390342(VS.85).aspx">Intelligent Connect</a> by implementing <a href="http://msdn.microsoft.com/en-us/library/dd389376(VS.85).aspx">IAMGraphBuilderCallback</a> interface.</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/967/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

