summaryrefslogtreecommitdiff
path: root/avstream
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
committerDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
commit97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch)
tree46f3701832d70b420eb0fc0eb93261f9da45db3f /avstream
parentef1905bf1e8825bb31120dfb27e0daf3154d859a (diff)
Initial publish
Diffstat (limited to 'avstream')
-rw-r--r--avstream/avshws/ReadMe.md10
-rw-r--r--avstream/avshws/avshws.h232
-rw-r--r--avstream/avshws/avshws.htm458
-rw-r--r--avstream/avshws/avshws.inf172
-rw-r--r--avstream/avshws/avshws.rc22
-rw-r--r--avstream/avshws/avshws.sln28
-rw-r--r--avstream/avshws/avshws.vcxproj201
-rw-r--r--avstream/avshws/avshws.vcxproj.Filters46
-rw-r--r--avstream/avshws/capture.cpp1704
-rw-r--r--avstream/avshws/capture.h313
-rw-r--r--avstream/avshws/device.cpp875
-rw-r--r--avstream/avshws/device.h294
-rw-r--r--avstream/avshws/filter.cpp203
-rw-r--r--avstream/avshws/filter.h88
-rw-r--r--avstream/avshws/hwsim.cpp868
-rw-r--r--avstream/avshws/hwsim.h290
-rw-r--r--avstream/avshws/image.cpp605
-rw-r--r--avstream/avshws/image.h478
-rw-r--r--avstream/avshws/purecall.c50
-rw-r--r--avstream/samplemft0/Mft0.cpp975
-rw-r--r--avstream/samplemft0/Mft0.h224
-rw-r--r--avstream/samplemft0/Mft0.rgs15
-rw-r--r--avstream/samplemft0/ReadMe.md28
-rw-r--r--avstream/samplemft0/SampleHelpers.h143
-rw-r--r--avstream/samplemft0/SampleMft0.cpp83
-rw-r--r--avstream/samplemft0/SampleMft0.def16
-rw-r--r--avstream/samplemft0/SampleMft0.idl48
-rw-r--r--avstream/samplemft0/SampleMft0.rcbin0 -> 6644 bytes
-rw-r--r--avstream/samplemft0/SampleMft0.rgs3
-rw-r--r--avstream/samplemft0/SampleMft0.sln28
-rw-r--r--avstream/samplemft0/SampleMft0.vcxproj221
-rw-r--r--avstream/samplemft0/SampleMft0.vcxproj.Filters45
-rw-r--r--avstream/samplemft0/dllmain.cpp19
-rw-r--r--avstream/samplemft0/dllmain.h10
-rw-r--r--avstream/samplemft0/resource.hbin0 -> 1710 bytes
-rw-r--r--avstream/samplemft0/stdafx.cpp13
-rw-r--r--avstream/samplemft0/stdafx.h42
-rw-r--r--avstream/samplemft0/stdafxsrc.cpp1
-rw-r--r--avstream/samplemft0/targetver.h15
39 files changed, 8866 insertions, 0 deletions
diff --git a/avstream/avshws/ReadMe.md b/avstream/avshws/ReadMe.md
new file mode 100644
index 00000000..be81c949
--- /dev/null
+++ b/avstream/avshws/ReadMe.md
@@ -0,0 +1,10 @@
+AVStream simulated hardware sample driver (Avshws)
+==================================================
+
+The AVStream simulated hardware sample driver (Avshws) provides a pin-centric [AVStream](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554240) capture driver for a simulated piece of hardware. This streaming media driver performs video captures at 320 x 240 pixels in either RGB24 or YUV422 format using direct memory access (DMA) into capture buffers. The purpose of the sample is to demonstrate how to write a pin-centric AVStream minidriver. The sample also shows how to implement DMA by using the related functionality provided by the AVStream class driver.
+
+This sample features enhanced parameter validation and overflow detection.
+
+## Universal Compliant
+This sample builds a Windows Universal driver. It uses only APIs and DDIs that are included in Windows Core.
+
diff --git a/avstream/avshws/avshws.h b/avstream/avshws/avshws.h
new file mode 100644
index 00000000..3647c1ac
--- /dev/null
+++ b/avstream/avshws/avshws.h
@@ -0,0 +1,232 @@
+/**************************************************************************
+
+ AVStream Simulated Hardware Sample
+
+ Copyright (c) 2001, Microsoft Corporation.
+
+ File:
+
+ avshws.h
+
+ Abstract:
+
+ AVStream Simulated Hardware Sample header file. This is the
+ main header.
+
+ History:
+
+ created 3/12/2001
+
+**************************************************************************/
+
+/*************************************************
+
+ Standard Includes
+
+*************************************************/
+
+#ifndef _avshws_h_
+#define _avshws_h_
+
+extern "C" {
+#include <wdm.h>
+}
+
+#include <windef.h>
+#include <stdio.h>
+#include <ntstrsafe.h>
+#include <stdlib.h>
+#include <windef.h>
+#define NOBITMAP
+#include <mmreg.h>
+#undef NOBITMAP
+#include <unknown.h>
+#include <ks.h>
+#include <ksmedia.h>
+#include <kcom.h>
+
+/*************************************************
+
+ Misc Definitions
+
+*************************************************/
+#pragma warning (disable : 4100 4127 4131 4189 4701 4706)
+#define STR_MODULENAME "avshws: "
+#define DEBUGLVL_VERBOSE 2
+#define DEBUGLVL_TERSE 1
+#define DEBUGLVL_ERROR 0
+
+const DebugLevel = DEBUGLVL_TERSE;
+
+#if (DBG)
+#define _DbgPrintF(lvl, strings) \
+{ \
+ if (lvl <= DebugLevel) {\
+ DbgPrint(STR_MODULENAME);\
+ DbgPrint##strings;\
+ DbgPrint("\n");\
+ if ((lvl) == DEBUGLVL_ERROR) {\
+ NT_ASSERT(0);\
+ } \
+ }\
+}
+#else // !DBG
+ #define _DbgPrintF(lvl, strings)
+#endif // !DBG
+
+#define ABS(x) ((x) < 0 ? (-(x)) : (x))
+
+#ifndef mmioFOURCC
+#define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
+ ( (DWORD)(BYTE)(ch0) | ( (DWORD)(BYTE)(ch1) << 8 ) | \
+ ( (DWORD)(BYTE)(ch2) << 16 ) | ( (DWORD)(BYTE)(ch3) << 24 ) )
+#endif
+
+#define FOURCC_YUY2 mmioFOURCC('Y', 'U', 'Y', '2')
+//
+// CAPTURE_PIN_DATA_RANGE_COUNT:
+//
+// The number of ranges supported on the capture pin.
+//
+#define CAPTURE_PIN_DATA_RANGE_COUNT 2
+
+//
+// CAPTURE_FILTER_PIN_COUNT:
+//
+// The number of pins on the capture filter.
+//
+#define CAPTURE_FILTER_PIN_COUNT 1
+
+//
+// CAPTURE_FILTER_CATEGORIES_COUNT:
+//
+// The number of categories for the capture filter.
+//
+#define CAPTURE_FILTER_CATEGORIES_COUNT 3
+
+#define AVSHWS_POOLTAG 'hSVA'
+
+/*************************************************
+
+ Externed information
+
+*************************************************/
+//
+// filter.cpp externs:
+//
+extern
+const
+KSFILTER_DISPATCH
+CaptureFilterDispatch;
+
+extern
+const
+KSFILTER_DESCRIPTOR
+CaptureFilterDescriptor;
+
+extern
+const
+KSPIN_DESCRIPTOR_EX
+CaptureFilterPinDescriptors [CAPTURE_FILTER_PIN_COUNT];
+
+extern
+const
+GUID
+CaptureFilterCategories [CAPTURE_FILTER_CATEGORIES_COUNT];
+
+//
+// capture.cpp externs:
+//
+extern
+const
+KSALLOCATOR_FRAMING_EX
+CapturePinAllocatorFraming;
+
+extern
+const
+KSPIN_DISPATCH
+CapturePinDispatch;
+
+extern
+const
+PKSDATARANGE
+CapturePinDataRanges [CAPTURE_PIN_DATA_RANGE_COUNT];
+
+/*************************************************
+
+ Enums / Typedefs
+
+*************************************************/
+
+typedef enum _HARDWARE_STATE {
+
+ HardwareStopped = 0,
+ HardwarePaused,
+ HardwareRunning
+
+} HARDWARE_STATE, *PHARDWARE_STATE;
+
+/*************************************************
+
+ Class Definitions
+
+*************************************************/
+
+//
+// IHardwareSink:
+//
+// This interface is used by the hardware simulation to fake interrupt
+// service routines. The Interrupt method is called at DPC as a fake
+// interrupt.
+//
+class IHardwareSink {
+
+public:
+
+ virtual
+ void
+ Interrupt (
+ ) = 0;
+
+};
+
+//
+// ICaptureSink:
+//
+// This is a capture sink interface. The device level calls back the
+// CompleteMappings method passing the number of completed mappings for
+// the capture pin. This method is called during the device DPC.
+//
+class ICaptureSink {
+
+public:
+
+ virtual
+ void
+ CompleteMappings (
+ IN ULONG NumMappings
+ ) = 0;
+
+};
+
+
+
+/*************************************************
+
+ Global Functions
+
+*************************************************/
+
+/*************************************************
+
+ Internal Includes
+
+*************************************************/
+
+#include "image.h"
+#include "hwsim.h"
+#include "device.h"
+#include "filter.h"
+#include "capture.h"
+#include <uuids.h>
+#endif //_avshws_h_ \ No newline at end of file
diff --git a/avstream/avshws/avshws.htm b/avstream/avshws/avshws.htm
new file mode 100644
index 00000000..bd715e2c
--- /dev/null
+++ b/avstream/avshws/avshws.htm
@@ -0,0 +1,458 @@
+<html xmlns:o="urn:schemas-microsoft-com:office:office"
+xmlns:w="urn:schemas-microsoft-com:office:word"
+xmlns="http://www.w3.org/TR/REC-html40">
+
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=windows-1252">
+<meta name=ProgId content=Word.Document>
+<meta name=Generator content="Microsoft Word 11">
+<meta name=Originator content="Microsoft Word 11">
+<link rel=File-List href="avshws_files/filelist.xml">
+<title>AVSHwS</title>
+<!--[if gte mso 9]><xml>
+ <w:WordDocument>
+ <w:Zoom>130</w:Zoom>
+ <w:SpellingState>Clean</w:SpellingState>
+ <w:GrammarState>Clean</w:GrammarState>
+ <w:ValidateAgainstSchemas/>
+ <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
+ <w:IgnoreMixedContent>false</w:IgnoreMixedContent>
+ <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
+ <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
+ </w:WordDocument>
+</xml><![endif]--><!--[if gte mso 9]><xml>
+ <w:LatentStyles DefLockedState="false" LatentStyleCount="156">
+ </w:LatentStyles>
+</xml><![endif]-->
+<style>
+<!--
+ /* Font Definitions */
+ @font-face
+ {font-family:SimSun;
+ panose-1:2 1 6 0 3 1 1 1 1 1;
+ mso-font-alt:\5B8B\4F53;
+ mso-font-charset:134;
+ mso-generic-font-family:auto;
+ mso-font-format:other;
+ mso-font-pitch:variable;
+ mso-font-signature:1 135135232 16 0 262144 0;}
+@font-face
+ {font-family:Verdana;
+ panose-1:2 11 6 4 3 5 4 4 2 4;
+ mso-font-charset:0;
+ mso-generic-font-family:swiss;
+ mso-font-pitch:variable;
+ mso-font-signature:536871559 0 0 0 415 0;}
+@font-face
+ {font-family:"\@SimSun";
+ mso-font-charset:134;
+ mso-generic-font-family:auto;
+ mso-font-pitch:auto;
+ mso-font-signature:0 0 0 0 0 0;}
+ /* Style Definitions */
+ p.MsoNormal, li.MsoNormal, div.MsoNormal
+ {mso-style-parent:"";
+ margin:0in;
+ margin-bottom:.0001pt;
+ mso-pagination:widow-orphan;
+ font-size:12.0pt;
+ font-family:"Times New Roman";
+ mso-fareast-font-family:"Times New Roman";}
+h2
+ {mso-margin-top-alt:auto;
+ margin-right:0in;
+ mso-margin-bottom-alt:auto;
+ margin-left:0in;
+ mso-pagination:widow-orphan;
+ mso-outline-level:2;
+ font-size:18.0pt;
+ font-family:"Times New Roman";
+ font-weight:bold;}
+h3
+ {mso-margin-top-alt:auto;
+ margin-right:0in;
+ mso-margin-bottom-alt:auto;
+ margin-left:0in;
+ mso-pagination:widow-orphan;
+ mso-outline-level:3;
+ font-size:13.5pt;
+ font-family:"Times New Roman";
+ font-weight:bold;}
+h4
+ {mso-margin-top-alt:auto;
+ margin-right:0in;
+ mso-margin-bottom-alt:auto;
+ margin-left:0in;
+ mso-pagination:widow-orphan;
+ mso-outline-level:4;
+ font-size:12.0pt;
+ font-family:"Times New Roman";
+ font-weight:bold;}
+a:link, span.MsoHyperlink
+ {color:blue;
+ text-decoration:underline;
+ text-underline:single;}
+a:visited, span.MsoHyperlinkFollowed
+ {color:blue;
+ text-decoration:underline;
+ text-underline:single;}
+p
+ {mso-margin-top-alt:auto;
+ margin-right:0in;
+ mso-margin-bottom-alt:auto;
+ margin-left:0in;
+ mso-pagination:widow-orphan;
+ font-size:12.0pt;
+ font-family:"Times New Roman";
+ mso-fareast-font-family:"Times New Roman";}
+pre
+ {margin:0in;
+ margin-bottom:.0001pt;
+ mso-pagination:widow-orphan;
+ tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt;
+ font-size:10.0pt;
+ font-family:"Courier New";
+ mso-fareast-font-family:"Times New Roman";}
+ins
+ {mso-style-type:export-only;
+ text-decoration:none;}
+span.msoIns
+ {mso-style-type:export-only;
+ mso-style-name:"";
+ text-decoration:underline;
+ text-underline:single;}
+span.SpellE
+ {mso-style-name:"";
+ mso-spl-e:yes;}
+span.GramE
+ {mso-style-name:"";
+ mso-gram-e:yes;}
+@page Section1
+ {size:8.5in 11.0in;
+ margin:1.0in 1.25in 1.0in 1.25in;
+ mso-header-margin:.5in;
+ mso-footer-margin:.5in;
+ mso-paper-source:0;}
+div.Section1
+ {page:Section1;}
+ /* List Definitions */
+ @list l0
+ {mso-list-id:53240075;
+ mso-list-template-ids:2131904850;}
+@list l0:level1
+ {mso-level-number-format:bullet;
+ mso-level-text:\F0B7;
+ mso-level-tab-stop:.5in;
+ mso-level-number-position:left;
+ text-indent:-.25in;
+ mso-ansi-font-size:10.0pt;
+ font-family:Symbol;}
+@list l1
+ {mso-list-id:966544645;
+ mso-list-template-ids:-673255552;}
+@list l1:level1
+ {mso-level-number-format:bullet;
+ mso-level-text:\F0B7;
+ mso-level-tab-stop:.5in;
+ mso-level-number-position:left;
+ text-indent:-.25in;
+ mso-ansi-font-size:10.0pt;
+ font-family:Symbol;}
+@list l1:level2
+ {mso-level-tab-stop:1.0in;
+ mso-level-number-position:left;
+ text-indent:-.25in;}
+@list l1:level3
+ {mso-level-tab-stop:1.5in;
+ mso-level-number-position:left;
+ text-indent:-.25in;}
+@list l1:level4
+ {mso-level-tab-stop:2.0in;
+ mso-level-number-position:left;
+ text-indent:-.25in;}
+@list l1:level5
+ {mso-level-tab-stop:2.5in;
+ mso-level-number-position:left;
+ text-indent:-.25in;}
+@list l1:level6
+ {mso-level-tab-stop:3.0in;
+ mso-level-number-position:left;
+ text-indent:-.25in;}
+@list l1:level7
+ {mso-level-tab-stop:3.5in;
+ mso-level-number-position:left;
+ text-indent:-.25in;}
+@list l1:level8
+ {mso-level-tab-stop:4.0in;
+ mso-level-number-position:left;
+ text-indent:-.25in;}
+@list l1:level9
+ {mso-level-tab-stop:4.5in;
+ mso-level-number-position:left;
+ text-indent:-.25in;}
+ol
+ {margin-bottom:0in;}
+ul
+ {margin-bottom:0in;}
+-->
+</style>
+<!--[if gte mso 10]>
+<style>
+ /* Style Definitions */
+ table.MsoNormalTable
+ {mso-style-name:"Table Normal";
+ mso-tstyle-rowband-size:0;
+ mso-tstyle-colband-size:0;
+ mso-style-noshow:yes;
+ mso-style-parent:"";
+ mso-padding-alt:0in 5.4pt 0in 5.4pt;
+ mso-para-margin:0in;
+ mso-para-margin-bottom:.0001pt;
+ mso-pagination:widow-orphan;
+ font-size:10.0pt;
+ font-family:"Times New Roman";
+ mso-ansi-language:#0400;
+ mso-fareast-language:#0400;
+ mso-bidi-language:#0400;}
+</style>
+<![endif]-->
+</head>
+
+<body lang=EN-US link=blue vlink=blue style='tab-interval:.5in'>
+
+<div class=Section1>
+
+<h2><span class=SpellE><span style='font-family:Verdana'>AVSHwS</span></span><span
+style='font-family:Verdana'>: <span class=SpellE>AVStream</span> Simulated
+Hardware Sample Driver <o:p></o:p></span></h2>
+
+<h3><span style='font-family:Verdana'>SUMMARY<o:p></o:p></span></h3>
+
+<p><a name="OLE_LINK1"></a><a name="OLE_LINK2"><span style='mso-bookmark:OLE_LINK1'><span
+style='font-size:10.0pt;font-family:Verdana'>The </span></span></a><span
+class=SpellE><span style='mso-bookmark:OLE_LINK2'><span style='mso-bookmark:
+OLE_LINK1'><span style='font-size:10.0pt;font-family:Verdana'>AVSHwS</span></span></span></span><span
+style='mso-bookmark:OLE_LINK2'><span style='mso-bookmark:OLE_LINK1'><span
+style='font-size:10.0pt;font-family:Verdana'> sample provides a pin-centric <span
+class=SpellE>AVStream</span> capture driver for a simulated piece of hardware. The
+driver performs captures at 320x240 in either an RGB24 or YUV422 format via
+direct DMA into capture buffers. The purpose of the sample is to demonstrate
+how to write a pin-centric <span class=SpellE>AVStream</span> <span
+class=SpellE>minidriver</span>. The sample also shows how to implement DMA by
+using the related functionality provided by <span class=SpellE>AVStream</span>.<span
+style='mso-spacerun:yes'>� </span><o:p></o:p></span></span></span></p>
+
+<p><span style='mso-bookmark:OLE_LINK2'><span style='mso-bookmark:OLE_LINK1'><span
+style='font-size:10.0pt;font-family:Verdana'>This sample features enhanced
+parameter validation and overflow detection.<o:p></o:p></span></span></span></p>
+
+<span style='mso-bookmark:OLE_LINK1'></span><span style='mso-bookmark:OLE_LINK2'></span>
+
+<h3><span style='font-family:Verdana'>BUILDING THE SAMPLE<o:p></o:p></span></h3>
+
+<p>Build the sample by typing <span style='mso-bidi-font-weight:bold'>build -<span
+class=SpellE>c<span class=msoIns><ins cite="mailto:Sathya%20"
+datetime="2006-02-20T10:01">ez</ins></span></span></span> in either the standard
+checked or free WDK build environment. A successful build produces <span
+class=SpellE><span style='mso-bidi-font-style:italic'>AVSHwS.sys</span></span><span
+style='mso-bidi-font-style:italic'>.</span> <span style='font-size:10.0pt;
+font-family:Verdana'><o:p></o:p></span></p>
+
+<p><span style='font-size:10.0pt;font-family:Verdana'>The sample works on
+32-bit x86 and 64-bit amd64 platforms running Vista Beta 2 or higher, Windows XP
+SP2, Windows Server 2003 SP1 and Windows 2000 (If DirectX 8 or higher is
+installed on the system)<o:p></o:p></span></p>
+
+<p><span style='font-size:10.0pt;font-family:Verdana'>Installation
+instructions:<o:p></o:p></span></p>
+
+<ul type=disc>
+ <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;
+ mso-list:l1 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt;
+ font-family:Verdana'>Copy </span><span class=SpellE>AVSHwS<span
+ style='font-size:10.0pt;font-family:Verdana'>.sys</span></span><span
+ style='font-size:10.0pt;font-family:Verdana'> and </span><span
+ class=SpellE>AVSHwS<span style='font-size:10.0pt;font-family:Verdana'>.INF</span></span><span
+ style='font-size:10.0pt;font-family:Verdana'> to a directory <o:p></o:p></span></li>
+ <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;
+ mso-list:l1 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt;
+ font-family:Verdana'>Open �Add Hardware� wizard from Control Panel <o:p></o:p></span></li>
+ <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;
+ mso-list:l1 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt;
+ font-family:Verdana'>Select &quot;Install the hardware that I manually
+ select from a list (Advanced)&quot; <o:p></o:p></span></li>
+ <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;
+ mso-list:l1 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt;
+ font-family:Verdana'>When you see &quot;What type of hardware do you want
+ to install&quot;, select Sound, Video, and Game Controllers<o:p></o:p></span></li>
+ <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;
+ mso-list:l1 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt;
+ font-family:Verdana'>Select &quot;Have Disk...&quot; <o:p></o:p></span></li>
+ <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;
+ mso-list:l1 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt;
+ font-family:Verdana'>Browse to &quot; </span><span class=SpellE>AVSHwS<span
+ style='font-size:10.0pt;font-family:Verdana'>.INF</span></span><span
+ style='font-size:10.0pt;font-family:Verdana'> &quot;<o:p></o:p></span></li>
+ <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;
+ mso-list:l1 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt;
+ font-family:Verdana'>Follow the on screen instructions</span> <span
+ style='font-size:10.0pt;font-family:Verdana'><o:p></o:p></span></li>
+</ul>
+
+<h3>PROGRAMMING TOUR<span style='font-family:Verdana'><o:p></o:p></span></h3>
+
+<p><span class=SpellE><b><span style='font-size:10.0pt;font-family:Verdana'>DriverEntry</span></b></span><span
+style='font-size:10.0pt;font-family:Verdana'> in <span class=SpellE><i>device.cpp</i></span>
+is the initial point of entry. This routine passes control to <span
+class=SpellE>AVStream</span> through a call to <span class=SpellE><b>KsInitializeDriver</b></span>.
+In this call, the <span class=SpellE>minidriver</span> passes the device
+descriptor, an <span class=SpellE>AVStream</span> structure that recursively
+defines the <span class=SpellE>AVStream</span> object hierarchy for a driver.
+This is common behavior for an <span class=SpellE>AVStream</span> <span
+class=SpellE>minidriver</span>. <o:p></o:p></span></p>
+
+<p><span style='font-size:10.0pt;font-family:Verdana'>At device start time (see
+the <span class=SpellE><b>CcaptureDevice::PnpStart</b></span> method in <span
+class=SpellE><i>device.cpp</i></span>), a simulated piece of capture hardware
+is created (the <span class=SpellE>ChardwareSimulation</span> class)<span
+class=GramE>,</span> a DMA adapter is acquired from the operating system and is
+registered with <span class=SpellE>AVStream</span> through a call to <span
+class=SpellE><b>KsDeviceRegisterAdapterObject</b></span>. This call is required
+for a sample that performs DMA directly into the capture buffers, instead of
+using DMA to write to a common buffer. In <span class=SpellE>PnPStart</span>
+the driver creates the KS Filter for this device dynamically by calling </span><span
+class=SpellE><span style='font-family:"Courier New"'>KsCreateFilterFactory</span></span><span
+style='font-size:10.0pt;font-family:Verdana'>.<o:p></o:p></span></p>
+
+<p><span class=SpellE><i><span style='font-size:10.0pt;font-family:Verdana'>Filter.cpp</span></i></span><span
+style='font-size:10.0pt;font-family:Verdana'> is where the sample lays out the
+KSPIN_DESCRIPTOR_EX structure for the single capture pin. In addition, a
+KSFILTER_DISPATCH structure and a KSFILTER_DESCRIPTOR structure are provided in
+this source file. The filter dispatch provides only a create dispatch, a
+routine that is included in <span class=SpellE><i>Filter.cpp</i></span>. The
+process dispatch is provided on the pin, since this is a pin-centric sample.<span
+class=msoIns><ins cite="mailto:Sathya%20" datetime="2005-11-04T16:16"> </ins></span><o:p></o:p></span></p>
+
+<p><span class=SpellE><i><span style='font-size:10.0pt;font-family:Verdana'>Capture.cpp</span></i></span><span
+style='font-size:10.0pt;font-family:Verdana'> contains source for the video
+capture pin on the capture filter. This is where the KSPIN_DISPATCH structure
+for the unique pin is provided. This dispatch structure specifies a Process
+callback routine, also defined in this source file. This routine is where
+stream pointer manipulation and cloning occurs.<o:p></o:p></span></p>
+
+<p><span style='font-size:10.0pt;font-family:Verdana'>The process callback is
+one of two routines of interest in <span class=SpellE><i>Capture.cpp</i></span>
+that demonstrate how to do DMA transfers using <span class=SpellE>AVStream</span>
+functionality. The other is <span class=SpellE><b>CCapturePin::CompleteMappings</b></span>.
+These two methods show how to use the queue, obtain clone pointers, use
+scatter/gather lists, and perform other DMA-related tasks.<o:p></o:p></span></p>
+
+<p><span class=SpellE><i><span style='font-size:10.0pt;font-family:Verdana'>Hwsim.cpp</span></i></span><span
+style='font-size:10.0pt;font-family:Verdana'> contains the hardware simulation
+code and also code that fills the scatter/gather mappings. This source file
+includes the Start, Pause and Stop methods for the hardware simulation class (<span
+class=SpellE>CHardwaresimulation</span>). Image synthesis and overlay code is
+also here. The supplied objects provide image synthesis (pixel, color-bar,
+etc...) to RGB24 and UYVY buffers as well as software string overlay into these
+buffers. The <span class=SpellE><i>Image.cpp</i></span> file, including data,
+must exist in locked segments. <o:p></o:p></span></p>
+
+<p><span style='font-size:10.0pt;font-family:Verdana'>See comments in all .<span
+class=SpellE>cpp</span> files. Also see complete <span class=SpellE>AVStream</span>
+documentation in the WDK documentation. <o:p></o:p></span></p>
+
+<h3><span style='font-family:Verdana'>RUNNING THE SAMPLE<o:p></o:p></span></h3>
+
+<p><span class=GramE><span style='font-size:10.0pt;font-family:Verdana'>Once
+installation is complete, access the driver through the <span class=SpellE>graphedt</span>
+tool.</span></span><span style='font-size:10.0pt;font-family:Verdana'> <i>Graphedt.exe</i>
+is available in the <i>Tools</i> directory of the WDK. In the <span
+class=SpellE>Graphedt</span> application, click the Graph menu and select
+Insert Filters. The sample appears under &quot;WDM Streaming Capture
+Devices&quot; as &quot;<span class=SpellE>avshws</span> Source.&quot; Click
+Insert Filter and the sample appears in the graph as a single filter <span
+class=SpellE>labelled</span> <span class=GramE>as �</span><span class=SpellE>avshws</span>
+Source�. There is one output pin which is the video capture pin. It sends out
+video in YUY2 format. Attach this filter to either a DirectShow Video <span
+class=SpellE>Renderer</span> or the VMR default video <span class=SpellE>renderer</span>
+and click Play. <o:p></o:p></span></p>
+
+<p><span style='font-size:10.0pt;font-family:Verdana'>The output produced by
+the sample is a 320x240 image of standard EIA-189-A color bars. In the middle
+of the image near the bottom, a clock appears over the image. This clock
+displays the elapsed time since the graph was introduced into the run state
+following the last stop. The clock shows MINUTES<span class=GramE>:SECONDS.HUNDREDTHS</span>.
+<o:p></o:p></span></p>
+
+<p><span style='font-size:10.0pt;font-family:Verdana'>In the top left corner of
+the image, a counter counts the number of frames that have been dropped since
+the graph was introduced into the run state after the last stop. <o:p></o:p></span></p>
+
+<h3><span style='font-family:Verdana'>COMMENTS<o:p></o:p></span></h3>
+
+<p class=MsoNormal><span style='font-size:10.0pt;font-family:Verdana'>For more
+information on <span class=SpellE>AVStream</span>, see the WDK documentation. <o:p></o:p></span></p>
+
+<h3><span lang=FR style='font-family:Verdana;mso-ansi-language:FR'>CODE TOUR<o:p></o:p></span></h3>
+
+<h4><span lang=FR style='font-family:Verdana;mso-ansi-language:FR'>File
+Manifest<o:p></o:p></span></h4>
+
+<pre><u><span lang=FR style='mso-ansi-language:FR'>File</span></u><span
+lang=FR style='mso-ansi-language:FR'><span style='mso-tab-count:2'>���������� </span><u>Description<o:p></o:p></u></span></pre><pre><span
+lang=FR style='mso-ansi-language:FR'><o:p>&nbsp;</o:p></span></pre><pre>AVSHwS.htm<span
+style='mso-tab-count:1'>���� </span>The Sample Tour documentation for this sample (this file).</pre><pre><span
+class=GramE>Sources<span style='mso-tab-count:2'>������� </span>The generic file for building the code sample.</span></pre><pre><span
+class=SpellE>AVSHwS.inf</span><span style='mso-tab-count:1'>���� </span>A sample installation file.</pre><pre><span
+class=SpellE>AVSHwS.h</span><span style='mso-tab-count:1'>������ </span>The main <span
+class=GramE>header file</span> for the sample.</pre><pre><span class=SpellE><span
+class=GramE>device.cpp</span></span><span style='mso-tab-count:1'>���� </span><span
+class=SpellE>DriverEntry</span>, Plug and Play handling, initialization, device level code.</pre><pre><span
+class=SpellE><span class=GramE>device.h</span></span><span style='mso-tab-count:
+1'>������ </span>Header file for above.</pre><pre><span class=SpellE><span
+class=GramE>filter.cpp</span></span><span style='mso-tab-count:1'>���� </span>Filter level code for the capture filter.</pre><pre><span
+class=SpellE><span class=GramE>filter.h</span></span><span style='mso-tab-count:
+1'>������ </span>Header file for above.</pre><pre><span class=SpellE><span
+class=GramE>capture.cpp</span></span><span style='mso-tab-count:1'>��� </span>Pin level code for the capture pin, DMA handling.</pre><pre><span
+class=SpellE><span class=GramE>capture.h</span></span><span style='mso-tab-count:
+1'>����� </span>Header file for above.</pre><pre><span class=SpellE><span
+class=GramE>hwsim.cpp</span></span><span style='mso-tab-count:1'>����� </span>Hardware simulation code, filling scatter/gather mappings, etc.</pre><pre><span
+class=SpellE><span class=GramE>hwsim.h</span></span><span style='mso-tab-count:
+2'>������� </span>Header file for above.</pre><pre><span class=SpellE><span
+class=GramE>image.cpp</span></span><span class=GramE><span style='mso-tab-count:
+1'>����� </span>RGB24 and UYVY image synthesis and overlay code.</span></pre><pre><span
+class=SpellE><span class=GramE>image.h</span></span><span style='mso-tab-count:
+2'>������� </span>Header file for above.</pre><pre><span class=SpellE><span
+class=GramE>purecall.c</span></span><span style='mso-tab-count:1'>���� </span><span
+class=SpellE>P<span style='mso-fareast-font-family:SimSun;mso-no-proof:yes'>urecall</span></span><span
+style='mso-fareast-font-family:SimSun;mso-no-proof:yes'> stub for virtual function usage</span></pre><pre><span
+class=SpellE>AVSHwS.rc</span><span style='mso-tab-count:1'>����� </span>Resource <span
+class=GramE>file</span> mainly for version.</pre><pre><o:p>&nbsp;</o:p></pre><pre><o:p>&nbsp;</o:p></pre>
+
+<table class=MsoNormalTable border=0 cellspacing=0 cellpadding=0 width=624
+ style='width:6.5in;mso-cellspacing:0in;mso-padding-alt:0in 5.4pt 0in 5.4pt'>
+ <tr style='mso-yfti-irow:0;mso-yfti-firstrow:yes;mso-yfti-lastrow:yes;
+ height:1.5pt'>
+ <td style='background:aqua;padding:.75pt .75pt .75pt .75pt;height:1.5pt'>
+ <p class=MsoNormal><span style='font-size:2.0pt;mso-bidi-font-size:12.0pt'><o:p>&nbsp;</o:p></span></p>
+ </td>
+ </tr>
+</table>
+
+<pre><o:p>&nbsp;</o:p></pre>
+
+<p style='tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'>�
+2004- 2006 Microsoft Corporation<span style='font-size:10.0pt;font-family:Verdana'>
+</span><span style='font-size:10.0pt;font-family:Verdana;mso-bidi-font-family:
+"Courier New"'><o:p></o:p></span></p>
+
+<pre><o:p>&nbsp;</o:p></pre>
+
+<p class=MsoNormal style='tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><span
+style='mso-bidi-font-size:10.0pt'><o:p>&nbsp;</o:p></span></p>
+
+</div>
+
+</body>
+
+</html>
diff --git a/avstream/avshws/avshws.inf b/avstream/avshws/avshws.inf
new file mode 100644
index 00000000..5bf66468
--- /dev/null
+++ b/avstream/avshws/avshws.inf
@@ -0,0 +1,172 @@
+;/*++
+;
+;Copyright (c) Microsoft Corporation. All rights reserved.
+;
+; THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+; KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+; IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+; PURPOSE.
+;
+;Module Name:
+;
+; AVSHWS.INF
+;
+;Abstract:
+;
+;
+;AVStream pin centric sample mini driver (AVSHWS.sys) installation file.
+;Supports x86, amd64, arm and arm64 platforms
+;
+;--*/
+
+[Version]
+signature="$WINDOWS NT$"
+Class=Media
+ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318}
+Provider=%Msft%
+Catalogfile=avshws.cat
+DriverVer=08/31/2006,6.0.5600.0
+
+[SourceDisksNames]
+1000=%cdname%,,,
+
+[SourceDisksFiles]
+avshws.sys=1000
+
+[DestinationDirs]
+DefaultDestDir=12
+avshws.CopyFiles=12
+
+[avshws.CopyFiles]
+avshws.sys
+
+[Manufacturer]
+%Msft%=Microsoft,NTx86,NTamd64,ntarm,ntarm64
+
+[Microsoft.NTx86]
+%avshws.DeviceDesc%=avshws.NTx86,AVSHWS
+
+[Microsoft.NTamd64]
+%avshws.DeviceDesc%=avshws.NTamd64,AVSHWS
+
+[Microsoft.NTarm]
+%avshws.DeviceDesc%=avshws.NTarm,AVSHWS
+
+[Microsoft.NTarm64]
+%avshws.DeviceDesc%=avshws.NTarm64,AVSHWS
+
+;---------------------------------------------------------------
+; x 86 D D I n s t a l l
+;---------------------------------------------------------------
+
+[avshws.NTx86]
+Include=ks.inf, KSCAPTUR.inf
+Needs=KS.Registration,KSCAPTUR.Registration.NT
+CopyFiles=avshws.CopyFiles
+
+;---------------------------------------------------------------
+; A M D 64 D D I n s t a l l
+;---------------------------------------------------------------
+
+[avshws.NTamd64]
+Include=ks.inf,KSCAPTUR.inf
+Needs=KS.Registration,KSCAPTUR.Registration.NT
+CopyFiles=avshws.CopyFiles
+
+;---------------------------------------------------------------
+; A R M D D I n s t a l l
+;---------------------------------------------------------------
+
+[avshws.NTarm]
+Include=ks.inf,KSCAPTUR.inf
+Needs=KS.Registration,KSCAPTUR.Registration.NT
+CopyFiles=avshws.CopyFiles
+
+;---------------------------------------------------------------
+; A R M 64 D D I n s t a l l
+;---------------------------------------------------------------
+
+[avshws.NTarm64]
+Include=ks.inf,KSCAPTUR.inf
+Needs=KS.Registration,KSCAPTUR.Registration.NT
+CopyFiles=avshws.CopyFiles
+
+;---------------------------------------------------------------
+; I n t e r f a c e s
+;---------------------------------------------------------------
+
+[avshws.NTx86.Interfaces]
+AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
+AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
+AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
+
+[avshws.NTamd64.Interfaces]
+AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
+AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
+AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
+
+[avshws.NTarm.Interfaces]
+AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
+AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
+AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
+
+[avshws.NTarm64.Interfaces]
+AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
+AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
+AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
+
+[CaptureInterface.NT]
+AddReg=avshws.Reader.AddReg
+
+;---------------------------------------------------------------
+; A d d R e g
+;---------------------------------------------------------------
+
+[avshws.Reader.AddReg]
+HKR,,CLSID,,%Proxy.CLSID%
+HKR,,FriendlyName,,%avshws.Reader.FriendlyName%
+
+;---------------------------------------------------------------
+; S e r v i c e s
+;---------------------------------------------------------------
+
+[avshws.NTx86.Services]
+AddService=avshws, 0x00000002, avshws.ServiceInstall
+
+[avshws.NTamd64.Services]
+AddService=avshws, 0x00000002, avshws.ServiceInstall
+
+[avshws.NTarm.Services]
+AddService=avshws, 0x00000002, avshws.ServiceInstall
+
+[avshws.NTarm64.Services]
+AddService=avshws, 0x00000002, avshws.ServiceInstall
+
+[avshws.ServiceInstall]
+DisplayName=%avshws.DeviceDesc%
+ServiceType=%SERVICE_KERNEL_DRIVER%
+StartType=%SERVICE_DEMAND_START%
+ErrorControl=%SERVICE_ERROR_NORMAL%
+ServiceBinary=%12%\avshws.sys
+
+;---------------------------------------------------------------
+; S t r i n g s
+;---------------------------------------------------------------
+
+[Strings]
+; non-localizable
+Proxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
+KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
+KSCATEGORY_VIDEO="{6994AD05-93EF-11D0-A3CC-00A0C9223196}"
+KSCATEGORY_VIDEO_CAMERA="{E5323777-F976-4f5b-9B55-B94699C46E44}"
+
+SERVICE_KERNEL_DRIVER=1
+SERVICE_DEMAND_START=3
+SERVICE_ERROR_NORMAL=1
+REG_DWORD=0x00010001
+
+;localizable
+Msft="Microsoft"
+avshws.DeviceDesc="AVStream Simulated Hardware Sample"
+avshws.Reader.FriendlyName="avshws Source"
+cdname="AVSHWS Installation Disk" \ No newline at end of file
diff --git a/avstream/avshws/avshws.rc b/avstream/avshws/avshws.rc
new file mode 100644
index 00000000..3e8a3e6a
--- /dev/null
+++ b/avstream/avshws/avshws.rc
@@ -0,0 +1,22 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+//
+// Copyright (C) Microsoft Corporation, 1999 - 1999
+//
+// File: captst.rc
+//
+//--------------------------------------------------------------------------
+
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "AVStream Simulated Hardware Sample"
+#define VER_INTERNALNAME_STR "avshws.sys"
+#define VER_ORIGINALFILENAME_STR "avshws.sys"
+
+#include "common.ver"
+
diff --git a/avstream/avshws/avshws.sln b/avstream/avshws/avshws.sln
new file mode 100644
index 00000000..08896741
--- /dev/null
+++ b/avstream/avshws/avshws.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0
+MinimumVisualStudioVersion = 12.0
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avshws", "avshws.vcxproj", "{A186D470-31E9-4CAF-9919-6279777D8ABD}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A186D470-31E9-4CAF-9919-6279777D8ABD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A186D470-31E9-4CAF-9919-6279777D8ABD}.Debug|Win32.Build.0 = Debug|Win32
+ {A186D470-31E9-4CAF-9919-6279777D8ABD}.Release|Win32.ActiveCfg = Release|Win32
+ {A186D470-31E9-4CAF-9919-6279777D8ABD}.Release|Win32.Build.0 = Release|Win32
+ {A186D470-31E9-4CAF-9919-6279777D8ABD}.Debug|x64.ActiveCfg = Debug|x64
+ {A186D470-31E9-4CAF-9919-6279777D8ABD}.Debug|x64.Build.0 = Debug|x64
+ {A186D470-31E9-4CAF-9919-6279777D8ABD}.Release|x64.ActiveCfg = Release|x64
+ {A186D470-31E9-4CAF-9919-6279777D8ABD}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/avstream/avshws/avshws.vcxproj b/avstream/avshws/avshws.vcxproj
new file mode 100644
index 00000000..af274dcc
--- /dev/null
+++ b/avstream/avshws/avshws.vcxproj
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{A186D470-31E9-4CAF-9919-6279777D8ABD}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{FBEB03DA-BEFF-446C-AF78-E7ED9881996F}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>WDM</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>WDM</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>WDM</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>WDM</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>avshws</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>avshws</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>avshws</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>avshws</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ks.lib</AdditionalDependencies>
+ <AdditionalOptions>%(AdditionalOptions) -merge:PAGECONST=PAGE</AdditionalOptions>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ks.lib</AdditionalDependencies>
+ <AdditionalOptions>%(AdditionalOptions) -merge:PAGECONST=PAGE</AdditionalOptions>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ks.lib</AdditionalDependencies>
+ <AdditionalOptions>%(AdditionalOptions) -merge:PAGECONST=PAGE</AdditionalOptions>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ks.lib</AdditionalDependencies>
+ <AdditionalOptions>%(AdditionalOptions) -merge:PAGECONST=PAGE</AdditionalOptions>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="capture.cpp" />
+ <ClCompile Include="device.cpp" />
+ <ClCompile Include="filter.cpp" />
+ <ClCompile Include="hwsim.cpp" />
+ <ClCompile Include="image.cpp" />
+ <ClCompile Include="purecall.c" />
+ <ResourceCompile Include="avshws.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/avstream/avshws/avshws.vcxproj.Filters b/avstream/avshws/avshws.vcxproj.Filters
new file mode 100644
index 00000000..318e9d42
--- /dev/null
+++ b/avstream/avshws/avshws.vcxproj.Filters
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{C2894B1A-8188-468F-AF01-0EAE14CD2040}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{73B3B8CC-EA08-420A-AD92-489BAEEF0DE5}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{A91E7CB8-3994-4C84-8CBA-0B18FA3FDD11}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{8C5EEC35-3838-457C-A60E-507C6503A48D}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="capture.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="device.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="filter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="hwsim.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="image.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="purecall.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="avshws.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/avstream/avshws/capture.cpp b/avstream/avshws/capture.cpp
new file mode 100644
index 00000000..5632a4a1
--- /dev/null
+++ b/avstream/avshws/capture.cpp
@@ -0,0 +1,1704 @@
+/**************************************************************************
+
+ AVStream Simulated Hardware Sample
+
+ Copyright (c) 2001, Microsoft Corporation.
+
+ File:
+
+ capture.cpp
+
+ Abstract:
+
+ This file contains source for the video capture pin on the capture
+ filter. The capture sample performs "fake" DMA directly into
+ the capture buffers. Common buffer DMA will work slightly differently.
+
+ For common buffer DMA, the general technique would be DPC schedules
+ processing with KsPinAttemptProcessing. The processing routine grabs
+ the leading edge, copies data out of the common buffer and advances.
+ Cloning would not be necessary with this technique. It would be
+ similiar to the way "AVSSamp" works, but it would be pin-centric.
+
+ History:
+
+ created 3/8/2001
+
+**************************************************************************/
+
+#include "avshws.h"
+#include <ksmedia.h>
+#include "ntintsafe.h"
+
+/**************************************************************************
+
+ PAGEABLE CODE
+
+**************************************************************************/
+
+
+#ifdef ALLOC_PRAGMA
+#pragma code_seg("PAGE")
+#endif // ALLOC_PRAGMA
+
+#define DMAX_X 320
+#define DMAX_Y 240
+#define D_X 320
+#define D_Y 240
+
+CCapturePin::
+CCapturePin (
+ IN PKSPIN Pin
+ ) :
+ m_Pin (Pin)
+ ,m_PresentationTime (0)
+
+/*++
+
+Routine Description:
+
+ Construct a new capture pin.
+
+Arguments:
+
+ Pin -
+ The AVStream pin object corresponding to the capture pin
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ PKSDEVICE Device = KsPinGetDevice (Pin);
+
+ //
+ // Set up our device pointer. This gives us access to "hardware I/O"
+ // during the capture routines.
+ //
+ m_Device = reinterpret_cast <CCaptureDevice *> (Device -> Context);
+}
+
+/*************************************************/
+
+
+NTSTATUS
+CCapturePin::
+DispatchCreate (
+ IN PKSPIN Pin,
+ IN PIRP Irp
+ )
+
+/*++
+
+Routine Description:
+
+ Create a new capture pin. This is the creation dispatch for
+ the video capture pin.
+
+Arguments:
+
+ Pin -
+ The pin being created
+
+ Irp -
+ The creation Irp
+
+Return Value:
+
+ Success / Failure
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ CCapturePin *CapPin = new (NonPagedPool) CCapturePin (Pin);
+
+ if (!CapPin) {
+ //
+ // Return failure if we couldn't create the pin.
+ //
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+
+ } else {
+ //
+ // Add the item to the object bag if we we were successful.
+ // Whenever the pin closes, the bag is cleaned up and we will be
+ // freed.
+ //
+ Status = KsAddItemToObjectBag (
+ Pin -> Bag,
+ reinterpret_cast <PVOID> (CapPin),
+ reinterpret_cast <PFNKSFREE> (CCapturePin::Cleanup)
+ );
+
+ if (!NT_SUCCESS (Status)) {
+ delete CapPin;
+ } else {
+ Pin -> Context = reinterpret_cast <PVOID> (CapPin);
+ }
+
+ }
+
+ //
+ // If we succeeded so far, stash the video info header away and change
+ // our allocator framing to reflect the fact that only now do we know
+ // the framing requirements based on the connection format.
+ //
+ PKS_VIDEOINFOHEADER VideoInfoHeader = NULL;
+
+ if (NT_SUCCESS (Status)) {
+
+ VideoInfoHeader = CapPin -> CaptureVideoInfoHeader ();
+ if (!VideoInfoHeader) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ if (NT_SUCCESS(Status)) {
+ //
+ // We need to edit the descriptor to ensure we don't mess up any other
+ // pins using the descriptor or touch read-only memory.
+ //
+ Status = KsEdit (
+ Pin,
+ &Pin -> Descriptor,
+ AVSHWS_POOLTAG);
+
+ if (NT_SUCCESS (Status)) {
+
+ //
+ // If the edits proceeded without running out of memory, adjust
+ // the framing based on the video info header.
+ //
+ Status = KsEdit (
+ Pin,
+ &Pin -> Descriptor -> AllocatorFraming,
+ AVSHWS_POOLTAG);
+
+ if (NT_SUCCESS (Status)) {
+
+ //
+ // We've KsEdit'ed this... I'm safe to cast away constness as
+ // long as the edit succeeded.
+ //
+ PKSALLOCATOR_FRAMING_EX Framing =
+ const_cast <PKSALLOCATOR_FRAMING_EX> (
+ Pin -> Descriptor -> AllocatorFraming
+ );
+
+ Framing -> FramingItem [0].Frames = 2;
+
+ //
+ // The physical and optimal ranges must be biSizeImage. We only
+ // support one frame size, precisely the size of each capture
+ // image.
+ //
+ Framing -> FramingItem [0].PhysicalRange.MinFrameSize =
+ Framing -> FramingItem [0].PhysicalRange.MaxFrameSize =
+ Framing -> FramingItem [0].FramingRange.Range.MinFrameSize =
+ Framing -> FramingItem [0].FramingRange.Range.MaxFrameSize =
+ VideoInfoHeader -> bmiHeader.biSizeImage;
+
+ Framing -> FramingItem [0].PhysicalRange.Stepping =
+ Framing -> FramingItem [0].FramingRange.Range.Stepping =
+ 0;
+
+ }
+
+ }
+ }
+
+ if (NT_SUCCESS (Status)) {
+ //
+ // Adjust the stream header size. The video packets have extended
+ // header info (KS_FRAME_INFO).
+ //
+ Pin -> StreamHeaderSize = sizeof (KSSTREAM_HEADER) +
+ sizeof (KS_FRAME_INFO);
+
+ }
+ return Status;
+}
+
+/*************************************************/
+
+
+PKS_VIDEOINFOHEADER
+CCapturePin::
+CaptureVideoInfoHeader (
+ )
+
+/*++
+
+Routine Description:
+
+ Capture the video info header out of the connection format. This
+ is what we use to base synthesized images off.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ The captured video info header or NULL if there is insufficient
+ memory.
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ PKS_VIDEOINFOHEADER ConnectionHeader =
+ &((reinterpret_cast <PKS_DATAFORMAT_VIDEOINFOHEADER>
+ (m_Pin -> ConnectionFormat)) ->
+ VideoInfoHeader);
+
+ m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
+ ExAllocatePoolWithTag (
+ NonPagedPool,
+ KS_SIZE_VIDEOHEADER (ConnectionHeader),
+ AVSHWS_POOLTAG
+ )
+ );
+
+ if (!m_VideoInfoHeader)
+ return NULL;
+
+ //
+ // Bag the newly allocated header space. This will get cleaned up
+ // automatically when the pin closes.
+ //
+ NTSTATUS Status =
+ KsAddItemToObjectBag (
+ m_Pin -> Bag,
+ reinterpret_cast <PVOID> (m_VideoInfoHeader),
+ NULL
+ );
+
+ if (!NT_SUCCESS (Status)) {
+
+ ExFreePool (m_VideoInfoHeader);
+ return NULL;
+
+ } else {
+
+ //
+ // Copy the connection format video info header into the newly
+ // allocated "captured" video info header.
+ //
+ RtlCopyMemory (
+ m_VideoInfoHeader,
+ ConnectionHeader,
+ KS_SIZE_VIDEOHEADER (ConnectionHeader)
+ );
+
+ }
+
+ return m_VideoInfoHeader;
+
+}
+
+
+NTSTATUS
+CCapturePin::
+Process (
+ )
+
+/*++
+
+Routine Description:
+
+ The process dispatch for the pin bridges to this location.
+ We handle setting up scatter gather mappings, etc...
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Success / Failure
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ PKSSTREAM_POINTER Leading;
+
+ _DbgPrintF(DEBUGLVL_VERBOSE, ("Process"));
+
+ Leading = KsPinGetLeadingEdgeStreamPointer (
+ m_Pin,
+ KSSTREAM_POINTER_STATE_LOCKED
+ );
+
+ while (NT_SUCCESS (Status) && Leading) {
+
+ PKSSTREAM_POINTER ClonePointer;
+ PSTREAM_POINTER_CONTEXT SPContext = NULL;
+
+ //
+ // If no data is present in the Leading edge stream pointer, just
+ // move on to the next frame
+ //
+ if ( NULL == Leading -> StreamHeader -> Data ) {
+ Status = KsStreamPointerAdvance(Leading);
+ continue;
+ }
+ //
+ // For optimization sake in this particular sample, I will only keep
+ // one clone stream pointer per frame. This complicates the logic
+ // here but simplifies the completions.
+ //
+ // I'm also choosing to do this since I need to keep track of the
+ // virtual addresses corresponding to each mapping since I'm faking
+ // DMA. It simplifies that too.
+ //
+ if (!m_PreviousStreamPointer) {
+ //
+ // First thing we need to do is clone the leading edge. This allows
+ // us to keep reference on the frames while they're in DMA.
+ //
+ Status = KsStreamPointerClone (
+ Leading,
+ NULL,
+ sizeof (STREAM_POINTER_CONTEXT),
+ &ClonePointer
+ );
+
+ //
+ // I use this for easy chunking of the buffer. We're not really
+ // dealing with physical addresses. This keeps track of what
+ // virtual address in the buffer the current scatter / gather
+ // mapping corresponds to for the fake hardware.
+ //
+ if (NT_SUCCESS (Status)) {
+
+ //
+ // Set the stream header data used to 0. We update this
+ // in the DMA completions. For queues with DMA, we must
+ // update this field ourselves.
+ //
+ ClonePointer -> StreamHeader -> DataUsed = 0;
+
+ SPContext = reinterpret_cast <PSTREAM_POINTER_CONTEXT>
+ (ClonePointer -> Context);
+
+ SPContext -> BufferVirtual =
+ reinterpret_cast <PUCHAR> (
+ ClonePointer -> StreamHeader -> Data
+ );
+ }
+
+ } else {
+
+ ClonePointer = m_PreviousStreamPointer;
+ SPContext = reinterpret_cast <PSTREAM_POINTER_CONTEXT>
+ (ClonePointer -> Context);
+ Status = STATUS_SUCCESS;
+ }
+
+ //
+ // If the clone failed, likely we're out of resources. Break out
+ // of the loop for now. We may end up starving DMA.
+ //
+ if (!NT_SUCCESS (Status)) {
+ KsStreamPointerUnlock (Leading, FALSE);
+ break;
+ }
+
+ //
+ // Program the fake hardware. I would use Clone -> OffsetOut.*, but
+ // because of the optimization of one stream pointer per frame, it
+ // doesn't make complete sense.
+ //
+ ULONG MappingsUsed =
+ m_Device -> ProgramScatterGatherMappings (
+ ClonePointer,
+ &(SPContext -> BufferVirtual),
+ Leading -> OffsetOut.Mappings,
+ Leading -> OffsetOut.Remaining
+ );
+
+ //
+ // In order to keep one clone per frame and simplify the fake DMA
+ // logic, make a check to see if we completely used the mappings in
+ // the leading edge. Set a flag.
+ //
+ if (MappingsUsed == Leading -> OffsetOut.Remaining) {
+ m_PreviousStreamPointer = NULL;
+ } else {
+ m_PreviousStreamPointer = ClonePointer;
+ }
+
+ if (MappingsUsed) {
+ //
+ // If any mappings were added to scatter / gather queues,
+ // advance the leading edge by that number of mappings. If
+ // we run off the end of the queue, Status will be
+ // STATUS_DEVICE_NOT_READY. Otherwise, the leading edge will
+ // point to a new frame. The previous one will not have been
+ // dismissed (unless "DMA" completed) since there's a clone
+ // pointer referencing the frames.
+ //
+ Status =
+ KsStreamPointerAdvanceOffsets (
+ Leading,
+ 0,
+ MappingsUsed,
+ FALSE
+ );
+ } else {
+
+ //
+ // The hardware was incapable of adding more entries. The S/G
+ // table is full.
+ //
+ Status = STATUS_PENDING;
+ break;
+
+ }
+
+ }
+
+ //
+ // If the leading edge failed to lock (this is always possible, remember
+ // that locking CAN occassionally fail), don't blow up passing NULL
+ // into KsStreamPointerUnlock. Also, set m_PendIo to kick us later...
+ //
+ if (!Leading) {
+
+ m_PendIo = TRUE;
+
+ //
+ // If the lock failed, there's no point in getting called back
+ // immediately. The lock could fail due to insufficient memory,
+ // etc... In this case, we don't want to get called back immediately.
+ // Return pending. The m_PendIo flag will cause us to get kicked
+ // later.
+ //
+ Status = STATUS_PENDING;
+ }
+
+ //
+ // If we didn't run the leading edge off the end of the queue, unlock it.
+ //
+ if (NT_SUCCESS (Status) && Leading) {
+ KsStreamPointerUnlock (Leading, FALSE);
+ } else {
+ //
+ // DEVICE_NOT_READY indicates that the advancement ran off the end
+ // of the queue. We couldn't lock the leading edge.
+ //
+ if (Status == STATUS_DEVICE_NOT_READY) Status = STATUS_SUCCESS;
+ }
+
+ //
+ // If we failed with something that requires pending, set the pending I/O
+ // flag so we know we need to start it again in a completion DPC.
+ //
+ if (!NT_SUCCESS (Status) || Status == STATUS_PENDING) {
+ m_PendIo = TRUE;
+ }
+
+ _DbgPrintF(DEBUGLVL_VERBOSE, ("Leaving Process..."));
+ return Status;
+
+}
+
+/*************************************************/
+
+
+NTSTATUS
+CCapturePin::
+CleanupReferences (
+ )
+
+/*++
+
+Routine Description:
+
+ Clean up any references we're holding on frames after we abruptly
+ stop the hardware.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Success / Failure
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ PKSSTREAM_POINTER Clone = KsPinGetFirstCloneStreamPointer (m_Pin);
+ PKSSTREAM_POINTER NextClone = NULL;
+
+ //
+ // Walk through the clones, deleting them, and setting DataUsed to
+ // zero since we didn't use any data!
+ //
+ while (Clone) {
+
+ NextClone = KsStreamPointerGetNextClone (Clone);
+
+ Clone -> StreamHeader -> DataUsed = 0;
+ KsStreamPointerDelete (Clone);
+
+ Clone = NextClone;
+
+ }
+
+ return STATUS_SUCCESS;
+
+}
+
+/*************************************************/
+
+
+NTSTATUS
+CCapturePin::
+SetState (
+ IN KSSTATE ToState,
+ IN KSSTATE FromState
+ )
+
+/*++
+
+Routine Description:
+
+ This is called when the caputre pin transitions state. The routine
+ attempts to acquire / release any hardware resources and start up
+ or shut down capture based on the states we are transitioning to
+ and away from.
+
+Arguments:
+
+ ToState -
+ The state we're transitioning to
+
+ FromState -
+ The state we're transitioning away from
+
+Return Value:
+
+ Success / Failure
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ switch (ToState) {
+
+ case KSSTATE_STOP:
+
+ //
+ // First, stop the hardware if we actually did anything to it.
+ //
+ if (m_HardwareState != HardwareStopped) {
+ Status = m_Device -> Stop ();
+ NT_ASSERT (NT_SUCCESS (Status));
+
+ m_HardwareState = HardwareStopped;
+ }
+
+ //
+ // We've stopped the "fake hardware". It has cleared out
+ // it's scatter / gather tables and will no longer be
+ // completing clones. We had locks on some frames that were,
+ // however, in hardware. This will clean them up. An
+ // alternative location would be in the reset dispatch.
+ // Note, however, that the reset dispatch can occur in any
+ // state and this should be understood.
+ //
+ // Some hardware may fill all S/G mappings before stopping...
+ // in this case, you may not have to do this. The
+ // "fake hardware" here simply stops filling mappings and
+ // cleans its scatter / gather tables out on the Stop call.
+ //
+ Status = CleanupReferences ();
+
+ //
+ // Release any hardware resources related to this pin.
+ //
+ if (m_AcquiredResources) {
+ //
+ // If we got an interface to the clock, we must release it.
+ //
+ if (m_Clock) {
+ m_Clock -> Release ();
+ m_Clock = NULL;
+ }
+
+ m_Device -> ReleaseHardwareResources (
+ );
+
+ m_AcquiredResources = FALSE;
+ }
+
+ break;
+
+ case KSSTATE_ACQUIRE:
+ //
+ // Acquire any hardware resources related to this pin. We should
+ // only acquire them here -- **NOT** at filter create time.
+ // This means we do not fail creation of a filter because of
+ // limited hardware resources.
+ //
+ if (FromState == KSSTATE_STOP) {
+ Status = m_Device -> AcquireHardwareResources (
+ this,
+ m_VideoInfoHeader
+ );
+
+ if (NT_SUCCESS (Status)) {
+ m_AcquiredResources = TRUE;
+
+ //
+ // Attempt to get an interface to the master clock.
+ // This will fail if one has not been assigned. Since
+ // one must be assigned while the pin is still in
+ // KSSTATE_STOP, this is a guranteed method of getting
+ // the clock should one be assigned.
+ //
+ if (!NT_SUCCESS (
+ KsPinGetReferenceClockInterface (
+ m_Pin,
+ &m_Clock
+ )
+ )) {
+
+ //
+ // If we could not get an interface to the clock,
+ // don't use one.
+ //
+ m_Clock = NULL;
+
+ }
+
+ } else {
+ m_AcquiredResources = FALSE;
+ }
+
+ } else {
+ //
+ // Standard transport pins will always receive transitions in
+ // +/- 1 manner. This means we'll always see a PAUSE->ACQUIRE
+ // transition before stopping the pin.
+ //
+ // The below is done because on DirectX 8.0, when the pin gets
+ // a message to stop, the queue is inaccessible. The reset
+ // which comes on every stop happens after this (at which time
+ // the queue is inaccessible also). So, for compatibility with
+ // DirectX 8.0, I am stopping the "fake" hardware at this
+ // point and cleaning up all references we have on frames. See
+ // the comments above regarding the CleanupReferences call.
+ //
+ // If this sample were targeting XP only, the below code would
+ // not be here. Again, I only do this so the sample does not
+ // hang when it is stopped running on a configuration such as
+ // Win2K + DX8.
+ //
+ if (m_HardwareState != HardwareStopped) {
+ Status = m_Device -> Stop ();
+ NT_ASSERT (NT_SUCCESS (Status));
+
+ m_HardwareState = HardwareStopped;
+ }
+
+ Status = CleanupReferences ();
+ }
+
+ m_FrameNumber = 0;
+ m_DroppedFrames = 0;
+ break;
+
+ case KSSTATE_PAUSE:
+ //
+ // Stop the hardware simulation if we're coming down from run.
+ //
+ if (FromState == KSSTATE_RUN) {
+
+ m_PresentationTime = 0;
+ Status = m_Device -> Pause (TRUE);
+
+ if (NT_SUCCESS (Status)) {
+ m_HardwareState = HardwarePaused;
+ }
+
+ }
+ m_FrameNumber = 0;
+ break;
+
+ case KSSTATE_RUN:
+ //
+ // Start the hardware simulation or unpause it depending on
+ // whether we're initially running or we've paused and restarted.
+ //
+ if (m_HardwareState == HardwarePaused) {
+ Status = m_Device -> Pause (FALSE);
+ } else {
+ Status = m_Device -> Start ();
+ }
+
+ if (NT_SUCCESS (Status)) {
+ m_HardwareState = HardwareRunning;
+ }
+
+ break;
+
+ }
+
+ return Status;
+
+}
+
+/*************************************************/
+
+
+NTSTATUS
+CCapturePin::
+IntersectHandler (
+ IN PKSFILTER Filter,
+ IN PIRP Irp,
+ IN PKSP_PIN PinInstance,
+ IN PKSDATARANGE CallerDataRange,
+ IN PKSDATARANGE DescriptorDataRange,
+ IN ULONG BufferSize,
+ OUT PVOID Data OPTIONAL,
+ OUT PULONG DataSize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine handles video pin intersection queries by determining the
+ intersection between two data ranges.
+
+Arguments:
+
+ Filter -
+ Contains a void pointer to the filter structure.
+
+ Irp -
+ Contains a pointer to the data intersection property request.
+
+ PinInstance -
+ Contains a pointer to a structure indicating the pin in question.
+
+ CallerDataRange -
+ Contains a pointer to one of the data ranges supplied by the client
+ in the data intersection request. The format type, subtype and
+ specifier are compatible with the DescriptorDataRange.
+
+ DescriptorDataRange -
+ Contains a pointer to one of the data ranges from the pin descriptor
+ for the pin in question. The format type, subtype and specifier are
+ compatible with the CallerDataRange.
+
+ BufferSize -
+ Contains the size in bytes of the buffer pointed to by the Data
+ argument. For size queries, this value will be zero.
+
+ Data -
+ Optionally contains a pointer to the buffer to contain the data
+ format structure representing the best format in the intersection
+ of the two data ranges. For size queries, this pointer will be
+ NULL.
+
+ DataSize -
+ Contains a pointer to the location at which to deposit the size
+ of the data format. This information is supplied by the function
+ when the format is actually delivered and in response to size
+ queries.
+
+Return Value:
+
+ STATUS_SUCCESS if there is an intersection and it fits in the supplied
+ buffer, STATUS_BUFFER_OVERFLOW for successful size queries,
+ STATUS_NO_MATCH if the intersection is empty, or
+ STATUS_BUFFER_TOO_SMALL if the supplied buffer is too small.
+
+--*/
+
+{
+ PAGED_CODE();
+
+ const GUID VideoInfoSpecifier =
+ {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VIDEOINFO)};
+
+ NT_ASSERT(Filter);
+ NT_ASSERT(Irp);
+ NT_ASSERT(PinInstance);
+ NT_ASSERT(CallerDataRange);
+ NT_ASSERT(DescriptorDataRange);
+ NT_ASSERT(DataSize);
+
+ ULONG DataFormatSize;
+
+ //
+ // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
+ //
+ if (IsEqualGUID(CallerDataRange->Specifier, VideoInfoSpecifier) &&
+ CallerDataRange -> FormatSize >= sizeof (KS_DATARANGE_VIDEO)) {
+
+ PKS_DATARANGE_VIDEO callerDataRange =
+ reinterpret_cast <PKS_DATARANGE_VIDEO> (CallerDataRange);
+
+ PKS_DATARANGE_VIDEO descriptorDataRange =
+ reinterpret_cast <PKS_DATARANGE_VIDEO> (DescriptorDataRange);
+
+ PKS_DATAFORMAT_VIDEOINFOHEADER FormatVideoInfoHeader;
+
+ //
+ // Check that the other fields match
+ //
+ if ((callerDataRange->bFixedSizeSamples !=
+ descriptorDataRange->bFixedSizeSamples) ||
+ (callerDataRange->bTemporalCompression !=
+ descriptorDataRange->bTemporalCompression) ||
+ (callerDataRange->StreamDescriptionFlags !=
+ descriptorDataRange->StreamDescriptionFlags) ||
+ (callerDataRange->MemoryAllocationFlags !=
+ descriptorDataRange->MemoryAllocationFlags) ||
+ (RtlCompareMemory (&callerDataRange->ConfigCaps,
+ &descriptorDataRange->ConfigCaps,
+ sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)) !=
+ sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)))
+ {
+ return STATUS_NO_MATCH;
+ }
+
+ //
+ // KS_SIZE_VIDEOHEADER() below is relying on bmiHeader.biSize from
+ // the caller's data range. This **MUST** be validated; the
+ // extended bmiHeader size (biSize) must not extend past the end
+ // of the range buffer. Possible arithmetic overflow is also
+ // checked for.
+ //
+ {
+ ULONG VideoHeaderSize = KS_SIZE_VIDEOHEADER (
+ &callerDataRange->VideoInfoHeader
+ );
+
+ ULONG DataRangeSize =
+ FIELD_OFFSET (KS_DATARANGE_VIDEO, VideoInfoHeader) +
+ VideoHeaderSize;
+
+ //
+ // Check that biSize does not extend past the buffer. The
+ // first two checks are for arithmetic overflow on the
+ // operations to compute the alleged size. (On unsigned
+ // math, a+b < a iff an arithmetic overflow occurred).
+ //
+ if (
+ VideoHeaderSize < callerDataRange->
+ VideoInfoHeader.bmiHeader.biSize ||
+ DataRangeSize < VideoHeaderSize ||
+ DataRangeSize > callerDataRange -> DataRange.FormatSize
+ ) {
+
+ return STATUS_INVALID_PARAMETER;
+
+ }
+
+ }
+
+ DataFormatSize =
+ sizeof (KSDATAFORMAT) +
+ KS_SIZE_VIDEOHEADER (&callerDataRange->VideoInfoHeader);
+
+
+ //
+ // If the passed buffer size is 0, it indicates that this is a size
+ // only query. Return the size of the intersecting data format and
+ // pass back STATUS_BUFFER_OVERFLOW.
+ //
+ if (BufferSize == 0) {
+
+ *DataSize = DataFormatSize;
+ return STATUS_BUFFER_OVERFLOW;
+
+ }
+
+ //
+ // Verify that the provided structure is large enough to
+ // accept the result.
+ //
+ if (BufferSize < DataFormatSize)
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Copy over the KSDATAFORMAT, followed by the actual VideoInfoHeader
+ //
+ *DataSize = DataFormatSize;
+
+ FormatVideoInfoHeader = PKS_DATAFORMAT_VIDEOINFOHEADER( Data );
+
+ //
+ // Copy over the KSDATAFORMAT. This is precisely the same as the
+ // KSDATARANGE (it's just the GUIDs, etc... not the format information
+ // following any data format.
+ //
+ RtlCopyMemory (
+ &FormatVideoInfoHeader->DataFormat,
+ DescriptorDataRange,
+ sizeof (KSDATAFORMAT));
+
+ FormatVideoInfoHeader->DataFormat.FormatSize = DataFormatSize;
+
+ //
+ // Copy over the callers requested VIDEOINFOHEADER
+ //
+
+ RtlCopyMemory (
+ &FormatVideoInfoHeader->VideoInfoHeader,
+ &callerDataRange->VideoInfoHeader,
+ KS_SIZE_VIDEOHEADER (&callerDataRange->VideoInfoHeader)
+ );
+
+ //
+ // Calculate biSizeImage for this request, and put the result in both
+ // the biSizeImage field of the bmiHeader AND in the SampleSize field
+ // of the DataFormat.
+ //
+ // Note that for compressed sizes, this calculation will probably not
+ // be just width * height * bitdepth
+ //
+ FormatVideoInfoHeader->VideoInfoHeader.bmiHeader.biSizeImage =
+ FormatVideoInfoHeader->DataFormat.SampleSize =
+ KS_DIBSIZE (FormatVideoInfoHeader->VideoInfoHeader.bmiHeader);
+
+ //
+ // REVIEW - Perform other validation such as cropping and scaling checks
+ //
+
+ return STATUS_SUCCESS;
+
+ } // End of VIDEOINFOHEADER specifier
+
+ return STATUS_NO_MATCH;
+}
+
+/*************************************************/
+
+BOOL
+MultiplyCheckOverflow (
+ ULONG a,
+ ULONG b,
+ ULONG *pab
+ )
+
+/*++
+
+Routine Description:
+
+ Perform a 32 bit unsigned multiplication and check for arithmetic overflow.
+
+Arguments:
+
+ a -
+ First operand
+
+ b -
+ Second operand
+
+ pab -
+ Result
+
+Return Value:
+
+ TRUE -
+ no overflow
+
+ FALSE -
+ overflow occurred
+
+--*/
+
+{
+ PAGED_CODE();
+
+ *pab = a * b;
+ if ((a == 0) || (((*pab) / a) == b)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*************************************************/
+
+
+NTSTATUS
+CCapturePin::
+DispatchSetFormat (
+ IN PKSPIN Pin,
+ IN PKSDATAFORMAT OldFormat OPTIONAL,
+ IN PKSMULTIPLE_ITEM OldAttributeList OPTIONAL,
+ IN const KSDATARANGE *DataRange,
+ IN const KSATTRIBUTE_LIST *AttributeRange OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This is the set data format dispatch for the capture pin. It is called
+ in two circumstances.
+
+ 1: before Pin's creation dispatch has been made to verify that
+ Pin -> ConnectionFormat is an acceptable format for the range
+ DataRange. In this case OldFormat is NULL.
+
+ 2: after Pin's creation dispatch has been made and an initial format
+ selected in order to change the format for the pin. In this case,
+ OldFormat will not be NULL.
+
+ Validate that the format is acceptible and perform the actions necessary
+ to change format if appropriate.
+
+Arguments:
+
+ Pin -
+ The pin this format is being set on. The format itself will be in
+ Pin -> ConnectionFormat.
+
+ OldFormat -
+ The previous format used on this pin. If this is NULL, it is an
+ indication that Pin's creation dispatch has not yet been made and
+ that this is a request to validate the initial format and not to
+ change formats.
+
+ OldAttributeList -
+ The old attribute list for the prior format
+
+ DataRange -
+ A range out of our list of data ranges which was determined to be
+ at least a partial match for Pin -> ConnectionFormat. If the format
+ there is unacceptable for the range, STATUS_NO_MATCH should be
+ returned.
+
+ AttributeRange -
+ The attribute range
+
+Return Value:
+
+ Success / Failure
+
+ STATUS_SUCCESS -
+ The format is acceptable / the format has been changed
+
+ STATUS_NO_MATCH -
+ The format is not-acceptable / the format has not been changed
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_NO_MATCH;
+
+ const GUID VideoInfoSpecifier =
+ {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VIDEOINFO)};
+
+ CCapturePin *CapPin = NULL;
+
+ //
+ // Find the pin, if it exists yet. OldFormat will be an indication of
+ // this. If we're changing formats, OldFormat will be non-NULL.
+ //
+ // You cannot use Pin -> Context to make the determination. AVStream
+ // preinitializes this to the filter's context.
+ //
+ if (OldFormat) {
+ CapPin = reinterpret_cast <CCapturePin *> (Pin -> Context);
+ }
+
+ if (IsEqualGUID (Pin -> ConnectionFormat -> Specifier,
+ VideoInfoSpecifier) &&
+ Pin -> ConnectionFormat -> FormatSize >=
+ sizeof (KS_DATAFORMAT_VIDEOINFOHEADER)) {
+
+ PKS_DATAFORMAT_VIDEOINFOHEADER ConnectionFormat =
+ reinterpret_cast <PKS_DATAFORMAT_VIDEOINFOHEADER>
+ (Pin -> ConnectionFormat);
+
+ //
+ // DataRange comes out of OUR data range list. I know the range
+ // is valid as such.
+ //
+ const KS_DATARANGE_VIDEO *VIRange =
+ reinterpret_cast <const KS_DATARANGE_VIDEO *>
+ (DataRange);
+
+ //
+ // Check that bmiHeader.biSize is valid since we use it later.
+ //
+ ULONG VideoHeaderSize = KS_SIZE_VIDEOHEADER (
+ &ConnectionFormat -> VideoInfoHeader
+ );
+
+ ULONG DataFormatSize = FIELD_OFFSET (
+ KS_DATAFORMAT_VIDEOINFOHEADER, VideoInfoHeader
+ ) + VideoHeaderSize;
+
+ if (
+ VideoHeaderSize < ConnectionFormat->
+ VideoInfoHeader.bmiHeader.biSize ||
+ DataFormatSize < VideoHeaderSize ||
+ DataFormatSize > ConnectionFormat -> DataFormat.FormatSize
+ ) {
+
+ Status = STATUS_INVALID_PARAMETER;
+
+ }
+
+ //
+ // Check that the format is a match for the selected range.
+ //
+ else if (
+ (ConnectionFormat -> VideoInfoHeader.bmiHeader.biWidth !=
+ VIRange -> VideoInfoHeader.bmiHeader.biWidth) ||
+
+ (ConnectionFormat -> VideoInfoHeader.bmiHeader.biHeight !=
+ VIRange -> VideoInfoHeader.bmiHeader.biHeight) ||
+
+ (ConnectionFormat -> VideoInfoHeader.bmiHeader.biCompression !=
+ VIRange -> VideoInfoHeader.bmiHeader.biCompression)
+
+ ) {
+
+ Status = STATUS_NO_MATCH;
+
+ } else {
+
+ //
+ // Compute the minimum size of our buffers to validate against.
+ // The image synthesis routines synthesize |biHeight| rows of
+ // biWidth pixels in either RGB24 or UYVY. In order to ensure
+ // safe synthesis into the buffer, we need to know how large an
+ // image this will produce.
+ //
+ // I do this explicitly because of the method that the data is
+ // synthesized. A variation of this may or may not be necessary
+ // depending on the mechanism the driver in question fills the
+ // capture buffers. The important thing is to ensure that they
+ // aren't overrun during capture.
+ //
+ ULONG ImageSize;
+
+ if (!MultiplyCheckOverflow (
+ (ULONG)ConnectionFormat->VideoInfoHeader.bmiHeader.biWidth,
+ (ULONG)abs (ConnectionFormat->
+ VideoInfoHeader.bmiHeader.biHeight),
+ &ImageSize
+ )) {
+
+ Status = STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // We only support KS_BI_RGB (24) and KS_BI_YUV422 (16), so
+ // this is valid for those formats.
+ //
+ else if (!MultiplyCheckOverflow (
+ ImageSize,
+ (ULONG)(ConnectionFormat->
+ VideoInfoHeader.bmiHeader.biBitCount / 8),
+ &ImageSize
+ )) {
+
+ Status = STATUS_INVALID_PARAMETER;
+
+ }
+
+ //
+ // Valid for the formats we use. Otherwise, this would be
+ // checked later.
+ //
+ else if (ConnectionFormat->VideoInfoHeader.bmiHeader.biSizeImage <
+ ImageSize) {
+
+ Status = STATUS_INVALID_PARAMETER;
+
+ } else {
+
+ //
+ // We can accept the format.
+ //
+ Status = STATUS_SUCCESS;
+
+ //
+ // OldFormat is an indication that this is a format change.
+ // Since I do not implement the
+ // KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT, by default, I do
+ // not handle dynamic format changes.
+ //
+ // If something changes while we're in the stop state, we're
+ // fine to handle it since we haven't "configured the hardware"
+ // yet.
+ //
+ if (OldFormat) {
+ //
+ // If we're in the stop state, we can handle just about any
+ // change. We don't support dynamic format changes.
+ //
+ if (Pin -> DeviceState == KSSTATE_STOP) {
+ if (!CapPin -> CaptureVideoInfoHeader ()) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ } else {
+ //
+ // Because we don't accept dynamic format changes, we
+ // should never get here. Just being over-protective.
+ //
+ Status = STATUS_INVALID_DEVICE_STATE;
+ }
+ }
+
+ }
+
+ }
+
+ }
+ return Status;
+}
+
+/**************************************************************************
+
+ LOCKED CODE
+
+**************************************************************************/
+
+#ifdef ALLOC_PRAGMA
+#pragma code_seg()
+#endif // ALLOC_PRAGMA
+
+void
+CCapturePin::
+CompleteMappings (
+ IN ULONG NumMappings
+ )
+
+/*++
+
+Routine Description:
+
+ Called to notify the pin that a given number of scatter / gather
+ mappings have completed. Let the buffers go if possible.
+ We're called at DPC.
+
+Arguments:
+
+ NumMappings -
+ The number of mappings that have completed.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ ULONG MappingsRemaining = NumMappings;
+
+ //
+ // Walk through the clones list and delete clones whose time has come.
+ // The list is guaranteed to be kept in the order they were cloned.
+ //
+ PKSSTREAM_POINTER Clone = KsPinGetFirstCloneStreamPointer (m_Pin);
+
+ while (MappingsRemaining && Clone) {
+
+ PKSSTREAM_POINTER NextClone = KsStreamPointerGetNextClone (Clone);
+
+#if defined(_X86_)
+ //
+ // Count up the number of bytes we've completed and mark this
+ // in the Stream Header. In mapped queues
+ // (KSPIN_FLAG_GENERATE_MAPPINGS), this is the responsibility of
+ // the minidriver. In non-mapped queues, AVStream performs this.
+ //
+ ULONG MappingsToCount =
+ (MappingsRemaining > Clone -> OffsetOut.Remaining) ?
+ Clone -> OffsetOut.Remaining :
+ MappingsRemaining;
+
+ //
+ // Update DataUsed according to the mappings.
+ //
+ for (ULONG CurMapping = 0; CurMapping < MappingsToCount; CurMapping++) {
+ Clone -> StreamHeader -> DataUsed +=
+ Clone -> OffsetOut.Mappings [CurMapping].ByteCount;
+ }
+#endif
+
+ //
+ // If we have completed all remaining mappings in this clone, it
+ // is an indication that the clone is ready to be deleted and the
+ // buffer released. Set anything required in the stream header which
+ // has not yet been set. If we have a clock, we can timestamp the
+ // sample.
+ //
+#if !defined(_X86_)
+ if (Clone -> StreamHeader -> DataUsed >= Clone -> OffsetOut.Remaining) {
+#else
+ if (MappingsRemaining >= Clone -> OffsetOut.Remaining) {
+#endif
+ Clone -> StreamHeader -> Duration =
+ m_VideoInfoHeader -> AvgTimePerFrame;
+
+ Clone -> StreamHeader -> PresentationTime.Numerator =
+ Clone -> StreamHeader -> PresentationTime.Denominator = 1;
+
+ //
+ // If a clock has been assigned, timestamp the packets with the
+ // time shown on the clock.
+ //
+ if (m_Clock) {
+
+ LONGLONG ClockTime = m_Clock -> GetTime ();
+
+ Clone -> StreamHeader -> PresentationTime.Time = ClockTime;
+
+ Clone -> StreamHeader -> OptionsFlags =
+ KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
+ KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
+
+ } else {
+ //
+ // If there is no clock, don't time stamp the packets.
+ //
+ Clone -> StreamHeader -> PresentationTime.Time = 0;
+
+ }
+
+ //
+ // Increment the frame number. This is the total count of frames which
+ // have attempted capture.
+ //
+ m_FrameNumber++;
+
+ //
+ // Double check the Stream Header size. AVStream makes no guarantee
+ // that because StreamHeaderSize is set to a specific size that you
+ // will get that size. If the proper data type handlers are not
+ // installed, the stream header will be of default size.
+ //
+ if ( Clone -> StreamHeader -> Size >= sizeof (KSSTREAM_HEADER) +
+ sizeof (KS_FRAME_INFO)) {
+
+ PKS_FRAME_INFO FrameInfo = reinterpret_cast <PKS_FRAME_INFO> (
+ Clone -> StreamHeader + 1
+ );
+
+ FrameInfo -> ExtendedHeaderSize = sizeof (KS_FRAME_INFO);
+ FrameInfo -> dwFrameFlags = KS_VIDEO_FLAG_FRAME;
+ FrameInfo -> PictureNumber = (LONGLONG)m_FrameNumber;
+
+ // I don't really have a way to tell if the device has dropped a frame
+ // or was not able to send a frame on time.
+ FrameInfo -> DropCount = (LONGLONG)m_DroppedFrames;
+ }
+
+
+ //
+ // If all of the mappings in this clone have been completed,
+ // delete the clone. We've already updated DataUsed above.
+ //
+
+#if !defined(_X86_)
+ MappingsRemaining--;
+#else
+ MappingsRemaining -= Clone -> OffsetOut.Remaining;
+#endif
+ KsStreamPointerDelete (Clone);
+
+ } else {
+ //
+ // If only part of the mappings in this clone have been completed,
+ // update the pointers. Since we're guaranteed this won't advance
+ // to a new frame by the check above, it won't fail.
+ //
+#if !defined(_X86_)
+ (void)KsStreamPointerAdvanceOffsets (
+ Clone,
+ 0,
+ Clone -> StreamHeader -> DataUsed,
+ FALSE
+ );
+
+#else
+ (void)KsStreamPointerAdvanceOffsets (
+ Clone,
+ 0,
+ MappingsRemaining,
+ FALSE
+ );
+
+#endif
+ MappingsRemaining = 0;
+
+ }
+
+ //
+ // Go to the next clone.
+ //
+ Clone = NextClone;
+
+ }
+
+ //
+ // If we've used all the mappings in hardware and pended, we can kick
+ // processing to happen again if we've completed mappings.
+ //
+ if (m_PendIo) {
+ m_PendIo = TRUE;
+ KsPinAttemptProcessing (m_Pin, TRUE);
+ }
+
+}
+
+/**************************************************************************
+
+ DISPATCH AND DESCRIPTOR LAYOUT
+
+**************************************************************************/
+
+//
+// FormatRGB24Bpp_Capture:
+//
+// This is the data range description of the RGB24 capture format we support.
+//
+const
+KS_DATARANGE_VIDEO
+FormatRGB24Bpp_Capture = {
+
+ //
+ // KSDATARANGE
+ //
+ {
+ sizeof (KS_DATARANGE_VIDEO), // FormatSize
+ 0, // Flags
+ D_X * D_Y * 3, // SampleSize
+ 0, // Reserved
+
+ STATICGUIDOF (KSDATAFORMAT_TYPE_VIDEO), // aka. MEDIATYPE_Video
+ 0xe436eb7d, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20,
+ 0xaf, 0x0b, 0xa7, 0x70, // aka. MEDIASUBTYPE_RGB24,
+ STATICGUIDOF (KSDATAFORMAT_SPECIFIER_VIDEOINFO) // aka. FORMAT_VideoInfo
+ },
+
+ TRUE, // BOOL, bFixedSizeSamples (all samples same size?)
+ FALSE, // BOOL, bTemporalCompression (all I frames?)
+ 0, // Reserved (was StreamDescriptionFlags)
+ 0, // Reserved (was MemoryAllocationFlags
+ // (KS_VIDEO_ALLOC_*))
+ //
+ // _KS_VIDEO_STREAM_CONFIG_CAPS
+ //
+ {
+ STATICGUIDOF( KSDATAFORMAT_SPECIFIER_VIDEOINFO ), // GUID
+ KS_AnalogVideo_None, // AnalogVideoStandard
+ D_X,D_Y, // InputSize, (the inherent size of the incoming signal
+ // with every digitized pixel unique)
+ D_X,D_Y, // MinCroppingSize, smallest rcSrc cropping rect allowed
+ D_X,D_Y, // MaxCroppingSize, largest rcSrc cropping rect allowed
+ 8, // CropGranularityX, granularity of cropping size
+ 1, // CropGranularityY
+ 8, // CropAlignX, alignment of cropping rect
+ 1, // CropAlignY;
+ D_X, D_Y, // MinOutputSize, smallest bitmap stream can produce
+ D_X, D_Y, // MaxOutputSize, largest bitmap stream can produce
+ 8, // OutputGranularityX, granularity of output bitmap size
+ 1, // OutputGranularityY;
+ 0, // StretchTapsX (0 no stretch, 1 pix dup, 2 interp...)
+ 0, // StretchTapsY
+ 0, // ShrinkTapsX
+ 0, // ShrinkTapsY
+ 333667, // MinFrameInterval, 100 nS units
+ 640000000, // MaxFrameInterval, 100 nS units
+ 8 * 3 * 30 * D_X * D_Y, // MinBitsPerSecond;
+ 8 * 3 * 30 * D_X * D_Y // MaxBitsPerSecond;
+ },
+
+ //
+ // KS_VIDEOINFOHEADER (default format)
+ //
+ {
+ 0,0,0,0, // RECT rcSource;
+ 0,0,0,0, // RECT rcTarget;
+ D_X * D_Y * 3 * 8 * 30, // DWORD dwBitRate;
+ 0L, // DWORD dwBitErrorRate;
+ 333667, // REFERENCE_TIME AvgTimePerFrame;
+ sizeof (KS_BITMAPINFOHEADER), // DWORD biSize;
+ D_X, // LONG biWidth;
+ D_Y, // LONG biHeight;
+ 1, // WORD biPlanes;
+ 24, // WORD biBitCount;
+ KS_BI_RGB, // DWORD biCompression;
+ D_X * D_Y * 3, // DWORD biSizeImage;
+ 0, // LONG biXPelsPerMeter;
+ 0, // LONG biYPelsPerMeter;
+ 0, // DWORD biClrUsed;
+ 0 // DWORD biClrImportant;
+ }
+};
+
+//
+// FormatYUY2_Capture:
+//
+// This is the data range description of the YUY2 format we support.
+//
+const
+KS_DATARANGE_VIDEO
+FormatYUY2_Capture = {
+
+ //
+ // KSDATARANGE
+ //
+ {
+ sizeof (KS_DATARANGE_VIDEO), // FormatSize
+ 0, // Flags
+ DMAX_X * DMAX_Y * 2, // SampleSize
+ 0, // Reserved
+ STATICGUIDOF (KSDATAFORMAT_TYPE_VIDEO), // aka. MEDIATYPE_Video
+ 0x32595559, 0x0000, 0x0010, 0x80, 0x00,
+ 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71, //aka. MEDIASUBTYPE_YUY2,
+ STATICGUIDOF (KSDATAFORMAT_SPECIFIER_VIDEOINFO) // aka. FORMAT_VideoInfo
+ },
+
+ TRUE, // BOOL, bFixedSizeSamples (all samples same size?)
+ FALSE, // BOOL, bTemporalCompression (all I frames?)
+ 0, // Reserved (was StreamDescriptionFlags)
+ 0, // Reserved (was MemoryAllocationFlags
+ // (KS_VIDEO_ALLOC_*))
+
+ //
+ // _KS_VIDEO_STREAM_CONFIG_CAPS
+ //
+ {
+ STATICGUIDOF( KSDATAFORMAT_SPECIFIER_VIDEOINFO ), // GUID
+ KS_AnalogVideo_None, // AnalogVideoStandard
+ DMAX_X, DMAX_Y, // InputSize, (the inherent size of the incoming signal
+ // with every digitized pixel unique)
+ D_X,D_Y, // MinCroppingSize, smallest rcSrc cropping rect allowed
+ DMAX_X, DMAX_Y, // MaxCroppingSize, largest rcSrc cropping rect allowed
+ 8, // CropGranularityX, granularity of cropping size
+ 1, // CropGranularityY
+ 8, // CropAlignX, alignment of cropping rect
+ 1, // CropAlignY;
+ D_X, D_Y, // MinOutputSize, smallest bitmap stream can produce
+ DMAX_X, DMAX_Y, // MaxOutputSize, largest bitmap stream can produce
+ 8, // OutputGranularityX, granularity of output bitmap size
+ 1, // OutputGranularityY;
+ 0, // StretchTapsX (0 no stretch, 1 pix dup, 2 interp...)
+ 0, // StretchTapsY
+ 0, // ShrinkTapsX
+ 0, // ShrinkTapsY
+ 333667, // MinFrameInterval, 100 nS units
+ 640000000, // MaxFrameInterval, 100 nS units
+ 8 * 2 * 30 * D_X * D_Y, // MinBitsPerSecond;
+ 8 * 2 * 30 * DMAX_X * DMAX_Y, // MaxBitsPerSecond;
+ },
+
+ //
+ // KS_VIDEOINFOHEADER (default format)
+ //
+ {
+ 0, 0, 0, 0, // RECT rcSource;
+ 0, 0, 0, 0, // RECT rcTarget;
+ DMAX_X * DMAX_Y * 2 * 8 * 30, // DWORD dwBitRate;
+ 0L, // DWORD dwBitErrorRate;
+ 333667, // REFERENCE_TIME AvgTimePerFrame;
+ sizeof (KS_BITMAPINFOHEADER), // DWORD biSize;
+ DMAX_X, // LONG biWidth;
+ DMAX_Y, // LONG biHeight;
+ 1, // WORD biPlanes;
+ 16, // WORD biBitCount;
+ FOURCC_YUY2, // DWORD biCompression;
+ DMAX_X * DMAX_Y * 2, // DWORD biSizeImage;
+ 0, // LONG biXPelsPerMeter;
+ 0, // LONG biYPelsPerMeter;
+ 0, // DWORD biClrUsed;
+ 0 // DWORD biClrImportant;
+ }
+};
+
+//
+// CapturePinDispatch:
+//
+// This is the dispatch table for the capture pin. It provides notifications
+// about creation, closure, processing, data formats, etc...
+//
+const
+KSPIN_DISPATCH
+CapturePinDispatch = {
+ CCapturePin::DispatchCreate, // Pin Create
+ NULL, // Pin Close
+ CCapturePin::DispatchProcess, // Pin Process
+ NULL, // Pin Reset
+ CCapturePin::DispatchSetFormat, // Pin Set Data Format
+ CCapturePin::DispatchSetState, // Pin Set Device State
+ NULL, // Pin Connect
+ NULL, // Pin Disconnect
+ NULL, // Clock Dispatch
+ NULL // Allocator Dispatch
+};
+
+//
+// CapturePinAllocatorFraming:
+//
+// This is the simple framing structure for the capture pin. Note that this
+// will be modified via KsEdit when the actual capture format is determined.
+//
+DECLARE_SIMPLE_FRAMING_EX (
+ CapturePinAllocatorFraming,
+ STATICGUIDOF (KSMEMORY_TYPE_KERNEL_NONPAGED),
+ KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY |
+ KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY,
+ 2,
+ 0,
+ 2 * PAGE_SIZE,
+ 2 * PAGE_SIZE
+ );
+
+//
+// CapturePinDataRanges:
+//
+// This is the list of data ranges supported on the capture pin. We support
+// two: one RGB24, and one YUY2.
+//
+const
+PKSDATARANGE
+CapturePinDataRanges [CAPTURE_PIN_DATA_RANGE_COUNT] = {
+ (PKSDATARANGE) &FormatYUY2_Capture,
+ (PKSDATARANGE) &FormatRGB24Bpp_Capture
+ };
diff --git a/avstream/avshws/capture.h b/avstream/avshws/capture.h
new file mode 100644
index 00000000..502e01e3
--- /dev/null
+++ b/avstream/avshws/capture.h
@@ -0,0 +1,313 @@
+/**************************************************************************
+
+ AVStream Simulated Hardware Sample
+
+ Copyright (c) 2001, Microsoft Corporation.
+
+ File:
+
+ capture.h
+
+ Abstract:
+
+ This file contains header for the video capture pin on the capture
+ filter. The capture sample performs "fake" DMA directly into
+ the capture buffers. Common buffer DMA will work slightly differently.
+
+ For common buffer DMA, the general technique would be DPC schedules
+ processing with KsPinAttemptProcessing. The processing routine grabs
+ the leading edge, copies data out of the common buffer and advances.
+ Cloning would not be necessary with this technique. It would be
+ similiar to the way "AVSSamp" works, but it would be pin-centric.
+
+ History:
+
+ created 3/8/2001
+
+**************************************************************************/
+#include <initguid.h>
+//
+// STREAM_POINTER_CONTEXT:
+//
+// This is the context structure we associate with all clone stream pointers.
+// It allows the mapping code to rip apart the buffer into chunks the same
+// size as the scatter/gather mappings in order to fake scatter / gather
+// bus-master DMA.
+//
+typedef struct _STREAM_POINTER_CONTEXT {
+
+ PUCHAR BufferVirtual;
+
+} STREAM_POINTER_CONTEXT, *PSTREAM_POINTER_CONTEXT;
+
+//
+// CCapturePin:
+//
+// The video capture pin class.
+//
+class CCapturePin :
+ public ICaptureSink {
+
+private:
+
+ //
+ // The AVStream pin we're associated with.
+ //
+ PKSPIN m_Pin;
+
+ //
+ // Pointer to the internal device object for our capture device.
+ // We access the "fake" hardware through this object.
+ //
+ CCaptureDevice *m_Device;
+
+ //
+ // The state we've put the hardware into. This allows us to keep track
+ // of whether to do things like unpausing or restarting.
+ //
+ HARDWARE_STATE m_HardwareState;
+
+ //
+ // The clock we've been assigned. As with other capture filters, we do
+ // not expose a clock. If one has been assigned, we will use it to
+ // time stamp packets (plus a reasonable delta to work the capture stream
+ // in a preview graph).
+ //
+ PIKSREFERENCECLOCK m_Clock;
+
+ //
+ // The captured video info header. The settings for "fake" hardware will be
+ // programmed via this video info header.
+ //
+ PKS_VIDEOINFOHEADER m_VideoInfoHeader;
+
+ //
+ // If we are unable to insert all of the mappings in a stream pointer into
+ // the "fake" hardware's scatter / gather table, we set this to the
+ // stream pointer that's incomplete. This is done both to make the
+ // relasing easier and to make it easier to fake the scatter / gather
+ // hardware.
+ //
+ PKSSTREAM_POINTER m_PreviousStreamPointer;
+
+ //
+ // An indication of whether or not we pended I/O for some reason. If this
+ // is set, the DPC will resume I/O when any mappings are completed.
+ //
+ BOOLEAN m_PendIo;
+
+ //
+ // An indication of whether or not this pin has acquired the necessary
+ // hardware resources to operate. When the pin reaches KSSTATE_ACQUIRE,
+ // we attempt to acquire the hardware. This flag will be set based on
+ // our success / failure.
+ //
+ BOOLEAN m_AcquiredResources;
+
+ //
+ // Presentation time for the sample
+ //
+ LONGLONG m_PresentationTime;
+
+ LONGLONG m_FrameNumber;
+ LONGLONG m_DroppedFrames;
+
+ //
+ // CleanupReferences():
+ //
+ // Clean up any references we hold on frames in the queue. This is called
+ // when we abruptly stop the fake hardware.
+ //
+ NTSTATUS
+ CleanupReferences (
+ );
+
+ //
+ // SetState():
+ //
+ // This is the state transition handler for the capture pin. It attempts
+ // to acquire resources for the capture pin (or releasing them if
+ // necessary) and starts and stops the hardware as required.
+ //
+ NTSTATUS
+ SetState (
+ IN KSSTATE ToState,
+ IN KSSTATE FromState
+ );
+
+ //
+ // Process():
+ //
+ // This is the processing dispatch for the capture pin. It handles
+ // programming the scatter / gather tables for the hardware as buffers
+ // become available. This processing routine is designed for a direct
+ // into the capture buffers kind of DMA as opposed to common-buffer
+ // and copy strategies.
+ //
+ NTSTATUS
+ Process (
+ );
+ //
+ // CaptureVideoInfoHeader():
+ //
+ // This routine stashes the video info header set on the pin connection
+ // in the CCapturePin object. This is used to base hardware settings.
+ //
+ PKS_VIDEOINFOHEADER
+ CaptureVideoInfoHeader (
+ );
+
+ //
+ // Cleanup():
+ //
+ // This is the free callback from the bagged item (CCapturePin). If we
+ // do not provide a callback when we bag the CCapturePin, ExFreePool
+ // would be called. This is not desirable for C++ constructed objects.
+ // We merely delete the object here.
+ //
+ static
+ void
+ Cleanup (
+ IN CCapturePin *Pin
+ )
+ {
+ delete Pin;
+ }
+
+public:
+ //
+ // CCapturePin():
+ //
+ // The capture pin's constructor. Initialize any non-0, non-NULL fields
+ // (since new will have zero'ed the memory anyway) and set up our
+ // device level pointers for access during capture routines.
+ //
+ CCapturePin (
+ IN PKSPIN Pin
+ );
+
+ //
+ // ~CCapturePin():
+ //
+ // The capture pin's destructor.
+ //
+ ~CCapturePin (
+ )
+ {
+ }
+
+ //
+ // ICaptureSink::CompleteMappings()
+ //
+ // This is the capture sink notification mechanism for mapping completion.
+ // When the device DPC detects that a given number of mappings have been
+ // completed by the fake hardware, it signals the capture sink of this
+ // through this method.
+ //
+ virtual
+ void
+ CompleteMappings (
+ IN ULONG NumMappings
+ );
+
+ /*************************************************
+
+ Dispatch Routines
+
+ *************************************************/
+
+ //
+ // DispatchCreate():
+ //
+ // This is the creation dispatch for the capture pin. It creates
+ // the CCapturePin object and associates it with the AVStream object
+ // bagging it in the process.
+ //
+ static
+ NTSTATUS
+ DispatchCreate (
+ IN PKSPIN Pin,
+ IN PIRP Irp
+ );
+
+ //
+ // DispatchSetState():
+ //
+ // This is the set device state dispatch for the pin. The routine bridges
+ // to SetState() in the context of the CCapturePin.
+ //
+ static
+ NTSTATUS
+ DispatchSetState (
+ IN PKSPIN Pin,
+ IN KSSTATE ToState,
+ IN KSSTATE FromState
+ )
+ {
+ return
+ (reinterpret_cast <CCapturePin *> (Pin -> Context)) ->
+ SetState (ToState, FromState);
+ }
+
+ //
+ // DispatchSetFormat():
+ //
+ // This is the set data format dispatch for the pin. This will be called
+ // BEFORE pin creation to validate that a data format selected is a match
+ // for the range pulled out of our range list. It will also be called
+ // for format changes.
+ //
+ // If OldFormat is NULL, this is an indication that it's the initial
+ // call and not a format change. Even fixed format pins get this call
+ // once.
+ //
+ static
+ NTSTATUS
+ DispatchSetFormat (
+ IN PKSPIN Pin,
+ IN PKSDATAFORMAT OldFormat OPTIONAL,
+ IN PKSMULTIPLE_ITEM OldAttributeList OPTIONAL,
+ IN const KSDATARANGE *DataRange,
+ IN const KSATTRIBUTE_LIST *AttributeRange OPTIONAL
+ );
+
+ //
+ // DispatchProcess():
+ //
+ // This is the processing dispatch for the capture pin. The routine
+ // bridges to Process() in the context of the CCapturePin.
+ //
+ static
+ NTSTATUS
+ DispatchProcess (
+ IN PKSPIN Pin
+ )
+ {
+ return
+ (reinterpret_cast <CCapturePin *> (Pin -> Context)) ->
+ Process ();
+
+ }
+
+ //
+ // IntersectHandler():
+ //
+ // This is the data intersection handler for the capture pin. This
+ // determines an optimal format in the intersection of two ranges,
+ // one local and one possibly foreign. If there is no compatible format,
+ // STATUS_NO_MATCH is returned.
+ //
+ static
+ NTSTATUS
+ IntersectHandler (
+ IN PKSFILTER Filter,
+ IN PIRP Irp,
+ IN PKSP_PIN PinInstance,
+ IN PKSDATARANGE CallerDataRange,
+ IN PKSDATARANGE DescriptorDataRange,
+ IN ULONG BufferSize,
+ OUT PVOID Data OPTIONAL,
+ OUT PULONG DataSize
+ );
+
+}; \ No newline at end of file
diff --git a/avstream/avshws/device.cpp b/avstream/avshws/device.cpp
new file mode 100644
index 00000000..ce4818b8
--- /dev/null
+++ b/avstream/avshws/device.cpp
@@ -0,0 +1,875 @@
+/**************************************************************************
+
+ AVStream Simulated Hardware Sample
+
+ Copyright (c) 2001, Microsoft Corporation.
+
+ File:
+
+ device.cpp
+
+ Abstract:
+
+ This file contains the device level implementation of the AVStream
+ hardware sample. Note that this is not the "fake" hardware. The
+ "fake" hardware is in hwsim.cpp.
+
+ History:
+
+ created 3/9/2001
+
+**************************************************************************/
+
+#include "avshws.h"
+/**************************************************************************
+
+ PAGEABLE CODE
+
+**************************************************************************/
+
+#ifdef ALLOC_PRAGMA
+#pragma code_seg("PAGE")
+#endif // ALLOC_PRAGMA
+
+NTSTATUS
+CCaptureDevice::
+DispatchCreate (
+ IN PKSDEVICE Device
+ )
+
+/*++
+
+Routine Description:
+
+ Create the capture device. This is the creation dispatch for the
+ capture device.
+
+Arguments:
+
+ Device -
+ The AVStream device being created.
+
+Return Value:
+
+ Success / Failure
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ NTSTATUS Status;
+
+ CCaptureDevice *CapDevice = new (NonPagedPool) CCaptureDevice (Device);
+
+ if (!CapDevice) {
+ //
+ // Return failure if we couldn't create the pin.
+ //
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+
+ } else {
+
+ //
+ // Add the item to the object bag if we were successful.
+ // Whenever the device goes away, the bag is cleaned up and
+ // we will be freed.
+ //
+ // For backwards compatibility with DirectX 8.0, we must grab
+ // the device mutex before doing this. For Windows XP, this is
+ // not required, but it is still safe.
+ //
+ KsAcquireDevice (Device);
+ Status = KsAddItemToObjectBag (
+ Device -> Bag,
+ reinterpret_cast <PVOID> (CapDevice),
+ reinterpret_cast <PFNKSFREE> (CCaptureDevice::Cleanup)
+ );
+ KsReleaseDevice (Device);
+
+ if (!NT_SUCCESS (Status)) {
+ delete CapDevice;
+ } else {
+ Device -> Context = reinterpret_cast <PVOID> (CapDevice);
+ }
+
+ }
+
+ return Status;
+
+}
+
+/*************************************************/
+
+
+NTSTATUS
+CCaptureDevice::
+PnpStart (
+ IN PCM_RESOURCE_LIST TranslatedResourceList,
+ IN PCM_RESOURCE_LIST UntranslatedResourceList
+ )
+
+/*++
+
+Routine Description:
+
+ Called at Pnp start. We start up our virtual hardware simulation.
+
+Arguments:
+
+ TranslatedResourceList -
+ The translated resource list from Pnp
+
+ UntranslatedResourceList -
+ The untranslated resource list from Pnp
+
+Return Value:
+
+ Success / Failure
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ //
+ // Normally, we'd do things here like parsing the resource lists and
+ // connecting our interrupt. Since this is a simulation, there isn't
+ // much to parse. The parsing and connection should be the same as
+ // any WDM driver. The sections that will differ are illustrated below
+ // in setting up a simulated DMA.
+ //
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ if (!m_Device -> Started) {
+ // Create the Filter for the device
+ KsAcquireDevice(m_Device);
+ Status = KsCreateFilterFactory( m_Device->FunctionalDeviceObject,
+ &CaptureFilterDescriptor,
+ L"GLOBAL",
+ NULL,
+ KSCREATE_ITEM_FREEONSTOP,
+ NULL,
+ NULL,
+ NULL );
+ KsReleaseDevice(m_Device);
+
+ }
+ //
+ // By PnP, it's possible to receive multiple starts without an intervening
+ // stop (to reevaluate resources, for example). Thus, we only perform
+ // creations of the simulation on the initial start and ignore any
+ // subsequent start. Hardware drivers with resources should evaluate
+ // resources and make changes on 2nd start.
+ //
+ if (NT_SUCCESS(Status) && (!m_Device -> Started)) {
+
+ m_HardwareSimulation = new (NonPagedPool) CHardwareSimulation (this);
+ if (!m_HardwareSimulation) {
+ //
+ // If we couldn't create the hardware simulation, fail.
+ //
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+
+ } else {
+ Status = KsAddItemToObjectBag (
+ m_Device -> Bag,
+ reinterpret_cast <PVOID> (m_HardwareSimulation),
+ reinterpret_cast <PFNKSFREE> (CHardwareSimulation::Cleanup)
+ );
+
+ if (!NT_SUCCESS (Status)) {
+ delete m_HardwareSimulation;
+ }
+ }
+#if defined(_X86_)
+ //
+ // DMA operations illustrated in this sample are applicable only for 32bit platform.
+ //
+ INTERFACE_TYPE InterfaceBuffer;
+ ULONG InterfaceLength;
+ DEVICE_DESCRIPTION DeviceDescription;
+
+ if (NT_SUCCESS (Status)) {
+ //
+ // Set up DMA...
+ //
+ // Ordinarilly, we'd be using InterfaceBuffer or
+ // InterfaceTypeUndefined if !NT_SUCCESS (IfStatus) as the
+ // InterfaceType below; however, for the purposes of this sample,
+ // we lie and say we're on the PCI Bus. Otherwise, we're using map
+ // registers on x86 32 bit physical to 32 bit logical and this isn't
+ // what I want to show in this sample.
+ //
+ //
+ // NTSTATUS IfStatus =
+
+ IoGetDeviceProperty (
+ m_Device -> PhysicalDeviceObject,
+ DevicePropertyLegacyBusType,
+ sizeof (INTERFACE_TYPE),
+ &InterfaceBuffer,
+ &InterfaceLength
+ );
+
+ //
+ // Initialize our fake device description. We claim to be a
+ // bus-mastering 32-bit scatter/gather capable piece of hardware.
+ //
+ DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
+ DeviceDescription.DmaChannel = ((ULONG) ~0);
+ DeviceDescription.InterfaceType = PCIBus;
+ DeviceDescription.DmaWidth = Width32Bits;
+ DeviceDescription.DmaSpeed = Compatible;
+ DeviceDescription.ScatterGather = TRUE;
+ DeviceDescription.Master = TRUE;
+ DeviceDescription.Dma32BitAddresses = TRUE;
+ DeviceDescription.AutoInitialize = FALSE;
+ DeviceDescription.MaximumLength = (ULONG) -1;
+
+ //
+ // Get a DMA adapter object from the system.
+ //
+ m_DmaAdapterObject = IoGetDmaAdapter (
+ m_Device -> PhysicalDeviceObject,
+ &DeviceDescription,
+ &m_NumberOfMapRegisters
+ );
+
+ if (!m_DmaAdapterObject) {
+ Status = STATUS_UNSUCCESSFUL;
+ }
+
+ }
+
+ if (NT_SUCCESS (Status)) {
+ //
+ // Initialize our DMA adapter object with AVStream. This is
+ // **ONLY** necessary **IF** you are doing DMA directly into
+ // capture buffers as this sample does. For this,
+ // KSPIN_FLAG_GENERATE_MAPPINGS must be specified on a queue.
+ //
+
+ //
+ // The (1 << 20) below is the maximum size of a single s/g mapping
+ // that this hardware can handle. Note that I have pulled this
+ // number out of thin air for the "fake" hardware.
+ //
+ KsDeviceRegisterAdapterObject (
+ m_Device,
+ m_DmaAdapterObject,
+ (1 << 20),
+ sizeof (KSMAPPING)
+ );
+
+ }
+#endif
+ }
+
+ return Status;
+
+}
+
+/*************************************************/
+
+
+void
+CCaptureDevice::
+PnpStop (
+ )
+
+/*++
+
+Routine Description:
+
+ This is the pnp stop dispatch for the capture device. It releases any
+ adapter object previously allocated by IoGetDmaAdapter during Pnp Start.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ if (m_DmaAdapterObject) {
+ //
+ // Return the DMA adapter back to the system.
+ //
+ m_DmaAdapterObject -> DmaOperations ->
+ PutDmaAdapter (m_DmaAdapterObject);
+
+ m_DmaAdapterObject = NULL;
+ }
+
+}
+
+/*************************************************/
+
+
+NTSTATUS
+CCaptureDevice::
+AcquireHardwareResources (
+ IN ICaptureSink *CaptureSink,
+ IN PKS_VIDEOINFOHEADER VideoInfoHeader
+ )
+
+/*++
+
+Routine Description:
+
+ Acquire hardware resources for the capture hardware. If the
+ resources are already acquired, this will return an error.
+ The hardware configuration must be passed as a VideoInfoHeader.
+
+Arguments:
+
+ CaptureSink -
+ The capture sink attempting to acquire resources. When scatter /
+ gather mappings are completed, the capture sink specified here is
+ what is notified of the completions.
+
+ VideoInfoHeader -
+ Information about the capture stream. This **MUST** remain
+ stable until the caller releases hardware resources. Note
+ that this could also be guaranteed by bagging it in the device
+ object bag as well.
+
+Return Value:
+
+ Success / Failure
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ //
+ // If we're the first pin to go into acquire (remember we can have
+ // a filter in another graph going simultaneously), grab the resources.
+ //
+ if (InterlockedCompareExchange (
+ &m_PinsWithResources,
+ 1,
+ 0) == 0) {
+
+ m_VideoInfoHeader = VideoInfoHeader;
+
+ //
+ // If there's an old hardware simulation sitting around for some
+ // reason, blow it away.
+ //
+ if (m_ImageSynth) {
+ delete m_ImageSynth;
+ m_ImageSynth = NULL;
+ }
+
+ //
+ // Create the necessary type of image synthesizer.
+ //
+ if (m_VideoInfoHeader -> bmiHeader.biBitCount == 24 &&
+ m_VideoInfoHeader -> bmiHeader.biCompression == KS_BI_RGB) {
+
+ //
+ // If we're RGB24, create a new RGB24 synth. RGB24 surfaces
+ // can be in either orientation. The origin is lower left if
+ // height < 0. Otherwise, it's upper left.
+ //
+ m_ImageSynth = new (NonPagedPool, 'RysI')
+ CRGB24Synthesizer (
+ m_VideoInfoHeader -> bmiHeader.biHeight >= 0
+ );
+
+ } else
+ if (m_VideoInfoHeader -> bmiHeader.biBitCount == 16 &&
+ (m_VideoInfoHeader -> bmiHeader.biCompression == FOURCC_YUY2)) {
+
+ //
+ // If we're UYVY, create the YUV synth.
+ //
+ m_ImageSynth = new(NonPagedPool, 'YysI') CYUVSynthesizer;
+
+ }
+ else
+ //
+ // We don't synthesize anything but RGB 24 and UYVY.
+ //
+ Status = STATUS_INVALID_PARAMETER;
+
+ if (NT_SUCCESS (Status) && !m_ImageSynth) {
+
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+
+ }
+
+ if (NT_SUCCESS (Status)) {
+ //
+ // If everything has succeeded thus far, set the capture sink.
+ //
+ m_CaptureSink = CaptureSink;
+
+ } else {
+ //
+ // If anything failed in here, we release the resources we've
+ // acquired.
+ //
+ ReleaseHardwareResources ();
+ }
+
+ } else {
+
+ //
+ // TODO: Better status code?
+ //
+ Status = STATUS_SHARING_VIOLATION;
+
+ }
+
+ return Status;
+
+}
+
+/*************************************************/
+
+
+void
+CCaptureDevice::
+ReleaseHardwareResources (
+ )
+
+/*++
+
+Routine Description:
+
+ Release hardware resources. This should only be called by
+ an object which has acquired them.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ //
+ // Blow away the image synth.
+ //
+ if (m_ImageSynth) {
+ delete m_ImageSynth;
+ m_ImageSynth = NULL;
+
+ }
+
+ m_VideoInfoHeader = NULL;
+ m_CaptureSink = NULL;
+
+ //
+ // Release our "lock" on hardware resources. This will allow another
+ // pin (perhaps in another graph) to acquire them.
+ //
+ InterlockedExchange (
+ &m_PinsWithResources,
+ 0
+ );
+
+}
+
+/*************************************************/
+
+
+NTSTATUS
+CCaptureDevice::
+Start (
+ )
+
+/*++
+
+Routine Description:
+
+ Start the capture device based on the video info header we were told
+ about when resources were acquired.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Success / Failure
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ m_LastMappingsCompleted = 0;
+ m_InterruptTime = 0;
+
+ return
+ m_HardwareSimulation -> Start (
+ m_ImageSynth,
+ m_VideoInfoHeader -> AvgTimePerFrame,
+ m_VideoInfoHeader -> bmiHeader.biWidth,
+ ABS (m_VideoInfoHeader -> bmiHeader.biHeight),
+ m_VideoInfoHeader -> bmiHeader.biSizeImage
+ );
+
+
+}
+
+/*************************************************/
+
+
+NTSTATUS
+CCaptureDevice::
+Pause (
+ IN BOOLEAN Pausing
+ )
+
+/*++
+
+Routine Description:
+
+ Pause or unpause the hardware simulation. This is an effective start
+ or stop without resetting counters and formats. Note that this can
+ only be called to transition from started -> paused -> started. Calling
+ this without starting the hardware with Start() does nothing.
+
+Arguments:
+
+ Pausing -
+ An indicatation of whether we are pausing or unpausing
+
+ TRUE -
+ Pause the hardware simulation
+
+ FALSE -
+ Unpause the hardware simulation
+
+Return Value:
+
+ Success / Failure
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ return
+ m_HardwareSimulation -> Pause (
+ Pausing
+ );
+
+}
+
+/*************************************************/
+
+
+NTSTATUS
+CCaptureDevice::
+Stop (
+ )
+
+/*++
+
+Routine Description:
+
+ Stop the capture device.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Success / Failure
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ return
+ m_HardwareSimulation -> Stop ();
+
+}
+
+/*************************************************/
+
+
+ULONG
+CCaptureDevice::
+ProgramScatterGatherMappings (
+ IN PKSSTREAM_POINTER Clone,
+ IN PUCHAR *Buffer,
+ IN PKSMAPPING Mappings,
+ IN ULONG MappingsCount
+ )
+
+/*++
+
+Routine Description:
+
+ Program the scatter / gather mappings for the "fake" hardware.
+
+Arguments:
+
+ Buffer -
+ Points to a pointer to the virtual address of the topmost
+ scatter / gather chunk. The pointer will be updated as the
+ device "programs" mappings. Reason for this is that we get
+ the physical addresses and sizes, but must calculate the virtual
+ addresses... This is used as scratch space for that.
+
+ Mappings -
+ An array of mappings to program
+
+ MappingsCount -
+ The count of mappings in the array
+
+Return Value:
+
+ The number of mappings successfully programmed
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+
+
+ return
+ m_HardwareSimulation -> ProgramScatterGatherMappings (
+ Clone,
+ Buffer,
+ Mappings,
+ MappingsCount,
+ sizeof (KSMAPPING)
+ );
+
+}
+
+/*************************************************************************
+
+ LOCKED CODE
+
+**************************************************************************/
+
+#ifdef ALLOC_PRAGMA
+#pragma code_seg()
+#endif // ALLOC_PRAGMA
+
+
+ULONG
+CCaptureDevice::
+QueryInterruptTime (
+ )
+
+/*++
+
+Routine Description:
+
+ Return the number of frame intervals that have elapsed since the
+ start of the device. This will be the frame number.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ The interrupt time of the device (the number of frame intervals that
+ have elapsed since the start of the device).
+
+--*/
+
+{
+
+ return m_InterruptTime;
+
+}
+
+/*************************************************/
+
+
+void
+CCaptureDevice::
+Interrupt (
+ )
+
+/*++
+
+Routine Description:
+
+ This is the "faked" interrupt service routine for this device. It
+ is called at dispatch level by the hardware simulation.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ m_InterruptTime++;
+
+ //
+ // Realistically, we'd do some hardware manipulation here and then queue
+ // a DPC. Since this is fake hardware, we do what's necessary here. This
+ // is pretty much what the DPC would look like short of the access
+ // of hardware registers (ReadNumberOfMappingsCompleted) which would likely
+ // be done in the ISR.
+ //
+ ULONG NumMappingsCompleted =
+ m_HardwareSimulation -> ReadNumberOfMappingsCompleted ();
+
+ //
+ // Inform the capture sink that a given number of scatter / gather
+ // mappings have completed.
+ //
+ m_CaptureSink -> CompleteMappings (
+ NumMappingsCompleted - m_LastMappingsCompleted
+ );
+
+ m_LastMappingsCompleted = NumMappingsCompleted;
+
+}
+
+/**************************************************************************
+
+ DESCRIPTOR AND DISPATCH LAYOUT
+
+**************************************************************************/
+
+//
+// CaptureFilterDescriptor:
+//
+// The filter descriptor for the capture device.
+DEFINE_KSFILTER_DESCRIPTOR_TABLE (FilterDescriptors) {
+ &CaptureFilterDescriptor
+};
+
+//
+// CaptureDeviceDispatch:
+//
+// This is the dispatch table for the capture device. Plug and play
+// notifications as well as power management notifications are dispatched
+// through this table.
+//
+const
+KSDEVICE_DISPATCH
+CaptureDeviceDispatch = {
+ CCaptureDevice::DispatchCreate, // Pnp Add Device
+ CCaptureDevice::DispatchPnpStart, // Pnp Start
+ NULL, // Post-Start
+ NULL, // Pnp Query Stop
+ NULL, // Pnp Cancel Stop
+ CCaptureDevice::DispatchPnpStop, // Pnp Stop
+ NULL, // Pnp Query Remove
+ NULL, // Pnp Cancel Remove
+ NULL, // Pnp Remove
+ NULL, // Pnp Query Capabilities
+ NULL, // Pnp Surprise Removal
+ NULL, // Power Query Power
+ NULL, // Power Set Power
+ NULL // Pnp Query Interface
+};
+
+//
+// CaptureDeviceDescriptor:
+//
+// This is the device descriptor for the capture device. It points to the
+// dispatch table and contains a list of filter descriptors that describe
+// filter-types that this device supports. Note that the filter-descriptors
+// can be created dynamically and the factories created via
+// KsCreateFilterFactory as well.
+//
+const
+KSDEVICE_DESCRIPTOR
+CaptureDeviceDescriptor = {
+ &CaptureDeviceDispatch,
+ 0,
+ NULL
+};
+
+/**************************************************************************
+
+ INITIALIZATION CODE
+
+**************************************************************************/
+
+
+extern "C" DRIVER_INITIALIZE DriverEntry;
+
+extern "C"
+NTSTATUS
+DriverEntry (
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+/*++
+
+Routine Description:
+
+ Driver entry point. Pass off control to the AVStream initialization
+ function (KsInitializeDriver) and return the status code from it.
+
+Arguments:
+
+ DriverObject -
+ The WDM driver object for our driver
+
+ RegistryPath -
+ The registry path for our registry info
+
+Return Value:
+
+ As from KsInitializeDriver
+
+--*/
+
+{
+ //
+ // Simply pass the device descriptor and parameters off to AVStream
+ // to initialize us. This will cause filter factories to be set up
+ // at add & start. Everything is done based on the descriptors passed
+ // here.
+ //
+ return
+ KsInitializeDriver (
+ DriverObject,
+ RegistryPath,
+ &CaptureDeviceDescriptor
+ );
+
+}
diff --git a/avstream/avshws/device.h b/avstream/avshws/device.h
new file mode 100644
index 00000000..2bd9899d
--- /dev/null
+++ b/avstream/avshws/device.h
@@ -0,0 +1,294 @@
+/**************************************************************************
+
+ AVStream Simulated Hardware Sample
+
+ Copyright (c) 2001, Microsoft Corporation.
+
+ File:
+
+ device.h
+
+ Abstract:
+
+ The header for the device level of the simulated hardware. This is
+ not actually the hardware simulation itself. The hardware simulation
+ is contained in hwsim.*, image.*.
+
+ History:
+
+ created 3/9/2001
+
+**************************************************************************/
+
+class CCaptureDevice :
+ public IHardwareSink {
+
+private:
+
+ //
+ // The AVStream device we're associated with.
+ //
+ PKSDEVICE m_Device;
+
+ //
+ // Number of pins with resources acquired. This is used as a locking
+ // mechanism for resource acquisition on the device.
+ //
+ LONG m_PinsWithResources;
+
+ //
+ // Since we don't have physical hardware, this provides the hardware
+ // simulation. m_HardwareSimulation provides the fake ISR, fake DPC,
+ // etc... m_ImageSynth provides RGB24 and UYVY image synthesis and
+ // overlay in software.
+ //
+ CHardwareSimulation *m_HardwareSimulation;
+ CImageSynthesizer *m_ImageSynth;
+
+ //
+ // The number of ISR's that have occurred since capture started.
+ //
+ ULONG m_InterruptTime;
+
+ //
+ // The last reading of mappings completed.
+ //
+ ULONG m_LastMappingsCompleted;
+
+ //
+ // The Dma adapter object we acquired through IoGetDmaAdapter() during
+ // Pnp start. This must be initialized with AVStream in order to perform
+ // Dma directly into the capture buffers.
+ //
+ PADAPTER_OBJECT m_DmaAdapterObject;
+
+ //
+ // The number of map registers returned from IoGetDmaAdapter().
+ //
+ ULONG m_NumberOfMapRegisters;
+
+ //
+ // The capture sink. When we complete scatter / gather mappings, we
+ // notify the capture sink.
+ //
+ ICaptureSink *m_CaptureSink;
+
+ //
+ // The video info header we're basing hardware settings on. The pin
+ // provides this to us when acquiring resources and must guarantee its
+ // stability until resources are released.
+ //
+ PKS_VIDEOINFOHEADER m_VideoInfoHeader;
+
+ //
+ // Cleanup():
+ //
+ // This is the free callback for the bagged capture device. Not providing
+ // one will call ExFreePool, which is not what we want for a constructed
+ // C++ object. This simply deletes the capture device.
+ //
+ static
+ void
+ Cleanup (
+ IN CCaptureDevice *CapDevice
+ )
+ {
+ delete CapDevice;
+ }
+
+ //
+ // PnpStart():
+ //
+ // This is the Pnp start routine for our simulated hardware. Note that
+ // DispatchStart bridges to here in the context of the CCaptureDevice.
+ //
+ NTSTATUS
+ PnpStart (
+ IN PCM_RESOURCE_LIST TranslatedResourceList,
+ IN PCM_RESOURCE_LIST UntranslatedResourceList
+ );
+
+ //
+ // PnpStop():
+ //
+ // This is the Pnp stop routine for our simulated hardware. Note that
+ // DispatchStop bridges to here in the context of the CCaptureDevice.
+ //
+ void
+ PnpStop (
+ );
+
+public:
+
+ //
+ // CCaptureDevice():
+ //
+ // The capture device class constructor. Since everything should have
+ // been zero'ed by the new operator, don't bother setting anything to
+ // zero or NULL. Only initialize non-NULL, non-0 fields.
+ //
+ CCaptureDevice (
+ IN PKSDEVICE Device
+ ) :
+ m_Device (Device)
+ {
+ }
+
+ //
+ // ~CCaptureDevice():
+ //
+ // The capture device destructor.
+ //
+ ~CCaptureDevice (
+ )
+ {
+ }
+
+ //
+ // DispatchCreate():
+ //
+ // This is the Add Device dispatch for the capture device. It creates
+ // the CCaptureDevice and associates it with the device via the bag.
+ //
+ static
+ NTSTATUS
+ DispatchCreate (
+ IN PKSDEVICE Device
+ );
+ //
+ // DispatchPnpStart():
+ //
+ // This is the Pnp Start dispatch for the capture device. It simply
+ // bridges to PnpStart() in the context of the CCaptureDevice.
+ //
+ static
+ NTSTATUS
+ DispatchPnpStart (
+ IN PKSDEVICE Device,
+ IN PIRP Irp,
+ IN PCM_RESOURCE_LIST TranslatedResourceList,
+ IN PCM_RESOURCE_LIST UntranslatedResourceList
+ )
+ {
+ return
+ (reinterpret_cast <CCaptureDevice *> (Device -> Context)) ->
+ PnpStart (
+ TranslatedResourceList,
+ UntranslatedResourceList
+ );
+ }
+
+ //
+ // DispatchPnpStop():
+ //
+ // This is the Pnp stop dispatch for the capture device. It simply
+ // bridges to PnpStop() in the context of the CCaptureDevice.
+ //
+ static
+ void
+ DispatchPnpStop (
+ IN PKSDEVICE Device,
+ IN PIRP Irp
+ )
+ {
+ return
+ (reinterpret_cast <CCaptureDevice *> (Device -> Context)) ->
+ PnpStop (
+ );
+ }
+
+ //
+ // AcquireHardwareResources():
+ //
+ // Called to acquire hardware resources for the device based on a given
+ // video info header. This will fail if another object has already
+ // acquired hardware resources since we emulate a single capture
+ // device.
+ //
+ NTSTATUS
+ AcquireHardwareResources (
+ IN ICaptureSink *CaptureSink,
+ IN PKS_VIDEOINFOHEADER VideoInfoHeader
+ );
+
+ //
+ // ReleaseHardwareResources():
+ //
+ // Called to release hardware resources for the device.
+ //
+ void
+ ReleaseHardwareResources (
+ );
+
+ //
+ // Start():
+ //
+ // Called to start the hardware simulation. This causes us to simulate
+ // interrupts, simulate filling buffers with synthesized data, etc...
+ //
+ NTSTATUS
+ Start (
+ );
+
+ //
+ // Pause():
+ //
+ // Called to pause or unpause the hardware simulation. This will be
+ // indentical to a start or stop but it will not reset formats and
+ // counters.
+ //
+ NTSTATUS
+ Pause (
+ IN BOOLEAN Pausing
+ );
+
+ //
+ // Stop():
+ //
+ // Called to stop the hardware simulation. This causes interrupts to
+ // stop issuing. When this call returns, the "fake" hardware has
+ // stopped accessing all s/g buffers, etc...
+ //
+ NTSTATUS
+ Stop (
+ );
+
+ //
+ // ProgramScatterGatherMappings():
+ //
+ // Called to program the hardware simulation's scatter / gather table.
+ // This synchronizes with the "fake" ISR and hardware simulation via
+ // a spinlock.
+ //
+ ULONG
+ ProgramScatterGatherMappings (
+ IN PKSSTREAM_POINTER Clone,
+ IN PUCHAR *Buffer,
+ IN PKSMAPPING Mappings,
+ IN ULONG MappingsCount
+ );
+
+ //
+ // QueryInterruptTime():
+ //
+ // Determine the frame number that this frame corresponds to.
+ //
+ ULONG
+ QueryInterruptTime (
+ );
+
+ //
+ // IHardwareSink::Interrupt():
+ //
+ // The interrupt service routine as called through the hardware sink
+ // interface. The "fake" hardware uses this method to inform the device
+ // of a "fake" ISR. The routine is called at dispatch level and must
+ // be in locked code.
+ //
+ virtual
+ void
+ Interrupt (
+ );
+
+ LONG GetDroppedFrameCount(){return m_HardwareSimulation->GetSkippedFrameCount();};
+};
diff --git a/avstream/avshws/filter.cpp b/avstream/avshws/filter.cpp
new file mode 100644
index 00000000..be0012cb
--- /dev/null
+++ b/avstream/avshws/filter.cpp
@@ -0,0 +1,203 @@
+/**************************************************************************
+
+ AVStream Simulated Hardware Sample
+
+ Copyright (c) 2001, Microsoft Corporation.
+
+ File:
+
+ filter.cpp
+
+ Abstract:
+
+ This file contains the filter level implementation for the
+ capture filter.
+
+ History:
+
+ created 3/12/2001
+
+**************************************************************************/
+
+#include "avshws.h"
+
+/**************************************************************************
+
+ PAGEABLE CODE
+
+**************************************************************************/
+
+#ifdef ALLOC_PRAGMA
+#pragma code_seg("PAGE")
+#endif // ALLOC_PRAGMA
+
+
+NTSTATUS
+CCaptureFilter::
+DispatchCreate (
+ IN PKSFILTER Filter,
+ IN PIRP Irp
+ )
+
+/*++
+
+Routine Description:
+
+ This is the creation dispatch for the capture filter. It creates
+ the CCaptureFilter object, associates it with the AVStream filter
+ object, and bag the CCaptureFilter for later cleanup.
+
+Arguments:
+
+ Filter -
+ The AVStream filter being created
+
+ Irp -
+ The creation Irp
+
+Return Value:
+
+ Success / failure
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ CCaptureFilter *CapFilter = new (NonPagedPool) CCaptureFilter (Filter);
+
+ if (!CapFilter) {
+ //
+ // Return failure if we couldn't create the filter.
+ //
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+
+ } else {
+ //
+ // Add the item to the object bag if we we were successful.
+ // Whenever the filter closes, the bag is cleaned up and we will be
+ // freed.
+ //
+ Status = KsAddItemToObjectBag (
+ Filter -> Bag,
+ reinterpret_cast <PVOID> (CapFilter),
+ reinterpret_cast <PFNKSFREE> (CCaptureFilter::Cleanup)
+ );
+
+ if (!NT_SUCCESS (Status)) {
+ delete CapFilter;
+ } else {
+ Filter -> Context = reinterpret_cast <PVOID> (CapFilter);
+ }
+
+ }
+
+ return Status;
+
+}
+
+/**************************************************************************
+
+ DESCRIPTOR AND DISPATCH LAYOUT
+
+**************************************************************************/
+
+GUID g_PINNAME_VIDEO_CAPTURE = {STATIC_PINNAME_VIDEO_CAPTURE};
+
+//
+// CaptureFilterCategories:
+//
+// The list of category GUIDs for the capture filter.
+//
+const
+GUID
+CaptureFilterCategories [CAPTURE_FILTER_CATEGORIES_COUNT] = {
+ STATICGUIDOF (KSCATEGORY_VIDEO),
+ STATICGUIDOF (KSCATEGORY_CAPTURE),
+ STATICGUIDOF (KSCATEGORY_VIDEO_CAMERA)
+};
+
+//
+// CaptureFilterPinDescriptors:
+//
+// The list of pin descriptors on the capture filter.
+//
+const
+KSPIN_DESCRIPTOR_EX
+CaptureFilterPinDescriptors [CAPTURE_FILTER_PIN_COUNT] = {
+ //
+ // Video Capture Pin
+ //
+ {
+ &CapturePinDispatch,
+ NULL,
+ {
+ 0, // Interfaces (NULL, 0 == default)
+ NULL,
+ 0, // Mediums (NULL, 0 == default)
+ NULL,
+ SIZEOF_ARRAY(CapturePinDataRanges),// Range Count
+ CapturePinDataRanges, // Ranges
+ KSPIN_DATAFLOW_OUT, // Dataflow
+ KSPIN_COMMUNICATION_BOTH, // Communication
+ &PIN_CATEGORY_CAPTURE, // Category
+ &g_PINNAME_VIDEO_CAPTURE, // Name
+ 0 // Reserved
+ },
+#ifdef _X86_
+ KSPIN_FLAG_GENERATE_MAPPINGS | // Pin Flags
+#endif
+ KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY,
+ 1, // Instances Possible
+ 1, // Instances Necessary
+ &CapturePinAllocatorFraming, // Allocator Framing
+ reinterpret_cast <PFNKSINTERSECTHANDLEREX>
+ (CCapturePin::IntersectHandler)
+ }
+};
+
+//
+// CaptureFilterDispatch:
+//
+// This is the dispatch table for the capture filter. It provides notification
+// of creation, closure, processing (for filter-centrics, not for the capture
+// filter), and resets (for filter-centrics, not for the capture filter).
+//
+const
+KSFILTER_DISPATCH
+CaptureFilterDispatch = {
+ CCaptureFilter::DispatchCreate, // Filter Create
+ NULL, // Filter Close
+ NULL, // Filter Process
+ NULL // Filter Reset
+};
+
+
+//
+// CaptureFilterDescription:
+//
+// The descriptor for the capture filter. We don't specify any topology
+// since there's only one pin on the filter. Realistically, there would
+// be some topological relationships here because there would be input
+// pins from crossbars and the like.
+//
+const
+KSFILTER_DESCRIPTOR
+CaptureFilterDescriptor = {
+ &CaptureFilterDispatch, // Dispatch Table
+ NULL, // Automation Table
+ KSFILTER_DESCRIPTOR_VERSION, // Version
+ 0, // Flags
+ &KSNAME_Filter, // Reference GUID
+ DEFINE_KSFILTER_PIN_DESCRIPTORS (CaptureFilterPinDescriptors),
+ DEFINE_KSFILTER_CATEGORIES (CaptureFilterCategories),
+ 0,
+ sizeof (KSNODE_DESCRIPTOR),
+ NULL,
+ 0,
+ NULL,
+ NULL // Component ID
+}; \ No newline at end of file
diff --git a/avstream/avshws/filter.h b/avstream/avshws/filter.h
new file mode 100644
index 00000000..e5cb9895
--- /dev/null
+++ b/avstream/avshws/filter.h
@@ -0,0 +1,88 @@
+/**************************************************************************
+
+ AVStream Simulated Hardware Sample
+
+ Copyright (c) 2001, Microsoft Corporation.
+
+ File:
+
+ filter.h
+
+ Abstract:
+
+ This file contains the filter level header for the capture filter.
+
+ History:
+
+ created 3/12/2001
+
+**************************************************************************/
+
+class CCaptureFilter {
+
+private:
+
+ //
+ // The AVStream filter object associated with this CCaptureFilter.
+ //
+ PKSFILTER m_Filter;
+
+ //
+ // Cleanup():
+ //
+ // This is the bag cleanup callback for the CCaptureFilter. Not providing
+ // one would cause ExFreePool to be used. This is not good for C++
+ // constructed objects. We simply delete the object here.
+ //
+ static
+ void
+ Cleanup (
+ IN CCaptureFilter *CapFilter
+ )
+ {
+ delete CapFilter;
+ }
+
+public:
+
+ //
+ // CCaptureFilter():
+ //
+ // The capture filter object constructor. Since the new operator will
+ // have zeroed the memory, do not bother initializing any NULL or 0
+ // fields. Only initialize non-NULL, non-0 fields.
+ //
+ CCaptureFilter (
+ IN PKSFILTER Filter
+ ) :
+ m_Filter (Filter)
+ {
+ }
+
+ //
+ // ~CCaptureFilter():
+ //
+ // The capture filter destructor.
+ //
+ ~CCaptureFilter (
+ )
+ {
+ }
+
+ //
+ // DispatchCreate():
+ //
+ // This is the filter creation dispatch for the capture filter. It
+ // creates the CCaptureFilter object, associates it with the AVStream
+ // object, and bags it for easy cleanup later.
+ //
+ static
+ NTSTATUS
+ DispatchCreate (
+ IN PKSFILTER Filter,
+ IN PIRP Irp
+ );
+
+};
+
+
diff --git a/avstream/avshws/hwsim.cpp b/avstream/avshws/hwsim.cpp
new file mode 100644
index 00000000..8966f7a1
--- /dev/null
+++ b/avstream/avshws/hwsim.cpp
@@ -0,0 +1,868 @@
+/**************************************************************************
+
+ AVStream Simulated Hardware Sample
+
+ Copyright (c) 2001, Microsoft Corporation.
+
+ File:
+
+ hwsim.cpp
+
+ Abstract:
+
+ This file contains the hardware simulation. It fakes "DMA" transfers,
+ scatter gather mapping handling, ISR's, etc... The ISR routine in
+ here will be called when an ISR would be generated by the fake hardware
+ and it will directly call into the device level ISR for more accurate
+ simulation.
+
+ History:
+
+ created 3/9/2001
+
+**************************************************************************/
+
+#include "avshws.h"
+
+
+/*************************************************/
+KDEFERRED_ROUTINE SimulatedInterrupt;
+
+void
+SimulatedInterrupt (
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SystemArg1,
+ IN PVOID SystemArg2
+ )
+{
+ CHardwareSimulation* HardwareSim = (CHardwareSimulation*)DeferredContext;
+
+ if (HardwareSim)
+ {
+ HardwareSim -> FakeHardware ();
+ }
+}
+
+
+/**************************************************************************
+
+ PAGEABLE CODE
+
+**************************************************************************/
+
+#ifdef ALLOC_PRAGMA
+#pragma code_seg("PAGE")
+#endif // ALLOC_PRAGMA
+
+
+
+CHardwareSimulation::
+CHardwareSimulation (
+ IN IHardwareSink *HardwareSink
+ ) :
+ m_HardwareSink (HardwareSink),
+ m_ScatterGatherMappingsMax (SCATTER_GATHER_MAPPINGS_MAX)
+
+/*++
+
+Routine Description:
+
+ Construct a hardware simulation
+
+Arguments:
+
+ HardwareSink -
+ The hardware sink interface. This is used to trigger
+ fake interrupt service routines from.
+
+Return Value:
+
+ Success / Failure
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ //
+ // Initialize the DPC's, timer's, and locks necessary to simulate
+ // this capture hardware.
+ //
+ KeInitializeDpc (
+ &m_IsrFakeDpc,
+ SimulatedInterrupt,
+ this
+ );
+
+ KeInitializeEvent (
+ &m_HardwareEvent,
+ SynchronizationEvent,
+ FALSE
+ );
+
+ KeInitializeTimer (&m_IsrTimer);
+
+ KeInitializeSpinLock (&m_ListLock);
+
+}
+
+/*************************************************/
+
+
+CHardwareSimulation *
+CHardwareSimulation::
+Initialize (
+ IN KSOBJECT_BAG Bag,
+ IN IHardwareSink *HardwareSink
+ )
+
+/*++
+
+Routine Description:
+
+ Initialize the hardware simulation
+
+Arguments:
+
+ HardwareSink -
+ The hardware sink interface. This is what ISR's will be
+ triggered through.
+
+Return Value:
+
+ A fully initialized hardware simulation or NULL if the simulation
+ could not be initialized.
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ CHardwareSimulation *HwSim =
+ new (NonPagedPool) CHardwareSimulation (HardwareSink);
+
+ return HwSim;
+
+}
+
+/*************************************************/
+
+
+NTSTATUS
+CHardwareSimulation::
+Start (
+ IN CImageSynthesizer *ImageSynth,
+ IN LONGLONG TimePerFrame,
+ IN ULONG Width,
+ IN ULONG Height,
+ IN ULONG ImageSize
+ )
+
+/*++
+
+Routine Description:
+
+ Start the hardware simulation. This will kick the interrupts on,
+ begin issuing DPC's, filling in capture information, etc...
+ We keep track of starvation starting at this point.
+
+Arguments:
+
+ ImageSynth -
+ The image synthesizer to use to generate pictures to display
+ on the capture buffer.
+
+ TimePerFrame -
+ The time per frame... we issue interrupts this often.
+
+ Width -
+ The image width
+
+ Height -
+ The image height
+
+ ImageSize -
+ The size of the image. We allocate a temporary scratch buffer
+ based on this size to fake hardware.
+
+Return Value:
+
+ Success / Failure (typical failure will be out of memory on the
+ scratch buffer, etc...)
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ m_ImageSynth = ImageSynth;
+ m_TimePerFrame = TimePerFrame;
+ m_ImageSize = ImageSize;
+ m_Height = Height;
+ m_Width = Width;
+
+ InitializeListHead (&m_ScatterGatherMappings);
+ m_NumMappingsCompleted = 0;
+ m_ScatterGatherMappingsQueued = 0;
+ m_NumFramesSkipped = 0;
+ m_InterruptTime = 0;
+
+ KeQuerySystemTime (&m_StartTime);
+
+ //
+ // Allocate a scratch buffer for the synthesizer.
+ //
+ m_SynthesisBuffer = reinterpret_cast <PUCHAR> (
+ ExAllocatePoolWithTag (
+ NonPagedPool,
+ m_ImageSize,
+ AVSHWS_POOLTAG
+ )
+ );
+
+ if (!m_SynthesisBuffer) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // If everything is ok, start issuing interrupts.
+ //
+ if (NT_SUCCESS (Status)) {
+
+ //
+ // Initialize the entry lookaside.
+ //
+ ExInitializeNPagedLookasideList (
+ &m_ScatterGatherLookaside,
+ NULL,
+ NULL,
+ 0,
+ sizeof (SCATTER_GATHER_ENTRY),
+ 'nEGS',
+ 0
+ );
+
+ //
+ // Set up the synthesizer with the width, height, and scratch buffer.
+ //
+ m_ImageSynth -> SetImageSize (m_Width, m_Height);
+ m_ImageSynth -> SetBuffer (m_SynthesisBuffer);
+
+ LARGE_INTEGER NextTime;
+ NextTime.QuadPart = m_StartTime.QuadPart + m_TimePerFrame;
+
+ m_HardwareState = HardwareRunning;
+ KeSetTimer (&m_IsrTimer, NextTime, &m_IsrFakeDpc);
+
+ }
+
+ return Status;
+
+}
+
+/*************************************************/
+
+
+NTSTATUS
+CHardwareSimulation::
+Pause (
+ BOOLEAN Pausing
+ )
+
+/*++
+
+Routine Description:
+
+ Pause the hardware simulation... When the hardware simulation is told
+ to pause, it stops issuing interrupts, etc... but it does not reset
+ the counters
+
+Arguments:
+
+ Pausing -
+ Indicates whether the hardware is pausing or not.
+
+ TRUE -
+ Pause the hardware
+
+ FALSE -
+ Unpause the hardware from a previous pause
+
+
+Return Value:
+
+ Success / Failure
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ if (Pausing && m_HardwareState == HardwareRunning) {
+ //
+ // If we were running, stop completing mappings, etc...
+ //
+ m_StopHardware = TRUE;
+
+ KeWaitForSingleObject (
+ &m_HardwareEvent,
+ Suspended,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ NT_ASSERT (m_StopHardware == FALSE);
+
+ m_HardwareState = HardwarePaused;
+
+ } else if (!Pausing && m_HardwareState == HardwarePaused) {
+
+ //
+ // For unpausing the hardware, we need to compute the relative time
+ // and restart interrupts.
+ //
+ LARGE_INTEGER UnpauseTime;
+
+ KeQuerySystemTime (&UnpauseTime);
+ m_InterruptTime = (ULONG) (
+ (UnpauseTime.QuadPart - m_StartTime.QuadPart) /
+ m_TimePerFrame
+ );
+
+ UnpauseTime.QuadPart = m_StartTime.QuadPart +
+ (m_InterruptTime + 1) * m_TimePerFrame;
+
+ m_HardwareState = HardwareRunning;
+ KeSetTimer (&m_IsrTimer, UnpauseTime, &m_IsrFakeDpc);
+
+ }
+
+ return STATUS_SUCCESS;
+
+}
+
+/**************************************************************************
+
+ LOCKED CODE
+
+**************************************************************************/
+
+#ifdef ALLOC_PRAGMA
+#pragma code_seg()
+#endif // ALLOC_PRAGMA
+
+NTSTATUS
+CHardwareSimulation::
+Stop (
+ )
+
+/*++
+
+Routine Description:
+
+ Stop the hardware simulation.... Wait until the hardware simulation
+ has successfully stopped and then return.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Success / Failure
+
+--*/
+
+{
+ KIRQL Irql;
+ //
+ // If the hardware is told to stop while it's running, we need to
+ // halt the interrupts first. If we're already paused, this has
+ // already been done.
+ //
+ if (m_HardwareState == HardwareRunning) {
+
+ m_StopHardware = TRUE;
+
+ KeWaitForSingleObject (
+ &m_HardwareEvent,
+ Suspended,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ NT_ASSERT (m_StopHardware == FALSE);
+
+ }
+
+ m_HardwareState = HardwareStopped;
+
+ //
+ // The image synthesizer may still be around. Just for safety's
+ // sake, NULL out the image synthesis buffer and toast it.
+ //
+ m_ImageSynth -> SetBuffer (NULL);
+
+ if (m_SynthesisBuffer) {
+ ExFreePool (m_SynthesisBuffer);
+ m_SynthesisBuffer = NULL;
+ }
+
+ //
+ // Protect the S/G list
+ //
+ KeAcquireSpinLock (&m_ListLock, &Irql);
+ //
+ // Free S/G buffer
+ //
+ //
+ while (m_ScatterGatherMappingsQueued > 0) {
+ LIST_ENTRY *listEntry = RemoveHeadList (&m_ScatterGatherMappings);
+ m_ScatterGatherMappingsQueued--;
+ PSCATTER_GATHER_ENTRY SGEntry =
+ reinterpret_cast <PSCATTER_GATHER_ENTRY> (
+ CONTAINING_RECORD (
+ listEntry,
+ SCATTER_GATHER_ENTRY,
+ ListEntry
+ )
+ );
+ //
+ // Release the scatter / gather entry back to our lookaside.
+ //
+ ExFreeToNPagedLookasideList (
+ &m_ScatterGatherLookaside,
+ reinterpret_cast <PVOID> (SGEntry)
+ );
+ }
+
+ m_NumMappingsCompleted = 0;
+ m_ScatterGatherBytesQueued = 0;
+ //
+ // Delete the scatter / gather lookaside for this run.
+ //
+ ExDeleteNPagedLookasideList (&m_ScatterGatherLookaside);
+
+ KeReleaseSpinLock (&m_ListLock, Irql);
+
+ return STATUS_SUCCESS;
+
+}
+
+
+ULONG
+CHardwareSimulation::
+ReadNumberOfMappingsCompleted (
+ )
+
+/*++
+
+Routine Description:
+
+ Read the number of scatter / gather mappings which have been
+ completed (TOTAL NUMBER) since the last reset of the simulated
+ hardware
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Total number of completed mappings.
+
+--*/
+
+{
+
+ //
+ // Don't care if this is being updated this moment in the DPC... I only
+ // need a number to return which isn't too great (too small is ok).
+ // In real hardware, this wouldn't be done this way anyway.
+ //
+ return m_NumMappingsCompleted;
+
+}
+
+/*************************************************/
+
+
+ULONG
+CHardwareSimulation::
+ProgramScatterGatherMappings (
+ IN PKSSTREAM_POINTER Clone,
+ IN PUCHAR *Buffer,
+ IN PKSMAPPING Mappings,
+ IN ULONG MappingsCount,
+ IN ULONG MappingStride
+ )
+
+/*++
+
+Routine Description:
+
+ Program the scatter gather mapping list. This shoves a bunch of
+ entries on a list for access during the fake interrupt. Note that
+ we have physical addresses here only for simulation. We really
+ access via the virtual address.... although we chunk it into multiple
+ buffers to more realistically simulate S/G
+
+Arguments:
+
+ Buffer -
+ The virtual address of the buffer mapped by the mapping list
+
+ Mappings -
+ The KSMAPPINGS array corresponding to the buffer
+
+ MappingsCount -
+ The number of mappings in the mappings array
+
+ MappingStride -
+ The mapping stride used in initialization of AVStream DMA
+
+Return Value:
+
+ Number of mappings actually inserted.
+
+--*/
+
+{
+
+ KIRQL Irql;
+
+ ULONG MappingsInserted = 0;
+
+ //
+ // Protect our S/G list with a spinlock.
+ //
+ KeAcquireSpinLock (&m_ListLock, &Irql);
+
+ //
+ // Loop through the scatter / gather list and break the buffer up into
+ // chunks equal to the scatter / gather mappings. Stuff the virtual
+ // addresses of these chunks on a list somewhere. We update the buffer
+ // pointer the caller passes as a more convenient way of doing this.
+ //
+ // If I could just remap physical in the list to virtual easily here,
+ // I wouldn't need to do it.
+ //
+#if !defined(_X86_)
+ do
+ {
+ PSCATTER_GATHER_ENTRY Entry =
+ reinterpret_cast <PSCATTER_GATHER_ENTRY> (
+ ExAllocateFromNPagedLookasideList (
+ &m_ScatterGatherLookaside
+ )
+ );
+
+ if (!Entry) {
+ break;
+ }
+ Entry -> Virtual = *Buffer;
+ Entry -> ByteCount = MappingsCount;
+ Entry -> CloneEntry = Clone;
+
+ //
+ // Move forward a specific number of bytes in chunking this into
+ // mapping sized va buffers.
+ //
+ *Buffer += MappingsCount;
+ Mappings = reinterpret_cast <PKSMAPPING> (
+ (reinterpret_cast <PUCHAR> (Mappings) + MappingStride)
+ );
+
+ InsertTailList (&m_ScatterGatherMappings, &(Entry -> ListEntry));
+ MappingsInserted = MappingsCount;
+ m_ScatterGatherMappingsQueued++;
+ m_ScatterGatherBytesQueued += MappingsCount;
+
+ }
+ while(FALSE);
+
+#else
+ for (ULONG MappingNum = 0;
+ MappingNum < MappingsCount &&
+ m_ScatterGatherMappingsQueued < m_ScatterGatherMappingsMax;
+ MappingNum++) {
+
+ PSCATTER_GATHER_ENTRY Entry =
+ reinterpret_cast <PSCATTER_GATHER_ENTRY> (
+ ExAllocateFromNPagedLookasideList (
+ &m_ScatterGatherLookaside
+ )
+ );
+
+ if (!Entry) {
+ break;
+ }
+
+ Entry -> Virtual = *Buffer;
+ Entry -> ByteCount = Mappings -> ByteCount;
+
+ //
+ // Move forward a specific number of bytes in chunking this into
+ // mapping sized va buffers.
+ //
+ *Buffer += Entry -> ByteCount;
+ Mappings = reinterpret_cast <PKSMAPPING> (
+ (reinterpret_cast <PUCHAR> (Mappings) + MappingStride)
+ );
+
+ InsertTailList (&m_ScatterGatherMappings, &(Entry -> ListEntry));
+ MappingsInserted++;
+ m_ScatterGatherMappingsQueued++;
+ m_ScatterGatherBytesQueued += Entry -> ByteCount;
+
+ }
+#endif
+
+ KeReleaseSpinLock (&m_ListLock, Irql);
+
+ return MappingsInserted;
+
+}
+
+/*************************************************/
+
+
+NTSTATUS
+CHardwareSimulation::
+FillScatterGatherBuffers (
+ )
+
+/*++
+
+Routine Description:
+
+ The hardware has synthesized a buffer in scratch space and we're to
+ fill scatter / gather buffers.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Success / Failure
+
+--*/
+
+{
+
+ //
+ // We're using this list lock to protect our scatter / gather lists instead
+ // of some hardware mechanism / KeSynchronizeExecution / whatever.
+ //
+ KeAcquireSpinLockAtDpcLevel (&m_ListLock);
+
+ PUCHAR Buffer = reinterpret_cast <PUCHAR> (m_SynthesisBuffer);
+ ULONG BufferRemaining = m_ImageSize;
+
+ //
+ // For simplification, if there aren't enough scatter / gather buffers
+ // queued, we don't partially fill the ones that are available. We just
+ // skip the frame and consider it starvation.
+ //
+ // This could be enforced by only programming scatter / gather mappings
+ // for a buffer if all of them fit in the table also...
+ //
+ while (BufferRemaining &&
+ m_ScatterGatherMappingsQueued > 0 &&
+ m_ScatterGatherBytesQueued >= BufferRemaining) {
+
+ LIST_ENTRY *listEntry = RemoveHeadList (&m_ScatterGatherMappings);
+ m_ScatterGatherMappingsQueued--;
+
+ PSCATTER_GATHER_ENTRY SGEntry =
+ reinterpret_cast <PSCATTER_GATHER_ENTRY> (
+ CONTAINING_RECORD (
+ listEntry,
+ SCATTER_GATHER_ENTRY,
+ ListEntry
+ )
+ );
+
+ //
+ // Since we're software, we'll be accessing this by virtual address...
+ //
+ ULONG BytesToCopy =
+ (BufferRemaining < SGEntry -> ByteCount) ?
+ BufferRemaining :
+ SGEntry -> ByteCount;
+
+ LONG Width = m_Width*(m_ImageSynth->GetBytesPerPixel());
+
+ LONG Stride = Width;
+ if(SGEntry->CloneEntry->StreamHeader->Size >= sizeof(KSSTREAM_HEADER)+sizeof(KS_FRAME_INFO))
+ {
+ PKS_FRAME_INFO FrameInfo = reinterpret_cast <PKS_FRAME_INFO> (SGEntry->CloneEntry->StreamHeader+1);
+ if(FrameInfo->lSurfacePitch != 0)
+ {
+ Stride = FrameInfo->lSurfacePitch;
+ if(FrameInfo->lSurfacePitch < 0)
+ {
+ Stride = -Stride;
+ }
+ }
+ }
+
+ for(ULONG y = 0; y < m_Height; y++)
+ {
+ RtlCopyMemory((SGEntry->Virtual+(ULONG)Stride*y), Buffer, Width);
+ Buffer += Width;
+ BytesToCopy -= Width;
+ BufferRemaining -= Width;
+ }
+
+ m_NumMappingsCompleted++;
+ m_ScatterGatherBytesQueued -= SGEntry -> ByteCount;
+
+ //
+ // Release the scatter / gather entry back to our lookaside.
+ //
+ ExFreeToNPagedLookasideList (
+ &m_ScatterGatherLookaside,
+ reinterpret_cast <PVOID> (SGEntry)
+ );
+
+ }
+
+ KeReleaseSpinLockFromDpcLevel (&m_ListLock);
+
+ if (BufferRemaining) return STATUS_INSUFFICIENT_RESOURCES;
+ else return STATUS_SUCCESS;
+
+}
+
+/*************************************************/
+
+
+void
+CHardwareSimulation::
+FakeHardware (
+ )
+
+/*++
+
+Routine Description:
+
+ Simulate an interrupt and what the hardware would have done in the
+ time since the previous interrupt.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ m_InterruptTime++;
+
+ //
+ // The hardware can be in a pause state in which case, it issues interrupts
+ // but does not complete mappings. In this case, don't bother synthesizing
+ // a frame and doing the work of looking through the mappings table.
+ //
+ if (m_HardwareState == HardwareRunning) {
+
+ //
+ // Generate a "time stamp" just to overlay it onto the capture image.
+ // It makes it more exciting than bars that do nothing.
+ //
+ LONGLONG PtsRel = ((m_InterruptTime + 1) * m_TimePerFrame);
+
+ ULONG Min = (ULONG)(PtsRel / 600000000);
+ ULONG RemMin = (ULONG)(PtsRel % 600000000);
+ ULONG Sec = (ULONG)(RemMin / 10000000);
+ ULONG RemSec = (ULONG)(RemMin % 10000000);
+ ULONG Hund = (ULONG)(RemSec / 100000);
+
+ //
+ // Synthesize a buffer in scratch space.
+ //
+ m_ImageSynth -> SynthesizeBars ();
+
+ CHAR Text [256];
+ Text[0] = '\0';
+ (void) RtlStringCbPrintfA(Text, sizeof(Text), "%ld:%02ld.%02ld", Min, Sec, Hund);
+
+ //
+ // Overlay a clock onto the scratch space image.
+ //
+ m_ImageSynth -> OverlayText (
+ POSITION_CENTER,
+ (m_Height - 28),
+ 1,
+ Text,
+ BLACK,
+ WHITE
+ );
+
+ //
+ // Overlay a counter of skipped frames onto the scratch image.
+ //
+ (void) RtlStringCbPrintfA(Text, sizeof(Text), "Skipped: %ld", m_NumFramesSkipped);
+ m_ImageSynth -> OverlayText (
+ 10,
+ 10,
+ 1,
+ Text,
+ TRANSPARENT,
+ BLUE
+ );
+
+ //
+ // Fill scatter gather buffers
+ //
+ if (!NT_SUCCESS (FillScatterGatherBuffers ())) {
+ InterlockedIncrement (PLONG (&m_NumFramesSkipped));
+ }
+
+ }
+
+ //
+ // Issue an interrupt to our hardware sink. This is a "fake" interrupt.
+ // It will occur at DISPATCH_LEVEL.
+ //
+ m_HardwareSink -> Interrupt ();
+
+ //
+ // Reschedule the timer if the hardware isn't being stopped.
+ //
+ if (!m_StopHardware) {
+
+ //
+ // Reschedule the timer for the next interrupt time.
+ //
+ LARGE_INTEGER NextTime;
+ NextTime.QuadPart = m_StartTime.QuadPart +
+ (m_TimePerFrame * (m_InterruptTime + 1));
+
+ KeSetTimer (&m_IsrTimer, NextTime, &m_IsrFakeDpc);
+
+ } else {
+ //
+ // If someone is waiting on the hardware to stop, raise the stop
+ // event and clear the flag.
+ //
+ m_StopHardware = FALSE;
+ KeSetEvent (&m_HardwareEvent, IO_NO_INCREMENT, FALSE);
+ }
+
+}
diff --git a/avstream/avshws/hwsim.h b/avstream/avshws/hwsim.h
new file mode 100644
index 00000000..21ddcb41
--- /dev/null
+++ b/avstream/avshws/hwsim.h
@@ -0,0 +1,290 @@
+/**************************************************************************
+
+ AVStream Simulated Hardware Sample
+
+ Copyright (c) 2001, Microsoft Corporation.
+
+ File:
+
+ hwsim.cpp
+
+ Abstract:
+
+ This file is the hardware simulation header.
+
+ The simulation fakes "DMA" transfers, scatter gather mapping handling,
+ ISR's, etc... The ISR routine in here will be called when an ISR
+ would be generated by the fake hardware and it will directly call into
+ the device level ISR for more accurate simulation.
+
+ History:
+
+ created 3/9/2001
+
+**************************************************************************/
+
+//
+// SCATTER_GATHER_MAPPINGS_MAX:
+//
+// The maximum number of entries in the hardware's scatter/gather list. I
+// am making this so large for a few reasons:
+//
+// 1) we're faking this with uncompressed surfaces --
+// these are large buffers which will map to a lot of s/g entries
+// 2) the fake hardware implementation requires at least one frame's
+// worth of s/g entries to generate a frame
+//
+#define SCATTER_GATHER_MAPPINGS_MAX 128
+
+//
+// SCATTER_GATHER_ENTRY:
+//
+// This structure is used to keep the scatter gather table for the fake
+// hardware as a doubly linked list.
+//
+typedef struct _SCATTER_GATHER_ENTRY {
+
+ LIST_ENTRY ListEntry;
+ PKSSTREAM_POINTER CloneEntry;
+ PUCHAR Virtual;
+ ULONG ByteCount;
+
+} SCATTER_GATHER_ENTRY, *PSCATTER_GATHER_ENTRY;
+
+//
+// CHardwareSimulation:
+//
+// The hardware simulation class.
+//
+class CHardwareSimulation {
+
+private:
+
+ //
+ // The image synthesizer. This is a piece of code which actually draws
+ // the requested images.
+ //
+ CImageSynthesizer *m_ImageSynth;
+
+ //
+ // The synthesis buffer. This is a private buffer we use to generate the
+ // capture image in. The fake "scatter / gather" mappings are filled
+ // in from this buffer during each interrupt.
+ //
+ PUCHAR m_SynthesisBuffer;
+
+ //
+ // Key information regarding the frames we generate.
+ //
+ LONGLONG m_TimePerFrame;
+ ULONG m_Width;
+ ULONG m_Height;
+ ULONG m_ImageSize;
+
+ //
+ // Scatter gather mappings for the simulated hardware.
+ //
+ KSPIN_LOCK m_ListLock;
+ LIST_ENTRY m_ScatterGatherMappings;
+
+ //
+ // Lookaside for memory for the scatter / gather entries on the scatter /
+ // gather list.
+ //
+ NPAGED_LOOKASIDE_LIST m_ScatterGatherLookaside;
+
+ //
+ // The current state of the fake hardware.
+ //
+ HARDWARE_STATE m_HardwareState;
+
+ //
+ // The pause / stop hardware flag and event.
+ //
+ BOOLEAN m_StopHardware;
+ KEVENT m_HardwareEvent;
+
+ //
+ // Maximum number of scatter / gather mappins in the s/g table of the
+ // fake hardware.
+ //
+ ULONG m_ScatterGatherMappingsMax;
+
+ //
+ // Number of scatter / gather mappings that have been completed (total)
+ // since the start of the hardware or any reset.
+ //
+ ULONG m_NumMappingsCompleted;
+
+ //
+ // Number of scatter / gather mappings that are queued for this hardware.
+ //
+ ULONG m_ScatterGatherMappingsQueued;
+ ULONG m_ScatterGatherBytesQueued;
+
+ //
+ // Number of frames skipped due to lack of scatter / gather mappings.
+ //
+ ULONG m_NumFramesSkipped;
+
+ //
+ // The "Interrupt Time". Number of "fake" interrupts that have occurred
+ // since the hardware was started.
+ //
+ ULONG m_InterruptTime;
+
+ //
+ // The system time at start.
+ //
+ LARGE_INTEGER m_StartTime;
+
+ //
+ // The DPC used to "fake" ISR
+ //
+ KDPC m_IsrFakeDpc;
+ KTIMER m_IsrTimer;
+
+ //
+ // The hardware sink that will be used for interrupt notifications.
+ //
+ IHardwareSink *m_HardwareSink;
+
+ //
+ // FillScatterGatherBuffers():
+ //
+ // This is called by the hardware simulation to fill a series of scatter /
+ // gather buffers with synthesized data.
+ //
+ NTSTATUS
+ FillScatterGatherBuffers (
+ );
+
+public:
+
+ LONG GetSkippedFrameCount()
+ {
+ return InterlockedExchange((LONG*)&this->m_NumFramesSkipped, this->m_NumFramesSkipped);
+ }
+ //
+ // CHardwareSimulation():
+ //
+ // The hardware simulation constructor. Since the new operator will
+ // have zeroed the memory, only initialize non-NULL, non-0 fields.
+ //
+ CHardwareSimulation (
+ IN IHardwareSink *HardwareSink
+ );
+
+ //
+ // ~CHardwareSimulation():
+ //
+ // The hardware simulation destructor.
+ //
+ ~CHardwareSimulation (
+ )
+ {
+ }
+
+ //
+ // Cleanup():
+ //
+ // This is the free callback for the bagged hardware sim. Not providing
+ // one will call ExFreePool, which is not what we want for a constructed
+ // C++ object. This simply deletes the simulation.
+ //
+ static
+ void
+ Cleanup (
+ IN CHardwareSimulation *HwSim
+ )
+ {
+ delete HwSim;
+ }
+
+ //
+ // FakeHardware():
+ //
+ // Called from the simulated interrupt. First we fake the hardware's
+ // actions (at DPC) then we call the "Interrupt service routine" on
+ // the hardware sink.
+ //
+ void
+ FakeHardware (
+ );
+
+ //
+ // Start():
+ //
+ // "Start" the fake hardware. This will start issuing interrupts and
+ // DPC's.
+ //
+ // The frame rate, image size, and a synthesizer must be provided.
+ //
+ NTSTATUS
+ Start (
+ CImageSynthesizer *ImageSynth,
+ IN LONGLONG TimePerFrame,
+ IN ULONG Width,
+ IN ULONG Height,
+ IN ULONG ImageSize
+ );
+
+ //
+ // Pause():
+ //
+ // "Pause" or "unpause" the fake hardware. This will stop issuing
+ // interrupts or DPC's on a pause and restart them on an unpause. Note
+ // that this will not reset counters as a Stop() would.
+ //
+ NTSTATUS
+ Pause (
+ IN BOOLEAN Pausing
+ );
+
+ //
+ // Stop():
+ //
+ // "Stop" the fake hardware. This will stop issuing interrupts and
+ // DPC's.
+ //
+ NTSTATUS
+ Stop (
+ );
+
+ //
+ // ProgramScatterGatherMappings():
+ //
+ // Program a series of scatter gather mappings into the fake hardware.
+ //
+ ULONG
+ ProgramScatterGatherMappings (
+ IN PKSSTREAM_POINTER Clone,
+ IN PUCHAR *Buffer,
+ IN PKSMAPPING Mappings,
+ IN ULONG MappingsCount,
+ IN ULONG MappingStride
+ );
+
+ //
+ // Initialize():
+ //
+ // Initialize a piece of simulated hardware.
+ //
+ static
+ CHardwareSimulation *
+ Initialize (
+ IN KSOBJECT_BAG Bag,
+ IN IHardwareSink *HardwareSink
+ );
+
+ //
+ // ReadNumberOfMappingsCompleted():
+ //
+ // Read the number of mappings completed since the last hardware reset.
+ //
+ ULONG
+ ReadNumberOfMappingsCompleted (
+ );
+
+};
+
diff --git a/avstream/avshws/image.cpp b/avstream/avshws/image.cpp
new file mode 100644
index 00000000..8ab35624
--- /dev/null
+++ b/avstream/avshws/image.cpp
@@ -0,0 +1,605 @@
+/**************************************************************************
+
+ AVStream Simulated Hardware Sample
+
+ Copyright (c) 2001, Microsoft Corporation.
+
+ File:
+
+ image.cpp
+
+ Abstract:
+
+ The image synthesis and overlay code. These objects provide image
+ synthesis (pixel, color-bar, etc...) onto RGB24 and UYVY buffers as
+ well as software string overlay into these buffers.
+
+ This entire file, data and all, must be in locked segments.
+
+ History:
+
+ created 1/16/2001
+
+**************************************************************************/
+
+#include "avshws.h"
+
+/**************************************************************************
+
+ Constants
+
+**************************************************************************/
+
+//
+// g_FontData:
+//
+// The following is an 8x8 bitmapped font for use in the text overlay
+// code.
+//
+UCHAR g_FontData [256][8] = {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e},
+ {0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e},
+ {0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00},
+ {0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00},
+ {0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c},
+ {0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c},
+ {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00},
+ {0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff},
+ {0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00},
+ {0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff},
+ {0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78},
+ {0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18},
+ {0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0},
+ {0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0},
+ {0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99},
+ {0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00},
+ {0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00},
+ {0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18},
+ {0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00},
+ {0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00},
+ {0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78},
+ {0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00},
+ {0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff},
+ {0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00},
+ {0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00},
+ {0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00},
+ {0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00},
+ {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00},
+ {0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00},
+ {0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00},
+ {0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00},
+ {0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00},
+ {0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00},
+ {0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00},
+ {0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00},
+ {0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00},
+ {0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00},
+ {0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00},
+ {0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60},
+ {0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00},
+ {0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00},
+ {0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00},
+ {0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00},
+ {0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00},
+ {0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00},
+ {0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00},
+ {0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00},
+ {0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00},
+ {0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00},
+ {0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00},
+ {0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00},
+ {0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00},
+ {0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60},
+ {0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00},
+ {0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00},
+ {0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00},
+ {0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00},
+ {0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00},
+ {0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00},
+ {0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00},
+ {0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00},
+ {0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00},
+ {0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00},
+ {0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00},
+ {0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00},
+ {0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00},
+ {0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00},
+ {0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00},
+ {0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00},
+ {0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00},
+ {0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00},
+ {0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00},
+ {0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
+ {0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00},
+ {0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00},
+ {0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00},
+ {0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00},
+ {0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00},
+ {0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00},
+ {0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00},
+ {0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00},
+ {0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00},
+ {0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00},
+ {0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00},
+ {0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff},
+ {0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00},
+ {0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00},
+ {0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00},
+ {0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00},
+ {0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00},
+ {0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00},
+ {0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8},
+ {0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00},
+ {0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00},
+ {0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78},
+ {0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00},
+ {0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00},
+ {0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00},
+ {0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00},
+ {0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00},
+ {0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0},
+ {0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e},
+ {0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00},
+ {0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00},
+ {0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00},
+ {0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00},
+ {0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00},
+ {0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00},
+ {0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00},
+ {0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8},
+ {0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00},
+ {0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00},
+ {0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00},
+ {0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00},
+ {0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00},
+ {0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78},
+ {0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00},
+ {0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00},
+ {0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00},
+ {0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00},
+ {0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00},
+ {0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00},
+ {0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38},
+ {0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00},
+ {0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00},
+ {0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00},
+ {0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00},
+ {0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00},
+ {0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00},
+ {0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00},
+ {0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00},
+ {0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00},
+ {0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00},
+ {0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00},
+ {0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00},
+ {0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00},
+ {0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00},
+ {0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00},
+ {0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00},
+ {0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8},
+ {0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00},
+ {0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00},
+ {0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18},
+ {0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00},
+ {0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30},
+ {0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7},
+ {0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70},
+ {0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00},
+ {0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00},
+ {0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00},
+ {0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00},
+ {0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00},
+ {0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00},
+ {0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00},
+ {0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00},
+ {0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00},
+ {0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00},
+ {0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f},
+ {0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03},
+ {0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00},
+ {0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00},
+ {0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00},
+ {0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88},
+ {0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa},
+ {0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee},
+ {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+ {0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18},
+ {0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18},
+ {0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36},
+ {0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36},
+ {0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18},
+ {0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36},
+ {0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+ {0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36},
+ {0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00},
+ {0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00},
+ {0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18},
+ {0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00},
+ {0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18},
+ {0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18},
+ {0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00},
+ {0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18},
+ {0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18},
+ {0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36},
+ {0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36},
+ {0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36},
+ {0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36},
+ {0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00},
+ {0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36},
+ {0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00},
+ {0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18},
+ {0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36},
+ {0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00},
+ {0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18},
+ {0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36},
+ {0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36},
+ {0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18},
+ {0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18},
+ {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ {0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff},
+ {0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0},
+ {0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f},
+ {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00},
+ {0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0},
+ {0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00},
+ {0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00},
+ {0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00},
+ {0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00},
+ {0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0},
+ {0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00},
+ {0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc},
+ {0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00},
+ {0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00},
+ {0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00},
+ {0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00},
+ {0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0},
+ {0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00},
+ {0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00},
+ {0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00},
+ {0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00},
+ {0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00},
+ {0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00},
+ {0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18},
+ {0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70},
+ {0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00},
+ {0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00},
+ {0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00},
+ {0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c},
+ {0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00},
+ {0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+//
+// Standard definition of EIA-189-A color bars. The actual color definitions
+// are either in CRGB24Synthesizer or CYUVSynthesizer.
+//
+const COLOR g_ColorBars[] =
+ {WHITE, YELLOW, CYAN, GREEN, MAGENTA, RED, BLUE, BLACK};
+
+const UCHAR CRGB24Synthesizer::Colors [MAX_COLOR][3] = {
+ {0, 0, 0}, // BLACK
+ {255, 255, 255}, // WHITE
+ {0, 255, 255}, // YELLOW
+ {255, 255, 0}, // CYAN
+ {0, 255, 0}, // GREEN
+ {255, 0, 255}, // MAGENTA
+ {0, 0, 255}, // RED
+ {255, 0, 0}, // BLUE
+ {128, 128, 128} // GREY
+};
+
+const UCHAR CYUVSynthesizer::Colors [MAX_COLOR][3] = {
+ {128, 16, 128}, // BLACK
+ {128, 235, 128}, // WHITE
+ {16, 211, 146}, // YELLOW
+ {166, 170, 16}, // CYAN
+ {54, 145, 34}, // GREEN
+ {202, 106, 222}, // MAGENTA
+ {90, 81, 240}, // RED
+ {240, 41, 109}, // BLUE
+ {128, 125, 128}, // GREY
+};
+
+/**************************************************************************
+
+ LOCKED CODE
+
+**************************************************************************/
+
+#ifdef ALLOC_PRAGMA
+#pragma code_seg()
+#endif // ALLOC_PRAGMA
+
+
+void
+CImageSynthesizer::
+SynthesizeBars (
+ )
+
+/*++
+
+Routine Description:
+
+ Synthesize EIA-189-A standard color bars onto the Image. The image
+ in question is the current synthesis buffer.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ const COLOR *CurColor = g_ColorBars;
+ ULONG ColorCount = SIZEOF_ARRAY (g_ColorBars);
+
+ //
+ // Set the default cursor...
+ //
+ GetImageLocation (0, 0);
+
+ //
+ // Synthesize a single line.
+ //
+ PUCHAR ImageStart = m_Cursor;
+ for (ULONG x = 0; x < m_Width; x++)
+ PutPixel (g_ColorBars [((x * ColorCount) / m_Width)]);
+
+ PUCHAR ImageEnd = m_Cursor;
+
+ //
+ // Copy the synthesized line to all subsequent lines.
+ //
+ for (ULONG line = 1; line < m_Height; line++) {
+
+ GetImageLocation (0, line);
+
+ RtlCopyMemory (
+ m_Cursor,
+ ImageStart,
+ ImageEnd - ImageStart
+ );
+ }
+}
+
+/*************************************************/
+
+
+void
+CImageSynthesizer::
+OverlayText (
+ _In_ ULONG LocX,
+ _In_ ULONG LocY,
+ _In_ ULONG Scaling,
+ _In_ LPSTR Text,
+ _In_ COLOR BgColor,
+ _In_ COLOR FgColor
+ )
+
+/*++
+
+Routine Description:
+
+ Overlay text onto the synthesized image. Clip to fit the image
+ if the overlay does not fit. The image buffer used is the set
+ synthesis buffer.
+
+Arguments:
+
+ LocX -
+ The X location on the image to begin the overlay. This MUST
+ be inside the image. POSITION_CENTER may be used to indicate
+ horizontal centering.
+
+ LocY -
+ The Y location on the image to begin the overlay. This MUST
+ be inside the image. POSITION_CENTER may be used to indicate
+ vertical centering.
+
+ Scaling -
+ Normally, the overlay is done in 8x8 font. A scaling of
+ 2 indicates 16x16, 3 indicates 24x24 and so forth.
+
+ Text -
+ A character string containing the information to overlay
+
+ BgColor -
+ The background color of the overlay window. For transparency,
+ indicate TRANSPARENT here.
+
+ FgColor -
+ The foreground color for the text overlay.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ NT_ASSERT ((LocX <= m_Width || LocX == POSITION_CENTER) &&
+ (LocY <= m_Height || LocY == POSITION_CENTER));
+
+ ULONG StrLen = 0;
+ CHAR* CurChar;
+
+ //
+ // Determine the character length of the string.
+ //
+ for (CurChar = Text; CurChar && *CurChar; CurChar++)
+ StrLen++;
+
+ //
+ // Determine the physical size of the string plus border. There is
+ // a definable NO_CHARACTER_SEPARATION. If this is defined, there will
+ // be no added space between font characters. Otherwise, one empty pixel
+ // column is added between characters.
+ //
+ #ifndef NO_CHARACTER_SEPARATION
+ ULONG LenX = (StrLen * (Scaling << 3)) + 1 + StrLen;
+ #else // NO_CHARACTER_SEPARATION
+ ULONG LenX = (StrLen * (Scaling << 3)) + 2;
+ #endif // NO_CHARACTER_SEPARATION
+
+ ULONG LenY = 2 + (Scaling << 3);
+
+ //
+ // Adjust for center overlays.
+ //
+ // NOTE: If the overlay doesn't fit into the synthesis buffer, this
+ // merely left aligns the overlay and clips off the right side.
+ //
+ if (LocX == POSITION_CENTER) {
+ if (LenX >= m_Width) {
+ LocX = 0;
+ } else {
+ LocX = (m_Width >> 1) - (LenX >> 1);
+ }
+ }
+
+ if (LocY == POSITION_CENTER) {
+ if (LenY >= m_Height) {
+ LocY = 0;
+ } else {
+ LocY = (m_Height >> 1) - (LenY >> 1);
+ }
+ }
+
+ //
+ // Determine the amount of space available on the synthesis buffer.
+ // We will clip anything that finds itself outside the synthesis buffer.
+ //
+ ULONG SpaceX = m_Width - LocX;
+ ULONG SpaceY = m_Height - LocY;
+
+ //
+ // Set the default cursor position.
+ //
+ GetImageLocation (LocX, LocY);
+
+ //
+ // Overlay a background color row.
+ //
+ if (BgColor != TRANSPARENT && SpaceY) {
+ for (ULONG x = 0; x < LenX && x < SpaceX; x++) {
+ PutPixel (BgColor);
+ }
+ }
+ LocY++;
+ if (SpaceY) SpaceY--;
+
+ //
+ // Loop across each row of the image.
+ //
+ for (ULONG row = 0; row < 8 && SpaceY; row++) {
+ //
+ // Generate a line.
+ //
+ GetImageLocation (LocX, LocY++);
+
+ PUCHAR ImageStart = m_Cursor;
+
+ ULONG CurSpaceX = SpaceX;
+ if (CurSpaceX) {
+ PutPixel (BgColor);
+ CurSpaceX--;
+ }
+
+ //
+ // Generate the row'th row of the overlay.
+ //
+ CurChar = Text;
+ while (CurChar && *CurChar) {
+
+ UCHAR CharBase = g_FontData [*CurChar++][row];
+ for (ULONG mask = 0x80; mask && CurSpaceX; mask >>= 1) {
+ for (ULONG scale = 0; scale < Scaling && CurSpaceX; scale++) {
+ if (CharBase & mask) {
+ PutPixel (FgColor);
+ } else {
+ PutPixel (BgColor);
+ }
+ CurSpaceX--;
+ }
+ }
+
+ //
+ // Separate each character by one space. Account for the border
+ // space at the end by placing the separator after the last
+ // character also.
+ //
+ #ifndef NO_CHARACTER_SEPARATION
+ if (CurSpaceX) {
+ PutPixel (BgColor);
+ CurSpaceX--;
+ }
+ #endif // NO_CHARACTER_SEPARATION
+
+ }
+
+ //
+ // If there is no separation character defined, account for the
+ // border.
+ //
+ #ifdef NO_CHARACTER_SEPARATION
+ if (CurSpaceX) {
+ PutPixel (BgColor);
+ CurSpaceX--;
+ }
+ #endif // NO_CHARACTER_SEPARATION
+
+
+ PUCHAR ImageEnd = m_Cursor;
+ //
+ // Copy the line downward scale times.
+ //
+ for (ULONG scale = 1; scale < Scaling && SpaceY; scale++) {
+ GetImageLocation (LocX, LocY++);
+ RtlCopyMemory (m_Cursor, ImageStart, ImageEnd - ImageStart);
+ SpaceY--;
+ }
+
+ }
+
+ //
+ // Add the bottom section of the overlay.
+ //
+ GetImageLocation (LocX, LocY);
+ if (BgColor != TRANSPARENT && SpaceY) {
+ for (ULONG x = 0; x < LenX && x < SpaceX; x++) {
+ PutPixel (BgColor);
+ }
+ }
+
+}
diff --git a/avstream/avshws/image.h b/avstream/avshws/image.h
new file mode 100644
index 00000000..95574479
--- /dev/null
+++ b/avstream/avshws/image.h
@@ -0,0 +1,478 @@
+/**************************************************************************
+
+ AVStream Simulated Hardware Sample
+
+ Copyright (c) 2001, Microsoft Corporation.
+
+ File:
+
+ image.h
+
+ Abstract:
+
+ The image synthesis and overlay header. These objects provide image
+ synthesis (pixel, color-bar, etc...) onto RGB24 and UYVY buffers as
+ well as software string overlay into these buffers.
+
+ History:
+
+ created 1/16/2001
+
+**************************************************************************/
+
+/**************************************************************************
+
+ Constants
+
+**************************************************************************/
+
+//
+// COLOR:
+//
+// Pixel color for placement onto the synthesis buffer.
+//
+typedef enum {
+
+ BLACK = 0,
+ WHITE,
+ YELLOW,
+ CYAN,
+ GREEN,
+ MAGENTA,
+ RED,
+ BLUE,
+ GREY,
+
+ MAX_COLOR,
+ TRANSPARENT,
+
+} COLOR;
+
+//
+// POSITION_CENTER:
+//
+// Only useful for text overlay. This can be substituted for LocX or LocY
+// in order to center the text screen on the synthesis buffer.
+//
+#define POSITION_CENTER ((ULONG)-1)
+
+/*************************************************
+
+ CImageSynthesizer
+
+ This class synthesizes images in various formats for output from the
+ capture filter. It is capable of performing various text overlays onto
+ the image surface.
+
+*************************************************/
+
+class CImageSynthesizer {
+
+protected:
+
+ //
+ // The width and height the synthesizer is set to.
+ //
+ ULONG m_Width;
+ ULONG m_Height;
+
+ //
+ // The synthesis buffer. All scan conversion happens in the synthesis
+ // buffer. This must be set with SetBuffer() before any scan conversion
+ // routines are called.
+ //
+ PUCHAR m_SynthesisBuffer;
+
+ //
+ // The default cursor. This is a pointer into the synthesis buffer where
+ // a non specific PutPixel will be placed.
+ //
+ PUCHAR m_Cursor;
+
+public:
+
+ //
+ // PutPixel():
+ //
+ // Place a pixel at the specified image cursor and move right
+ // by one pixel. No bounds checking... wrap around occurs.
+ //
+ virtual void
+ PutPixel (
+ PUCHAR *ImageLocation,
+ COLOR Color
+ ) = 0;
+
+ //
+ // PutPixel():
+ //
+ // Place a pixel at the default image cursor and move right
+ // by one pixel. No bounds checking... wrap around occurs.
+ //
+ // If the derived class doesn't provide an implementation, provide
+ // one.
+ //
+ virtual void
+ PutPixel (
+ COLOR Color
+ )
+ {
+ PutPixel (&m_Cursor, Color);
+ }
+
+ virtual long
+ GetBytesPerPixel() = 0;
+
+
+ //
+ // GetImageLocation():
+ //
+ // Get the location into the image buffer for a specific X/Y location.
+ // This also sets the synthesizer's default cursor to the position
+ // LocX, LocY.
+ //
+ virtual PUCHAR
+ GetImageLocation (
+ ULONG LocX,
+ ULONG LocY
+ ) = 0;
+
+ //
+ // SetImageSize():
+ //
+ // Set the image size of the synthesis buffer.
+ //
+ void
+ SetImageSize (
+ ULONG Width,
+ ULONG Height
+ )
+ {
+ m_Width = Width;
+ m_Height = Height;
+ }
+
+ //
+ // SetBuffer():
+ //
+ // Set the buffer the synthesizer generates images to.
+ //
+ void
+ SetBuffer (
+ PUCHAR SynthesisBuffer
+ )
+ {
+ m_SynthesisBuffer = SynthesisBuffer;
+ }
+
+ //
+ // SynthesizeBars():
+ //
+ // Synthesize EIA-189-A standard color bars.
+ //
+ void
+ SynthesizeBars (
+ );
+
+ //
+ // OverlayText():
+ //
+ // Overlay a text string onto the image.
+ //
+ void
+ OverlayText (
+ _In_ ULONG LocX,
+ _In_ ULONG LocY,
+ _In_ ULONG Scaling,
+ _In_ LPSTR Text,
+ _In_ COLOR BgColor,
+ _In_ COLOR FgColor
+ );
+
+ //
+ // DEFAULT CONSTRUCTOR
+ //
+ CImageSynthesizer (
+ ) :
+ m_Width (0),
+ m_Height (0),
+ m_SynthesisBuffer (NULL)
+ {
+ }
+
+ //
+ // CONSTRUCTOR:
+ //
+ CImageSynthesizer (
+ ULONG Width,
+ ULONG Height
+ ) :
+ m_Width (Width),
+ m_Height (Height),
+ m_SynthesisBuffer (NULL)
+ {
+ }
+
+ //
+ // DESTRUCTOR:
+ //
+ virtual
+ ~CImageSynthesizer (
+ )
+ {
+ }
+
+};
+
+/*************************************************
+
+ CRGB24Synthesizer
+
+ Image synthesizer for RGB24 format.
+
+*************************************************/
+
+class CRGB24Synthesizer : public CImageSynthesizer {
+
+private:
+
+ const static UCHAR Colors [MAX_COLOR][3];
+
+ BOOLEAN m_FlipVertical;
+
+public:
+
+ //
+ // PutPixel():
+ //
+ // Place a pixel at a specific cursor location. *ImageLocation must
+ // reside within the synthesis buffer.
+ //
+ virtual void
+ PutPixel (
+ PUCHAR *ImageLocation,
+ COLOR Color
+ )
+ {
+ if (Color != TRANSPARENT) {
+ *(*ImageLocation)++ = Colors [(ULONG)Color][0];
+ *(*ImageLocation)++ = Colors [(ULONG)Color][1];
+ *(*ImageLocation)++ = Colors [(ULONG)Color][2];
+ } else {
+ *ImageLocation += 3;
+ }
+ }
+
+ //
+ // PutPixel():
+ //
+ // Place a pixel at the default cursor location. The cursor location
+ // must be set via GetImageLocation(x, y).
+ //
+ virtual void
+ PutPixel (
+ COLOR Color
+ )
+ {
+ if (Color != TRANSPARENT) {
+ *m_Cursor++ = Colors [(ULONG)Color][0];
+ *m_Cursor++ = Colors [(ULONG)Color][1];
+ *m_Cursor++ = Colors [(ULONG)Color][2];
+ } else {
+ m_Cursor += 3;
+ }
+ }
+
+ virtual long
+ GetBytesPerPixel ()
+ {
+ return 3;
+ }
+
+ virtual PUCHAR
+ GetImageLocation (
+ ULONG LocX,
+ ULONG LocY
+ )
+ {
+ if (m_FlipVertical) {
+ return (m_Cursor =
+ (m_SynthesisBuffer + 3 *
+ (LocX + (m_Height - 1 - LocY) * m_Width))
+ );
+ } else {
+ return (m_Cursor =
+ (m_SynthesisBuffer + 3 * (LocX + LocY * m_Width))
+ );
+ }
+ }
+
+ //
+ // DEFAULT CONSTRUCTOR:
+ //
+ CRGB24Synthesizer (
+ BOOLEAN FlipVertical
+ ) :
+ m_FlipVertical (FlipVertical)
+ {
+ }
+
+ //
+ // CONSTRUCTOR:
+ //
+ CRGB24Synthesizer (
+ BOOLEAN FlipVertical,
+ ULONG Width,
+ ULONG Height
+ ) :
+ CImageSynthesizer (Width, Height),
+ m_FlipVertical (FlipVertical)
+ {
+ }
+
+ //
+ // DESTRUCTOR:
+ //
+ virtual
+ ~CRGB24Synthesizer (
+ )
+ {
+ }
+
+};
+
+/*************************************************
+
+ CYUVSynthesizer
+
+ Image synthesizer for YUV format.
+
+*************************************************/
+
+class CYUVSynthesizer : public CImageSynthesizer {
+
+private:
+
+ const static UCHAR Colors [MAX_COLOR][3];
+
+ BOOLEAN m_Parity;
+
+public:
+
+ //
+ // PutPixel():
+ //
+ // Place a pixel at a specific cursor location. *ImageLocation must
+ // reside within the synthesis buffer.
+ //
+ virtual void
+ PutPixel (
+ PUCHAR *ImageLocation,
+ COLOR Color
+ )
+ {
+
+ BOOLEAN Parity = (((*ImageLocation - m_SynthesisBuffer) & 0x2) != 0);
+
+#if DBG
+ //
+ // Check that the current pixel points to a valid start pixel
+ // in the UYVY buffer.
+ //
+ BOOLEAN Odd = (((*ImageLocation - m_SynthesisBuffer) & 0x1) != 0);
+ NT_ASSERT ((m_Parity && Odd) || (!m_Parity && !Odd));
+#endif // DBG
+
+ if (Color != TRANSPARENT) {
+ if (Parity) {
+ *(*ImageLocation)++ = Colors [(ULONG)Color][2];
+ } else {
+ *(*ImageLocation)++ = Colors [(ULONG)Color][1];
+ *(*ImageLocation)++ = Colors [(ULONG)Color][0];
+ *(*ImageLocation)++ = Colors [(ULONG)Color][1];
+ }
+ } else {
+ *ImageLocation += (Parity ? 1 : 3);
+ }
+
+ }
+
+ //
+ // PutPixel():
+ //
+ // Place a pixel at the default cursor location. The cursor location
+ // must be set via GetImageLocation(x, y).
+ //
+ virtual void
+ PutPixel (
+ COLOR Color
+ )
+
+ {
+
+ if (Color != TRANSPARENT) {
+ if (m_Parity) {
+ *m_Cursor++ = Colors [(ULONG)Color][2];
+ } else {
+ *m_Cursor++ = Colors [(ULONG)Color][1];
+ *m_Cursor++ = Colors [(ULONG)Color][0];
+ *m_Cursor++ = Colors [(ULONG)Color][1];
+ }
+ } else {
+ m_Cursor += (m_Parity ? 1 : 3);
+ }
+
+ m_Parity = !m_Parity;
+
+ }
+
+ virtual long
+ GetBytesPerPixel ()
+ {
+ return 2;
+ }
+
+ virtual PUCHAR
+ GetImageLocation (
+ ULONG LocX,
+ ULONG LocY
+ )
+ {
+
+ m_Cursor = m_SynthesisBuffer + ((LocX + LocY * m_Width) << 1);
+ if (m_Parity = ((LocX & 1) != 0))
+ m_Cursor++;
+
+ return m_Cursor;
+ }
+
+ //
+ // DEFAULT CONSTRUCTOR:
+ //
+ CYUVSynthesizer (
+ )
+ {
+ }
+
+ //
+ // CONSTRUCTOR:
+ //
+ CYUVSynthesizer (
+ ULONG Width,
+ ULONG Height
+ ) :
+ CImageSynthesizer (Width, Height)
+ {
+ }
+
+ //
+ // DESTRUCTOR:
+ //
+ virtual
+ ~CYUVSynthesizer (
+ )
+ {
+ }
+
+};
+
diff --git a/avstream/avshws/purecall.c b/avstream/avshws/purecall.c
new file mode 100644
index 00000000..ea61fbff
--- /dev/null
+++ b/avstream/avshws/purecall.c
@@ -0,0 +1,50 @@
+/**************************************************************************
+
+ AVStream Simulated Hardware Sample
+
+ Copyright (c) 2001, Microsoft Corporation.
+
+ File:
+
+ purecall.c
+
+ Abstract:
+
+ This file contains the _purecall stub necessary for virtual function
+ usage in drivers on 98 gold.
+
+ History:
+
+ created 9/16/02
+
+**************************************************************************/
+
+/*************************************************
+
+ Function:
+
+ _purecall
+
+ Description:
+
+ _purecall stub for virtual function usage
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ 0
+
+*************************************************/
+#pragma warning (disable : 4100 4131)
+int __cdecl
+_purecall (
+ VOID
+ )
+
+{
+ return 0;
+}
+
diff --git a/avstream/samplemft0/Mft0.cpp b/avstream/samplemft0/Mft0.cpp
new file mode 100644
index 00000000..044a4e71
--- /dev/null
+++ b/avstream/samplemft0/Mft0.cpp
@@ -0,0 +1,975 @@
+// Mft0.cpp : Implementation of CMft0
+
+#include "stdafx.h"
+#include "Mft0.h"
+#include "SampleHelpers.h"
+#include <WinString.h>
+
+// CMft0
+STDMETHODIMP CMft0::UpdateDsp(UINT32 uiPercentOfScreen)
+{
+ m_percentOfScreen = uiPercentOfScreen;
+ return S_OK;
+}
+
+STDMETHODIMP CMft0::Enable(void)
+{
+ m_bEnableEffects = TRUE;
+ return S_OK;
+}
+
+STDMETHODIMP CMft0::Disable(void)
+{
+ m_bEnableEffects = FALSE;
+ return S_OK;
+}
+
+STDMETHODIMP CMft0::GetDspSetting(UINT* puiPercentOfScreen, BOOL* pIsEnabled)
+{
+ HRESULT hr = S_OK;
+ do {
+ CHK_NULL_PTR_BRK(puiPercentOfScreen);
+ CHK_NULL_PTR_BRK(pIsEnabled);
+ *puiPercentOfScreen = m_percentOfScreen;
+ *pIsEnabled = m_bEnableEffects;
+ } while (FALSE);
+
+ return S_OK;
+}
+
+STDMETHODIMP CMft0::GetIids(
+ /* [out] */ _Out_ ULONG *iidCount,
+ /* [size_is][size_is][out] */ _Outptr_result_buffer_maybenull_(*iidCount) IID **iids)
+{
+ HRESULT hr = S_OK;
+ do {
+ CHK_NULL_PTR_BRK(iidCount);
+ CHK_NULL_PTR_BRK(iids);
+ *iids = NULL;
+ *iidCount = 0;
+ } while (FALSE);
+
+ return hr;
+}
+
+STDMETHODIMP CMft0::GetRuntimeClassName(
+ /* [out] */ _Outptr_result_maybenull_ HSTRING *className)
+{
+ HRESULT hr = S_OK;
+ if(className != nullptr)
+ {
+ hr = WindowsCreateString(NULL, 0, className);
+ if(FAILED(hr)){
+ hr = E_OUTOFMEMORY;
+ }
+ }else {
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+STDMETHODIMP CMft0::GetTrustLevel(
+ /* [out] */ _Out_ TrustLevel *trustLevel)
+{
+ HRESULT hr = S_OK;
+ do {
+ CHK_NULL_PTR_BRK(trustLevel);
+ *trustLevel = TrustLevel::BaseTrust;
+ } while (FALSE);
+
+ return hr;
+}
+
+
+STDMETHODIMP CMft0::GetStreamLimits(
+ /* [out] */ _Out_ DWORD *pdwInputMinimum,
+ /* [out] */ _Out_ DWORD *pdwInputMaximum,
+ /* [out] */ _Out_ DWORD *pdwOutputMinimum,
+ /* [out] */ _Out_ DWORD *pdwOutputMaximum)
+{
+ HRESULT hr = S_OK;
+ do {
+ if ((pdwInputMinimum == NULL) ||
+ (pdwInputMaximum == NULL) ||
+ (pdwOutputMinimum == NULL) ||
+ (pdwOutputMaximum == NULL))
+ {
+ hr = E_POINTER;
+ break;
+ }
+
+ // This MFT has a fixed number of streams.
+ *pdwInputMinimum = 1;
+ *pdwInputMaximum = 1;
+ *pdwOutputMinimum = 1;
+ *pdwOutputMaximum = 1;
+ } while (FALSE);
+
+ return hr;
+}
+
+
+STDMETHODIMP CMft0::GetStreamCount(
+ /* [out] */ _Out_ DWORD *pcInputStreams,
+ /* [out] */ _Out_ DWORD *pcOutputStreams)
+{
+ HRESULT hr = S_OK;
+
+ do {
+ if ((pcInputStreams == NULL) || (pcOutputStreams == NULL))
+
+ {
+ hr = E_POINTER;
+ break;
+ }
+
+ // This MFT has a fixed number of streams.
+ *pcInputStreams = 1;
+ *pcOutputStreams = 1;
+ } while (FALSE);
+
+ return hr;
+}
+STDMETHODIMP CMft0::GetStreamIDs(
+ DWORD dwInputIDArraySize,
+ /* [size_is][out] */ _Out_writes_(dwInputIDArraySize) DWORD *pdwInputIDs,
+ DWORD dwOutputIDArraySize,
+ /* [size_is][out] */ _Out_writes_(dwOutputIDArraySize) DWORD *pdwOutputIDs)
+{
+ dwOutputIDArraySize = 0;
+ dwInputIDArraySize = 0;
+ pdwInputIDs = NULL;
+ pdwOutputIDs = NULL;
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CMft0::GetInputStreamInfo(
+ DWORD dwInputStreamID,
+ /* [out] */ _Out_ MFT_INPUT_STREAM_INFO *pStreamInfo)
+{
+ HRESULT hr = S_OK;
+ EnterCriticalSection(&m_critSec);
+
+ do {
+ CHK_NULL_BRK(pStreamInfo);
+ if (!IsValidInputStream(dwInputStreamID))
+ {
+ CHK_LOG_BRK(MF_E_INVALIDSTREAMNUMBER);
+ }
+ if(m_pInputType) {
+ pStreamInfo->cbAlignment = 0;
+ pStreamInfo->cbSize = 0;
+ pStreamInfo->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER ;
+ pStreamInfo->hnsMaxLatency = 0;
+ } else {
+ hr = MF_E_TRANSFORM_TYPE_NOT_SET;
+ }
+ } while (FALSE);
+
+ LeaveCriticalSection(&m_critSec);
+ return hr;
+}
+
+
+STDMETHODIMP CMft0::GetOutputStreamInfo(
+ DWORD dwOutputStreamID,
+ /* [out] */ _Out_ MFT_OUTPUT_STREAM_INFO *pStreamInfo)
+{
+ HRESULT hr = S_OK;
+ EnterCriticalSection(&m_critSec);
+
+ do {
+ CHK_NULL_BRK(pStreamInfo);
+ if (!IsValidInputStream(dwOutputStreamID))
+ {
+ CHK_LOG_BRK(MF_E_INVALIDSTREAMNUMBER);
+ }
+ if(m_pOutputType) {
+ pStreamInfo->cbAlignment = 0;
+ pStreamInfo->cbSize = 0;
+ pStreamInfo->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
+ } else {
+ hr = MF_E_TRANSFORM_TYPE_NOT_SET;
+ }
+
+ } while (FALSE);
+
+ LeaveCriticalSection(&m_critSec);
+ return hr;
+}
+
+STDMETHODIMP CMft0::GetAttributes(
+ /* [out] */ _Outptr_result_maybenull_ IMFAttributes **ppAttributes)
+{
+ HRESULT hr = S_OK;
+
+ do {
+ CHK_NULL_PTR_BRK(ppAttributes);
+ if(!m_pGlobalAttributes) {
+ CHK_LOG_BRK(MFCreateAttributes(&m_pGlobalAttributes, 3));
+ CHK_LOG_BRK(m_pGlobalAttributes->SetUINT32(MF_TRANSFORM_ASYNC, FALSE));
+ CHK_LOG_BRK(m_pGlobalAttributes->SetString(MFT_ENUM_HARDWARE_URL_Attribute, L"Sample_CameraExtensionMft"));
+ CHK_LOG_BRK(m_pGlobalAttributes->SetUINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, TRUE));
+ }
+ *ppAttributes = m_pGlobalAttributes;
+ (*ppAttributes)->AddRef();
+ } while (FALSE);
+
+ return hr;
+}
+
+STDMETHODIMP CMft0::GetInputStreamAttributes(
+ DWORD dwInputStreamID,
+ /* [out] */ _Outptr_result_maybenull_ IMFAttributes **ppAttributes)
+{
+ HRESULT hr = S_OK;
+
+ do {
+ if(dwInputStreamID > 0) {
+ hr = MF_E_INVALIDSTREAMNUMBER;
+ break;
+ }
+ CHK_NULL_PTR_BRK(ppAttributes);
+ if(!m_pInputAttributes){
+ CHK_LOG_BRK(MFCreateAttributes(&m_pInputAttributes, 2));
+ CHK_LOG_BRK(m_pInputAttributes->SetUINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, TRUE));
+ CHK_LOG_BRK(m_pInputAttributes->SetString(MFT_ENUM_HARDWARE_URL_Attribute, L"Sample_CameraExtensionMft"));
+ }
+ *ppAttributes = m_pInputAttributes;
+ (*ppAttributes)->AddRef();
+ } while (FALSE);
+
+ return hr;
+}
+
+STDMETHODIMP CMft0::GetOutputStreamAttributes(
+ DWORD dwOutputStreamID,
+ /* [out] */ _Outptr_result_maybenull_ IMFAttributes **ppAttributes)
+{
+ HRESULT hr = S_OK;
+
+ do {
+ if(dwOutputStreamID > 0) {
+ hr = MF_E_INVALIDSTREAMNUMBER;
+ break;
+ }
+ CHK_NULL_PTR_BRK(ppAttributes);
+ CHK_NULL_PTR_BRK(m_pInputAttributes);
+
+ *ppAttributes = m_pInputAttributes;
+ (*ppAttributes)->AddRef();
+ } while (FALSE);
+
+ return hr;
+}
+
+STDMETHODIMP CMft0::DeleteInputStream(
+ DWORD dwStreamID)
+{
+ HRESULT hr = S_OK;
+ if(dwStreamID > 0) {
+ hr = MF_E_INVALIDSTREAMNUMBER;
+ } else {
+ hr = E_NOTIMPL;
+ }
+ return hr;
+}
+
+STDMETHODIMP CMft0::AddInputStreams(
+ DWORD cStreams,
+ /* [in] */ _In_ DWORD *adwStreamIDs)
+{
+ HRESULT hr = S_OK;
+
+ if( !adwStreamIDs || cStreams > 0) {
+ hr = E_INVALIDARG;
+ } else {
+ hr = E_NOTIMPL;
+ }
+ return hr;
+}
+
+STDMETHODIMP CMft0::GetInputAvailableType(
+ DWORD dwInputStreamID,
+ DWORD dwTypeIndex,
+ /* [out] */ _Outptr_result_maybenull_ IMFMediaType **ppType)
+{
+ HRESULT hr = S_OK;
+ IUnknown *pUnk = NULL;
+ IMFAttributes *pSourceAttributes = NULL;
+ UINT32 uiSourceStreamId = 0;
+ wchar_t *pszName;
+
+ EnterCriticalSection(&m_critSec);
+
+ do {
+ CHK_BOOL_BRK(IsValidInputStream(dwInputStreamID));
+
+ if(!m_pSourceTransform && m_pInputAttributes) {
+ CHK_LOG_BRK(m_pInputAttributes->GetUnknown(MFT_CONNECTED_STREAM_ATTRIBUTE, IID_PPV_ARGS(&pSourceAttributes)));
+ CHK_LOG_BRK(pSourceAttributes->GetUnknown(MF_DEVICESTREAM_EXTENSION_PLUGIN_CONNECTION_POINT, IID_PPV_ARGS(&pUnk)));
+ CHK_LOG_BRK(pUnk->QueryInterface(__uuidof(IMFTransform), (void**)&m_pSourceTransform));
+ CHK_LOG_BRK(pSourceAttributes->GetGUID( MF_DEVICESTREAM_STREAM_CATEGORY, &m_stStreamType));
+ CHK_LOG_BRK(pSourceAttributes->GetUINT32( MF_DEVICESTREAM_STREAM_ID, &uiSourceStreamId));
+
+ if(m_stStreamType == PINNAME_VIDEO_CAPTURE) {
+ wprintf(L"Stream type: PINNAME_VIDEO_CAPTURE\n");
+ } else if(m_stStreamType == PINNAME_VIDEO_PREVIEW) {
+ wprintf(L"Stream type: PINNAME_VIDEO_PREVIEW\n");
+ } else if(m_stStreamType == PINNAME_VIDEO_STILL) {
+ wprintf(L"Stream type: PINNAME_VIDEO_STILL\n");
+ } else if(m_stStreamType == PINNAME_IMAGE) {
+ wprintf(L"Stream type: PINNAME_IMAGE\n");
+ } else {
+ StringFromCLSID(m_stStreamType, &pszName);
+ if(pszName){
+ wprintf(L"Stream type: %s\n", pszName);
+ CoTaskMemFree(pszName);
+ }
+ }
+ CHK_LOG_BRK((m_stStreamType == PINNAME_VIDEO_PREVIEW || m_stStreamType == PINNAME_VIDEO_CAPTURE) ? S_OK : E_UNEXPECTED);
+ CHK_LOG_BRK(GenerateMFMediaTypeListFromDevice(uiSourceStreamId));
+ }
+
+ CHK_LOG_BRK(GetMediaType(dwInputStreamID, dwTypeIndex, ppType));
+ } while (FALSE);
+
+ LeaveCriticalSection(&m_critSec);
+ SAFERELEASE(pUnk);
+ SAFERELEASE(pSourceAttributes);
+ return hr;
+}
+
+STDMETHODIMP CMft0::GetOutputAvailableType(
+ DWORD dwOutputStreamID,
+ DWORD dwTypeIndex,
+ /* [out] */ _Outptr_result_maybenull_ IMFMediaType **ppType)
+{
+ HRESULT hr = S_OK;
+ IUnknown *pUnk = NULL;
+ IMFAttributes *pSourceAttributes = NULL;
+ UINT32 uiSourceStreamId = 0;
+ wchar_t *pszName;
+
+ EnterCriticalSection(&m_critSec);
+
+ do {
+ CHK_BOOL_BRK(IsValidOutputStream(dwOutputStreamID));
+ if(!m_pSourceTransform && m_pInputAttributes) {
+ CHK_LOG_BRK(m_pInputAttributes->GetUnknown(MFT_CONNECTED_STREAM_ATTRIBUTE, IID_PPV_ARGS(&pSourceAttributes)));
+ CHK_LOG_BRK(pSourceAttributes->GetUnknown(MF_DEVICESTREAM_EXTENSION_PLUGIN_CONNECTION_POINT, IID_PPV_ARGS(&pUnk)));
+ CHK_LOG_BRK(pUnk->QueryInterface(__uuidof(IMFTransform), (void**)&m_pSourceTransform));
+ CHK_LOG_BRK(pSourceAttributes->GetGUID( MF_DEVICESTREAM_STREAM_CATEGORY, &m_stStreamType));
+ CHK_LOG_BRK(pSourceAttributes->GetUINT32( MF_DEVICESTREAM_STREAM_ID, &uiSourceStreamId));
+ if(m_stStreamType == PINNAME_VIDEO_CAPTURE) {
+ wprintf(L"Stream type: PINNAME_VIDEO_CAPTURE\n");
+ } else if(m_stStreamType == PINNAME_VIDEO_PREVIEW) {
+ wprintf(L"Stream type: PINNAME_VIDEO_PREVIEW\n");
+ } else if(m_stStreamType == PINNAME_VIDEO_STILL) {
+ wprintf(L"Stream type: PINNAME_VIDEO_STILL\n");
+ } else if(m_stStreamType == PINNAME_IMAGE) {
+ wprintf(L"Stream type: PINNAME_IMAGE\n");
+ } else {
+ StringFromCLSID(m_stStreamType, &pszName);
+ wprintf(L"Stream type: %s\n", pszName);
+ }
+ CHK_LOG_BRK((m_stStreamType == PINNAME_VIDEO_PREVIEW || m_stStreamType == PINNAME_VIDEO_CAPTURE) ? S_OK : E_UNEXPECTED);
+ CHK_LOG_BRK(GenerateMFMediaTypeListFromDevice(uiSourceStreamId));
+ }
+
+ CHK_LOG_BRK(GetMediaType(dwOutputStreamID, dwTypeIndex, ppType));
+ } while (FALSE);
+
+ LeaveCriticalSection(&m_critSec);
+ SAFERELEASE(pUnk);
+ SAFERELEASE(pSourceAttributes);
+ return hr;
+}
+
+STDMETHODIMP CMft0::SetInputType(
+ DWORD dwInputStreamID,
+ /* [in] */ _In_opt_ IMFMediaType *pType,
+ DWORD dwFlags)
+{
+ HRESULT hr = S_OK;
+
+ EnterCriticalSection(&m_critSec);
+
+ BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
+ // Validate flags.
+ do {
+ if(bReallySet) {
+ CComPtr<IMFMediaType> pFullType;
+ CHK_LOG_BRK(IsMediaTypeSupported(dwInputStreamID, pType, &pFullType));
+ SAFERELEASE(m_pInputType);
+ SAFERELEASE(m_pOutputType);
+ m_pOutputType = pFullType;
+ m_pOutputType->AddRef();
+ m_pInputType = pFullType;
+ m_pInputType->AddRef();
+ } else {
+ CHK_LOG_BRK(IsMediaTypeSupported(dwInputStreamID, pType));
+ }
+ } while(FALSE);
+
+ LeaveCriticalSection(&m_critSec);
+ return hr;
+}
+
+STDMETHODIMP CMft0::SetOutputType(
+ DWORD dwOutputStreamID,
+ /* [in] */ _In_opt_ IMFMediaType *pType,
+ DWORD dwFlags)
+{
+ HRESULT hr = S_OK;
+
+ do {
+ CHK_LOG_BRK(SetInputType(dwOutputStreamID, pType, dwFlags));
+ } while (FALSE);
+
+ return hr;
+}
+
+STDMETHODIMP CMft0::GetInputCurrentType(
+ DWORD dwInputStreamID,
+ /* [out] */ _Outptr_result_maybenull_ IMFMediaType **ppType)
+{
+ HRESULT hr = S_OK;
+
+ EnterCriticalSection(&m_critSec);
+
+ do {
+ CHK_NULL_BRK(ppType);
+
+ if (!IsValidInputStream(dwInputStreamID))
+ {
+ CHK_LOG_BRK(MF_E_INVALIDSTREAMNUMBER);
+ }
+ else if(m_pInputType)
+ {
+ *ppType = m_pInputType;
+ (*ppType)->AddRef();
+ }
+ else
+ {
+ CHK_LOG_BRK(MF_E_TRANSFORM_TYPE_NOT_SET);
+ }
+ } while (FALSE);
+
+ LeaveCriticalSection(&m_critSec);
+ return hr;
+}
+
+STDMETHODIMP CMft0::GetOutputCurrentType(
+ DWORD dwOutputStreamID,
+ /* [out] */ _Outptr_result_maybenull_ IMFMediaType **ppType)
+{
+ HRESULT hr = S_OK;
+
+ EnterCriticalSection(&m_critSec);
+
+ do {
+ CHK_NULL_BRK(ppType);
+
+ if (!IsValidOutputStream(dwOutputStreamID))
+ {
+ CHK_LOG_BRK(MF_E_INVALIDSTREAMNUMBER);
+ }
+ else if(m_pOutputType)
+ {
+ *ppType = m_pOutputType;
+ (*ppType)->AddRef();
+ }
+ else
+ {
+ CHK_LOG_BRK(MF_E_TRANSFORM_TYPE_NOT_SET);
+ }
+ } while (FALSE);
+
+ LeaveCriticalSection(&m_critSec);
+ return hr;
+}
+
+STDMETHODIMP CMft0::GetInputStatus(
+ DWORD dwInputStreamID,
+ /* [out] */ _Out_ DWORD *pdwFlags)
+{
+ HRESULT hr = S_OK;
+
+ EnterCriticalSection(&m_critSec);
+
+ do {
+ CHK_BOOL_BRK(pdwFlags);
+
+ if (!IsValidInputStream(dwInputStreamID))
+ {
+ CHK_LOG_BRK(MF_E_INVALIDSTREAMNUMBER);
+ }
+
+ // If we already have an input sample, we don't accept
+ // another one until the client calls ProcessOutput or Flush.
+ if (m_pSample == NULL)
+ {
+ *pdwFlags = MFT_INPUT_STATUS_ACCEPT_DATA;
+ }
+ else
+ {
+ *pdwFlags = 0;
+ }
+ } while (FALSE);
+
+ LeaveCriticalSection(&m_critSec);
+ return hr;
+}
+
+STDMETHODIMP CMft0::GetOutputStatus(
+ /* [out] */ _Out_ DWORD *pdwFlags)
+{
+ HRESULT hr = S_OK;
+
+ EnterCriticalSection(&m_critSec);
+
+ do {
+ CHK_NULL_BRK(pdwFlags);
+ // We can produce an output sample if (and only if)
+ // we have an input sample.
+ if (m_pSample != NULL)
+ {
+ *pdwFlags = MFT_OUTPUT_STATUS_SAMPLE_READY;
+ }
+ else
+ {
+ *pdwFlags = 0;
+ }
+ } while (FALSE);
+
+ LeaveCriticalSection(&m_critSec);
+ return hr;
+}
+
+STDMETHODIMP CMft0::SetOutputBounds(
+ LONGLONG hnsLowerBound,
+ LONGLONG hnsUpperBound)
+{
+ UNREFERENCED_PARAMETER(hnsLowerBound);
+ UNREFERENCED_PARAMETER(hnsUpperBound);
+ return S_OK;
+}
+
+STDMETHODIMP CMft0::ProcessEvent(
+ DWORD dwInputStreamID,
+ /* [in] */ _In_opt_ IMFMediaEvent *pEvent)
+{
+ UNREFERENCED_PARAMETER(dwInputStreamID);
+ UNREFERENCED_PARAMETER(pEvent);
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CMft0::ProcessMessage(
+ MFT_MESSAGE_TYPE eMessage,
+ ULONG_PTR ulParam)
+{
+ UNREFERENCED_PARAMETER(ulParam);
+ HRESULT hr = S_OK;
+
+ EnterCriticalSection(&m_critSec);
+
+ switch (eMessage)
+ {
+ case MFT_MESSAGE_COMMAND_FLUSH:
+ // Flush the MFT.
+ hr = OnFlush();
+ break;
+
+ case MFT_MESSAGE_COMMAND_DRAIN:
+ // Drain: Tells the MFT not to accept any more input until
+ // all of the pending output has been processed. That is our
+ // default behevior already, so there is nothing to do.
+ break;
+
+ case MFT_MESSAGE_SET_D3D_MANAGER:
+ // The pipeline should never send this message unless the MFT
+ // has the MF_SA_D3D_AWARE attribute set to TRUE. However, if we
+ // do get this message, it's invalid and we don't implement it.
+ hr = E_NOTIMPL;
+ break;
+
+ // The remaining messages do not require any action from this MFT.
+ case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
+ case MFT_MESSAGE_NOTIFY_END_STREAMING:
+ case MFT_MESSAGE_NOTIFY_END_OF_STREAM:
+ case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
+ break;
+ }
+
+ LeaveCriticalSection(&m_critSec);
+ return hr;
+}
+
+STDMETHODIMP CMft0::ProcessInput(
+ DWORD dwInputStreamID,
+ IMFSample *pSample,
+ DWORD dwFlags)
+{
+ HRESULT hr = S_OK;
+
+ EnterCriticalSection(&m_critSec);
+
+ do {
+ CHK_NULL_BRK(pSample);
+
+ CHK_BOOL_BRK(dwFlags == 0)
+
+ DWORD dwBufferCount = 0;
+
+ if (!IsValidInputStream(dwInputStreamID))
+ {
+ CHK_LOG_BRK(hr = MF_E_INVALIDSTREAMNUMBER);
+ }
+
+ if (!m_pInputType || !m_pOutputType)
+ {
+ CHK_LOG_BRK(MF_E_NOTACCEPTING); // Client must set input and output types.
+ }
+
+ if (m_pSample != NULL)
+ {
+ CHK_LOG_BRK(MF_E_NOTACCEPTING); // We already have an input sample.
+ }
+
+ // Validate the number of buffers. There should only be a single buffer to hold the video frame.
+ CHK_LOG_BRK(pSample->GetBufferCount(&dwBufferCount));
+
+ if (dwBufferCount == 0)
+ {
+ CHK_LOG_BRK(E_FAIL);
+ }
+ if (dwBufferCount > 1)
+ {
+ CHK_LOG_BRK(MF_E_SAMPLE_HAS_TOO_MANY_BUFFERS);
+ }
+
+ // Cache the sample. We do the actual work in ProcessOutput.
+ m_pSample = pSample;
+ pSample->AddRef(); // Hold a reference count on the sample.
+ } while (FALSE);
+
+ LeaveCriticalSection(&m_critSec);
+ return hr;
+}
+
+STDMETHODIMP CMft0::ProcessOutput(
+ DWORD dwFlags,
+ DWORD cOutputBufferCount,
+ /* [size_is][out][in] */ MFT_OUTPUT_DATA_BUFFER *pOutputSamples,
+ /* [out] */ DWORD *pdwStatus)
+{
+ HRESULT hr = S_OK;
+
+ IMFMediaBuffer *pMediaBufInput = NULL,
+ *pMediaBufOutput = NULL;
+ IMFSample *pOutputIMFSample = NULL;
+ LONGLONG hnsDuration = 0,
+ hnsTime = 0;
+
+ EnterCriticalSection(&m_critSec);
+
+ do {
+ CHK_BOOL_BRK(dwFlags == 0);
+ CHK_NULL_BRK(pOutputSamples);
+ CHK_NULL_BRK(pdwStatus);
+
+ // Must be exactly one output buffer.
+ CHK_BOOL_BRK(cOutputBufferCount == 1);
+
+ // If we don't have an input sample, we need some input before
+ // we can generate any output.
+ if (m_pSample == NULL)
+ {
+ hr = MF_E_TRANSFORM_NEED_MORE_INPUT;
+ break;
+ }
+
+ CHK_LOG_BRK(m_pSample->ConvertToContiguousBuffer(&pMediaBufInput));
+
+ MFCreateSample(&pOutputIMFSample);
+
+ if(!pOutputSamples[0].pSample){
+ CHK_LOG_BRK(m_pSample->ConvertToContiguousBuffer(&pMediaBufOutput));
+
+ } else {
+ CHK_LOG_BRK(pOutputSamples[0].pSample->ConvertToContiguousBuffer(&pMediaBufOutput));
+ }
+
+ pOutputIMFSample->AddBuffer(pMediaBufOutput);
+
+ CHK_LOG_BRK(OnProcessOutput(pMediaBufInput, pMediaBufOutput));
+ pOutputSamples[0].pSample = pOutputIMFSample;
+ pOutputIMFSample->AddRef();
+
+ pOutputSamples[0].dwStatus = 0;
+ *pdwStatus = 0;
+ if (SUCCEEDED(m_pSample->GetSampleDuration(&hnsDuration)))
+ {
+ CHK_LOG_BRK(pOutputSamples[0].pSample->SetSampleDuration(hnsDuration));
+ }
+
+ if (SUCCEEDED(m_pSample->GetSampleTime(&hnsTime)))
+ {
+ CHK_LOG_BRK(pOutputSamples[0].pSample->SetSampleTime(hnsTime));
+ }
+ } while (FALSE);
+
+ SAFERELEASE(pOutputIMFSample);
+ SAFERELEASE(pMediaBufInput);
+ SAFERELEASE(pMediaBufOutput);
+ SAFERELEASE(m_pSample); // Release our input sample.
+ LeaveCriticalSection(&m_critSec);
+ return hr;
+}
+
+BOOL CMft0::IsValidInputStream(DWORD dwInputStreamID)
+{
+ return dwInputStreamID == 0;
+}
+
+// IsValidOutputStream: Returns TRUE if dwOutputStreamID is a valid output stream identifier.
+BOOL CMft0::IsValidOutputStream(DWORD dwOutputStreamID)
+{
+ //update
+ return dwOutputStreamID == 0;
+}
+
+
+STDMETHODIMP CMft0::OnProcessOutput(IMFMediaBuffer *pIn, IMFMediaBuffer *pOut)
+{
+ HRESULT hr = S_OK;
+ LONG lDefaultStride = 0,
+ lSrcStride = 0,
+ lDestStride = 0;
+ UINT uiWidth = 0,
+ uiHeight = 0;
+ BYTE *pDest = NULL,
+ *pSrc = NULL;
+ //BOOL bCompressed = TRUE;
+ GUID stSubType = {0};
+
+ do {
+ CHK_NULL_PTR_BRK(m_pSample);
+ CHK_NULL_PTR_BRK(m_pInputType);
+
+ CHK_LOG_BRK(m_pInputType->GetGUID(MF_MT_SUBTYPE, &stSubType));
+
+ if(((stSubType == MFVideoFormat_RGB8) || (stSubType == MFVideoFormat_RGB555) ||
+ (stSubType == MFVideoFormat_RGB565) || (stSubType == MFVideoFormat_RGB24) ||
+ (stSubType == MFVideoFormat_RGB32) || (stSubType == MFVideoFormat_ARGB32) ||
+ (stSubType == MFVideoFormat_AI44) || (stSubType == MFVideoFormat_AYUV) ||
+ (stSubType == MFVideoFormat_I420) || (stSubType == MFVideoFormat_IYUV) ||
+ (stSubType == MFVideoFormat_NV11) || (stSubType == MFVideoFormat_NV12) ||
+ (stSubType == MFVideoFormat_UYVY) || (stSubType == MFVideoFormat_Y41P) ||
+ (stSubType == MFVideoFormat_Y41T) || (stSubType == MFVideoFormat_Y42T) ||
+ (stSubType == MFVideoFormat_YUY2) || (stSubType == MFVideoFormat_YV12) ||
+ (stSubType == MFVideoFormat_P010) || (stSubType == MFVideoFormat_P016) ||
+ (stSubType == MFVideoFormat_P210) || (stSubType == MFVideoFormat_P216) ||
+ (stSubType == MFVideoFormat_v210) || (stSubType == MFVideoFormat_v216) ||
+ (stSubType == MFVideoFormat_v410) || (stSubType == MFVideoFormat_Y210) ||
+ (stSubType == MFVideoFormat_Y216) || (stSubType == MFVideoFormat_Y410) ||
+ (stSubType == MFVideoFormat_Y416)) && m_bEnableEffects)
+ {
+ CHK_LOG_BRK(GetDefaultStride(&lDefaultStride));
+ CHK_LOG_BRK(MFGetAttributeSize(m_pInputType, MF_MT_FRAME_SIZE, &uiWidth, &uiHeight));
+ VideoBufferLock inputLock(pIn);
+ VideoBufferLock outputLock(pOut);
+
+ // Lock the input buffer.
+ CHK_LOG_BRK(inputLock.LockBuffer(lDefaultStride, uiHeight, &pSrc, &lSrcStride));
+
+ // Lock the output buffer.
+ CHK_LOG_BRK(outputLock.LockBuffer(lDefaultStride, uiHeight, &pDest, &lDestStride));
+ long lines = uiHeight;
+ if(m_percentOfScreen != -1 && m_percentOfScreen != 0) {
+ lines = (UINT)(uiHeight * (1.0- m_percentOfScreen/100.00));
+ }
+ for(long i = 0; i < (long)uiHeight; i++) {
+ if(lDestStride < 0) {
+ if(i >= lines) {
+ memset(pDest+i*lDestStride, 0, abs(lDefaultStride));
+ } else {
+ memcpy(pDest+i*lDestStride, pSrc+i*lDefaultStride, abs(lDefaultStride));
+ }
+ } else {
+ if(i >= lines) {
+ memset(pDest+i*lDestStride, 0, lDestStride);
+ } else {
+ memcpy(pDest+i*lDestStride, pSrc+i*lDestStride, lDestStride);
+ }
+ }
+ }
+ }
+ } while (FALSE);
+
+ return hr;
+}
+
+STDMETHODIMP CMft0::GetDefaultStride(LONG *plStride)
+{
+ LONG lStride = 0;
+
+ // Try to get the default stride from the media type.
+ HRESULT hr = m_pInputType->GetUINT32(MF_MT_DEFAULT_STRIDE, (UINT32*)&lStride);
+ if (FAILED(hr))
+ {
+ // Attribute not set. Try to calculate the default stride.
+ GUID subtype = GUID_NULL;
+ UINT32 width = 0;
+ UINT32 height = 0;
+
+ // Get the subtype and the image size.
+ hr = m_pInputType->GetGUID(MF_MT_SUBTYPE, &subtype);
+ if (SUCCEEDED(hr))
+ {
+ hr = MFGetAttributeSize(m_pInputType, MF_MT_FRAME_SIZE, &width, &height);
+ }
+ if (SUCCEEDED(hr))
+ {
+ hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, width, &lStride);
+ }
+
+ // Set the attribute for later reference.
+ if (SUCCEEDED(hr))
+ {
+ (void)m_pInputType->SetUINT32(MF_MT_DEFAULT_STRIDE, UINT32(lStride));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *plStride = lStride;
+ }
+
+ return hr;
+}
+
+STDMETHODIMP CMft0::OnFlush()
+{
+ HRESULT hr = S_OK;
+
+ // For this MFT, flushing just means releasing the input sample.
+ SAFERELEASE(m_pSample);
+
+ return hr;
+}
+
+STDMETHODIMP CMft0::GetMediaType( DWORD dwStreamId, DWORD dwTypeIndex, IMFMediaType **ppType)
+{
+ HRESULT hr = S_OK;
+
+ do {
+ CHK_NULL_PTR_BRK(ppType);
+ if(dwStreamId != 0)
+ CHK_LOG_BRK(MF_E_INVALIDSTREAMNUMBER);
+ if(dwTypeIndex >= m_listOfMediaTypes.GetCount())
+ CHK_LOG_BRK(MF_E_NO_MORE_TYPES);
+
+ *ppType = m_listOfMediaTypes[dwTypeIndex];
+ (*ppType)->AddRef();
+ } while (FALSE);
+
+ return hr;
+}
+
+STDMETHODIMP CMft0::IsMediaTypeSupported(UINT uiStreamId, IMFMediaType *pIMFMediaType, IMFMediaType **ppIMFMediaTypeFull)
+{
+ HRESULT hr = S_OK;
+
+ do {
+ CHK_NULL_PTR_BRK(pIMFMediaType);
+
+ if(uiStreamId != 0)
+ {
+ CHK_LOG_BRK(MF_E_INVALIDINDEX);
+ }
+ BOOL bFound =FALSE;
+ for(UINT i = 0; i< m_listOfMediaTypes.GetCount(); i++)
+ {
+ DWORD dwResult = 0;
+ hr = m_listOfMediaTypes[i]->IsEqual(pIMFMediaType, &dwResult);
+ if(hr == S_FALSE)
+ {
+
+ if((dwResult & MF_MEDIATYPE_EQUAL_MAJOR_TYPES) &&
+ (dwResult& MF_MEDIATYPE_EQUAL_FORMAT_TYPES) &&
+ (dwResult& MF_MEDIATYPE_EQUAL_FORMAT_DATA))
+ {
+ hr = S_OK;
+ }
+ }
+ if(hr == S_OK)
+ {
+ bFound = TRUE;
+ if(ppIMFMediaTypeFull) {
+ *ppIMFMediaTypeFull = m_listOfMediaTypes[i];
+ (*ppIMFMediaTypeFull)->AddRef();
+ }
+ break;
+ }
+ else if(FAILED(hr))
+ {
+ CHK_LOG_BRK(hr);
+ }
+
+ }
+ if(bFound == FALSE)
+ {
+ CHK_LOG_BRK(MF_E_INVALIDMEDIATYPE);
+ }
+ } while (FALSE);
+
+ return hr;
+}
+
+STDMETHODIMP CMft0::GenerateMFMediaTypeListFromDevice(UINT uiStreamId)
+{
+ HRESULT hr = S_OK;
+ GUID stSubType = {0};
+
+ do {
+ CHK_NULL_PTR_BRK(m_pSourceTransform);
+
+ m_listOfMediaTypes.RemoveAll();
+ for(UINT iMediaType = 0; TRUE; iMediaType++)
+ {
+ CComPtr<IMFMediaType> pMediaType;
+ hr = m_pSourceTransform->GetOutputAvailableType(uiStreamId, iMediaType, &pMediaType);
+ if(hr != S_OK)
+ break;
+ CHK_LOG_BRK(pMediaType->GetGUID(MF_MT_SUBTYPE, &stSubType));
+
+ if(((stSubType == MFVideoFormat_RGB8) || (stSubType == MFVideoFormat_RGB555) ||
+ (stSubType == MFVideoFormat_RGB565) || (stSubType == MFVideoFormat_RGB24) ||
+ (stSubType == MFVideoFormat_RGB32) || (stSubType == MFVideoFormat_ARGB32) ||
+ (stSubType == MFVideoFormat_AI44) || (stSubType == MFVideoFormat_AYUV) ||
+ (stSubType == MFVideoFormat_I420) || (stSubType == MFVideoFormat_IYUV) ||
+ (stSubType == MFVideoFormat_NV11) || (stSubType == MFVideoFormat_NV12) ||
+ (stSubType == MFVideoFormat_UYVY) || (stSubType == MFVideoFormat_Y41P) ||
+ (stSubType == MFVideoFormat_Y41T) || (stSubType == MFVideoFormat_Y42T) ||
+ (stSubType == MFVideoFormat_YUY2) || (stSubType == MFVideoFormat_YV12) ||
+ (stSubType == MFVideoFormat_P010) || (stSubType == MFVideoFormat_P016) ||
+ (stSubType == MFVideoFormat_P210) || (stSubType == MFVideoFormat_P216) ||
+ (stSubType == MFVideoFormat_v210) || (stSubType == MFVideoFormat_v216) ||
+ (stSubType == MFVideoFormat_v410) || (stSubType == MFVideoFormat_Y210) ||
+ (stSubType == MFVideoFormat_Y216) || (stSubType == MFVideoFormat_Y410) ||
+ (stSubType == MFVideoFormat_Y416)) && m_bEnableEffects)
+ {
+ m_listOfMediaTypes[(ULONG)(m_listOfMediaTypes.GetCount())] = pMediaType;
+ }
+ }
+
+ } while (FALSE);
+
+ if(hr == MF_E_NO_MORE_TYPES) {
+ hr = S_OK;
+ }
+
+ return hr;
+} \ No newline at end of file
diff --git a/avstream/samplemft0/Mft0.h b/avstream/samplemft0/Mft0.h
new file mode 100644
index 00000000..0cc85733
--- /dev/null
+++ b/avstream/samplemft0/Mft0.h
@@ -0,0 +1,224 @@
+// Mft0.h : Declaration of the CMft0
+
+#pragma once
+#include "resource.h" // main symbols
+#include "SampleMft0.h"
+#include "SampleHelpers.h"
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
+#endif
+
+using namespace ATL;
+
+// CMft0
+
+class ATL_NO_VTABLE CMft0 :
+ public CComObjectRootEx<CComMultiThreadModel>,
+ public CComCoClass<CMft0, &CLSID_Mft0>,
+ public IMft0,
+ public IMFTransform,
+ public IInspectable
+{
+public:
+ CMft0() : m_pSample(NULL),
+ m_pInputType(NULL),
+ m_pOutputType(NULL),
+ m_pInputAttributes(0),
+ m_pGlobalAttributes(0),
+ m_pSourceTransform(0),
+ m_bEnableEffects(TRUE),
+ m_uiStreamId(0),
+ m_percentOfScreen(50),
+ m_nRefCount(1)
+ {
+ InitializeCriticalSection(&m_critSec);
+ }
+
+ DECLARE_REGISTRY_RESOURCEID(IDR_MFT0)
+
+ DECLARE_NOT_AGGREGATABLE(CMft0)
+
+ BEGIN_COM_MAP(CMft0)
+ COM_INTERFACE_ENTRY(IMft0)
+ COM_INTERFACE_ENTRY(IMFTransform)
+ COM_INTERFACE_ENTRY(IInspectable)
+ END_COM_MAP()
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ return S_OK;
+ }
+
+ void FinalRelease()
+ {
+ }
+
+public:
+ STDMETHOD(UpdateDsp)(UINT32 uiPercentOfScreen);
+ STDMETHOD(Enable)(void);
+ STDMETHOD(Disable)(void);
+ STDMETHOD(GetDspSetting)(UINT* puiPercentOfScreen, BOOL* pIsEnabled);
+
+ STDMETHODIMP GetIids(
+ /* [out] */ _Out_ ULONG *iidCount,
+ /* [size_is][size_is][out] */ _Outptr_result_buffer_maybenull_(*iidCount) IID **iids);
+
+ STDMETHODIMP GetRuntimeClassName(
+ /* [out] */ _Outptr_result_maybenull_ HSTRING *className);
+
+ STDMETHODIMP GetTrustLevel(
+ /* [out] */ _Out_ TrustLevel *trustLevel);
+
+ STDMETHODIMP GetStreamLimits(
+ /* [out] */ _Out_ DWORD *pdwInputMinimum,
+ /* [out] */ _Out_ DWORD *pdwInputMaximum,
+ /* [out] */ _Out_ DWORD *pdwOutputMinimum,
+ /* [out] */ _Out_ DWORD *pdwOutputMaximum);
+
+ STDMETHODIMP GetStreamCount(
+ /* [out] */ _Out_ DWORD *pcInputStreams,
+ /* [out] */ _Out_ DWORD *pcOutputStreams);
+
+ STDMETHODIMP GetStreamIDs(
+ DWORD dwInputIDArraySize,
+ /* [size_is][out] */ _Out_writes_(dwInputIDArraySize) DWORD *pdwInputIDs,
+ DWORD dwOutputIDArraySize,
+ /* [size_is][out] */ _Out_writes_(dwOutputIDArraySize) DWORD *pdwOutputIDs);
+
+ STDMETHODIMP GetInputStreamInfo(
+ DWORD dwInputStreamID,
+ /* [out] */ _Out_ MFT_INPUT_STREAM_INFO *pStreamInfo);
+
+ STDMETHODIMP GetOutputStreamInfo(
+ DWORD dwOutputStreamID,
+ /* [out] */ _Out_ MFT_OUTPUT_STREAM_INFO *pStreamInfo);
+
+ STDMETHODIMP GetAttributes(
+ /* [out] */ _Outptr_result_maybenull_ IMFAttributes **pAttributes);
+
+ STDMETHODIMP GetInputStreamAttributes(
+ DWORD dwInputStreamID,
+ /* [out] */ _Outptr_result_maybenull_ IMFAttributes **pAttributes);
+
+ STDMETHODIMP GetOutputStreamAttributes(
+ DWORD dwOutputStreamID,
+ /* [out] */ _Outptr_result_maybenull_ IMFAttributes **pAttributes);
+
+ STDMETHODIMP DeleteInputStream(
+ DWORD dwStreamID);
+
+ STDMETHODIMP AddInputStreams(
+ DWORD cStreams,
+ /* [in] */ _In_ DWORD *adwStreamIDs);
+
+ STDMETHODIMP GetInputAvailableType(
+ DWORD dwInputStreamID,
+ DWORD dwTypeIndex,
+ /* [out] */ _Outptr_result_maybenull_ IMFMediaType **ppType);
+
+ STDMETHODIMP GetOutputAvailableType(
+ DWORD dwOutputStreamID,
+ DWORD dwTypeIndex,
+ /* [out] */ _Outptr_result_maybenull_ IMFMediaType **ppType);
+
+ STDMETHODIMP SetInputType(
+ DWORD dwInputStreamID,
+ /* [in] */ _In_opt_ IMFMediaType *pType,
+ DWORD dwFlags);
+
+ STDMETHODIMP SetOutputType(
+ DWORD dwOutputStreamID,
+ /* [in] */ _In_opt_ IMFMediaType *pType,
+ DWORD dwFlags);
+
+ STDMETHODIMP GetInputCurrentType(
+ DWORD dwInputStreamID,
+ /* [out] */ _Outptr_result_maybenull_ IMFMediaType **ppType);
+
+ STDMETHODIMP GetOutputCurrentType(
+ DWORD dwOutputStreamID,
+ /* [out] */ _Outptr_result_maybenull_ IMFMediaType **ppType);
+
+ STDMETHODIMP GetInputStatus(
+ DWORD dwInputStreamID,
+ /* [out] */ _Out_ DWORD *pdwFlags);
+
+ STDMETHODIMP GetOutputStatus(
+ /* [out] */ _Out_ DWORD *pdwFlags);
+
+ STDMETHODIMP SetOutputBounds(
+ LONGLONG hnsLowerBound,
+ LONGLONG hnsUpperBound);
+
+ STDMETHODIMP ProcessEvent(
+ DWORD dwInputStreamID,
+ /* [in] */ _In_opt_ IMFMediaEvent *pEvent);
+
+ STDMETHODIMP ProcessMessage(
+ MFT_MESSAGE_TYPE eMessage,
+ ULONG_PTR ulParam);
+
+ STDMETHODIMP ProcessInput(
+ DWORD dwInputStreamID,
+ IMFSample *pSample,
+ DWORD dwFlags);
+
+ STDMETHODIMP ProcessOutput(
+ DWORD dwFlags,
+ DWORD cOutputBufferCount,
+ /* [size_is][out][in] */ MFT_OUTPUT_DATA_BUFFER *pOutputSamples,
+ /* [out] */ DWORD *pdwStatus);
+
+protected:
+ virtual ~CMft0()
+ {
+ SAFERELEASE(m_pInputAttributes);
+ SAFERELEASE(m_pGlobalAttributes);
+ SAFERELEASE(m_pSourceTransform);
+ SAFERELEASE(m_pInputType);
+ SAFERELEASE(m_pOutputType);
+ SAFERELEASE(m_pSample);
+ DeleteCriticalSection(&m_critSec);
+ }
+
+ STDMETHODIMP GetMediaType(DWORD dwStreamID, DWORD dwTypeIndex, IMFMediaType **ppType);
+ STDMETHODIMP IsMediaTypeSupported(UINT uiStreamId, IMFMediaType *pIMFMediaType, IMFMediaType **ppIMFMediaTypeFull = NULL);
+ STDMETHODIMP GenerateMFMediaTypeListFromDevice(UINT uiStreamId);
+
+ // HasPendingOutput: Returns TRUE if the MFT is holding an input sample.
+ BOOL HasPendingOutput() const { return m_pSample != NULL; }
+
+ // IsValidInputStream: Returns TRUE if dwInputStreamID is a valid input stream identifier.
+ BOOL IsValidInputStream(DWORD dwInputStreamID);
+
+ // IsValidOutputStream: Returns TRUE if dwOutputStreamID is a valid output stream identifier.
+ BOOL IsValidOutputStream(DWORD dwOutputStreamID);
+
+ STDMETHODIMP GetDefaultStride(LONG *plStride);
+
+ STDMETHODIMP OnProcessOutput(IMFMediaBuffer *pIn, IMFMediaBuffer *pOut);
+
+ STDMETHODIMP OnFlush();
+
+ CRITICAL_SECTION m_critSec;
+
+ IMFSample *m_pSample; // Input sample.
+ IMFMediaType *m_pInputType; // Input media type.
+ IMFMediaType *m_pOutputType; // Output media type.
+
+ // Image transform function. (Changes based on the media type.)
+ IMFAttributes *m_pInputAttributes;
+ IMFAttributes *m_pGlobalAttributes;
+ GUID m_stStreamType;
+ IMFTransform *m_pSourceTransform;
+ volatile BOOL m_bEnableEffects;
+ UINT m_uiStreamId;
+ UINT m_percentOfScreen;
+ UINT m_nRefCount;
+ CAtlMap<DWORD, CComPtr<IMFMediaType>> m_listOfMediaTypes;
+};
+
+OBJECT_ENTRY_AUTO(__uuidof(Mft0), CMft0)
diff --git a/avstream/samplemft0/Mft0.rgs b/avstream/samplemft0/Mft0.rgs
new file mode 100644
index 00000000..9ff876f4
--- /dev/null
+++ b/avstream/samplemft0/Mft0.rgs
@@ -0,0 +1,15 @@
+HKCR
+{
+ NoRemove CLSID
+ {
+ ForceRemove {7BB640D9-33A4-4759-B290-F41A31DCF848} = s 'Mft0 Class'
+ {
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Both'
+ }
+ TypeLib = s '{DE05674A-C564-4C0E-9B7C-E1519F7AA767}'
+ Version = s '1.0'
+ }
+ }
+}
diff --git a/avstream/samplemft0/ReadMe.md b/avstream/samplemft0/ReadMe.md
new file mode 100644
index 00000000..94a09507
--- /dev/null
+++ b/avstream/samplemft0/ReadMe.md
@@ -0,0 +1,28 @@
+Driver MFT Sample
+=================
+
+Provides a *driver MFT* for use with a camera's Windows Store device app.A *driver MFT* is a Media Foundation Transform that's used with a specific camera when capturing video. The driver MFT is also known as MFT0 because it is the first MFT applied to the video stream captured from the camera. This MFT can provide a video effect or other processing when capturing photos or video from the camera. It can be distributed along with the driver package for a camera.
+
+In this sample, the driver MFT, when enabled, replaces a portion of the captured video with a green box. To test this sample, download the [Windows Store device app for camera sample](http://go.microsoft.com/fwlink/p/?linkid=249442) and the [Camera Capture UI sample](http://go.microsoft.com/fwlink/p/?linkid=249441). The [Windows Store device app for camera sample](http://go.microsoft.com/fwlink/p/?linkid=249442) provides a *Windows Store device app* that controls the effect implemented by the driver MFT. The [Camera Capture UI sample](http://go.microsoft.com/fwlink/p/?linkid=249441) provides a way to invoke the *Windows Store device app*.
+
+This sample is designed to be used with a specific camera. To run the sample, you need the your camera's device ID and device metadata package.
+
+
+Related topics
+--------------
+
+**Concepts**
+
+[Windows Store device apps for cameras](http://go.microsoft.com/fwlink/p/?LinkId=306683)
+
+[Windows 8 device experience](http://go.microsoft.com/fwlink/p/?linkid=241442)
+
+[Media Foundation Transforms](http://msdn.microsoft.com/en-us/library/windows/hardware/ms703138)
+
+[Roadmap for Developing Streaming Media Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff568130)
+
+**Samples**
+
+[Windows Store device app for camera sample](http://go.microsoft.com/fwlink/p/?linkid=249442)
+
+[Camera Capture UI sample](http://go.microsoft.com/fwlink/p/?linkid=249441%20)
diff --git a/avstream/samplemft0/SampleHelpers.h b/avstream/samplemft0/SampleHelpers.h
new file mode 100644
index 00000000..870e2cd3
--- /dev/null
+++ b/avstream/samplemft0/SampleHelpers.h
@@ -0,0 +1,143 @@
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+
+#pragma once
+#include "stdafx.h"
+
+#define WIDEN2(x) L ## x
+#define WIDEN(x) WIDEN2(x)
+#define __WFILE__ WIDEN(__FILE__)
+
+
+#define WPP_CONTROL_GUIDS \
+ WPP_DEFINE_CONTROL_GUID(WPPCameraExtensionMFt_Sample, \
+ (31A88041,BBF0,4D2C,A752,16EB1E51859C), \
+ WPP_DEFINE_BIT(AllMessages) \
+ )
+
+#define SAFEFREE(x) \
+ if(x) { \
+ free(x); \
+ x = NULL; \
+ }
+#define SAFERELEASE(x) \
+ if(x) { \
+ x->Release(); \
+ x = NULL; \
+ }
+
+#define CHK_LOG_BRK(exp) \
+ if(FAILED(hr = (exp))) { \
+ wprintf(L"HR=%08x File: %S Ln: %d\n", hr, __FILE__, __LINE__); \
+ break; \
+ }
+
+#define CHK_NULL_BRK(exp) \
+ if((exp) == NULL) { \
+ hr = E_OUTOFMEMORY; \
+ wprintf(L"HR=%08x File: %S Ln: %d\n", hr, __FILE__, __LINE__); \
+ break; \
+ }
+#define CHK_NULL_PTR_BRK(exp) \
+ if((exp) == NULL) { \
+ hr = E_INVALIDARG; \
+ wprintf(L"HR=%08x File: %S Ln: %d\n", hr, __FILE__, __LINE__); \
+ break; \
+ }
+
+#define CHK_BOOL_BRK(exp) \
+ if(!exp) { \
+ hr = E_FAIL; \
+ wprintf(L"HR=%08x File: %S Ln: %d\n", hr, __FILE__, __LINE__); \
+ break; \
+ }
+
+
+class VideoBufferLock
+{
+public:
+ VideoBufferLock(IMFMediaBuffer *pBuffer) : m_p2DBuffer(NULL)
+ {
+ m_pBuffer = pBuffer;
+ m_pBuffer->AddRef();
+
+ // Query for the 2-D buffer interface. OK if this fails.
+ m_pBuffer->QueryInterface(IID_IMF2DBuffer, (void**)&m_p2DBuffer);
+ }
+
+ ~VideoBufferLock()
+ {
+ UnlockBuffer();
+ SAFERELEASE(m_pBuffer);
+ SAFERELEASE(m_p2DBuffer);
+ }
+
+ // LockBuffer:
+ // Locks the buffer. Returns a pointer to scan line 0 and returns the stride.
+
+ // The caller must provide the default stride as an input parameter, in case
+ // the buffer does not expose IMF2DBuffer. You can calculate the default stride
+ // from the media type.
+
+ HRESULT LockBuffer(
+ LONG lDefaultStride, // Minimum stride (with no padding).
+ DWORD dwHeightInPixels, // Height of the image, in pixels.
+ BYTE **ppbScanLine0, // Receives a pointer to the start of scan line 0.
+ LONG *plStride // Receives the actual stride.
+ )
+ {
+ HRESULT hr = S_OK;
+
+ // Use the 2-D version if available.
+ if (m_p2DBuffer)
+ {
+ hr = m_p2DBuffer->Lock2D(ppbScanLine0, plStride);
+ }
+ else
+ {
+ // Use non-2D version.
+ BYTE *pData = NULL;
+
+ hr = m_pBuffer->Lock(&pData, NULL, NULL);
+ if (SUCCEEDED(hr))
+ {
+ *plStride = lDefaultStride;
+ if (lDefaultStride < 0)
+ {
+ // Bottom-up orientation. Return a pointer to the start of the
+ // last row *in memory* which is the top row of the image.
+ *ppbScanLine0 = pData + abs(lDefaultStride) * (dwHeightInPixels - 1);
+ }
+ else
+ {
+ // Top-down orientation. Return a pointer to the start of the
+ // buffer.
+ *ppbScanLine0 = pData;
+ }
+ }
+ }
+ return hr;
+ }
+
+ HRESULT UnlockBuffer()
+ {
+ if (m_p2DBuffer)
+ {
+ return m_p2DBuffer->Unlock2D();
+ }
+ else
+ {
+ return m_pBuffer->Unlock();
+ }
+ }
+
+private:
+ IMFMediaBuffer *m_pBuffer;
+ IMF2DBuffer *m_p2DBuffer;
+};
+
diff --git a/avstream/samplemft0/SampleMft0.cpp b/avstream/samplemft0/SampleMft0.cpp
new file mode 100644
index 00000000..997f05af
--- /dev/null
+++ b/avstream/samplemft0/SampleMft0.cpp
@@ -0,0 +1,83 @@
+// SampleMft0.cpp : Implementation of DLL Exports.
+
+
+#include "stdafx.h"
+#include "resource.h"
+#include "SampleMft0.h"
+#include "dllmain.h"
+
+
+// Used to determine whether the DLL can be unloaded by OLE.
+STDAPI DllCanUnloadNow(void)
+{
+#ifdef _MERGE_PROXYSTUB
+ HRESULT hr = PrxDllCanUnloadNow();
+ if (hr != S_OK)
+ return hr;
+#endif
+ return _AtlModule.DllCanUnloadNow();
+}
+
+// Returns a class factory to create an object of the requested type.
+STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID* ppv)
+{
+#ifdef _MERGE_PROXYSTUB
+ if (PrxDllGetClassObject(rclsid, riid, ppv) == S_OK)
+ return S_OK;
+#endif
+ return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
+}
+
+// DllRegisterServer - Adds entries to the system registry.
+STDAPI DllRegisterServer(void)
+{
+ // registers object, typelib and all interfaces in typelib
+ HRESULT hr = _AtlModule.DllRegisterServer();
+#ifdef _MERGE_PROXYSTUB
+ if (FAILED(hr))
+ return hr;
+ hr = PrxDllRegisterServer();
+#endif
+ return hr;
+}
+
+// DllUnregisterServer - Removes entries from the system registry.
+STDAPI DllUnregisterServer(void)
+{
+ HRESULT hr = _AtlModule.DllUnregisterServer();
+#ifdef _MERGE_PROXYSTUB
+ if (FAILED(hr))
+ return hr;
+ hr = PrxDllRegisterServer();
+ if (FAILED(hr))
+ return hr;
+ hr = PrxDllUnregisterServer();
+#endif
+ return hr;
+}
+
+// DllInstall - Adds/Removes entries to the system registry per user per machine.
+STDAPI DllInstall(BOOL bInstall, _In_opt_ LPCWSTR pszCmdLine)
+{
+ UNREFERENCED_PARAMETER(pszCmdLine);
+ HRESULT hr = E_FAIL;
+ static const wchar_t szUserSwitch[] = L"user";
+
+
+ if (bInstall)
+ {
+ hr = DllRegisterServer();
+ if (FAILED(hr))
+ {
+ DllUnregisterServer();
+ }
+ }
+ else
+ {
+ hr = DllUnregisterServer();
+ }
+
+ return hr;
+}
+
+
diff --git a/avstream/samplemft0/SampleMft0.def b/avstream/samplemft0/SampleMft0.def
new file mode 100644
index 00000000..f4c9fe1c
--- /dev/null
+++ b/avstream/samplemft0/SampleMft0.def
@@ -0,0 +1,16 @@
+; THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+; ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+; THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+; PARTICULAR PURPOSE.
+; Copyright (c) Microsoft Corporation. All rights reserved
+
+; SampleMft0.def : Declares the module parameters.
+
+LIBRARY
+
+EXPORTS
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
+ DllInstall PRIVATE
diff --git a/avstream/samplemft0/SampleMft0.idl b/avstream/samplemft0/SampleMft0.idl
new file mode 100644
index 00000000..3b59f79a
--- /dev/null
+++ b/avstream/samplemft0/SampleMft0.idl
@@ -0,0 +1,48 @@
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+// SampleMft0.idl : IDL source for SampleMft0
+//
+
+// This file will be processed by the MIDL tool to
+// produce the type library (SampleMft0.tlb) and marshalling code.
+
+import "oaidl.idl";
+import "ocidl.idl";
+import "Inspectable.idl";
+import "mftransform.idl";
+[
+ object,
+ uuid(F5208B72-A37A-457E-A309-AE3060780E21),
+ oleautomation,
+ nonextensible,
+ pointer_default(unique)
+]
+interface IMft0 : IUnknown{
+ [id(1)] HRESULT UpdateDsp([in] UINT32 uiPercentOfScreen);
+ [id(2)] HRESULT Enable(void);
+ [id(3)] HRESULT Disable(void);
+ [id(4)] HRESULT GetDspSetting([out] UINT* puiPercentOfScreen, [out] BOOL* pIsEnabled);
+};
+[
+ uuid(DE05674A-C564-4C0E-9B7C-E1519F7AA767),
+ version(1.0),
+]
+library SampleMft0Lib
+{
+ importlib("stdole2.tlb");
+ [
+ uuid(7BB640D9-33A4-4759-B290-F41A31DCF848)
+ ]
+ coclass Mft0
+ {
+ [default] interface IMft0;
+ interface IInspectable;
+ interface IMFTransform;
+ };
+};
+
diff --git a/avstream/samplemft0/SampleMft0.rc b/avstream/samplemft0/SampleMft0.rc
new file mode 100644
index 00000000..60d75128
--- /dev/null
+++ b/avstream/samplemft0/SampleMft0.rc
Binary files differ
diff --git a/avstream/samplemft0/SampleMft0.rgs b/avstream/samplemft0/SampleMft0.rgs
new file mode 100644
index 00000000..e7d37400
--- /dev/null
+++ b/avstream/samplemft0/SampleMft0.rgs
@@ -0,0 +1,3 @@
+HKCR
+{
+}
diff --git a/avstream/samplemft0/SampleMft0.sln b/avstream/samplemft0/SampleMft0.sln
new file mode 100644
index 00000000..fc84dbf4
--- /dev/null
+++ b/avstream/samplemft0/SampleMft0.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0
+MinimumVisualStudioVersion = 12.0
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleMft0", "SampleMft0.vcxproj", "{3661ABB3-1FA5-44BC-8027-1B444A275EEE}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3661ABB3-1FA5-44BC-8027-1B444A275EEE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {3661ABB3-1FA5-44BC-8027-1B444A275EEE}.Debug|Win32.Build.0 = Debug|Win32
+ {3661ABB3-1FA5-44BC-8027-1B444A275EEE}.Release|Win32.ActiveCfg = Release|Win32
+ {3661ABB3-1FA5-44BC-8027-1B444A275EEE}.Release|Win32.Build.0 = Release|Win32
+ {3661ABB3-1FA5-44BC-8027-1B444A275EEE}.Debug|x64.ActiveCfg = Debug|x64
+ {3661ABB3-1FA5-44BC-8027-1B444A275EEE}.Debug|x64.Build.0 = Debug|x64
+ {3661ABB3-1FA5-44BC-8027-1B444A275EEE}.Release|x64.ActiveCfg = Release|x64
+ {3661ABB3-1FA5-44BC-8027-1B444A275EEE}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/avstream/samplemft0/SampleMft0.vcxproj b/avstream/samplemft0/SampleMft0.vcxproj
new file mode 100644
index 00000000..0bf821f3
--- /dev/null
+++ b/avstream/samplemft0/SampleMft0.vcxproj
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{3661ABB3-1FA5-44BC-8027-1B444A275EEE}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{47328477-96F3-446D-8354-FC9AC4B6154D}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>SampleMft0</TargetName>
+ <UseOfAtl>Static</UseOfAtl>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>SampleMft0</TargetName>
+ <UseOfAtl>Static</UseOfAtl>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>SampleMft0</TargetName>
+ <UseOfAtl>Static</UseOfAtl>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>SampleMft0</TargetName>
+ <UseOfAtl>Static</UseOfAtl>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(IntDir)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(IntDir)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(IntDir)</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(IntDir)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(IntDir)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(IntDir)</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(IntDir)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(IntDir)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(IntDir)</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(IntDir)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(IntDir)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(IntDir)</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);advapi32.lib;comctl32.lib;comdlg32.lib;gdi32.lib;kernel32.lib;mf.lib;mfplat.lib;mfuuid.lib;ntdll.lib;ole32.lib;Oleaut32.lib;runtimeobject.lib;Shlwapi.lib;user32.lib;uuid.lib;version.lib;winmm.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>SampleMft0.def</ModuleDefinitionFile>
+ </Link>
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);advapi32.lib;comctl32.lib;comdlg32.lib;gdi32.lib;kernel32.lib;mf.lib;mfplat.lib;mfuuid.lib;ntdll.lib;ole32.lib;Oleaut32.lib;runtimeobject.lib;Shlwapi.lib;user32.lib;uuid.lib;version.lib;winmm.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>SampleMft0.def</ModuleDefinitionFile>
+ </Link>
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);advapi32.lib;comctl32.lib;comdlg32.lib;gdi32.lib;kernel32.lib;mf.lib;mfplat.lib;mfuuid.lib;ntdll.lib;ole32.lib;Oleaut32.lib;runtimeobject.lib;Shlwapi.lib;user32.lib;uuid.lib;version.lib;winmm.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>SampleMft0.def</ModuleDefinitionFile>
+ </Link>
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);advapi32.lib;comctl32.lib;comdlg32.lib;gdi32.lib;kernel32.lib;mf.lib;mfplat.lib;mfuuid.lib;ntdll.lib;ole32.lib;Oleaut32.lib;runtimeobject.lib;Shlwapi.lib;user32.lib;uuid.lib;version.lib;winmm.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>SampleMft0.def</ModuleDefinitionFile>
+ </Link>
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="$(IntDir)\SampleMft0_i.c" />
+ <ClCompile Include="dllmain.cpp">
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>stdafx.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\stdafx.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="Mft0.cpp">
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>stdafx.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\stdafx.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="SampleMft0.cpp">
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>stdafx.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\stdafx.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="stdafxsrc.cpp">
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>stdafx.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Create</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\stdafx.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <Midl Include="SampleMft0.idl" />
+ <ResourceCompile Include="SampleMft0.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/avstream/samplemft0/SampleMft0.vcxproj.Filters b/avstream/samplemft0/SampleMft0.vcxproj.Filters
new file mode 100644
index 00000000..b8df8584
--- /dev/null
+++ b/avstream/samplemft0/SampleMft0.vcxproj.Filters
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{60B49576-F845-4721-98B6-4B94304459BD}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{176EFA30-A762-4CC7-98E3-21230AC1411A}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{87076883-275D-4C8B-84E7-B0108688E1C1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="Debug\\SampleMft0_i.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="dllmain.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Mft0.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SampleMft0.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="stdafxsrc.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <Midl Include="SampleMft0.idl">
+ <Filter>Source Files</Filter>
+ </Midl>
+ <None Include="SampleMft0.def">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="SampleMft0.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/avstream/samplemft0/dllmain.cpp b/avstream/samplemft0/dllmain.cpp
new file mode 100644
index 00000000..df86088a
--- /dev/null
+++ b/avstream/samplemft0/dllmain.cpp
@@ -0,0 +1,19 @@
+// dllmain.cpp : Implementation of DllMain.
+
+#include "stdafx.h"
+#include "resource.h"
+#include "SampleMft0.h"
+#include "dllmain.h"
+
+CSampleMft0Module _AtlModule;
+
+// DLL Entry Point
+extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
+{
+#ifdef _MERGE_PROXYSTUB
+ if (!PrxDllMain(hInstance, dwReason, lpReserved))
+ return FALSE;
+#endif
+ hInstance;
+ return _AtlModule.DllMain(dwReason, lpReserved);
+}
diff --git a/avstream/samplemft0/dllmain.h b/avstream/samplemft0/dllmain.h
new file mode 100644
index 00000000..04e95ab3
--- /dev/null
+++ b/avstream/samplemft0/dllmain.h
@@ -0,0 +1,10 @@
+// dllmain.h : Declaration of module class.
+
+class CSampleMft0Module : public ATL::CAtlDllModuleT< CSampleMft0Module >
+{
+public :
+ DECLARE_LIBID(LIBID_SampleMft0Lib)
+ DECLARE_REGISTRY_APPID_RESOURCEID(IDR_SAMPLEMFT0, "{F9ED475B-DC47-458A-A138-55D7E8A57AF0}")
+};
+
+extern class CSampleMft0Module _AtlModule;
diff --git a/avstream/samplemft0/resource.h b/avstream/samplemft0/resource.h
new file mode 100644
index 00000000..d20cf5a1
--- /dev/null
+++ b/avstream/samplemft0/resource.h
Binary files differ
diff --git a/avstream/samplemft0/stdafx.cpp b/avstream/samplemft0/stdafx.cpp
new file mode 100644
index 00000000..feacb859
--- /dev/null
+++ b/avstream/samplemft0/stdafx.cpp
@@ -0,0 +1,13 @@
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+
+// stdafx.cpp : source file that includes just the standard includes
+// SampleMft0.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
diff --git a/avstream/samplemft0/stdafx.h b/avstream/samplemft0/stdafx.h
new file mode 100644
index 00000000..86d812ec
--- /dev/null
+++ b/avstream/samplemft0/stdafx.h
@@ -0,0 +1,42 @@
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#pragma once
+
+#ifndef STRICT
+#define STRICT
+#endif
+
+#include "targetver.h"
+
+#define _ATL_APARTMENT_THREADED
+
+#define _ATL_NO_AUTOMATIC_NAMESPACE
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+
+
+#define ATL_NO_ASSERT_ON_DESTROY_NONEXISTENT_WINDOW
+
+#include "resource.h"
+#include <atlbase.h>
+#include <atlcom.h>
+#include <atlctl.h>
+#include <atlcoll.h>
+#include <DbgHelp.h>
+
+#include <mfapi.h>
+#include <mfidl.h>
+#include <mferror.h>
+#include <ks.h>
+#include <ksmedia.h>
+
+#include <inspectable.h> \ No newline at end of file
diff --git a/avstream/samplemft0/stdafxsrc.cpp b/avstream/samplemft0/stdafxsrc.cpp
new file mode 100644
index 00000000..1577c4e3
--- /dev/null
+++ b/avstream/samplemft0/stdafxsrc.cpp
@@ -0,0 +1 @@
+#include "stdafx.h" \ No newline at end of file
diff --git a/avstream/samplemft0/targetver.h b/avstream/samplemft0/targetver.h
new file mode 100644
index 00000000..fc349fa5
--- /dev/null
+++ b/avstream/samplemft0/targetver.h
@@ -0,0 +1,15 @@
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>