<?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; renderer</title>
	<atom:link href="http://alax.info/blog/tag/renderer/feed" rel="self" type="application/rss+xml" />
	<link>http://alax.info/blog</link>
	<description>// Software Production Line</description>
	<lastBuildDate>Wed, 02 May 2012 15:42:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Oops, AMAP_3D_TARGET</title>
		<link>http://alax.info/blog/1335</link>
		<comments>http://alax.info/blog/1335#comments</comments>
		<pubDate>Mon, 13 Feb 2012 18:43:44 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[Seriously]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[3D]]></category>
		<category><![CDATA[DirectDraw]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[mixing]]></category>
		<category><![CDATA[renderer]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=1335</guid>
		<description><![CDATA[<a href="http://alax.info/blog/1335" title="Oops, AMAP_3D_TARGET"></a>Unfortunately, AMAP_3D_TARGET appears to be useless. Internally, surface allocation comes up with the following capabilities for the surface: DDSCAPS_VIDEOMEMORY &#124; DDSCAPS_LOCALVIDMEM &#124; DDSCAPS_OFFSCREENPLAIN &#124; DDSCAPS_3DDEVICE. Sadly, DirectDraw responds (might respond?) with E_NOTIMPL. While one can advance one step further by &#8230;<p class="read-more"><a href="http://alax.info/blog/1335">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/1335" title="Oops, AMAP_3D_TARGET"></a><p>Unfortunately, <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd407394%28v=vs.85%29.aspx">AMAP_3D_TARGET</a> appears to be useless. Internally, surface allocation comes up with the following capabilities for the surface: <strong>DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE</strong>. Sadly, DirectDraw responds (might respond?) with <strong>E_NOTIMPL</strong>.</p>
<p>While one can advance one step further by removing <strong>DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM</strong>, another problem is hit that you are no longer able to create a surface with is both FourCC enabled and in the same time has 3D rendering capabilities. Remove your YUV four character code (such as NV12, YV12, YUY2 you would normally have as codec&#8217;s output) or fail miserably with <strong>DDERR_INVALIDPIXELFORMAT</strong>.</p>
<p>Back to the original problem, the <strong>AMAP_3D_TARGET</strong> flag failing to work makes it impossible to allocate 3D-enabled DirectDraw surface with DirectShow <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd407343%28v=vs.85%29.aspx">Video Mixing Renderer</a>. While it might sound as deprecated technology, it is yet a supported Windows SDK component, the most efficient video rendering component, the least hardware sensitive video rendering component, and &#8211; the most immediately important &#8211; the only way an SDK I am working with can deliver its video overlay.</p>
<p>So, there is no easy way to request a 3D enabled surface through a custom allocator-presenter, with a hook in the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd390521%28v=vs.85%29.aspx">IVMRSurfaceAllocator::AllocateSurface</a> updating the allocation flags. It does not make much sense to replace the whole allocator-presenter either: while an earlier DirectShow/Windows SDK provides a decent base for custom allocator-presenter, it is going to eventually hit the same problems mentioned above. And you cannot blit from 3D surface into a plain offscreen surface either without getting <strong>E_FAIL</strong>.</p>
<p>What appears to still be possible is allocating an addition 3D enabled surface, such as within <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd390446%28v=vs.85%29.aspx">IVMRImagePresenter::StartPresenting</a> and using it as a replacement surface within <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd390445%28v=vs.85%29.aspx">IVMRImagePresenter::PresentImage</a>. Having a custom allocator-presenter receive video frame, you can blit the picture into 3D-enabled surface, do your thing and pass the updated <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd407392%28v=vs.85%29.aspx">VMRPRESENTATIONINFO</a> to default allocator-presenter so that it presents the additional update surface, not the original one.</p>
<p><span id="more-1335"></span></p>
<p><img class="alignnone size-full wp-image-1336" title="3D-enabled DirectDraw Surface with a Video Mixing Renderer through Custom Allocator-Presenter" src="http://alax.info/blog/wp-content/uploads/2012/02/Image001.png" alt="" width="576" height="423" /></p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/1335/feed</wfw:commentRss>
		<slash:comments>0</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[<a href="http://alax.info/blog/1082" title="How to use windowless Video Mixing Renderer Filter to show video fullscreen"></a>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 &#8230;<p class="read-more"><a href="http://alax.info/blog/1082">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/1082" title="How to use windowless Video Mixing Renderer Filter to show video fullscreen"></a><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>Multiple Windowless Video Mixing Renderers (VMR9) Sample</title>
		<link>http://alax.info/blog/711</link>
		<comments>http://alax.info/blog/711#comments</comments>
		<pubDate>Wed, 19 Nov 2008 11:05:12 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Source]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[renderer]]></category>
		<category><![CDATA[VMR]]></category>
		<category><![CDATA[windowless]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=711</guid>
		<description><![CDATA[<a href="http://alax.info/blog/711" title="Multiple Windowless Video Mixing Renderers (VMR9) Sample"></a>This is a begged MFC code for multiple windowless video renderers. MFC project, two independent video renderers hosted by the same parent window (actually through owned controls but this makes no major difference), VMR9 in windowless mode. There are no &#8230;<p class="read-more"><a href="http://alax.info/blog/711">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/711" title="Multiple Windowless Video Mixing Renderers (VMR9) Sample"></a><p>This is a <a href="http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=4129792&amp;SiteID=1">begged</a> MFC code for multiple windowless video renderers. MFC project, two independent video renderers hosted by the same parent window (actually through owned controls but this makes no major difference), VMR9 in windowless mode.</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/11/19-image001.png"><img class="alignnone size-medium wp-image-712" title="MFC Windowless Video Renderer" src="http://alax.info/blog/wp-content/uploads/2008/11/19-image001-300x218.png" alt="" width="300" height="218" /></a></p>
<p>There are no <a href="http://msdn.microsoft.com/en-us/library/ms534901(VS.85).aspx">WM_PAINT</a>/<a href="http://msdn.microsoft.com/en-us/library/ms648055(VS.85).aspx">WM_ERASEBKGND</a> handlers, <a href="http://msdn.microsoft.com/en-us/library/ms787156(VS.85).aspx">IVMRWindowlessControl9::RepaintVideo</a> calls and other basically required code, instead a minimalistic snippet to make video rendered the requested way.</p>
<p>A Visual C++ .NET 2008 source code <a href="http://trac2.assembla.com/roatl-utilities/browser/trunk/MfcWindowlessVideoRenderer01">is available from SVN</a>, release binary <a href="http://trac2.assembla.com/roatl-utilities/browser/trunk/MfcWindowlessVideoRenderer01/Release/MfcWindowlessVideoRenderer01.exe?format=raw">included</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/711/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How To: Take care of DirectShow filters that impose unreasonable requirements</title>
		<link>http://alax.info/blog/614</link>
		<comments>http://alax.info/blog/614#comments</comments>
		<pubDate>Wed, 27 Aug 2008 17:59:28 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[renderer]]></category>
		<category><![CDATA[Source]]></category>
		<category><![CDATA[workaround]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=614</guid>
		<description><![CDATA[<a href="http://alax.info/blog/614" title="How To: Take care of DirectShow filters that impose unreasonable requirements"></a>Although I personally have no experience with tricky DirectShow filters that decide on possibility of connection not only looking at media type and other capabilities, there has been a number of cases mentioned that certain video decoders will only connect &#8230;<p class="read-more"><a href="http://alax.info/blog/614">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/614" title="How To: Take care of DirectShow filters that impose unreasonable requirements"></a><p>Although I personally have no experience with tricky <a href="http://msdn.microsoft.com/en-us/library/ms783323(VS.85).aspx">DirectShow</a> <a href="http://msdn.microsoft.com/en-us/library/ms783348.aspx">filters</a> that decide on possibility of connection not only looking at media type and other capabilities, there has been a number of cases mentioned that certain video decoders will only connect to renderers or video renderers in order to avoid interception of decoded data.</p>
<p>It was recently mentioned that one of such filters checked <a href="http://msdn.microsoft.com/en-us/library/ms779020(VS.85).aspx">Misc Flags</a> obtained through <a href="http://msdn.microsoft.com/en-us/library/ms783950(VS.85).aspx">IAMFilterMiscFlags</a> interface to make sure it is connected to renderer downstream. Before we proceed, let us make it clear that it is silly and can only protect from beginner, a complete newbie. At the very least it should have checked peer filter&#8217;s CLSID and compare against white list of stock video renderer: <a href="http://msdn.microsoft.com/en-us/library/ms787925(VS.85).aspx">Video Renderer</a>, <a href="http://msdn.microsoft.com/en-us/library/ms787917(VS.85).aspx">Video Mixing Rendeder 7</a>, <a href="http://msdn.microsoft.com/en-us/library/ms787918(VS.85).aspx">Video Mixing Rendeder 9</a>, <a href="http://msdn.microsoft.com/en-us/library/ms694916(VS.85).aspx">Enhanced Video Renderer</a>. A custom video renderer or even just a transformation filter with a renderer flag would be able to receive decoded data and make it available for any further processing.</p>
<p>What I am going to do is to take <a href="http://msdn.microsoft.com/en-us/library/ms787594(VS.85).aspx">Sample Grabber Filter</a> as a base and make a new filter from it which will only connect to renderer (it will check the flags as described above). Then another filter, which will also use <a href="http://msdn.microsoft.com/en-us/library/ms787594(VS.85).aspx">Sample Grabber Filter</a> base, will accurately fool the first one and connect to output of the first filter and will render video to complete the graph.</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/08/27-image001.png"><img class="alignnone size-medium wp-image-615" title="New Filters" src="http://alax.info/blog/wp-content/uploads/2008/08/27-image001-253x300.png" alt="" width="253" height="300" /></a></p>
<p><span id="more-614"></span></p>
<p>Both new filters will use COM aggregation to reuse existing implementation of <a href="http://msdn.microsoft.com/en-us/library/ms787594(VS.85).aspx">Sample Grabber Filter</a>, refer to <a href="http://alax.info/blog/511">DirectShow Fitler through COM Aggregation</a> post for details. For a brief explanation, new filter aggregates another COM object and exposes all its interfaces except main IUnknown (as required by aggregation), <a href="http://msdn.microsoft.com/en-us/library/ms883820.aspx">IPersist</a>/<a href="http://msdn.microsoft.com/en-us/library/ms785914(VS.85).aspx">IMediaFilter</a>/<a href="http://msdn.microsoft.com/en-us/library/ms784601(VS.85).aspx">IBaseFilter</a> in order to override CLSID and flag check, and additionally the second filter will implement its own <a href="http://msdn.microsoft.com/en-us/library/ms783950(VS.85).aspx">IAMFilterMiscFlags</a> interface natively. The filter classes register themselves using <a href="http://msdn.microsoft.com/en-us/library/ms787861(VS.85).aspx">Filter Mapper</a>&#8216;s <a href="http://msdn.microsoft.com/en-us/library/ms785742(VS.85).aspx">IFilterMapper2::RegisterFilter</a> as a part of regular COM registration.</p>
<p>The first filter class <strong>CImpudence</strong> is going to check the downstream connection. Because we are basing on an initialized sample grabber, the filter will accept any connection and pass media sample further downstream without any modification. It makes no principal difference where to check the connection at, but for simplicity and code brevity, since we are already implementing <a href="http://msdn.microsoft.com/en-us/library/ms784601(VS.85).aspx">IBaseFilter</a>, we will do the check inside <a href="http://msdn.microsoft.com/en-us/library/ms784601(VS.85).aspx">IBaseFilter</a><a href="http://msdn.microsoft.com/en-us/library/ms785915(VS.85).aspx">::Pause</a> call and in case of unsatisfactory connection on the output the filter would return an error code, let it be <a href="http://msdn.microsoft.com/en-us/library/ms783645(VS.85).aspx">VFW_E_CERTIFICATION_FAILURE</a> to make sure we see the message in <a href="http://msdn.microsoft.com/en-us/library/ms787460(VS.85).aspx">GraphEdit</a> coming right from our code. So the method is:</p>
<pre>STDMETHOD(Pause)() throw()
{
	ATLTRACE2(atlTraceCOM, 4, _T("...\n"));
	_ATLTRY
	{
		FILTER_STATE State;
		ATLENSURE_SUCCEEDED(GetState(0, &amp;State));
		if(State == State_Stopped)
		{
			CComPtr&lt;IPin&gt; pOutputPin = _FilterGraphHelper::GetFilterPin(this, PINDIR_OUTPUT);
			ATLENSURE_THROW(pOutputPin, E_NOINTERFACE);
			CComPtr&lt;IPin&gt; pOutputPeerPin = _FilterGraphHelper::GetPeerPin(pOutputPin);
			ATLENSURE_THROW(pOutputPeerPin, E_NOINTERFACE);
			CComPtr&lt;IBaseFilter&gt; pPeerBaseFilter = _FilterGraphHelper::GetPinFilter(pOutputPeerPin);
			ATLASSERT(pPeerBaseFilter);
			{
				CComQIPtr&lt;IAMFilterMiscFlags&gt; pAmFilterMiscFlags = pPeerBaseFilter;
				ATLENSURE_THROW(pAmFilterMiscFlags, VFW_E_CERTIFICATION_FAILURE);
				const ULONG nFlags = pAmFilterMiscFlags-&gt;GetMiscFlags();
				ATLTRACE2(atlTraceGeneral, 2, _T("nFlags 0x%x\n"), nFlags);
				ATLENSURE_THROW(nFlags &amp; AM_FILTER_MISC_FLAGS_IS_RENDERER, VFW_E_CERTIFICATION_FAILURE);
			}
		}
	}
	_ATLCATCH(Exception)
	{
		_ATLTRY
		{
			CComQIPtr&lt;IMediaEventSink&gt; pMediaEventSink = GetFilterGraph(this);
			if(pMediaEventSink)
				ATLVERIFY(SUCCEEDED(pMediaEventSink-&gt;Notify(EC_ERRORABORT, (HRESULT) Exception, 0)));
		}
		_ATLCATCHALL()
		{
			// TODO: Trace exception
		}
		return Exception;
	}
	return m_pInnerBaseFilter-&gt;Pause();
}</pre>
<p>Briefly, if the fitler is stopped and is going to be paused we are checking connected pin&#8217;s filter on our filter output, query its <a href="http://msdn.microsoft.com/en-us/library/ms783950(VS.85).aspx">IAMFilterMiscFlags</a>, if it&#8217;s absent we are not going to work, if the flags have no <a href="http://msdn.microsoft.com/en-us/library/ms779020(VS.85).aspx">AM_FILTER_MISC_FLAGS_IS_RENDERER</a> we are not going to work and return the error code. Additionally, error code is sent through <a href="http://msdn.microsoft.com/en-us/library/ms785910(VS.85).aspx">IMediaEventSink::Notify</a> so that the graph could stop.</p>
<p>Expectedly, if the filter is connected to something which is not a renderer, e.g. <a href="http://msdn.microsoft.com/en-us/library/ms781972(VS.85).aspx">Color Space Converter Filter</a>, it fails to run:</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/08/27-image002.png"><img class="alignnone size-medium wp-image-616" title="CImpudence won\'t run with not a Renderer" src="http://alax.info/blog/wp-content/uploads/2008/08/27-image002-300x125.png" alt="" width="300" height="125" /></a></p>
<p>The checking filter, which is an imitation of the real life decoder requiring connections to renderer only, is ready and I am getting down to the second part, the non-renderer filter which will still connect and receive the media samples.</p>
<p>The goal is to show <a href="http://msdn.microsoft.com/en-us/library/ms779020(VS.85).aspx">AM_FILTER_MISC_FLAGS_IS_RENDERER</a> flag to upstream filter only and show proper zero flags to the rest of the graph. This approach ensures proper graph operation and will also do the thing if we implemented CLSID comparison (as mentioned in the top of the post) showing wrong CLSID to the upstream filter and correct CLSID to the graph to allow load/save and other <a href="http://msdn.microsoft.com/en-us/library/ms690091(VS.85).aspx">IPersistStream</a>-based operations.</p>
<p>The second filter <strong>CFix</strong> is also using <a href="http://msdn.microsoft.com/en-us/library/ms787594(VS.85).aspx">Sample Grabber Filter</a> as a base and embeds it through COM aggregation. What is additionally required to the embedded implementation here is to add <a href="http://msdn.microsoft.com/en-us/library/ms783950(VS.85).aspx">IAMFilterMiscFlags</a> interface and implement <a href="http://msdn.microsoft.com/en-us/library/ms783949(VS.85).aspx">GetMiscFlags</a> method to return the flags.</p>
<p>Inside the method call it is unable to tell who exactly is calling the interface. Let us consider sufficient to know what is the image file name of the DLL from where the call has been received. Provided that it is known in advance what is the DLL that host implementation of the filter to fool, this information is sufficient for decision.</p>
<p>In order to identify the caller I am using debug helper <a href="http://msdn.microsoft.com/en-us/library/ms680650(VS.85).aspx">StackWalk64</a> API and initialize <a href="http://http://msdn.microsoft.com/en-us/library/ms680646(VS.85).aspx">STACKFRAME64</a> argument to be able to step out of the current method. The structure is initialized using current CPU register values and is passed to the debug API to step out of the function.</p>
<pre>	STACKFRAME64 StackFrame;
	ZeroMemory(&amp;StackFrame, sizeof StackFrame);
	StackFrame.AddrPC.Mode = AddrModeFlat;
	StackFrame.AddrFrame.Mode = AddrModeFlat;
	StackFrame.AddrStack.Mode = AddrModeFlat;
	__asm
	{
		call __1
__1:
		pop dword ptr [StackFrame.AddrPC.Offset]
		mov dword ptr [StackFrame.AddrFrame.Offset], ebp
		mov dword ptr [StackFrame.AddrStack.Offset], esp
	}</pre>
<p>A <a href="http://msdn.microsoft.com/en-us/library/ms680650(VS.85).aspx">StackWalk64</a> call that follows initializes return address from the function which already belongs to the caller code. Using information from <a href="http://msdn.microsoft.com/en-us/library/ms679316(VS.85).aspx">EnumerateLoadedModules64</a> API it is possible to locate the caller DLL name and decide on the value to return.</p>
<pre>const CLoadedModule&amp; LoadedModule = LoadedModuleList.GetAt(Position);
ATLTRACE2(atlTraceGeneral, 4, _T("LoadedModule.m_sName %s, .m_nBase 0x%08x, .m_nSize 0x%08x\n"), LoadedModule.m_sName, (ULONG) LoadedModule.m_nBase, LoadedModule.m_nSize);
if(LoadedModule.m_sName.CompareNoCase(_T("RendererOnlySample.dll")) == 0)
	return (ULONG) AM_FILTER_MISC_FLAGS_IS_RENDERER;</pre>
<p>This appears to be sufficient to connect <strong>CFix</strong> to the output of <strong>CImpudence</strong> filter and get the graph operational and receive media samples.</p>
<p>It is worth mentioning that nevertheless debug API functions are used, the functionality is easily implementable using a tiny insertion of assembler code and standard Windows API.</p>
<p>Reference source code (will require additional headers to compile): <a href="http://alax.info/blog/wp-content/uploads/2008/08/rendereronlysample01.zip">RendererOnlySample.01.zip</a> (note that Release build binary is included)</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/614/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

