{"id":511,"date":"2008-08-06T22:44:36","date_gmt":"2008-08-06T20:44:36","guid":{"rendered":"https:\/\/alax.info\/blog\/?p=511"},"modified":"2008-08-09T08:23:41","modified_gmt":"2008-08-09T06:23:41","slug":"how-to-wrap-an-existing-directshow-filter-with-a-private-video-source-filter","status":"publish","type":"post","link":"https:\/\/alax.info\/blog\/511","title":{"rendered":"How To: Wrap an existing DirectShow filter with a private video source filter (COM aggregation)"},"content":{"rendered":"<p>See beginning in <a href=\"http:\/\/groups.google.com\/group\/microsoft.public.win32.programmer.directx.video\/browse_thread\/thread\/05261b50e064cf37?lnk=igtc#\">microsoft.public.win32.programmer.directx.video<\/a> newsgroup.<\/p>\n<p>This sample is demonstrating <a href=\"http:\/\/support.microsoft.com\/kb\/173823\">COM aggregation<\/a> to embed an existing filter an re-expose it as a new filter having inner filter pre-initialized.<\/p>\n<p>The Visual Studio C++.NET 2008 projects contains a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms783323.aspx\">DirectShow<\/a> filter class that registers itself under <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms783347.aspx\">Video Capture Sources category<\/a> and embeds <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms783662.aspx\">File Source (Async) Filter<\/a> inside initialized to stream <em>clock.avi<\/em> file from Windows directory.<\/p>\n<p><a href=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2008\/08\/06-image002.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-513\" title=\"Filter running\" src=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2008\/08\/06-image002-300x152.png\" alt=\"\" width=\"300\" height=\"152\" srcset=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2008\/08\/06-image002-300x152.png 300w, https:\/\/alax.info\/blog\/wp-content\/uploads\/2008\/08\/06-image002.png 1196w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p><!--more--><\/p>\n<p><a href=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2008\/08\/06-image001.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-512\" title=\"New filter registration\" src=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2008\/08\/06-image001-253x300.png\" alt=\"\" width=\"253\" height=\"300\" srcset=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2008\/08\/06-image001-253x300.png 253w, https:\/\/alax.info\/blog\/wp-content\/uploads\/2008\/08\/06-image001.png 450w\" sizes=\"auto, (max-width: 253px) 100vw, 253px\" \/><\/a><\/p>\n<p>The code of interest is in <em>Filter.h<\/em>. <em>CFilter<\/em> class is the implementation of the DirectShow filter.<\/p>\n<p><em>CFilter<\/em> registers itself as a filter through static <em>UpdateRegistry<\/em> method, which overrides stock <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/w0ey2be3.aspx\">DECLARE_REGISTRY_RESOURCEID<\/a> macro and adds IFilterMapper2 interface calls to register\/unregister the filter.<\/p>\n<p>To take an advantage of aggregating another object we need <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/97c868sh.aspx\">DECLARE_PROTECT_FINAL_CONSTRUCT<\/a> macro to be able to instantiate inner (that is aggregated) object on the very start (we cannot do this right in constructor), <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/sf3y8zcf.aspx\">DECLARE_GET_CONTROLLING_UNKNOWN<\/a> macro to declare member menthod that exposes controlling unknown.<\/p>\n<p>In a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/afkt56xx.aspx\">FinalConstruct<\/a> method we instantiate aggregated object (note GetControllingUnknown() argument which indicates instantiating as aggregated):<\/p>\n<pre>ATLENSURE_SUCCEEDED(m_pInnerUnknown.CoCreateInstance(CLSID_AsyncReader, GetControllingUnknown()));<\/pre>\n<p>and initialize the object through <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms910558.aspx\">IFileSourceFilter::Load<\/a>. The inner object is ready and we are to expose its functionality as if implemented natively. We need to update object&#8217;s <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/6bwekse3.aspx\">COM MAP<\/a> for this:<\/p>\n<pre>BEGIN_COM_MAP(CFilter)\r\n\tCOM_INTERFACE_ENTRY(IFilter)\r\n\t\/\/ NOTE: We still implement IDispatch through IFilter but we hide it to hopefully expose inner filter's IDispatch\r\n\t\/\/COM_INTERFACE_ENTRY(IDispatch)\r\n\t\/\/ NOTE: We are hiding inner filter IFileSourceFilter to avoid GraphEdit prompts for file path on filter insertion\r\n\tCOM_INTERFACE_ENTRY_NOINTERFACE(IFileSourceFilter)\r\n\tCOM_INTERFACE_ENTRY_AGGREGATE_BLIND(m_pInnerUnknown)\r\nEND_COM_MAP()<\/pre>\n<p><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/7t02fskk.aspx\">COM_INTERFACE_ENTRY_AGGREGATE_BLIND<\/a> will expose all inner object interfaces (except mentioned higher on the map) to the outside world. And we explicitly suppress <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms785718.aspx\">IFileSourceFilter<\/a> through <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/a6ba4c4b.aspx\">COM_INTERFACE_ENTRY_NOINTERFACE<\/a> to prevent <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms787460(VS.85).aspx\">GraphEdit<\/a> from discovering it and popping up a file dialog to select a source file.<\/p>\n<p>Source code: <a href=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2008\/08\/directshowwrappersourcefiltersample01.zip\">DirectShowWrapperSourceFilterSample.01.zip<\/a> (note that Release build binary is included)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>See beginning in microsoft.public.win32.programmer.directx.video newsgroup. This sample is demonstrating COM aggregation to embed an existing filter an re-expose it as a new filter having inner filter pre-initialized. The Visual Studio C++.NET 2008 projects contains a DirectShow filter class that registers itself under Video Capture Sources category and embeds File Source (Async) Filter inside initialized to&hellip; <\/p>\n<p><a class=\"moretag\" href=\"https:\/\/alax.info\/blog\/511\">Read the full article<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11,13,10],"tags":[96,487,97,95,78,94,488,486],"class_list":["post-511","post","type-post","status-publish","format-standard","hentry","category-atl","category-source","category-video","tag-aggregation","tag-atl","tag-avi","tag-com","tag-directshow","tag-hack","tag-source","tag-video"],"_links":{"self":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts\/511","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/comments?post=511"}],"version-history":[{"count":0,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts\/511\/revisions"}],"wp:attachment":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/media?parent=511"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/categories?post=511"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/tags?post=511"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}