<?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; ATL</title>
	<atom:link href="http://alax.info/blog/category/technology/atl/feed" rel="self" type="application/rss+xml" />
	<link>http://alax.info/blog</link>
	<description>Software Production Line</description>
	<lastBuildDate>Tue, 03 Aug 2010 09:48:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Attributed ATL: Accessing BLOB with ISequentialStream</title>
		<link>http://alax.info/blog/1136</link>
		<comments>http://alax.info/blog/1136#comments</comments>
		<pubDate>Sat, 10 Jul 2010 10:23:22 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Seriously]]></category>
		<category><![CDATA[blob]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[template]]></category>
		<category><![CDATA[visual studio]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=1136</guid>
		<description><![CDATA[Before attributed ATL was deprecated, it was a convenient way to access databases using attributed classes on top of OLEDB Consumer Templates. Does not it look nice?

[
    db_command("SELECT ServerData FROM Server WHERE Server = ?")
]
class CGetServerData
{
public:
    [ db_param(1) ] LONG m_nServer;
    [ db_column(1, length = "m_nDataLength") [...]]]></description>
			<content:encoded><![CDATA[<p>Before <a href="http://social.msdn.microsoft.com/Forums/en/vclanguage/thread/a74bcacf-e1e3-44c7-994d-3ebb8fe37973">attributed ATL was deprecated</a>, it was a convenient way to access databases using attributed classes on top of <a href="http://msdn.microsoft.com/en-us/library/fk4h509a.aspx">OLEDB Consumer Templates</a>. Does not it look nice?</p>
<pre>
<pre style="color: #000000; background: none repeat scroll 0% 0% #ffffff;"><span style="color: #808030;">[</span>
    db_command<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">SELECT ServerData FROM Server WHERE Server = ?</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span>
<span style="color: #808030;">]</span>
<span style="color: #800000; font-weight: bold;">class</span> CGetServerData
<span style="color: #800080;">{</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    <span style="color: #808030;">[</span> db_param<span style="color: #808030;">(</span><span style="color: #008c00;">1</span><span style="color: #808030;">)</span> <span style="color: #808030;">]</span> <span style="color: #603000;">LONG</span> m_nServer<span style="color: #800080;">;</span>
    <span style="color: #808030;">[</span> db_column<span style="color: #808030;">(</span><span style="color: #008c00;">1</span><span style="color: #808030;">,</span> length <span style="color: #808030;">=</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">m_nDataLength</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span> <span style="color: #808030;">]</span> ISequentialStream<span style="color: #808030;">*</span> m_pDataStream<span style="color: #800080;">;</span> DBLENGTH m_nDataLength<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span></pre>
</pre>
<p>It worked great with Visual Studio .NET 2003 and it failed to work with later releases. There are <a href="http://www.google.com/search?q=db_column+ISequentialStream">questions on internet about the problem</a>, but there few answers if any. As I recently had to convert a project from 2003 version of the compiler to Visual Studio 2008, the problem was finally to be resolved.</p>
<p><span id="more-1136"></span>The first problem, and an easier one was that you have to put attribute values in quotes. &#8216;Db_column(1, &#8230;&#8217; has to be &#8220;db_column(&#8221;1&#8243;, &#8230;&#8217; and besides going through code and making changes, it appeared that if earlier implementation managed to distinguish between ordinal column numbers and field names by checking provided argument to be a number or a string, with Visual Studio 2008 one has to provide strings at any time. If the string is a valid integer, the attribute processor will treat it as an ordinal number.</p>
<p>So if you want your code to be both compiled with 2003 and 2008 versions of Visual Studio, you have a puzzle now: you have to use quotes, but version 2003 will no longer treat the argument as ordinal number. Note that version 2003 will keep compiling the code and the problem will only come up on runtime. As eventually in the project of interest support for version 2003 will be dropped, I was not interested in this problem anymore.</p>
<p>The main problem is related to use of ISequentialStream pointer variable as a data field. Again, it worked great with Visual Studio .NET 2003, it no longer did with Visual Studio .NET 2005. First of all, you cannot use this data type anymore, as templates don&#8217;t provide an automatic mapper to OLE DB Type.  Instead of ISequentialStream you have to use IUnknown and QueryInterface the provided pointer before use.</p>
<p>This solves compilation problem, but still the code does not work on runtime. An attempt to bind to the column using such accessor results in DB_E_ERRORSOCCURRED (0&#215;80040E21) &#8220;Multiple-step OLE DB operation generated errors. Check each OLE DB status value, if available. No work was done.&#8221; A more thorough look gave DBBINDSTATUS_BADBINDINFO (3) for binding to the column of interest.</p>
<p>The cause of the problem is missing DBOBJECT object pointer in the corresponding DBBINDING::pObject field. Why? A general rule for troubleshooting this kind of problem is to enable expanding attributed source code to check what exactly is generated.</p>
<p>The problem is that unlike previous versions of Visual Studio, ATL attributed code provider is no longer generates correct OLEDB template map code for BLOB fields. And this results in incorrectly generated DBBINDING structure, inability to bind to column and as a final result in DB_E_ERRORSOCCURRED error code which does not give a sufficient clue on the root of the problem.</p>
<p>While the map needs a BLOB_* macro for the BLOB column (e.g. BLOB_ENTRY or <a href="http://msdn.microsoft.com/en-us/library/w3k8764c.aspx">BLOB_ENTRY_LENGTH</a>), the generated code uses _COLUMN_ENTRY_CODE instead. This causes missing (null) DBBINDING::pObject field in the binding structure:</p>
<pre>
<pre style="color: #000000; background: none repeat scroll 0% 0% #ffffff;">BEGIN_ACCESSOR_MAP<span style="color: #808030;">(</span>_CGetServerDataAccessor<span style="color: #808030;">,</span> <span style="color: #008c00;">1</span><span style="color: #808030;">)</span>
    BEGIN_ACCESSOR<span style="color: #808030;">(</span><span style="color: #008c00;">0</span><span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">true</span><span style="color: #808030;">)</span>
        <span style="color: #696969;">//_COLUMN_ENTRY_CODE(1, DBTYPE_IUNKNOWN, _SIZE_TYPE(m_pDataUnknown), 0, 0, offsetbuf(m_pDataUnknown), offsetbuf(m_nDataLength), 0)</span>
        BLOB_ENTRY_LENGTH<span style="color: #808030;">(</span><span style="color: #008c00;">1</span><span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">__uuidof</span><span style="color: #808030;">(</span>ISequentialStream<span style="color: #808030;">)</span><span style="color: #808030;">,</span> STGM_READ<span style="color: #808030;">,</span> m_pDataUnknown<span style="color: #808030;">,</span> m_nDataLength<span style="color: #808030;">)</span>
    END_ACCESSOR<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
END_ACCESSOR_MAP<span style="color: #808030;">(</span><span style="color: #808030;">)</span></pre>
</pre>
<p>So it appears that to fix the problem, an attributed class needs to be replaced with a non-attributed update. To ease the conversion one can expand attributed source and use it as a base for the non-attributed class.</p>
<p>And example of such correction/replacement is provided below for a reference.</p>
<pre>
<pre style="color: #000000; background: none repeat scroll 0% 0% #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">if</span><span style="color: #004a43;"> TRUE</span>
<span style="color: #800000; font-weight: bold;">class</span> _CGetServerDataAccessor
<span style="color: #800080;">{</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>

DEFINE_COMMAND_EX<span style="color: #808030;">(</span>_CGetServerDataAccessor<span style="color: #808030;">,</span> <span style="color: #800000;">L"</span><span style="color: #0000e6;">SELECT Data FROM Server WHERE Server = ?</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span>

BEGIN_PARAM_MAP<span style="color: #808030;">(</span>_CGetServerDataAccessor<span style="color: #808030;">)</span>
    SET_PARAM_TYPE<span style="color: #808030;">(</span>DBPARAMIO_INPUT<span style="color: #808030;">)</span>
    <span style="color: #696969;">//_COLUMN_ENTRY_CODE(1, _OLEDB_TYPE(m_nServer), _SIZE_TYPE(m_nServer), 0, 0, offsetbuf(m_nServer), 0, 0)</span>
    COLUMN_ENTRY<span style="color: #808030;">(</span><span style="color: #008c00;">1</span><span style="color: #808030;">,</span> m_nServer<span style="color: #808030;">)</span>
END_PARAM_MAP<span style="color: #808030;">(</span><span style="color: #808030;">)</span>

BEGIN_ACCESSOR_MAP<span style="color: #808030;">(</span>_CGetServerDataAccessor<span style="color: #808030;">,</span> <span style="color: #008c00;">1</span><span style="color: #808030;">)</span>
    BEGIN_ACCESSOR<span style="color: #808030;">(</span><span style="color: #008c00;">0</span><span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">true</span><span style="color: #808030;">)</span>
        <span style="color: #696969;">//_COLUMN_ENTRY_CODE(1, DBTYPE_IUNKNOWN, _SIZE_TYPE(m_pDataUnknown), 0, 0, offsetbuf(m_pDataUnknown), offsetbuf(m_nDataLength), 0)</span>
        BLOB_ENTRY_LENGTH<span style="color: #808030;">(</span><span style="color: #008c00;">1</span><span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">__uuidof</span><span style="color: #808030;">(</span>ISequentialStream<span style="color: #808030;">)</span><span style="color: #808030;">,</span> STGM_READ<span style="color: #808030;">,</span> m_pDataUnknown<span style="color: #808030;">,</span> m_nDataLength<span style="color: #808030;">)</span>
    END_ACCESSOR<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
END_ACCESSOR_MAP<span style="color: #808030;">(</span><span style="color: #808030;">)</span>

<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    <span style="color: #603000;">LONG</span> m_nServer<span style="color: #800080;">;</span>
    IUnknown<span style="color: #808030;">*</span> m_pDataUnknown<span style="color: #800080;">;</span>
    DBLENGTH m_nDataLength<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span>

<span style="color: #800000; font-weight: bold;">class</span> CGetServerData <span style="color: #800080;">:</span>
    <span style="color: #800000; font-weight: bold;">public</span> CCommand<span style="color: #800080;">&lt;</span>CAccessor<span style="color: #800080;">&lt;</span>_CGetServerDataAccessor<span style="color: #800080;">&gt;</span> <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;">// CGetServerData</span>
    HRESULT OpenRowset<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">const</span> CSession<span style="color: #808030;">&amp;</span> Session<span style="color: #808030;">,</span> <span style="color: #603000;">LPCWSTR</span> pszCommand <span style="color: #808030;">=</span> <span style="color: #7d0045;">NULL</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;">if</span><span style="color: #808030;">(</span><span style="color: #808030;">!</span>pszCommand<span style="color: #808030;">)</span>
            _V<span style="color: #808030;">(</span>_CGetServerDataAccessor<span style="color: #800080;">::</span>GetDefaultCommand<span style="color: #808030;">(</span><span style="color: #808030;">&amp;</span>pszCommand<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        <span style="color: #800000; font-weight: bold;">return</span> Open<span style="color: #808030;">(</span>Session<span style="color: #808030;">,</span> pszCommand<span style="color: #808030;">,</span> <span style="color: #7d0045;">NULL</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800080;">}</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">else</span>
<span style="color: #808030;">[</span>
    db_command<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">SELECT Data FROM Server WHERE Server = ?</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span>
<span style="color: #808030;">]</span>
<span style="color: #800000; font-weight: bold;">class</span> CGetServerData
<span style="color: #800080;">{</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    <span style="color: #808030;">[</span> db_param<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">1</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span> <span style="color: #808030;">]</span> <span style="color: #603000;">LONG</span> m_nServer<span style="color: #800080;">;</span>
    <span style="color: #808030;">[</span> db_column<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">1</span><span style="color: #800000;">"</span><span style="color: #808030;">,</span> length <span style="color: #808030;">=</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">m_nDataLength</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span> <span style="color: #808030;">]</span> IUnknown<span style="color: #808030;">*</span> m_pDataUnknown<span style="color: #800080;">;</span> DBLENGTH m_nDataLength<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">endif</span></pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/1136/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MediaTools: Two samples to capture M-JPEG video into JPEG files and to play JPEG files back</title>
		<link>http://alax.info/blog/1127</link>
		<comments>http://alax.info/blog/1127#comments</comments>
		<pubDate>Thu, 13 May 2010 06:15:48 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Media Tools]]></category>
		<category><![CDATA[Source]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[ip camera]]></category>
		<category><![CDATA[JPEG]]></category>
		<category><![CDATA[M-JPEG]]></category>
		<category><![CDATA[sample]]></category>
		<category><![CDATA[Video]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=1127</guid>
		<description><![CDATA[I added two new simple samples for the MediaTools DirectShow filters to demonstrate how to capture M-JPEG video feed, esp. from an IP camera, and write the video frames into sequence of JPEG files. The other sample takes a directory on the input and plays the images back as video. If you are working on [...]]]></description>
			<content:encoded><![CDATA[<p>I added two new simple samples for the MediaTools DirectShow filters to demonstrate how to capture M-JPEG video feed, esp. from an IP camera, and write the video frames into sequence of JPEG files. The other sample takes a directory on the input and plays the images back as video. If you are working on certain transformation filter, it is an easy way to make a reference feed and use it for debugging purposes.</p>
<p>The filters behind that empower the sample are described in <a href="http://alax.info/blog/741">another post</a>.</p>
<p><strong>RenderHttpMjpegVideoIntoFiles01</strong> sample takes an URL on the input to generate <a href="http://www.w3schools.com/media/media_mimeref.asp">image/jpeg JPEG</a> or <a href="http://en.wikipedia.org/wiki/Motion_JPEG">multipart/x-mixed-replace M-JPEG</a> stream. For example, it might be <a href="http://demo1.stardotcams.com/nph-mjpeg.cgi">http://demo1.stardotcams.com/nph-mjpeg.cgi</a> feed from a demo <a href="http://www.stardot.com/">StarDot Technologies</a> IP camera.</p>
<p>The application will create a new directory to write files into, and will save each new video frame received into new JPEG file.</p>
<pre>Z:\MediaTools\Samples\RenderHttpMjpegVideoIntoFiles01\Release&gt;RenderHttpMjpegVideoIntoFiles01.exe http://demo1.stardotcams.com/nph-mjpeg.cgi
URL: http://demo1.stardotcams.com/nph-mjpeg.cgi
Writing to directory: Z:\MediaTools\Samples\RenderHttpMjpegVideoIntoFiles01\Release\2010-05-12 22-07-37
Event: nCode EC_CLOCK_CHANGED 0xD, nParameter1 0x00000000, nParameter2 0x00000000
Event: nCode EC_PAUSED 0xE, nResult 0x00000000, nParameter2 0x00000000
[...]
^C</pre>
<p>The application will generate the files and convert media sample time stamps into file time.</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2010/05/13-Image001.png"><img class="alignnone size-medium wp-image-1128" title="RenderHttpMjpegVideoIntoFiles01 Sample Output" src="http://alax.info/blog/wp-content/uploads/2010/05/13-Image001-320x175.png" alt="RenderHttpMjpegVideoIntoFiles01 Sample Output" width="320" height="175" /></a></p>
<p>The DirectShow graph that implements the operation is the following:</p>
<p><img class="alignnone size-full wp-image-1129" title="RenderHttpMjpegVideoIntoFiles01 Filter Graph" src="http://alax.info/blog/wp-content/uploads/2010/05/13-Image002.png" alt="RenderHttpMjpegVideoIntoFiles01 Filter Graph" width="661" height="346" /></p>
<p>The other sample <strong>RenderJpegFiles01</strong> takes a directory path to look for JPEG files, e.g. generated by previous sample, and pushes them into DirectShow graph as a video feed. File times will be converted [back] to media sample times.</p>
<p><span id="more-1127"></span></p>
<pre>Z:\MediaTools\Samples\RenderJpegFiles01\Release&gt;RenderJpegFiles01 "Z:\MediaTools\Samples\RenderHttpMjpegVideoIntoFiles01\Release\2010-05-12 22-07-37"
Directory: Z:\MediaTools\Samples\RenderHttpMjpegVideoIntoFiles01\Release\2010-05-12 22-07-37
Event: nCode EC_CLOCK_CHANGED 0xD, nParameter1 0x00000000, nParameter2 0x00000000
Event: nCode EC_PAUSED 0xE, nResult 0x00000000, nParameter2 0x00000000
Event: nCode EC_VMR_RECONNECTION_FAILED 0x55, nResult 0x80004005, nParameter2 0x00000000
Event: nCode EC_VMR_RENDERDEVICE_SET 0x53, RendererDeviceType 0x2, nParameter2 0x00000000
Event: nCode EC_VIDEO_SIZE_CHANGED 0xA, Extent 384x240, nParameter2 0x00000000
Event: nCode EC_COMPLETE 0x1, nResult 0x00000000, nParameter2 0x00000000
Event: nCode EC_ERRORABORT 0x3, nResult 0x80004005, nParameter2 0x00000000
Detected resolution change, new resolution is 1024x768, recreating filter graph...
Event: nCode EC_VMR_RECONNECTION_FAILED 0x55, nResult 0x80004005, nParameter2 0x00000000
Event: nCode EC_VMR_RENDERDEVICE_SET 0x53, RendererDeviceType 0x2, nParameter2 0x00000000
Event: nCode EC_VIDEO_SIZE_CHANGED 0xA, Extent 384x240, nParameter2 0x00000000
Event: nCode EC_CLOCK_CHANGED 0xD, nParameter1 0x00000000, nParameter2 0x00000000
Event: nCode EC_PAUSED 0xE, nResult 0x00000000, nParameter2 0x00000000</pre>
<p><a href="http://alax.info/blog/wp-content/uploads/2010/05/13-Image003.png"><img class="alignnone size-medium wp-image-1130" title="RenderJpegFiles01 DirectShow Graph and Output" src="http://alax.info/blog/wp-content/uploads/2010/05/13-Image003-312x320.png" alt="RenderJpegFiles01 DirectShow Graph and Output" width="312" height="320" /></a></p>
<p>Download links:</p>
<ul>
<li>RenderHttpMjpegVideoIntoFiles01: <a href="http://www.assembla.com/code/roatl-utilities/subversion/nodes/trunk/MediaTools/Samples/RenderHttpMjpegVideoIntoFiles01">source code</a>, <a href="http://www.assembla.com/code/roatl-utilities/subversion/nodes/trunk/MediaTools/Samples/RenderHttpMjpegVideoIntoFiles01/Release/RenderHttpMjpegVideoIntoFiles01.exe?format=raw">binary</a></li>
<li>RenderJpegFiles01: <a href="http://www.assembla.com/code/roatl-utilities/subversion/nodes/trunk/MediaTools/Samples/RenderJpegFiles01">source code</a>, <a href="http://www.assembla.com/code/roatl-utilities/subversion/nodes/trunk/MediaTools/Samples/RenderJpegFiles01/Release/RenderJpegFiles01.exe?format=raw">binary</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/1127/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>DirectShow Filter Graph Spy: 64-bit version and hook API</title>
		<link>http://alax.info/blog/1094</link>
		<comments>http://alax.info/blog/1094#comments</comments>
		<pubDate>Sun, 01 Nov 2009 19:30:19 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[64-bit]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[hook]]></category>
		<category><![CDATA[spy]]></category>
		<category><![CDATA[x64]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=1094</guid>
		<description><![CDATA[Today&#8217;s update for DirectShow Filter Graph Spy introduces 64-bit version (mind the beta state) and a mini-API for an external module to be involved into graph building process.
Filter Graph Spy is offering three new interfaces that provide extensibility of the spy:

IFilterGraphAddRemoveHook
IFilterGraphConnectHook
IFilterGraphStateControlHook

The interfaces are contained in the type library and can be imported using #import directive. [...]]]></description>
			<content:encoded><![CDATA[<p>Today&#8217;s update for DirectShow Filter Graph Spy introduces 64-bit version (mind the beta state) and a mini-API for an external module to be involved into graph building process.</p>
<p>Filter Graph Spy is offering three new interfaces that provide extensibility of the spy:</p>
<ul>
<li>IFilterGraphAddRemoveHook</li>
<li>IFilterGraphConnectHook</li>
<li>IFilterGraphStateControlHook</li>
</ul>
<p>The interfaces are contained in the type library and can be imported using <a href="http://msdn.microsoft.com/en-us/library/8etzzkb6%28VS.71%29.aspx">#import</a> directive. An implementation of one or more of these interfaces will receive hook style calls corresponding to respective <a href="http://msdn.microsoft.com/en-us/library/dd375786%28VS.85%29.aspx">Filter Graph Manager</a> calls, system wide including in context of other applications.</p>
<p>A COM object may be registered as a hook object with <em>Spy</em> and <em>NoThreadSpy</em> COM classes under predefined registry keys:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2009/11/02-Image001.png"><img class="alignnone size-medium wp-image-1095" title="Registering a DirectShow Filter Graph Spy Hook" src="http://alax.info/blog/wp-content/uploads/2009/11/02-Image001-320x136.png" alt="Registering a DirectShow Filter Graph Spy Hook" width="320" height="136" /></a></p>
<p>Spy will instantiate the registered hook objects and forward them the calls it receive, before passing them to system Filter Graph Manager object. A hook object has an option to override default processing, including, for example, inserting its own filter in between. For example, <a href="http://msdn.microsoft.com/en-us/library/dd390021%28VS.85%29.aspx">IFilterGraph::Reconnect</a> call is implemented the following way:</p>
<pre>
<pre style="background: #ffffff none repeat scroll 0% 0%; color: #000000;">STDMETHOD<span style="color: #808030;">(</span>Reconnect<span style="color: #808030;">)</span><span style="color: #808030;">(</span>IPin<span style="color: #808030;">*</span> pPin<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>
    _Z4<span style="color: #808030;">(</span>atlTraceCOM<span style="color: #808030;">,</span> <span style="color: #008c00;">4</span><span style="color: #808030;">,</span> _T<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">...</span><span style="color: #0f69ff;">\n</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    HOOK_PROLOG<span style="color: #808030;">(</span>CFilterGraphConnectHookHost<span style="color: #808030;">)</span>
        OnReconnect<span style="color: #808030;">(</span>pT<span style="color: #808030;">,</span> pPin<span style="color: #808030;">,</span> <span style="color: #808030;">&amp;</span>bDefault<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    HOOK_EPILOG<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
    <span style="color: #800000; font-weight: bold;">return</span> m_pInnerFilterGraph2<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>Reconnect<span style="color: #808030;">(</span>pPin<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span></pre>
</pre>
<p>Before passing the call to original Reconnect method, spy is iterating through associated hooks, passing them <em>IFilterGraphConnectHook::OnReconnect</em> call. Setting <em>bDefault</em> parameter to <em>FALSE</em> will prevent spy from passing the call to original method.</p>
<p>Included <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/FilterGraphSpy/BdaHooks">BdaHooks</a> project shows a sample implementation of the hooking COM classes (note <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/FilterGraphSpy/BdaHooks/ConnectHook.rgs">.rgs registration</a>).</p>
<p>Filter Graph Spy is compatible with all current Windows operating systems, 32-bit and 64-bit (<a href="http://en.wikipedia.org/wiki/X86-64">x64</a>), in particular including:</p>
<ul>
<li><a href="http://www.microsoft.com/windows/windows-7/">Windows 7</a></li>
<li>Windows Server 2008</li>
<li>Windows Vista</li>
<li>Windows Server 2003</li>
<li>Windows XP</li>
<li>Windows 2000</li>
</ul>
<p>NOTE: DirectShow Filter Graph Spy is <span style="text-decoration: underline;">NOT</span> suitable for production environment, it is <span style="text-decoration: underline;">NOT</span> licensed to be redistributed to be a part of production state software item.</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="http://alax.info/blog/777">another post</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/1094/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to use windowless Video Mixing Renderer Filter to show video fullscreen</title>
		<link>http://alax.info/blog/1082</link>
		<comments>http://alax.info/blog/1082#comments</comments>
		<pubDate>Fri, 09 Oct 2009 17:04:27 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Source]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[WTL]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[fullscreen]]></category>
		<category><![CDATA[IVideoWidow]]></category>
		<category><![CDATA[IVMRWindowlessControl]]></category>
		<category><![CDATA[renderer]]></category>
		<category><![CDATA[sample]]></category>
		<category><![CDATA[VMR]]></category>
		<category><![CDATA[windowless]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=1082</guid>
		<description><![CDATA[The question is being asked from time to time. Everyone knows what is full screen video. Video renderers implement full screen capability since long ago through their IVideoWindow::put_FullScreenMode property, and even Filter Graph Manager exposes its own IVideoWindow interface to forward calls to filter&#8217;s implementation of IVideoWindow interface.
However, for Video Mixing Renderers, version 7 and [...]]]></description>
			<content:encoded><![CDATA[<p>The question is being asked from time to time. Everyone knows what is full screen video. Video renderers implement full screen capability since long ago through their <a href="http://msdn.microsoft.com/en-us/library/dd377320(VS.85).aspx">IVideoWindow::put_FullScreenMode</a> property, and even <a href="http://msdn.microsoft.com/en-us/library/dd375786(VS.85).aspx">Filter Graph Manager</a> exposes its own <a href="http://msdn.microsoft.com/en-us/library/dd377276%28VS.85%29.aspx">IVideoWindow</a> interface to forward calls to filter&#8217;s implementation of <a href="http://msdn.microsoft.com/en-us/library/dd377276%28VS.85%29.aspx">IVideoWindow</a> interface.</p>
<p>However, for Video Mixing Renderers, version <a href="http://msdn.microsoft.com/en-us/library/dd407343(VS.85).aspx">7</a> and <a href="http://msdn.microsoft.com/en-us/library/dd407344%28VS.85%29.aspx">9</a>, the preferred and recommended mode is windowless, where no IVideoWindow interface is available.</p>
<blockquote><p><strong>Note</strong> The <a id="ctl00_MTCS_main_ctl01" onclick="javascript:Track('ctl00_MTCS_main_ctl00|ctl00_MTCS_main_ctl01',this);" href="http://msdn.microsoft.com/en-us/library/dd390536%28VS.85%29.aspx"><strong>IVMRWindowlessControl</strong></a> or <a id="ctl00_MTCS_main_ctl02" onclick="javascript:Track('ctl00_MTCS_main_ctl00|ctl00_MTCS_main_ctl02',this);" href="http://msdn.microsoft.com/en-us/library/dd390537%28VS.85%29.aspx"><strong>IVMRWindowlessControl9</strong></a> interface is now preferred over <strong>IVideoWindow</strong>. For more information, see <a id="ctl00_MTCS_main_ctl03" onclick="javascript:Track('ctl00_MTCS_main_ctl00|ctl00_MTCS_main_ctl03',this);" href="http://msdn.microsoft.com/en-us/library/dd407299%28VS.85%29.aspx">Using Windowless Mode</a>.</p></blockquote>
<p>So in order to implement full screen mode it takes the application to attach Video Mixing Renderer filter to a private frameless window, to its entire client area and expand the window to entire monitor area.</p>
<p>The sample project <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/FullScreenWindowlessVmrSample01">FullScreenWindowlessVmrSample01</a> is illustrating this technique.</p>
<p><img class="alignnone size-full wp-image-1083" title="FullScreenWindowlessVmrSample01 Main Dialog" src="http://alax.info/blog/wp-content/uploads/2009/10/09-Image001.png" alt="FullScreenWindowlessVmrSample01 Main Dialog" width="489" height="141" /></p>
<p><span id="more-1082"></span>Main application dialog owns a special window to host renderer, implemented by CRendererDialog class.</p>
<pre>
<pre style="background: #ffffff none repeat scroll 0% 0%; color: #000000;"><span style="color: #800000; font-weight: bold;">class</span> CRendererDialog <span style="color: #800080;">:</span>
    <span style="color: #800000; font-weight: bold;">public</span> CDialogImpl<span style="color: #800080;">&lt;</span>CRendererDialog<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: #800000; font-weight: bold;">enum</span> <span style="color: #800080;">{</span> IDD <span style="color: #808030;">=</span> IDD_RENDERER <span style="color: #800080;">}</span><span style="color: #800080;">;</span>

BEGIN_MSG_MAP_EX<span style="color: #808030;">(</span>CRendererDialog<span style="color: #808030;">)</span>
    MSG_WM_INITDIALOG<span style="color: #808030;">(</span>OnInitDialog<span style="color: #808030;">)</span>
    MSG_WM_DESTROY<span style="color: #808030;">(</span>OnDestroy<span style="color: #808030;">)</span>
    MSG_WM_ERASEBKGND<span style="color: #808030;">(</span><span style="color: #400000;">OnEraseBkgnd</span><span style="color: #808030;">)</span>
    MSG_WM_PAINT<span style="color: #808030;">(</span>OnPaint<span style="color: #808030;">)</span>
    MSG_WM_DISPLAYCHANGE<span style="color: #808030;">(</span>OnDisplayChange<span style="color: #808030;">)</span>
    MSG_WM_KEYDOWN<span style="color: #808030;">(</span>OnKeyDown<span style="color: #808030;">)</span>
    COMMAND_ID_HANDLER_EX<span style="color: #808030;">(</span>IDCANCEL<span style="color: #808030;">,</span> OnCancel<span style="color: #808030;">)</span>
END_MSG_MAP<span style="color: #808030;">(</span><span style="color: #808030;">)</span>

<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    CMainDialog<span style="color: #808030;">&amp;</span> m_Owner<span style="color: #800080;">;</span>
<span style="color: #696969;">//...</span></pre>
</pre>
<p>The dialog template does not have a caption, it has no frame and has its window rectangle equal to client area. As a result, spanning the Video Mixing Renderer to the entire client area and proper positioning of the dialog window is showing video on the entire monitor.</p>
<pre>
<pre style="background: #ffffff none repeat scroll 0% 0%; color: #000000;">ATLVERIFY<span style="color: #808030;">(</span>m_RendererDialog<span style="color: #808030;">.</span>Create<span style="color: #808030;">(</span>m_hWnd<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLVERIFY<span style="color: #808030;">(</span>m_RendererDialog<span style="color: #808030;">.</span><span style="color: #400000;">MoveWindow</span><span style="color: #808030;">(</span>MonitorData<span style="color: #808030;">.</span>m_Position<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
m_RendererDialog<span style="color: #808030;">.</span><span style="color: #400000;">ShowWindow</span><span style="color: #808030;">(</span>SW_SHOWNORMAL<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #696969;">// ...</span>
ATLENSURE_SUCCEEDED<span style="color: #808030;">(</span>pVmrWindowlessControl<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>SetVideoClippingWindow<span style="color: #808030;">(</span>m_RendererDialog<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLENSURE_SUCCEEDED<span style="color: #808030;">(</span>pVmrWindowlessControl<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>SetVideoPosition<span style="color: #808030;">(</span><span style="color: #7d0045;">NULL</span><span style="color: #808030;">,</span> m_RendererDialog<span style="color: #808030;">.</span>GetVideoPosition<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span></pre>
</pre>
<p>Visual C++ .NET 2008 source code is <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/FullScreenWindowlessVmrSample01">available from SVN</a>, release binary <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/FullScreenWindowlessVmrSample01/Release/FullScreenWindowlessVmrSample01.exe?format=raw">included</a>. The project is using ATL and <a href="http://wtl.sourceforge.net/">WTL</a> libraries.</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/1082/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>How to overlay a bitmap on top of video with Video Mixing Renderer (VMR-9)</title>
		<link>http://alax.info/blog/1044</link>
		<comments>http://alax.info/blog/1044#comments</comments>
		<pubDate>Mon, 21 Sep 2009 17:01:25 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Source]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[overlay]]></category>
		<category><![CDATA[sample]]></category>
		<category><![CDATA[VMR]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=1044</guid>
		<description><![CDATA[A 100-lines code snippet which illustrates how a bitmap is overlaid over displayed video with Video Mixing Renderer 9 Filter using IVMRMixerBitmap9 interface. A video clip is played (default is Windows clock.avi, but you can replace it with your longer one to see overlay is really in a loop).
http://code.assembla.com/&#8230;/VmrMixerBitmapSample01/&#8230;
VMR9AlphaBitmap AlphaBitmap;
ZeroMemory(&#38;AlphaBitmap, sizeof AlphaBitmap);
AlphaBitmap.dwFlags = VMR9AlphaBitmap_hDC;
AlphaBitmap.hdc = [...]]]></description>
			<content:encoded><![CDATA[<p>A 100-lines code snippet which illustrates how a bitmap is overlaid over displayed video with <a href="http://msdn.microsoft.com/en-us/library/dd407344%28VS.85%29.aspx">Video Mixing Renderer 9 Filter</a> using <a href="http://msdn.microsoft.com/en-us/library/dd390449%28VS.85%29.aspx">IVMRMixerBitmap9</a> interface. A video clip is played (default is Windows clock.avi, but you can replace it with your longer one to see overlay is really in a loop).</p>
<p><a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/VmrMixerBitmapSample01/VmrMixerBitmapSample01.cpp#ln49">http://code.assembla.com/&#8230;/VmrMixerBitmapSample01/&#8230;</a></p>
<pre>VMR9AlphaBitmap AlphaBitmap<span style="color: #800080;">;</span>
<span style="color: #400000;">ZeroMemory</span><span style="color: #808030;">(</span><span style="color: #808030;">&amp;</span>AlphaBitmap<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">sizeof</span> AlphaBitmap<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
AlphaBitmap<span style="color: #808030;">.</span>dwFlags <span style="color: #808030;">=</span> VMR9AlphaBitmap_hDC<span style="color: #800080;">;</span>
AlphaBitmap<span style="color: #808030;">.</span>hdc <span style="color: #808030;">=</span> Dc<span style="color: #800080;">;</span>
AlphaBitmap<span style="color: #808030;">.</span>rSrc <span style="color: #808030;">=</span> <span style="color: #603000;">CRect</span><span style="color: #808030;">(</span><span style="color: #008c00;">0</span><span style="color: #808030;">,</span> <span style="color: #008c00;">0</span><span style="color: #808030;">,</span> <span style="color: #008c00;">32</span><span style="color: #808030;">,</span> <span style="color: #008c00;">32</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
AlphaBitmap<span style="color: #808030;">.</span>rDest<span style="color: #808030;">.</span>left <span style="color: #808030;">=</span> <span style="color: #808030;">(</span><span style="color: #603000;">FLOAT</span><span style="color: #808030;">)</span> <span style="color: #008000;">0.75</span><span style="color: #800080;">;</span>
AlphaBitmap<span style="color: #808030;">.</span>rDest<span style="color: #808030;">.</span>top <span style="color: #808030;">=</span> <span style="color: #808030;">(</span><span style="color: #603000;">FLOAT</span><span style="color: #808030;">)</span> <span style="color: #008000;">0.75</span><span style="color: #800080;">;</span>
AlphaBitmap<span style="color: #808030;">.</span>rDest<span style="color: #808030;">.</span>right <span style="color: #808030;">=</span> <span style="color: #808030;">(</span><span style="color: #603000;">FLOAT</span><span style="color: #808030;">)</span> <span style="color: #008000;">0.95</span><span style="color: #800080;">;</span>
AlphaBitmap<span style="color: #808030;">.</span>rDest<span style="color: #808030;">.</span>bottom <span style="color: #808030;">=</span> <span style="color: #808030;">(</span><span style="color: #603000;">FLOAT</span><span style="color: #808030;">)</span> <span style="color: #008000;">0.95</span><span style="color: #800080;">;</span>
AlphaBitmap<span style="color: #808030;">.</span>fAlpha <span style="color: #808030;">=</span> <span style="color: #008000;">0.75</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">const</span> HRESULT nSetAlphaBitmapResult <span style="color: #808030;">=</span> pVmrMixerBitmap<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>SetAlphaBitmap<span style="color: #808030;">(</span><span style="color: #808030;">&amp;</span>AlphaBitmap<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLENSURE_SUCCEEDED<span style="color: #808030;">(</span>nSetAlphaBitmapResult<span style="color: #808030;">)</span><span style="color: #800080;">;</span></pre>
<p>With a low FPS clip like clock.avi it is clear that the overlaid image is only updated with the next &#8220;main&#8221; video frame.</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2009/09/21-image002.png"><img class="alignnone size-medium wp-image-1045" title="IVMRMixerBitmap9 Usage Sample" src="http://alax.info/blog/wp-content/uploads/2009/09/21-image002-320x272.png" alt="IVMRMixerBitmap9 Usage Sample" width="320" height="272" /></a></p>
<p>Visual C++ .NET 2008 source code is <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/VmrMixerBitmapSample01/">available from SVN</a>, release binary <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/VmrMixerBitmapSample01/Release/VmrMixerBitmapSample01.exe?format=raw">included</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/1044/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IAMGraphBuilderCallback and Intelligent Connect tuning</title>
		<link>http://alax.info/blog/989</link>
		<comments>http://alax.info/blog/989#comments</comments>
		<pubDate>Thu, 23 Jul 2009 07:26:16 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[IAMGraphBuilderCallback]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=989</guid>
		<description><![CDATA[There was a question asked about how IAMGraphBuilderCallback interface is used to prevent from particular filter insertion during Intelligent Connect.
First of all, there is sample code at The March Hare&#8217;s website:
The IAMGraphBuilderCallback class can be used to  remove problematic dshow filters when building a graph with intelligent connect.   This sample does not provide [...]]]></description>
			<content:encoded><![CDATA[<p>There was a question asked about how <a href="http://msdn.microsoft.com/en-us/library/dd389376%28VS.85%29.aspx">IAMGraphBuilderCallback</a> interface is used to prevent from particular filter insertion during <a href="http://msdn.microsoft.com/en-us/library/dd390342%28VS.85%29.aspx">Intelligent Connect</a>.</p>
<p>First of all, there is sample code at <a href="http://tmhare.mvps.org/downloads.htm">The March Hare</a>&#8217;s website:</p>
<p style="padding-left: 30px;">The IAMGraphBuilderCallback class can be used to  remove problematic dshow filters when building a graph with intelligent connect.   This sample does not provide the UI to blacklist filters but will give you a  better head start than the information in the documentation.  See the  header file for an example of how to use it in your code.  Add your own  code to the SelectedFilter or CreatedFilter methods to remove any unwanted  filters.</p>
<p>The idea behind the method can be easily illustrated with a code snippet. Each time <a href="http://msdn.microsoft.com/en-us/library/dd375786%28VS.85%29.aspx">Filter Graph Manager</a> considers trying a filter, before its instantiation it calls (if provided) <a href="http://msdn.microsoft.com/en-us/library/dd389378(VS.85).aspx">IAMGraphBuilderCallback::SelectedFilter</a> method, where there is an option to reject it (before it even was instantiated using <a href="http://msdn.microsoft.com/en-us/library/ms686615%28VS.85%29.aspx">CoCreateInstance</a>).</p>
<p>The code snippet below checks selected filter and instructs to reject it if it is an <a href="http://sourceforge.net/projects/ffdshow/">FFDshow</a> Audio Decoder filter.</p>
<pre><span style="color: #696969;">// IAMGraphBuilderCallback</span>
STDMETHOD<span style="color: #808030;">(</span>SelectedFilter<span style="color: #808030;">)</span><span style="color: #808030;">(</span>IMoniker<span style="color: #808030;">*</span> pMoniker<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>
    ATLTRACE<span style="color: #808030;">(</span>atlTraceCOM<span style="color: #808030;">,</span> <span style="color: #008c00;">4</span><span style="color: #808030;">,</span> _T<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">...</span><span style="color: #0f69ff;">\n</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    _ATLTRY
    <span style="color: #800080;">{</span>
        ATLASSERT<span style="color: #808030;">(</span>pMoniker<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        <span style="color: #800000; font-weight: bold;">const</span> CStringW sMonikerDisplayName <span style="color: #808030;">=</span> _FilterGraphHelper<span style="color: #800080;">::</span>GetMonikerDisplayName<span style="color: #808030;">(</span>pMoniker<span style="color: #808030;">,</span> <span style="color: #7d0045;">NULL</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        ATLTRACE<span style="color: #808030;">(</span>atlTraceGeneral<span style="color: #808030;">,</span> <span style="color: #008c00;">4</span><span style="color: #808030;">,</span> _T<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">sMonikerDisplayName </span><span style="color: #0f69ff;">%ls</span><span style="color: #0f69ff;">\n</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #808030;">,</span> sMonikerDisplayName<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        <span style="color: #800000; font-weight: bold;">static</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">LPCTSTR</span> g_pszFfdshowAudioDecoderClassIdentifier <span style="color: #808030;">=</span> _T<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">{0F40E1E5-4F79-4988-B1A9-CC98794E6B55}</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        <span style="color: #800000; font-weight: bold;">if</span><span style="color: #808030;">(</span>sMonikerDisplayName<span style="color: #808030;">.</span>Find<span style="color: #808030;">(</span>CStringW<span style="color: #808030;">(</span>g_pszFfdshowAudioDecoderClassIdentifier<span style="color: #808030;">)</span><span style="color: #808030;">)</span> <span style="color: #808030;">&gt;</span><span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: #808030;">)</span>
            <span style="color: #800000; font-weight: bold;">return</span> E_FAIL<span style="color: #800080;">;</span> <span style="color: #696969;">// Die!</span>
    <span style="color: #800080;">}</span>
    _ATLCATCH<span style="color: #808030;">(</span>Exception<span style="color: #808030;">)</span>
    <span style="color: #800080;">{</span>
        <span style="color: #800000; font-weight: bold;">return</span> Exception<span style="color: #800080;">;</span>
    <span style="color: #800080;">}</span>
    <span style="color: #800000; font-weight: bold;">return</span> S_OK<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span></pre>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/989/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RegSetKeySecurity, CRegKey::SetKeySecurity and CSecurityDesc</title>
		<link>http://alax.info/blog/950</link>
		<comments>http://alax.info/blog/950#comments</comments>
		<pubDate>Mon, 22 Jun 2009 18:10:43 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Source]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[CRegKey]]></category>
		<category><![CDATA[CSecurityDesc]]></category>
		<category><![CDATA[registry]]></category>
		<category><![CDATA[RegSetKeySecurity]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[SetKeySecurity]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=950</guid>
		<description><![CDATA[One thing is worth special mentioning in connection with previous post on DirectShow Filter Graph Spy on Microsoft Vista system: ATL&#8217;s CSecurityDesc class caused to waste some time.
CRegKey Key;
ATLENSURE_SUCCEEDED(HRESULT_FROM_WIN32(Key.Open(HKEY_CLASSES_ROOT, pszKeyName, READ_CONTROL &#124; WRITE_OWNER)));
CSecurityDesc AdministratorsOwnerSecurityDescriptor;
AdministratorsOwnerSecurityDescriptor.SetOwner(Sids::Admins());
ATLENSURE_SUCCEEDED(HRESULT_FROM_WIN32(Key.SetKeySecurity(OWNER_SECURITY_INFORMATION, &#38;AdministratorsOwnerSecurityDescriptor)));
The code compiles fine, but on runtime it gives error 87 (ERROR_INVALID_PARAMETER, E_INVALIDARG) in the last line, returned from RegSetKeySecurity API [...]]]></description>
			<content:encoded><![CDATA[<p>One thing is worth special mentioning in connection with previous post on <a href="http://alax.info/blog/944">DirectShow Filter Graph Spy</a> on <a href="http://www.microsoft.com/windows/windows-vista/default.aspx">Microsoft Vista</a> system: ATL&#8217;s CSecurityDesc class caused to waste some time.</p>
<pre style="background: #ffffff none repeat scroll 0% 0%; color: #000000;">CRegKey Key<span style="color: #800080;">;</span>
ATLENSURE_SUCCEEDED<span style="color: #808030;">(</span>HRESULT_FROM_WIN32<span style="color: #808030;">(</span>Key<span style="color: #808030;">.</span>Open<span style="color: #808030;">(</span>HKEY_CLASSES_ROOT<span style="color: #808030;">,</span> pszKeyName<span style="color: #808030;">,</span> READ_CONTROL <span style="color: #808030;">|</span> WRITE_OWNER<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
CSecurityDesc AdministratorsOwnerSecurityDescriptor<span style="color: #800080;">;</span>
AdministratorsOwnerSecurityDescriptor<span style="color: #808030;">.</span>SetOwner<span style="color: #808030;">(</span>Sids<span style="color: #800080;">::</span>Admins<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLENSURE_SUCCEEDED<span style="color: #808030;">(</span>HRESULT_FROM_WIN32<span style="color: #808030;">(</span>Key<span style="color: #808030;">.</span>SetKeySecurity<span style="color: #808030;">(</span>OWNER_SECURITY_INFORMATION<span style="color: #808030;">,</span> <span style="color: #808030;">&amp;</span>AdministratorsOwnerSecurityDescriptor<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span></pre>
<p>The code compiles fine, but on runtime it gives error <em>87</em> (<em>ERROR_INVALID_PARAMETER</em>, <em>E_INVALIDARG</em>) in the last line, returned from <a href="http://msdn.microsoft.com/en-us/library/aa379314(VS.85).aspx">RegSetKeySecurity</a> API call. My first guess was that ATL&#8217;s <a href="http://msdn.microsoft.com/en-us/library/k0c0e5w6.aspx">CSecurityDesc</a> class for some reason prepared wrong descriptor which resulted in rejecting it as an argument. From the first glance it looks (not sure) that this class deals, to some extent, with structures itself rather than using API functions, so it could be that it results in something looking differently from expected by API calls.</p>
<p>Still the problem is in class itself and its cast from <em>CSecurityDesc&amp;</em> to required <em>SECURITY_DESCRIPTOR*</em> type. The class only implements operator to automatically cast to <em><span style="color: #ff0000;">const</span> SECURITY_DESCRIPTOR*</em> type, so the following line would not be passed by compiler:</p>
<pre style="background: #ffffff none repeat scroll 0% 0%; color: #000000;">Key<span style="color: #808030;">.</span>SetKeySecurity<span style="color: #808030;">(</span>OWNER_SECURITY_INFORMATION<span style="color: #808030;">,</span> AdministratorsOwnerSecurityDescriptor<span style="color: #808030;">)</span></pre>
<p>However <em><span style="color: #ff0000;">&amp;</span>AdministratorsOwnerSecurityDescriptor</em> is another level of indirection and hence <em>SECURITY_DESCRIPTOR*</em><span style="color: #ff0000;">*</span> type, which is passed by compiler, but results in indeed invalid argument.</p>
<p>So in order to correctly convert <em>CSecurityDesc&amp;</em> to <em>SECURITY_DESCRIPTOR*</em> it can be done this way:</p>
<pre style="background: #ffffff none repeat scroll 0% 0%; color: #000000;">CRegKey Key<span style="color: #800080;">;</span>
ATLENSURE_SUCCEEDED<span style="color: #808030;">(</span>HRESULT_FROM_WIN32<span style="color: #808030;">(</span>Key<span style="color: #808030;">.</span>Open<span style="color: #808030;">(</span>HKEY_CLASSES_ROOT<span style="color: #808030;">,</span> pszKeyName<span style="color: #808030;">,</span> READ_CONTROL <span style="color: #808030;">|</span> WRITE_OWNER<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
CSecurityDesc AdministratorsOwnerSecurityDescriptor<span style="color: #800080;">;</span>
AdministratorsOwnerSecurityDescriptor<span style="color: #808030;">.</span>SetOwner<span style="color: #808030;">(</span>Sids<span style="color: #800080;">::</span>Admins<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLENSURE_SUCCEEDED<span style="color: #808030;">(</span>HRESULT_FROM_WIN32<span style="color: #808030;">(</span>Key<span style="color: #808030;">.</span>SetKeySecurity<span style="color: #808030;">(</span>OWNER_SECURITY_INFORMATION<span style="color: #808030;">,</span> const_cast<span style="color: #808030;">&lt;</span><span style="color: #603000;">SECURITY_DESCRIPTOR</span><span style="color: #808030;">*</span><span style="color: #808030;">&gt;</span><span style="color: #808030;">(</span><span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">SECURITY_DESCRIPTOR</span><span style="color: #808030;">*</span><span style="color: #808030;">)</span> AdministratorsOwnerSecurityDescriptor<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span></pre>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/950/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hint on how to easily find your filter graph on running object table (ROT)</title>
		<link>http://alax.info/blog/930</link>
		<comments>http://alax.info/blog/930#comments</comments>
		<pubDate>Thu, 11 Jun 2009 13:14:21 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Utilities]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[graphedit]]></category>
		<category><![CDATA[graphstudio]]></category>
		<category><![CDATA[moniker]]></category>
		<category><![CDATA[rot]]></category>
		<category><![CDATA[spy]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=930</guid>
		<description><![CDATA[With a lot of DirectShow Filter Graphs published on Running Object Table, especially those automatically published by Filter Graph Spy utility, it might be a bit tricky to locate your graph of interest in the list.
Filter graphs are published with a textual moniker item name of predefined format, which is recognized by GraphEdit or GraphStudio, [...]]]></description>
			<content:encoded><![CDATA[<p>With a lot of <a href="http://msdn.microsoft.com/en-us/library/dd407188(VS.85).aspx">DirectShow Filter Graphs</a> published on <a href="http://msdn.microsoft.com/en-us/library/ms684004(VS.85).aspx">Running Object Table</a>, especially those automatically published by <a href="http://alax.info/blog/793">Filter Graph Spy utility</a>, it might be a bit tricky to locate your graph of interest in the list.</p>
<p>Filter graphs are published with a textual <a href="http://msdn.microsoft.com/en-us/library/ms680140(VS.85).aspx">moniker item name</a> of predefined format, which is recognized by <a href="http://msdn.microsoft.com/en-us/library/ms787460(VS.85).aspx">GraphEdit</a> or <a href="http://blog.monogram.sk/janos/tools/monogram-graphstudio/">GraphStudio</a>, or similar utilities as an item corresponding to a filter graph. A template for such a string is &#8220;<em>FilterGraph %08x pid %08x</em>&#8220;, which obviously only contains raw pointer address and process identifier, which only help a bit in looking up for proper graph interactively. However, it is important how exactly applications are recognizing filter graph related names. For example, GraphStudio <a href="http://dev.monogram.sk/websvn/listing.php?repname=graphstudio">does it</a> the following way:</p>
<pre>rot<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>EnumRunning<span style="color: #808030;">(</span><span style="color: #808030;">&amp;</span>emon<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
emon<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>Reset<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">while</span> <span style="color: #808030;">(</span>emon<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>Next<span style="color: #808030;">(</span><span style="color: #008c00;">1</span><span style="color: #808030;">,</span> <span style="color: #808030;">&amp;</span>moniker<span style="color: #808030;">,</span> <span style="color: #808030;">&amp;</span>f<span style="color: #808030;">)</span> <span style="color: #808030;">=</span><span style="color: #808030;">=</span> NOERROR<span style="color: #808030;">)</span> <span style="color: #800080;">{</span>

    <span style="color: #696969;">// is this a graph object ?</span>
    LPOLESTR    displayname<span style="color: #800080;">;</span>
    moniker<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>GetDisplayName<span style="color: #808030;">(</span>bindctx<span style="color: #808030;">,</span> <span style="color: #7d0045;">NULL</span><span style="color: #808030;">,</span> <span style="color: #808030;">&amp;</span>displayname<span style="color: #808030;">)</span><span style="color: #800080;">;</span>

    <span style="color: #603000;">CString</span>        name<span style="color: #808030;">(</span>displayname<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">if</span> <span style="color: #808030;">(</span>name<span style="color: #808030;">.</span>Find<span style="color: #808030;">(</span>_T<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">!FilterGraph</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span> <span style="color: #808030;">=</span><span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: #808030;">)</span> <span style="color: #800080;">{</span></pre>
<p>The items that match are then listed in GUI with an original string, which means that it is possible to provide an informational suffix to be able to locate the graph in a more convenient way, e.g. with a process image name, not only identifier (&#8221;; process: &#8230;&#8221; was appended to the item name):</p>
<p><img class="alignnone size-full wp-image-932" title="GraphStudio's ROT Items" src="http://alax.info/blog/wp-content/uploads/2009/06/11-image001.png" alt="GraphStudio's ROT Items" width="400" height="249" /></p>
<p>GraphEdit is using another method and is more strict in selecting among available items. AFAIR earlier versions did not allow custom suffixes in item names, however the latest version still picks the items up from the global list. However, GraphEdit does not show graph&#8217;s original item name, so suffixes are merely useless with GraphEdit.</p>
<p><img class="alignnone size-full wp-image-933" title="GraphEdit ROT Items" src="http://alax.info/blog/wp-content/uploads/2009/06/11-image002.png" alt="GraphEdit ROT Items" width="314" height="215" /></p>
<p><a href="http://alax.info/blog/793">Filter Graph Spy utility</a> was updated to automatically append process name suffix, which should be OK for both GrapEdit and GraphStudio. Still, the feature can be disabled through registry DWORD value named &#8220;<em>Enable ROT Moniker Item Name Suffix</em>&#8221; under <em>HKEY_LOCAL_MACHINE\SOFTWARE\Alax.Info\Utilities</em>. The value of zero, or missing, is the default behavior to enable suffixes. The value of 1 disables the feature, the value of 2 makes sure it is enabled.</p>
<pre><span style="color: #800000; font-weight: bold;">static</span> CConstIntegerRegistryValue g_nEnableRotMonikerItemNameSuffix<span style="color: #808030;">(</span>_T<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">Enable ROT Moniker Item Name Suffix</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span> <span style="color: #696969;">// 0 Default, 1 Disable, 2 Enable</span>
<span style="color: #800000; font-weight: bold;">if</span><span style="color: #808030;">(</span>g_nEnableRotMonikerItemNameSuffix <span style="color: #808030;">!</span><span style="color: #808030;">=</span> <span style="color: #008c00;">1</span><span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    <span style="color: #603000;">TCHAR</span> pszPath<span style="color: #808030;">[</span>MAX_PATH<span style="color: #808030;">]</span> <span style="color: #808030;">=</span> <span style="color: #800080;">{</span> <span style="color: #008c00;">0</span> <span style="color: #800080;">}</span><span style="color: #800080;">;</span>
    _W<span style="color: #808030;">(</span><span style="color: #400000;">GetModuleFileName</span><span style="color: #808030;">(</span><span style="color: #7d0045;">NULL</span><span style="color: #808030;">,</span> pszPath<span style="color: #808030;">,</span> DIM<span style="color: #808030;">(</span>pszPath<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #603000;">CString</span> sItemName <span style="color: #808030;">=</span> AtlFormatString<span style="color: #808030;">(</span>_T<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0f69ff;">%s</span><span style="color: #0000e6;">; process: </span><span style="color: #0f69ff;">%s</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #808030;">,</span> m_RunningFilterGraph<span style="color: #808030;">.</span>GetDefaultMonikerItemName<span style="color: #808030;">(</span>GetControllingUnknown<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #808030;">,</span> FindFileName<span style="color: #808030;">(</span>pszPath<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    m_RunningFilterGraph<span style="color: #808030;">.</span>SetFilterGraph<span style="color: #808030;">(</span>GetControllingUnknown<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">,</span> CStringW<span style="color: #808030;">(</span>sItemName<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span> <span style="color: #800000; font-weight: bold;">else</span>
    m_RunningFilterGraph<span style="color: #808030;">.</span>SetFilterGraph<span style="color: #808030;">(</span>GetControllingUnknown<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span></pre>
<p>A 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 <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/FilterGraphSpy/Release%20Trace/FilterGraphSpy.dll?format=raw">included</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/930/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>YV12, Extended Video Renderer Strides, Private DMO and more</title>
		<link>http://alax.info/blog/893</link>
		<comments>http://alax.info/blog/893#comments</comments>
		<pubDate>Wed, 01 Apr 2009 07:48:45 +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[bug]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[DMO]]></category>
		<category><![CDATA[stride]]></category>
		<category><![CDATA[VMR]]></category>
		<category><![CDATA[wrapper]]></category>
		<category><![CDATA[YV12]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=893</guid>
		<description><![CDATA[Recently it was the time to sort out an issue with a video DMO, which outputs YV12 video and in the same time is capable of supporting extended video strides in order to efficiently make a direct connection to Video Mixing Renderer Filters.
From past experience, I already knew that some bugs are definitely involved but [...]]]></description>
			<content:encoded><![CDATA[<p>Recently it was the time to sort out an issue with a video <a href="http://msdn.microsoft.com/en-us/library/dd375512(VS.85).aspx">DMO</a>, which outputs <a href="http://fourcc.org/yuv.php#YV12">YV12</a> video and in the same time is capable of supporting <a href="http://msdn.microsoft.com/en-us/library/dd388799(VS.85).aspx">extended video strides</a> in order to efficiently make a direct connection to <a href="http://msdn.microsoft.com/en-us/library/dd407343(VS.85).aspx">Video Mixing Renderer Filters</a>.</p>
<p>From past experience, I already knew that some bugs are definitely involved but their effect was yet unexplored. For a testbed application, I took good old <a href="http://alax.info/blog/551">FrameRateSample02</a> application, which generates multiple video feeds and routes it to video renderers:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2009/04/01-image001.png"><img class="alignnone size-full wp-image-894" title="FrameRateSample02 Application with New Choices" src="http://alax.info/blog/wp-content/uploads/2009/04/01-image001.png" alt="FrameRateSample02 Application with New Choices" width="539" height="317" /></a></p>
<p>With new source video choices the application is capable of constructing filter graphs that use a private DMO (that is hosted inside the executable) wrapped with <a href="http://msdn.microsoft.com/en-us/library/dd375519(VS.85).aspx">DMO Wrapper Filter</a>, with a graph topology shown below:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2009/04/01-image002.png"><img class="alignnone size-medium wp-image-895" title="Filter Graph with a Private DMO" src="http://alax.info/blog/wp-content/uploads/2009/04/01-image002-300x172.png" alt="Filter Graph with a Private DMO" width="300" height="172" /></a></p>
<p><span id="more-893"></span>The DMO does not do any processing, except support for extended strides while copying original data into buffer streamed to video renderer. Extended strides for a planar YUV format is a bit tricky. Are they supported at all? Yes, they are and video renderer might still request an extended stride and in which case origial MxN video needs to be copied into (M+P)xN buffer. Unlike packed pixel format, unused space is distributed in a bit different way but still very much similarly: output buffer is still a regular  (M+P)xN rectangle, where the effective picture of size MxN should be copied into top left corner.</p>
<p>The problem I was aware of from past experience showed up immediately once the filters connected. After a dynamic format change initiated by the VMR, the filters report different connection media types. <a href="http://msdn.microsoft.com/en-us/library/dd375519(VS.85).aspx">DMO Wrapper Filter</a> still shows original connection time connection media type, while <a href="http://msdn.microsoft.com/en-us/library/dd407343(VS.85).aspx">Video Mixing Renderer Filter</a> shows media type it switched to.</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2009/04/01-image003.png"><img class="alignnone size-medium wp-image-896" title="Media Type Mismatch" src="http://alax.info/blog/wp-content/uploads/2009/04/01-image003-300x241.png" alt="Media Type Mismatch" width="300" height="241" /></a></p>
<p>This looks like <a href="http://msdn.microsoft.com/en-us/library/dd375519(VS.85).aspx">DMO Wrapper Filter</a> bug, but was yet to check if it still handles the new media type properly and passes the format change to the underlying DMO object. Taking into consideration the extent DMOs are used by <a href="http://microsoft.com">Microsoft</a>, it had to, thought I never met this in the <a href="http://msdn.microsoft.com">MSDN</a> documentation.</p>
<p>Further debugging revealed that <a href="http://msdn.microsoft.com/en-us/library/dd375519(VS.85).aspx">DMO Wrapper Filter</a> does handle the media type change and forward it to the DMO through <a href="http://msdn.microsoft.com/en-us/library/dd406963(VS.85).aspx">IMediaObject::SetOutputType</a> method. This happens when DMO already received its first input, and immediately before following <a href="http://msdn.microsoft.com/en-us/library/dd406960(VS.85).aspx">IMediaObject::ProcessOutput</a> method call:</p>
<pre>rodmo.h(293) : CMediaObjectT&lt;class CVideoDmo&gt;::AllocateStreamingResources: ...
rodshow.h(2716) : CBaseFilterT&lt;class CMainDialog::CSourceFilter&gt;::Pause: ...
rodshow.h(2722) : CBaseFilterT&lt;class CMainDialog::CSourceFilter&gt;::Pause: m_State 0
rodshow.h(2730) : CBaseFilterT&lt;class CMainDialog::CSourceFilter&gt;::Pause: m_State 1
rodshow.h(2784) : CBaseFilterT&lt;class CMainDialog::CSourceFilter&gt;::GetState: nTimeout 0
rodmo.h(679) : CSimpleMediaObjectT&lt;class CVideoDmo,1&gt;::GetInputStatus: nInputStreamIndex 0
<span style="color: #ff0000;"><strong>rodmo.h(702) : CSimpleMediaObjectT&lt;class CVideoDmo,1&gt;::ProcessInput: nInputStreamIndex 0, nFlags 0x1
rodmo.h(527) : CSimpleMediaObjectT&lt;class CVideoDmo,1&gt;::SetOutputType: nOutputStreamIndex 0, nFlags 0x0</strong>
</span>rodmo.h(727) : CSimpleMediaObjectT&lt;class CVideoDmo,1&gt;::ProcessOutput: nFlags 0x1, nOutputBufferCount 1</pre>
<p>So, the media type change is handled and the problem is only limited to reporting wrong (original) media type off the wrapper filter output pin.</p>
<p>Investigation of filter connection however brought up another interesting fact, memory allocator properties:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2009/04/01-image004.png"><img class="alignnone size-medium wp-image-897" title="Memory Allocator Properties" src="http://alax.info/blog/wp-content/uploads/2009/04/01-image004-300x241.png" alt="Memory Allocator Properties" width="300" height="241" /></a></p>
<p>As the filters switched to a new media type, with extended strides, the memory allocator should obviously have been updated accordingly, in order to support larger buffer. However current <a href="http://msdn.microsoft.com/en-us/library/dd373419(VS.85).aspx">memory allocator properties</a> indicate old buffer size of 460,800 bytes, while new media type assumes 737,280 buffer size at the very least. The samples are however streamed fine, so the issue is also limited to incorrectly reported size.</p>
<p>This memory allocator is managed by the <a href="http://msdn.microsoft.com/en-us/library/dd407343(VS.85).aspx">Video Mixing Renderer Filter</a>, so the problem seems to be relating to it.</p>
<p>Good news however was that video was streamed and displayed correctly.</p>
<p>One thing that deserves special attention is making a DMO private. I <a href="http://alax.info/blog/674">already wrote another post on private DMOs</a> some time ago, and this time the sample shows even a better way in case one does not need the DMO available for <a href="http://msdn.microsoft.com/en-us/library/dd390342(VS.85).aspx">Intelligent Connect</a> (in which case <a href="http://msdn.microsoft.com/en-us/library/dd375491.aspx">DMORegister</a> call along with administrative privileges will be required),  just for a private instantiation. DMO is typically created by <a href="http://msdn.microsoft.com/en-us/library/ms686615.aspx">CoCreateInstance</a> from inside the <a href="http://msdn.microsoft.com/en-us/library/dd375519(VS.85).aspx">DMO Wrapper Filter</a>, e.g. using <a href="http://msdn.microsoft.com/en-us/library/dd406849(VS.85).aspx">IDMOWrapperFilter::Init</a> method, so it is necessary to either register COM class, or&#8230; just register its class object for the process using <a href="http://msdn.microsoft.com/en-us/library/ms693407.aspx">CoRegisterClassObject</a>.</p>
<p>There is no need for direct usage of API since ATL already wrapped the calls and we are to take advantage of what is already available. First of all, the DMO class requires certain CLSID, because we don&#8217;t have one typically declared in IDL. A good place for attaching CLSID is class declaration and <a href="http://msdn.microsoft.com/en-us/library/dabb5z75.aspx">__declspec keyword</a>:</p>
<pre><span style="color: #800000; font-weight: bold;">class</span> <span style="color: #800000; font-weight: bold;">__declspec</span><span style="color: #808030;">(</span>uuid<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">88B976BE-EEE6-45b1-A21B-42A941DF8819</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span> ATL_NO_VTABLE CVideoDmo <span style="color: #800080;">:</span>
    <span style="color: #800000; font-weight: bold;">public</span> CComObjectRootEx<span style="color: #800080;">&lt;</span>CComMultiThreadModelNoCS<span style="color: #800080;">&gt;</span><span style="color: #808030;">,</span>
    <span style="color: #800000; font-weight: bold;">public</span> CComCoClass<span style="color: #800080;">&lt;</span>CVideoDmo<span style="color: #800080;">&gt;</span><span style="color: #808030;">,</span>
    <span style="color: #800000; font-weight: bold;">public</span> CSimpleMediaObjectT<span style="color: #800080;">&lt;</span>CVideoDmo<span style="color: #808030;">,</span> <span style="color: #008c00;">1</span><span style="color: #800080;">&gt;</span>
<span style="color: #800080;">{</span></pre>
<p>Further a COM class is typically referenced into module&#8217;s object map byan <a href="http://msdn.microsoft.com/en-us/library/exx3wywe.aspx">OBJECT_ENTRY_AUTO</a> macro:</p>
<pre><span class="Comment"><span class="Comment">//</span>OBJECT_ENTRY_AUTO(__uuidof(VideoDmo), CVideoDmo</span>)</pre>
<p>But we don&#8217;t need this this time as we don&#8217;t need standard COM registration for the class. We will register its class object manually and temporarily, at the time of DMO initialization:</p>
<pre>CComQIPtr<span style="color: #800080;">&lt;</span>IBaseFilter<span style="color: #800080;">&gt;</span> pBaseFilter<span style="color: #800080;">;</span>
CVideoDmo<span style="color: #808030;">*</span> pVideoDmo<span style="color: #800080;">;</span>
<span style="color: #800080;">{</span>
    BEGIN_OBJECT_MAP<span style="color: #808030;">(</span>g_pObjectMap<span style="color: #808030;">)</span>
        OBJECT_ENTRY<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">__uuidof</span><span style="color: #808030;">(</span>CVideoDmo<span style="color: #808030;">)</span><span style="color: #808030;">,</span> CVideoDmo<span style="color: #808030;">)</span>
    END_OBJECT_MAP<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
    ATLASSERT<span style="color: #808030;">(</span>DIM<span style="color: #808030;">(</span>g_pObjectMap<span style="color: #808030;">)</span> <span style="color: #808030;">=</span><span style="color: #808030;">=</span> <span style="color: #008c00;">2</span> <span style="color: #808030;">&amp;</span><span style="color: #808030;">&amp;</span> <span style="color: #808030;">!</span>g_pObjectMap<span style="color: #808030;">[</span><span style="color: #008c00;">1</span><span style="color: #808030;">]</span><span style="color: #808030;">.</span>pclsid<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    ATLENSURE_SUCCEEDED<span style="color: #808030;">(</span>g_pObjectMap<span style="color: #808030;">[</span><span style="color: #008c00;">0</span><span style="color: #808030;">]</span><span style="color: #808030;">.</span>RegisterClassObject<span style="color: #808030;">(</span>CLSCTX_INPROC_SERVER<span style="color: #808030;">,</span> REGCLS_SINGLEUSE<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    _ATLTRY
    <span style="color: #800080;">{</span>
        CComPtr<span style="color: #800080;">&lt;</span>IDMOWrapperFilter<span style="color: #800080;">&gt;</span> pDmoWrapperFilter <span style="color: #808030;">=</span> ConstructDmoWrappedFilter<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">__uuidof</span><span style="color: #808030;">(</span>CVideoDmo<span style="color: #808030;">)</span><span style="color: #808030;">,</span> CVideoDmo<span style="color: #800080;">::</span>GetCategory<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        pBaseFilter <span style="color: #808030;">=</span> pDmoWrapperFilter<span style="color: #800080;">;</span>
        ATLENSURE_THROW<span style="color: #808030;">(</span>pBaseFilter<span style="color: #808030;">,</span> E_NOINTERFACE<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        CComQIPtr<span style="color: #800080;">&lt;</span>IMediaObject<span style="color: #800080;">&gt;</span> pMediaObject <span style="color: #808030;">=</span> pDmoWrapperFilter<span style="color: #800080;">;</span>
        ATLENSURE_THROW<span style="color: #808030;">(</span>pMediaObject<span style="color: #808030;">,</span> E_NOINTERFACE<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        pVideoDmo <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">static_cast</span><span style="color: #800080;">&lt;</span>CVideoDmo<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span><span style="color: #808030;">(</span><span style="color: #808030;">(</span>IMediaObject<span style="color: #808030;">*</span><span style="color: #808030;">)</span> pMediaObject<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800080;">}</span>
    _ATLCATCHALL<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
    <span style="color: #800080;">{</span>
        ATLVERIFY<span style="color: #808030;">(</span>SUCCEEDED<span style="color: #808030;">(</span>g_pObjectMap<span style="color: #808030;">[</span><span style="color: #008c00;">0</span><span style="color: #808030;">]</span><span style="color: #808030;">.</span>RevokeClassObject<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        _ATLRETHROW<span style="color: #800080;">;</span>
    <span style="color: #800080;">}</span>
    ATLVERIFY<span style="color: #808030;">(</span>SUCCEEDED<span style="color: #808030;">(</span>g_pObjectMap<span style="color: #808030;">[</span><span style="color: #008c00;">0</span><span style="color: #808030;">]</span><span style="color: #808030;">.</span>RevokeClassObject<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span>
pVideoDmo<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>Initialize<span style="color: #808030;">(</span>CDmoMediaType<span style="color: #808030;">(</span>m_pMediaType<span style="color: #808030;">)</span><span style="color: #808030;">,</span> CopyYv12MediaBuffer<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLENSURE_SUCCEEDED<span style="color: #808030;">(</span>pGraphBuilder<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>AddFilter<span style="color: #808030;">(</span>pBaseFilter<span style="color: #808030;">,</span> CStringW<span style="color: #808030;">(</span>_T<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">Pass-Through DMO</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLENSURE_SUCCEEDED<span style="color: #808030;">(</span>pGraphBuilder<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>Connect<span style="color: #808030;">(</span>pOutputPin<span style="color: #808030;">,</span> _FilterGraphHelper<span style="color: #800080;">::</span>GetFilterPin<span style="color: #808030;">(</span>pBaseFilter<span style="color: #808030;">,</span> PINDIR_INPUT<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
pOutputPin <span style="color: #808030;">=</span> _FilterGraphHelper<span style="color: #800080;">::</span>GetFilterPin<span style="color: #808030;">(</span>pBaseFilter<span style="color: #808030;">,</span> PINDIR_OUTPUT<span style="color: #808030;">)</span></pre>
<p>What is being done in the code snippet above is:</p>
<ul>
<li>local object map with a single <a href="http://msdn.microsoft.com/en-us/library/0f31291x.aspx">OBJECT_ENTRY</a> item to have ATL manage class object registration/revokation for us</li>
<li>registration of a private class/CLSID</li>
<li>instantiation and initialization of a <a href="http://msdn.microsoft.com/en-us/library/dd375519(VS.85).aspx">DMO Wrapper Filter</a> which is to pick up our class</li>
<li>cast back to native C++ pointer for easy further access (a private interface would be more accurate here)</li>
<li>revokation for CLSID</li>
</ul>
<p>For information, the interfaces queried from the DMO:</p>
<pre style="background: #ffffff none repeat scroll 0% 0%; color: #000000;">Find all <span style="color: #800000;">"</span><span style="color: #0000e6;">CVideoDmo::InternalQueryInterface</span><span style="color: #800000;">"</span><span style="color: #808030;">,</span> Hidden<span style="color: #808030;">,</span> Find Results <span style="color: #008c00;">1</span><span style="color: #808030;">,</span> Current Document
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IMediaObject<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x00000000</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IDMOQualityControl<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IDMOVideoOutputOptimizations<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IMediaObject<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x00000000</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IWMGetSecureChannel<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IAMOpenProgress<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IAMDeviceRemoval<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IDirectVobSub<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IDirectVobSub<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IWMCodecAMVideoAccelerator<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IDirectVobSub<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IWMCodecAMVideoAccelerator<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IWMCodecAMVideoAccelerator<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IMediaSeeking<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IMediaPosition<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IAMFilterMiscFlags<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IVideoWindow<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IBasicAudio<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IAMFilterMiscFlags<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IKsPropertySet<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IReferenceClock<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IWMCodecAMVideoAccelerator<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IAMDeviceRemoval<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
CVideoDmo<span style="color: #800080;">::</span>InternalQueryInterface<span style="color: #800080;">:</span> Interface IAMOpenProgress<span style="color: #808030;">,</span> Result <span style="color: #008000;">0x80004002</span>
Matching lines<span style="color: #800080;">:</span> <span style="color: #008c00;">24</span></pre>
<p>A Visual C++ .NET 2008 source code <a rel="nofollow" href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/FrameRateSample02">is available from SVN</a>. Additional files will be required to compile, but <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/FrameRateSample02/Release/FrameRateSample02.exe?format=raw">binary</a> is also incuded.</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/893/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>MediaTools: Tone Source Filter to generate reference audio feed, dual Audio Source Filter and Virtual Audio Capture Device</title>
		<link>http://alax.info/blog/859</link>
		<comments>http://alax.info/blog/859#comments</comments>
		<pubDate>Sat, 28 Feb 2009 09:40:19 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Audio]]></category>
		<category><![CDATA[Media Tools]]></category>
		<category><![CDATA[Source]]></category>
		<category><![CDATA[WTL]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[capture]]></category>
		<category><![CDATA[device]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[PCM]]></category>
		<category><![CDATA[tone]]></category>
		<category><![CDATA[virtual]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=859</guid>
		<description><![CDATA[In order to obtain a reference audio source and especially useful for debugging purposes, including:

audio input device unrelated to physical device, to avoid conditions when device is already in use by someone else
non-zero audio signal which is independent of certain speaker or broadcasting service, including one that makes capture, transmission or rendering issues easily perceptible [...]]]></description>
			<content:encoded><![CDATA[<p>In order to obtain a reference audio source and especially useful for debugging purposes, including:</p>
<ul>
<li>audio input device unrelated to physical device, to avoid conditions when device is already in use by someone else</li>
<li>non-zero audio signal which is independent of certain speaker or broadcasting service, including one that makes capture, transmission or rendering issues easily perceptible by human</li>
<li>configurable to provide different audio media types, including through well known DirectShow interfaces, such as <a href="http://msdn.microsoft.com/en-us/library/dd319784(VS.85).aspx">IAMStreamConfig</a></li>
<li>configurable to present in system as both regular <a href="http://msdn.microsoft.com/en-us/library/dd375464(VS.85).aspx">DirectShow Filter</a>, and as an <a href="http://msdn.microsoft.com/en-us/library/dd375655(VS.85).aspx">Audio Capture Source</a> which can be enumerated by applications</li>
<li>to be able to check how exactly other applications are accessing and configuring audio capture source</li>
</ul>
<p>I added a new filter to the Media Tools library, a Tone Source Filter. The filter generates <a href="http://en.wikipedia.org/wiki/Pulse-code_modulation">PCM Audio</a> data, either infinite sine waveform, or interrupted signal  of requested parameters:</p>
<p><img class="alignnone size-full wp-image-863" title="Tone Source Filter General Property Page" src="http://alax.info/blog/wp-content/uploads/2009/02/27-image011.png" alt="Tone Source Filter General Property Page" width="370" height="428" /></p>
<p>The filter accepts connection on <a href="http://en.wikipedia.org/wiki/Pulse-code_modulation">PCM</a> media types with flexible sampling rates in range 8 KHz through 200 KHz, 8-bit audio and 1 channel. Media type is also configurable through or, if not configured this way, the first enumerated media type off the Output pin is also configurable through property page and/or persistent setting accessible via private IDispatch derived interface property.</p>
<p><img class="alignnone size-full wp-image-864" title="Tone Source Filter Prefered Format Property Page" src="http://alax.info/blog/wp-content/uploads/2009/02/27-image012.png" alt="Tone Source Filter Prefered Format Property Page" width="370" height="427" /></p>
<p>Additionally, the filter may configured as a system-wide available <a href="http://msdn.microsoft.com/en-us/library/ms783347(VS.85).aspx">audio input device</a>, such as for example available to <a href="http://videolan.org">VLC Media Player</a> or <a href="http://sourceforge.net/projects/guliverkli/">Media Player Classic</a>:</p>
<p><img class="alignnone size-full wp-image-865" title="VLC Media Player's Option to use Tone Source Filter based device" src="http://alax.info/blog/wp-content/uploads/2009/02/27-image013.png" alt="VLC Media Player's Option to use Tone Source Filter based device" width="528" height="352" /></p>
<p>In order to configure the filter as such device, the library exports function <em>DoToneSourceFilterDevicePropertySheetModal</em>, which can be called using <em>rundll32</em> utility (<em>&#8220;rundll32 Acquisition.dll,DoToneSourceFilterDevicePropertySheetModal&#8221;</em> from command line):</p>
<p><img class="alignnone size-full wp-image-866" title="Devices Property Page" src="http://alax.info/blog/wp-content/uploads/2009/02/27-image014.png" alt="Devices Property Page" width="367" height="426" /></p>
<p>A partial Visual C++ .NET 2008 source code is <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/Extended7zShell">available from SVN</a>, release binary <a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/MediaTools/_Bin/Release%20Trace/Acquisition.dll?format=raw">included</a>.</p>
<h2>File and Class Summary</h2>
<h3>Acqusition.dll</h3>
<p>Acqusition.dll (<a href="http://code.assembla.com/roatl-utilities/subversion/nodes/trunk/MediaTools/_Bin/Release%20Trace/Acquisition.dll?format=raw">download</a>) hosts the following classes:</p>
<ul>
<li>DirectShow Filters
<ul>
<li><span style="text-decoration: underline;">Tone Source Filter</span>, to generate reference/debug audio data</li>
</ul>
</li>
</ul>
<h2>Class Overview</h2>
<h3>Tone Source Filter</h3>
<p>The filter generates uninterrupted or interrupted reference sine waveform in form of PCM audio data.</p>
<ul>
<li>Filter Executable: Acquisition.dll</li>
<li>Filter CLSID: __uuidof(ToneSourceFilter) {8002935A-B2EC-40ef-968C-E0358E5DED10}</li>
<li>Filter Property Page CLSID: __uuidof(ToneSourceFilterGeneralPropertyPage), {EBD8ABB2-6DD3-4c54-A7F1-9FE4DA283EDF}, ToneSourceFilterPreferedFormatPropertyPage, {EE224187-4FA3-4c3f-9D5D-492694CCFEB7}</li>
<li>Filter Merit: <a href="http://msdn.microsoft.com/en-us/library/ms787275%28VS.85%29.aspx">MERIT_DO_NOT_USE</a></li>
<li>Filter Category: <a href="http://msdn.microsoft.com/en-us/library/ms783347%28VS.85%29.aspx">CLSID_LegacyAmFilterCategory</a> (also configurable as <a href="http://msdn.microsoft.com/en-us/library/ms783347(VS.85).aspx">CLSID_AudioInputDeviceCategory</a>)</li>
<li>Filter Interfaces: <a href="http://msdn.microsoft.com/en-us/library/ms682273%28VS.85%29.aspx">IPersistStreamInit</a>, <a href="http://msdn.microsoft.com/en-us/library/ms690091%28VS.85%29.aspx">IPersistStream</a>, <a href="http://msdn.microsoft.com/en-us/library/ms695217%28VS.85%29.aspx">ISpecifyPropertyPages</a>, <a href="http://msdn.microsoft.com/en-us/library/aa768205(VS.85).aspx">IPersistPropertyBag</a>, <a href="http://msdn.microsoft.com/en-us/library/ms784601%28VS.85%29.aspx">IBaseFilter</a>, <a href="http://msdn.microsoft.com/en-us/library/ms785914%28VS.85%29.aspx">IMediaFilter</a>, <a href="http://msdn.microsoft.com/en-us/library/ms688695%28VS.85%29.aspx">IPersist</a>, <a href="http://msdn.microsoft.com/en-us/library/ms784083%28VS.85%29.aspx">IAMovieSetup</a>, <a href="http://msdn.microsoft.com/en-us/library/ms783950%28VS.85%29.aspx">IAMFilterMiscFlags</a>, IToneSourceFilter, <a href="http://msdn.microsoft.com/en-us/library/ms221608.aspx">IDispatch</a></li>
<li>Filter Pins: single ouput pin (Ouput)</li>
<li>Output Pin Media Types: MEDIATYPE_Audio/MEDIASUBTYPE_PCM</li>
<li>Output Pin Interfaces: <a href="http://msdn.microsoft.com/en-us/library/ms786565%28VS.85%29.aspx">IPin</a>, <a href="http://msdn.microsoft.com/en-us/library/ms786054%28VS.85%29.aspx">IMemInputPin</a>, <a href="http://msdn.microsoft.com/en-us/library/dd319764(VS.85).aspx">IAMPushSource</a>, <a href="http://msdn.microsoft.com/en-us/library/dd389383(VS.85).aspx">IAMLatency</a>, <a href="http://msdn.microsoft.com/en-us/library/dd389142(VS.85).aspx">IAMBufferNegotiation</a>, <a href="http://msdn.microsoft.com/en-us/library/bb174586(VS.85).aspx">IKsPropertySet</a>, <a href="http://msdn.microsoft.com/en-us/library/dd319784(VS.85).aspx">IAMStreamConfig</a></li>
</ul>
<h4>Remarks</h4>
<p>The hosting library (DLL) exposes <em>DoToneSourceFilterDevicePropertySheetModal</em> function which provides GUI to configure the filter as one or more audio capture source device, which can be enumerated by <a href="http://msdn.microsoft.com/en-us/library/dd407180(VS.85).aspx">System Device Enumerator</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/859/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
