<?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; DMO</title>
	<atom:link href="http://alax.info/blog/tag/dmo/feed" rel="self" type="application/rss+xml" />
	<link>http://alax.info/blog</link>
	<description>// Software Production Line</description>
	<lastBuildDate>Fri, 03 Feb 2012 22:49:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Video Decoder DMO and AM_SAMPLE_PREROLL</title>
		<link>http://alax.info/blog/915</link>
		<comments>http://alax.info/blog/915#comments</comments>
		<pubDate>Sat, 02 May 2009 10:57:58 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[DMO]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=915</guid>
		<description><![CDATA[<a href="http://alax.info/blog/915" title="Video Decoder DMO and AM_SAMPLE_PREROLL"></a>This does not seem to be documented anywhere, so it makes sense to mention. A video decoder, wrapped by DMO Wrapper Filter, will receive preroll media samples with AM_SAMPLE_PREROLL flag (alternatively available using IMediaSample::IsPreroll), but it won&#8217;t even forward these &#8230;<p class="read-more"><a href="http://alax.info/blog/915">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/915" title="Video Decoder DMO and AM_SAMPLE_PREROLL"></a><p>This does not seem to be documented anywhere, so it makes sense to mention. A video decoder, wrapped by <a href="http://msdn.microsoft.com/en-us/library/dd375519(VS.85).aspx">DMO Wrapper Filter</a>, will receive preroll media samples with <a href="http://msdn.microsoft.com/en-us/library/dd373500(VS.85).aspx">AM_SAMPLE_PREROLL</a> flag (alternatively available using <a href="http://msdn.microsoft.com/en-us/library/dd407014(VS.85).aspx">IMediaSample::IsPreroll</a>), but it won&#8217;t even forward these samples to the underlying DMO, instead they are just ignored.</p>
<p>MSDN says:</p>
<p style="padding-left: 30px;"><em>Preroll samples are processed but not displayed. They are located in the  media stream before the displayable samples.</em></p>
<p>However this behavoir of DMO Wrapper Filter does not seem to be correct. A DMO might require (in my case, maybe there are other scenarios) to initialize its decoding context from a splice point and then be able to decode further samples. The way the wrapper is skipping samples it appears that DMO is not receiving splice point data and won&#8217;t be able to start decoding of non-preroll samples until it receives a non-preroll splice point media sample&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/915/feed</wfw:commentRss>
		<slash:comments>0</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[<a href="http://alax.info/blog/893" title="YV12, Extended Video Renderer Strides, Private DMO and more"></a>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 &#8230;<p class="read-more"><a href="http://alax.info/blog/893">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/893" title="YV12, Extended Video Renderer Strides, Private DMO and more"></a><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>Private DMO</title>
		<link>http://alax.info/blog/674</link>
		<comments>http://alax.info/blog/674#comments</comments>
		<pubDate>Sat, 25 Oct 2008 20:59:38 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Source]]></category>
		<category><![CDATA[alt]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[DMO]]></category>
		<category><![CDATA[sample]]></category>

		<guid isPermaLink="false">http://alax.info/blog/?p=674</guid>
		<description><![CDATA[<a href="http://alax.info/blog/674" title="Private DMO"></a>Started as Is it possible to use local component in DLL? on microsoft.public.vc.atl newsgroup. The question is to embed a custom DirectX Media Object (DMO) into executable so that it is only available to proprietary application and not to entire &#8230;<p class="read-more"><a href="http://alax.info/blog/674">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/674" title="Private DMO"></a><p>Started as <a href="http://groups.google.com/group/microsoft.public.vc.atl/browse_thread/thread/8b2bbcb309d9012a#">Is it possible to use local component in DLL?</a> on <a href="http://groups.google.com/group/microsoft.public.vc.atl">microsoft.public.vc.atl</a> newsgroup. The question is to embed a custom <a href="http://msdn.microsoft.com/en-us/library/ms783356(VS.85).aspx">DirectX Media Object</a> (DMO) into executable so that it is only available to proprietary application and not to entire system and could be reused in other applications. If in particular this DMO should be available to intelligent connect, e.g. used by embedded Windows Media Player control, the solution requires that private DMO appears fully registered as full featured regular DMO.</p>
<p>A while ago I <a href="http://groups.google.com/group/microsoft.public.win32.programmer.directx.video/browse_thread/thread/c50857317a54b2a/aa827bb9fabfc75b">proposed a solution</a> on getting COM Class/DMO embedded into executable and temporarily exposed as availble without registry registration through <a href="http://msdn.microsoft.com/en-us/library/ms693407.aspx">CoRegisterClassObject</a>/RegisterClassObject, however in addition to COM class registration, a DMO needs to also be specifically listed as a DMO, through <a href="http://msdn.microsoft.com/en-us/library/ms783385(VS.85).aspx">DMORegister</a> API.</p>
<p>In order to expose private DMO to DirectShow subsystem the following steps has to be performed:</p>
<ul>
<li>register COM class object as a COM class (CoRegisterClassObject) to enable its instantiation by its CLSID</li>
<li>use DMORegister API to list DMO in global list (warning, seems to be requiring write permission on HKEY_CLASSES_ROOT key)</li>
<li>have the filter graph of interest created</li>
<li>use DMOUnregister API as early as possible to unlist private DMO from global list</li>
</ul>
<pre>ATLENSURE_SUCCEEDED(__objMap_CPrivateMediaObject.RegisterClassObject(CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE));
DMO_PARTIAL_MEDIATYPE pInputMediaTypes[] = { { MEDIATYPE_Video, CPrivateMediaObject::GetXxxxSubtype() } };
ATLENSURE_SUCCEEDED(DMORegister(L"Private DMO", CLSID_PrivateMediaObject, DMOCATEGORY_VIDEO_DECODER, 0, _countof(pInputMediaTypes), pInputMediaTypes, 0, NULL));
...
ATLVERIFY(SUCCEEDED(DMOUnregister(CLSID_PrivateMediaObject, DMOCATEGORY_VIDEO_DECODER)));</pre>
<p>The sample code/project takes an .AVI file which is a XVID video file with a FOURCC compression code changed from XVID to XXXX. The file is unplayable but there is a private DMO which accepts XXXX video and copies data as is into XVID format on its output.</p>
<p>A Visual C++ .NET 2008 source code <a href="http://trac2.assembla.com/roatl-utilities/browser/trunk/PrivateDmoSample">is available from SVN</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/674/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 5: In-Place Processing)</title>
		<link>http://alax.info/blog/494</link>
		<comments>http://alax.info/blog/494#comments</comments>
		<pubDate>Sat, 26 Jul 2008 13:14:47 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Source]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[WTL]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[DMO]]></category>
		<category><![CDATA[howto]]></category>

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

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

		<guid isPermaLink="false">http://alax.info/blog/?p=475</guid>
		<description><![CDATA[<a href="http://alax.info/blog/475" title="Video Conversion: YUY2 to YV12 "></a>See topic on MSDN Forums about coloring issue. This is a demo of YUY2 to YV12 conversion as suggested copying Y values and averaging U and V. Original image is on the right. Code snippet to perform the transformation: ATLASSERT(pInputBitmapInfoHeader-&#62;biCompression &#8230;<p class="read-more"><a href="http://alax.info/blog/475">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://alax.info/blog/475" title="Video Conversion: YUY2 to YV12 "></a><p>See topic on <a href="http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3650255&amp;SiteID=1">MSDN Forums</a> about coloring issue.</p>
<p>This is a demo of <a href="http://fourcc.org/yuv.php#YUY2">YUY2</a> to <a href="http://fourcc.org/yuv.php#YV12">YV12</a> conversion as suggested copying Y values and averaging U and V.</p>
<p><a href="http://alax.info/blog/wp-content/uploads/2008/07/yuy2-yv12-01.png"><img class="alignnone size-medium wp-image-477" title="GraphEdit DirectShow filter graph demonstrating conversion from YUY2 to YV12" src="http://alax.info/blog/wp-content/uploads/2008/07/yuy2-yv12-01-300x155.png" alt="" width="300" height="155" /></a></p>
<p>Original image is on the right.</p>
<p>Code snippet to perform the transformation:</p>
<p><span id="more-475"></span></p>
<pre>ATLASSERT<span style="color: #808030;">(</span>pInputBitmapInfoHeader<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>biCompression <span style="color: #808030;">=</span><span style="color: #808030;">=</span> FOURCC_YUY2<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">CSize</span> Extent <span style="color: #808030;">=</span> pInputVideoInfoHeader<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>GetExtent<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLASSERT<span style="color: #808030;">(</span>Extent <span style="color: #808030;">=</span><span style="color: #808030;">=</span> pOutputVideoInfoHeader<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>GetExtent<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">BYTE</span><span style="color: #808030;">*</span> pnInputData <span style="color: #808030;">=</span> InputMediaBuffer<span style="color: #808030;">.</span>m_pnData<span style="color: #800080;">;</span>
SSIZE_T nFirstInputRowOffset<span style="color: #808030;">,</span> nNextInputRowOffset<span style="color: #800080;">;</span>
pInputVideoInfoHeader<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>GetData<span style="color: #808030;">(</span>nFirstInputRowOffset<span style="color: #808030;">,</span> nNextInputRowOffset<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLASSERT<span style="color: #808030;">(</span><span style="color: #808030;">!</span>nFirstInputRowOffset<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #603000;">BYTE</span><span style="color: #808030;">*</span> pnOutputData <span style="color: #808030;">=</span> OutputMediaBuffer<span style="color: #808030;">.</span>m_pnData<span style="color: #800080;">;</span>
SSIZE_T nFirstOutputRowOffset<span style="color: #808030;">,</span> nNextOutputRowOffset<span style="color: #800080;">;</span>
pOutputVideoInfoHeader<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>GetData<span style="color: #808030;">(</span>nFirstOutputRowOffset<span style="color: #808030;">,</span> nNextOutputRowOffset<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLASSERT<span style="color: #808030;">(</span><span style="color: #808030;">!</span>nFirstOutputRowOffset<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #603000;">BYTE</span><span style="color: #808030;">*</span> pnOutputDataY <span style="color: #808030;">=</span> pnOutputData<span style="color: #800080;">;</span>
<span style="color: #603000;">BYTE</span><span style="color: #808030;">*</span> pnOutputDataV <span style="color: #808030;">=</span> pnOutputDataY <span style="color: #808030;">+</span> Extent<span style="color: #808030;">.</span>cy <span style="color: #808030;">*</span> nNextOutputRowOffset<span style="color: #800080;">;</span>
<span style="color: #603000;">BYTE</span><span style="color: #808030;">*</span> pnOutputDataU <span style="color: #808030;">=</span> pnOutputDataV <span style="color: #808030;">+</span> <span style="color: #808030;">(</span>Extent<span style="color: #808030;">.</span>cy <span style="color: #808030;">*</span> nNextOutputRowOffset<span style="color: #808030;">)</span> <span style="color: #808030;">/</span> <span style="color: #008c00;">4</span><span style="color: #800080;">;</span>
ATLTRACE2<span style="color: #808030;">(</span>atlTraceGeneral<span style="color: #808030;">,</span> <span style="color: #008c00;">5</span><span style="color: #808030;">,</span> _T<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">pnInputData 0x</span><span style="color: #0f69ff;">%08x</span><span style="color: #0000e6;"> - 0x</span><span style="color: #0f69ff;">%08x</span><span style="color: #0000e6;">, Extent { </span><span style="color: #0f69ff;">%d</span><span style="color: #0000e6;">, </span><span style="color: #0f69ff;">%d</span><span style="color: #0000e6;"> }, pnOutputData 0x</span><span style="color: #0f69ff;">%08x</span><span style="color: #0000e6;"> - 0x</span><span style="color: #0f69ff;">%08x</span><span style="color: #0f69ff;">\n</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #808030;">,</span> pnInputData<span style="color: #808030;">,</span> pnInputData <span style="color: #808030;">+</span> pInputBitmapInfoHeader<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>biSizeImage<span style="color: #808030;">,</span> Extent<span style="color: #808030;">.</span>cx<span style="color: #808030;">,</span> Extent<span style="color: #808030;">.</span>cy<span style="color: #808030;">,</span> pnOutputData<span style="color: #808030;">,</span> pnOutputData <span style="color: #808030;">+</span> pOutputBitmapInfoHeader<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>biSizeImage<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLTRACE2<span style="color: #808030;">(</span>atlTraceGeneral<span style="color: #808030;">,</span> <span style="color: #008c00;">5</span><span style="color: #808030;">,</span> _T<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">nFirstInputRowOffset </span><span style="color: #0f69ff;">%d</span><span style="color: #0000e6;">, nNextInputRowOffset </span><span style="color: #0f69ff;">%d</span><span style="color: #0000e6;">, nFirstOutputRowOffset </span><span style="color: #0f69ff;">%d</span><span style="color: #0000e6;">, nNextOutputRowOffset </span><span style="color: #0f69ff;">%d</span><span style="color: #0f69ff;">\n</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #808030;">,</span> nFirstInputRowOffset<span style="color: #808030;">,</span> nNextInputRowOffset<span style="color: #808030;">,</span> nFirstOutputRowOffset<span style="color: #808030;">,</span> nNextOutputRowOffset<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
ATLTRACE2<span style="color: #808030;">(</span>atlTraceGeneral<span style="color: #808030;">,</span> <span style="color: #008c00;">5</span><span style="color: #808030;">,</span> _T<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">pnOutputDataY 0x</span><span style="color: #0f69ff;">%08x</span><span style="color: #0000e6;">, pnOutputDataV 0x</span><span style="color: #0f69ff;">%08x</span><span style="color: #0000e6;">, pnOutputDataU 0x</span><span style="color: #0f69ff;">%08x</span><span style="color: #0f69ff;">\n</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #808030;">,</span> pnOutputDataY<span style="color: #808030;">,</span> pnOutputDataV<span style="color: #808030;">,</span> pnOutputDataU<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
SSIZE_T nInputRowOffset <span style="color: #808030;">=</span> nFirstInputRowOffset<span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">for</span><span style="color: #808030;">(</span><span style="color: #603000;">LONG</span> nY <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: #800080;">;</span> nY <span style="color: #808030;">&lt;</span> Extent<span style="color: #808030;">.</span>cy<span style="color: #800080;">;</span> nY <span style="color: #808030;">+</span><span style="color: #808030;">=</span> <span style="color: #008c00;">2</span><span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    SSIZE_T nInputOffset <span style="color: #808030;">=</span> nInputRowOffset<span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">for</span><span style="color: #808030;">(</span><span style="color: #603000;">LONG</span> nX <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: #800080;">;</span> nX <span style="color: #808030;">&lt;</span> Extent<span style="color: #808030;">.</span>cx<span style="color: #800080;">;</span> nX <span style="color: #808030;">+</span><span style="color: #808030;">=</span> <span style="color: #008c00;">2</span><span style="color: #808030;">)</span>
    <span style="color: #800080;">{</span>
        pnOutputDataY<span style="color: #808030;">[</span><span style="color: #008c00;">0</span><span style="color: #808030;">]</span> <span style="color: #808030;">=</span> pnInputData<span style="color: #808030;">[</span>nInputOffset <span style="color: #808030;">+</span> <span style="color: #008c00;">0</span><span style="color: #808030;">]</span><span style="color: #800080;">;</span>
        <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">BYTE</span> nU0 <span style="color: #808030;">=</span> pnInputData<span style="color: #808030;">[</span>nInputOffset <span style="color: #808030;">+</span> <span style="color: #008c00;">1</span><span style="color: #808030;">]</span><span style="color: #800080;">;</span>
        pnOutputDataY<span style="color: #808030;">[</span><span style="color: #008c00;">1</span><span style="color: #808030;">]</span> <span style="color: #808030;">=</span> pnInputData<span style="color: #808030;">[</span>nInputOffset <span style="color: #808030;">+</span> <span style="color: #008c00;">2</span><span style="color: #808030;">]</span><span style="color: #800080;">;</span>
        <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">BYTE</span> nV0 <span style="color: #808030;">=</span> pnInputData<span style="color: #808030;">[</span>nInputOffset <span style="color: #808030;">+</span> <span style="color: #008c00;">3</span><span style="color: #808030;">]</span><span style="color: #800080;">;</span>
        pnOutputDataY<span style="color: #808030;">[</span>nNextOutputRowOffset <span style="color: #808030;">+</span> <span style="color: #008c00;">0</span><span style="color: #808030;">]</span> <span style="color: #808030;">=</span> pnInputData<span style="color: #808030;">[</span>nInputOffset <span style="color: #808030;">+</span> nNextInputRowOffset <span style="color: #808030;">+</span> <span style="color: #008c00;">0</span><span style="color: #808030;">]</span><span style="color: #800080;">;</span>
        <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">BYTE</span> nU1 <span style="color: #808030;">=</span> pnInputData<span style="color: #808030;">[</span>nInputOffset <span style="color: #808030;">+</span> nNextInputRowOffset <span style="color: #808030;">+</span> <span style="color: #008c00;">1</span><span style="color: #808030;">]</span><span style="color: #800080;">;</span>
        pnOutputDataY<span style="color: #808030;">[</span>nNextOutputRowOffset <span style="color: #808030;">+</span> <span style="color: #008c00;">1</span><span style="color: #808030;">]</span> <span style="color: #808030;">=</span> pnInputData<span style="color: #808030;">[</span>nInputOffset <span style="color: #808030;">+</span> nNextInputRowOffset <span style="color: #808030;">+</span> <span style="color: #008c00;">2</span><span style="color: #808030;">]</span><span style="color: #800080;">;</span>
        <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">BYTE</span> nV1 <span style="color: #808030;">=</span> pnInputData<span style="color: #808030;">[</span>nInputOffset <span style="color: #808030;">+</span> nNextInputRowOffset <span style="color: #808030;">+</span> <span style="color: #008c00;">3</span><span style="color: #808030;">]</span><span style="color: #800080;">;</span>
        pnOutputDataU<span style="color: #808030;">[</span><span style="color: #008c00;">0</span><span style="color: #808030;">]</span> <span style="color: #808030;">=</span> <span style="color: #808030;">(</span>nU0 <span style="color: #808030;">+</span> nU1<span style="color: #808030;">)</span> <span style="color: #808030;">/</span> <span style="color: #008c00;">2</span><span style="color: #800080;">;</span>
        pnOutputDataV<span style="color: #808030;">[</span><span style="color: #008c00;">0</span><span style="color: #808030;">]</span> <span style="color: #808030;">=</span> <span style="color: #808030;">(</span>nV0 <span style="color: #808030;">+</span> nV1<span style="color: #808030;">)</span> <span style="color: #808030;">/</span> <span style="color: #008c00;">2</span><span style="color: #800080;">;</span>
        nInputOffset <span style="color: #808030;">+</span><span style="color: #808030;">=</span> <span style="color: #008c00;">4</span><span style="color: #800080;">;</span>
        pnOutputDataY <span style="color: #808030;">+</span><span style="color: #808030;">=</span> <span style="color: #008c00;">2</span><span style="color: #800080;">;</span>
        pnOutputDataV <span style="color: #808030;">+</span><span style="color: #808030;">=</span> <span style="color: #008c00;">1</span><span style="color: #800080;">;</span>
        pnOutputDataU <span style="color: #808030;">+</span><span style="color: #808030;">=</span> <span style="color: #008c00;">1</span><span style="color: #800080;">;</span>
    <span style="color: #800080;">}</span>
    nInputRowOffset <span style="color: #808030;">+</span><span style="color: #808030;">=</span> <span style="color: #008c00;">2</span> <span style="color: #808030;">*</span> nNextInputRowOffset<span style="color: #800080;">;</span>
    pnOutputDataY <span style="color: #808030;">+</span><span style="color: #808030;">=</span> <span style="color: #008c00;">2</span> <span style="color: #808030;">*</span> nNextOutputRowOffset <span style="color: #808030;">-</span> Extent<span style="color: #808030;">.</span>cx<span style="color: #800080;">;</span>
    pnOutputDataV <span style="color: #808030;">+</span><span style="color: #808030;">=</span> nNextOutputRowOffset <span style="color: #808030;">/</span> <span style="color: #008c00;">2</span> <span style="color: #808030;">-</span> Extent<span style="color: #808030;">.</span>cx <span style="color: #808030;">/</span> <span style="color: #008c00;">2</span><span style="color: #800080;">;</span>
    pnOutputDataU <span style="color: #808030;">+</span><span style="color: #808030;">=</span> nNextOutputRowOffset <span style="color: #808030;">/</span> <span style="color: #008c00;">2</span> <span style="color: #808030;">-</span> Extent<span style="color: #808030;">.</span>cx <span style="color: #808030;">/</span> <span style="color: #008c00;">2</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span>
ATLTRACE2<span style="color: #808030;">(</span>atlTraceGeneral<span style="color: #808030;">,</span> <span style="color: #008c00;">5</span><span style="color: #808030;">,</span> _T<span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">pnOutputDataY 0x</span><span style="color: #0f69ff;">%08x</span><span style="color: #0000e6;">, pnOutputDataV 0x</span><span style="color: #0f69ff;">%08x</span><span style="color: #0000e6;">, pnOutputDataU 0x</span><span style="color: #0f69ff;">%08x</span><span style="color: #0f69ff;">\n</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #808030;">,</span> pnOutputDataY<span style="color: #808030;">,</span> pnOutputDataV<span style="color: #808030;">,</span> pnOutputDataU<span style="color: #808030;">)</span></pre>
<p>See also:</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/aa904813.aspx">Video Rendering with 8-Bit YUV Formats</a></li>
<li><a href="http://www.animemusicvideos.org/guides/avtech/colorspace.html">Colorspaces, YUY2 and YV12</a></li>
<li><a href="http://forum.doom9.org/archive/index.php/t-76455.html">IYUV or YV12 colorspace?, YUV colorspaces SMPTE vs 601 vs 709</a></li>
<li><a href="http://www.tomshardware.co.uk/forum/142470-15-feeding-cbcr-yv12-data-tmpgenc">Feeding Y&#8217;CbCr (&#8220;YUV&#8221;/&#8221;YV12&#8243;) data to TMPGEnc</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://alax.info/blog/475/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 3: Persistence, Automation and Property Pages)</title>
		<link>http://alax.info/blog/433</link>
		<comments>http://alax.info/blog/433#comments</comments>
		<pubDate>Fri, 18 Jul 2008 13:31:35 +0000</pubDate>
		<dc:creator>Roman</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Source]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[WTL]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[DMO]]></category>
		<category><![CDATA[howto]]></category>

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

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

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

