`
`Page 58 of 83
`
`Member function Description
`Transform
`Implement transform.
`CheckinoutTyoe Verify support of media type.
`
`Beyond providing your transform filter with a default implementation by providing the
`minimum overrides, you can override other member functions to provide more specialized
`behavior. Which member functions you override, of course, depends on what you want your
`filter to do. For example, you must override the GetPin and GetPinCount member functions if
`you want to have more than one input pin and one output pin on the filter.
`
`Also, several base class member functions, such as BreakConnect or ComoleteConnect, are
`called as notifications to your filter through the pins. Typically, most of these member
`functions exist only on the pins. In the classes based on CTransformFilter, the pin functions are
`implemented to call similarly named functions in the filter class. This means that the member
`functions you most likely will want to override are all collected into one filter class, so you can
`leave the pin classes unchanged, making implementation smaller and easier. These member
`functions are as follows:
`Reason to override
`Member function
`NonDelegatingOueryinterface To distribute any interfaces added in the derived class.
`GetPinCount
`If adding more pins to the transform filter.
`GetPin
`If adding more pins to the transform filter.
`CheckConnect
`To obtain extra interfaces at connect time or for other reasons.
`BreakConnect
`To release extra interfaces when connection is broken or for
`other reasons.
`To perform some action at the end of connection (such as
`reconnecting the input pin).
`To be notified when the media type has been set.
`To be notified when entering the streaming state.
`To be notified when exiting the streaming state.
`To do anything with quality-control messages other than
`passing them on.
`
`SetMediaTyoe
`Sta rtStrea ming
`StooStreaming
`AlterOuality
`
`ComoleteConnect
`
`A Sample Transform Filter Declaration
`
`An example of a filter derived from a transform class is the NullNull sample filter. This sample
`illustrates a true minimalist filter, which does nothing except demonstrate the least you must
`implement for a filter. It uses the transform-inplace classes and derives its filter class from the
`CTransinPlaceFilter class. Following is the class declaration for the derived filter class CNullNull.
`
`I I CNullNull
`II
`class CNullNull
`: public CTransinPlaceFilter
`
`public,
`
`static CUnknown *Createinstance(LPUNKNOWN punk, HRESULT *phr);
`
`DECLARE_IUNKNOWN;
`
`366
`
`
`
`Filter Developer's Guide
`
`Page 59 of 83
`
`LPAMOVIESETUP FILTER GetSetupData ()
`{
`-
`return &sudNullNull;
`
`}
`
`private:
`II constructor -
`just calls the base class constructor
`CNullNull(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr)
`: CTransinPlac eFilter (tszName, punk, CLSID_NullNull, phr )
`
`{ }
`II Overrides the PURE virtual Transform o f CTransinPlac eFilter base class
`II This is where the "real work" is done by altering *pSample.
`II we do the Null transfo rm by leaving it alone.
`HRESULT Transform(IMediaSample *pSample ) { return NOERROR; }
`II we accept any input type. We'd returns FALSE f o r any we didn't like.
`HRESULT CheckinputType (const CMediaType* mtln) { return S_OK; }
`
`This example illustrates the basic member functions required in the base class:
`Createlnstance Needed by every filter so that it can be instantiated as a COM object.
`GetSetupData Overrides CBaseFilter: :GetSetuoData and is used to provide the class with
`information required to register this particular filter. In this case, it
`provides the address of a structure defined in the Nullnull.cpp file included
`in the SDK.
`Class constructor, which typically just calls the base class constructor.
`Overrides CTransinPlaceFilter: :Transform and does the main work of
`CNullNull, which in this case is nothing.
`CheckinputType Overrides CTransinPlaceFilter: :CheckinoutTyoe to verify the media type
`during connection, and in this case accepts any media type offered, since it
`will simply pass it along to the next filter in line.
`
`CNullNull
`Transform
`
`Note that, strictly speaking, GetSetupData is required only if you want your filter to be self(cid:173)
`registering. However, since the base classes implement this feature and it is easy to
`implement, it is a good idea to include this in your base class.
`
`© 1997 Microsoft Corporation. All rights reserved. Terms of Use.
`
`MQl@[.jlj,M l!i.! 11!j Topic Contents
`
`l@i§illlj4M
`
`w QiM [.] ij,+ 111.Hj Topic Contents
`
`i@faiillj4M
`
`Connecting Transform Filters
`
`This article describes some of the connection issues faced when creating a transform filter.
`Connecting any two filters requires negotiating which media types to use and deciding on a
`common allocator for passing samples. Since transform filters are connected on both sides, and
`since some transform filters use the media types and allocators of other filters in the graph, it
`
`367
`
`
`
`Filter Developer's Guide
`
`Page 60 of 83
`
`is important to understand the concepts involved in transform filter connections.
`
`Contents of this article:
`
`• How Allocator Negotiation Works
`• Establishing Media Type Connections
`
`How All(l(:lltOt Negotiation Wotks
`
`For information about the connection process, including media type and allocator negotiation,
`see Connection Model. When you are determining your transform filter characteristics, it might
`help for you to understand the model of allocator negotiation for transform filters.
`
`If your transform filter requires copying, then it will copy media samples from a buffer
`establiShed by its input pin to a buffer established by its output pin. These buffers are provided
`by allocators that might actually be located in other filters, perhaps even several filters
`removed if the filters in between do not copy the data.
`
`A copying transform filter typically tries to use the allocator of the upstream filter for its input
`pin, and the allocator of the downstream filter for its output pin. During the connection
`process, the output pin of the upstream filter determines which allocator to use for the
`upstream transport, so the input pin of the copy transform must be prepared to create an
`allocator for the upstream transport if its IMeminputPin: :GetAllocator method iS called by the
`connecting output pin. The base classes provide a way to create a new allocator from the input
`pin of any connection.
`
`On the other hand, transform-inplace filters do not make copies, but rather modify the data in
`an existing bUffer. These filters should always offer the allocator from the downstream filter to
`the upstream filter. This requires a reconnection, because the filter does not know about the
`downstream filter when its input pin is first connected. Also, because in place-transforms do not
`change the media type, the media type from the downstream filter should be offered to the
`upstream filter upon reconnection.
`
`Connecting Filtet Graphs: An Example
`
`To better understand the allocation model for a transform-inplace filter, the following
`mustration shows a simple and common example of a filter graph.
`
`Source
`A
`
`,__..
`
`In Place
`B
`
`,__..
`
`Copy Dec
`c
`
`....
`
`InPlace
`D
`
`,__..
`
`In Place
`E
`
`,__..
`
`VidRen
`F
`
`This simple example demonstrates the model of the transform-inplace filter offering its
`downstream allocator to its upstream filter. Consider what happens when InPlace E is
`connected to VidRen F.
`
`Upon connection, the video renderer filter (VidRen F) offers its allocator for use by the
`upstream inplace filter (InPlace E). Because it is a transform-inplace filter, InPlace E offers the
`allocator to the next filter upstream, InPlace D, and so on. ThiS reconnection and renegotiation
`occurs until it encounters either the source filter or a copy transform filter. In this case it
`meets a decompressor, CopyDec C. (The copy transform filter cannot offer its allocator
`upstream, because it must perform a copy operation.) So the decompressor wm be writing
`directly to the video renderer's buffer, which might be a DirectDraw® surface. ThiS
`
`368
`
`
`
`Filter Developer's Guide
`
`Page 61of83
`
`demonstrates why it is a good practice to write a transform filter as a transform-inplace filter
`and pass allocators from the renderer upstream, if possible.
`
`On the other hand, consider filters InPlace Band CopyDec C. What if the downstream filter
`from a transform-inplace filter is a copy transform filter instead of a renderer? In this case, the
`copy transform filter will offer to create its own allocator on its input pin (the base classes
`handle this), and the transform-inplace filter can then offer that allocator downstream upon
`reconnection (the same as if it were connected to a renderer filter).
`
`However, even though CopyDec C can create its own allocator (from its
`!MemlnoutPin: :GetAllocator method), the source filter, Source A, uses its own buffer-say, a
`file. So when InPlace B connects to CopyDec C, InPlace B will have accepted the source filter's
`allocator already and will force that allocator to be used for the transport between itself and
`the decompressor filter. InPlace B can then provide the upstream filter, Source A, with the
`option of using the allocator offered by CopyDec C, but the source filter will refuse this
`allocator so that an extra copy does not have to be made from the file buffer to the
`decompressor's input buffer.
`
`Therefore, any upstream filter can force the use of its allocator downstream but should have
`good reason to do so (such as if it already has a buffer). In this example, only one copy is
`being made (by the decompression filter) between the file buffer and the video memory.
`
`Establishing Media Type Connections
`
`When pins from different filters are connected, they must both agree on a common media type
`for the samples they will exchange. A quick review of the connection mechanism might help
`highlight how transform filters handle media type negotiations.
`
`This section contains the following topics.
`
`• The Connection Process: A Summary
`• When Reconnections Occur
`
`The Connection Process: A Summary
`
`When one filter's output pin is called by the filter graph manager to connect to an input pin of
`a second filter, the !Pin: :Connect method is called. This, in turn, calls
`CBaseOutoutPin: :CheckConnect to obtain interfaces from the connected pin and
`CBasePin: :AgreeMediaTyoe to find a common media type.
`
`AgreeMediaTyoe calls CBasePin: :TryMediaTyoes, which uses media type enumerators to query
`the pins for preferred media types. !EnumMediaTyoes is an interface on the connected input
`pin that TryMediaTyoes uses first. The base classes use IEnumMediaTypes to repeatedly call
`a CBasePin member function called GetMediaTyoe for each media type in the list. You use this
`member function in your input and output pin classes to return the media types that your pin
`prefers.
`
`TryMediaTyoes calls the output pin's CheckMediaTyoe member function with each input type
`returned. You must use CheckMediaType to verify whether this type is acceptable. If no
`media types are found (for example GetMediaTyoe may not even be used on the connected
`input pin, or may return an unacceptable media type), then AgreeMediaTyoe obtains a media
`type enumerator for the output pin and tries each of these in turn. Again, the GetMediaType
`member function of the derived output pin is called for each type. In this case, it can
`
`369
`
`
`
`Filter Developer's Guide
`
`Page 62 of 83
`
`determine media types by inquiring about any existing connection established by the filter's
`input pin.
`
`When Reconnectlons Occut
`
`For transform filters that do not modify the media type from input pin to output pin (such as
`most in-place transforms and many copy transforms), a reconnection scheme must be in place
`for offering the downstream filter's media type to the upstream filter. To understand this,
`consider the media type negotiation of the transform-inplace Filter Bin the following
`mustration.
`
`Filter
`A
`
`AOutPin
`
`Bin Pin
`
`Filter
`B
`
`BOutPin
`
`ClnPin
`
`Filter
`c
`
`The input pin of Filter B is connected first and establishes a media type with the upstream
`output pin (AOutPin). When the output pin of Filter Bis connected next, it must use the
`enumerator from the output pin of the connected upstream filter (AOutPin), because it does
`not have one of its own.
`
`If the pin of the downstream filter, CinPin, can accept this, then the connection is complete.
`However, assume that Filter C does not agree to this media type but proposes a media type
`that Filter B can hand le.
`
`Before deciding that it can handle the media type, Filter B calls the IPiw ·QneryAccept method
`on AOutPin to ensure that it is acceptable. If no media type can be found that is acceptable for
`au the filters, then the BOutPin to CinPin connection wm fail. (It is possible to find that a
`transform-inplace filter wm connect to either its upstream or its downstream neighbors, but
`not both simultaneously.)
`
`If a suitable type iS found, BOutPin must force a reconnection on the entire filter, and pass the
`establiShed media type (the media type of CinPin) to AOutPin, when AOutPin and BinPin are
`connected again.
`
`w;•; "·II' a 111.11119 Topic Contents
`
`l@i§Mit§M
`
`+414 "·II' a 1:1.1 .. 19 Topic Contents
`
`l@i§MMt§M
`
`About Compression Filters
`
`A ccmpre$$iCn filter is a specialized type of transform filter. Compression filters (compressors)
`accept data, use a compression scheme to transform the data, and pass the compressed data
`downstream.
`
`Microsoft® DirectShow'" includes an AVI Compressor filter and an ACM Audio Compressor
`filter, which wm use any Microsoft Video for Windows® video or audio~ to compress data.
`You can write your own compressor filter if you need to compress data in a format that isn't
`
`370
`
`
`
`Filter Developer's Guide
`
`Page 63 of 83
`
`supported by the default filters that DirectShow provides.
`
`To begin writing a compression filter, write a transform filter that includes one input pin and
`one output pin. See the following articles for more information about writing a transform filter.
`
`• Creating a Transform Filter
`• Using the CTransformFilter and CTransinPlaceFilter Transform Base Classes
`• Connecting Transform Filters
`
`After you've written a transform filter, you should review the following points when completing
`your compression filter:
`
`• Register your filter.
`
`Register your compression filter by using the AMovieDllRegisterServer2 function. This
`enables applications to enumerate your filter with all the other compression filters on the
`system. See Enumerate and Access Hardware Devices in DirectShow Applications for
`more information about device enumeration.
`
`• Implement the recommended compressor interfaces.
`
`It is strongly recommended that you implement the IAMStreamConfiq interface on the
`output pin of all compression filters and IAMVideoCompression on the output pin of video
`compressors so that applications can access the compression features of your filter.
`
`IAMStreamConfig enables you to inform applications about the formats to which you can
`compress data, and enables the application to configure your compressor to compress to
`a particular data type.
`
`IAMVideoCompression enables an application set video-specific settings, like keyframe
`frequency, that do not appear in the AM MEDIA TYPE structure.
`
`The VidCap Sample (Video Capture Filter) sample video capture filter included with the
`DirectShow SDK implements the IAMStreamConfiq and IAMVideoCompression interfaces, and
`performs filter registration. Note that this sample code is for a capture filter, but the filter
`registration and implementation of these two interfaces is similar to that of a compression
`filter.
`
`© 1997 Microsoft Corporation. All rights reserved. Terms of Use.
`
`+;<§1[.]lj,i '!!·!:.!¥ Topic Contents i@i§ll!¥+
`
`About Effect Filters
`
`In DirectShow, effect filters are defined as filters that apply an effect to media data, but don't
`change the media type. DirectShow provides several effect filters, including Contrast, Gargle,
`and EzRGB24. Effect filters can apply a wide range of useful video and audio effects to media
`data.
`
`371
`
`
`
`Filter Developer's Guide
`
`Page 64 of 83
`
`Contents of this article:
`
`• Creating Effect Filters
`• List of DirectShow Effect Filters and Samples
`
`Creating Effect Filters
`
`Because the input and output media formats are the same, and the applied effect can't change
`the format, effect filters often contain a code that checks the media formatting. If the filter
`derives from one of the transform filter base classes, CTransformFilter or CTranslnPlaceFilter,
`the filter typically checks the format with the CheckMediaType, ChecklnputType, and
`CheckTra nsform methods. If the filter doesn't derive from one of the transform filter base
`classes, its pins typically check the format by calling the CBasePin: :CheckMediaType member
`function. See Negotiating Media Types with CBasePin: :AgreeMediaType for more information.
`
`You should choose a base class for your effect filter class that provides the greatest amount of
`the functionality you need. Often, the base class will be one of the transform filter base
`classes. If none of the higher-level base classes support your required functionality, you can
`choose CBaseFilter or CBasePin as your base class.
`
`Your effect filter must implement the !PersistStream interface if you want to save the state of
`your effects in the Filter Graph Editor. To access this interface, derive your effect filter class
`from CPersistStream and query for the IPersistStream interface. Saving the filter's state can
`be helpful during design, but it is often useful to have the effect filter return to a default state
`when the Filter Graph Editor closes it, in which case you don't need to implement
`IPersistStream.
`
`If you want the user to be able to manipulate the effect, you must create and display your
`effect filter's property page and provide a mechanism for returning the user's input to the
`filter. To do this, implement a property page class, the !SpecifyPropertyPages interface (which
`exposes property pages), and a custom interface that changes property page values. Typically,
`property pages use controls such as a slider, button, or check box to receive user input. You
`also must provide the resource file that displays the controls on the property page.
`
`To implement the property page class, create a class that derives from CBaseProoertyPage and
`implement the OnReceiveMessage method, the CPersistStream: :SetDirty method, and a data
`member for each effect parameter. To access the two interfaces, derive your effect filter class
`from !SoecifyProoertyPages and the custom interface, and then query for the interfaces. You
`can query for all the interfaces you need by overriding the NonDelegatingOuerylnterface
`method as shown in the following code from the Gargle sample (!Gargle is the custom
`interface):
`
`STDMETHODIMP CGargle, ,NonDelegatingQueryinterface(REFIID riid, void **ppv)
`{
`
`CheckPointer(ppv,E POINTER);
`if (riid == IID_IGargle) {
`return Getinterface((IGargle *) this, ppv);
`else if (riid == IID_ISpecifyPropertyPages) {
`return Getinterface((ISpecifyPropertyPages *) this, ppv);
`else if (riid == IID_IPersiststream) {
`return Getinterface((IPersiststream *) this, ppv);
`else {
`return CTransinPlaceFilter: :NonDelegatingQueryinterface(riid, ppv);
`
`372
`
`
`
`Filter Developer's Guide
`
`Page 65 of 83
`
`The effect filter's custom interface typically supplies a put and a get method for each effect
`parameter. For example, the !Gargle custom interface supplies put_GargleRate and
`get_GargleRate methods. The !Contrast custom interface in the Contrast sample supplies
`put_Contrastlevel and get_Contrastlevel methods. When the user accesses one of the controls
`on the property page, the page generates a windows message. The property page class's
`OnReceiveMessage member function handles this message. The following code fragment from
`the Contrast sample demonstrates this message generation and handling. IDB_DEFAULT is the
`resource ID of the Default button. The user clicks this button to set the video contrast to its
`default state. The CContrastProperties class implements the property page and the
`!Contrast:: put_DefaultContrastlevel method sets the contrast level to its default value.
`
`BOOL ccontrastProperties::OnReceiveMessage(HWND hwnd, UINT uMsg,
`WPARAM wParam, LPARAM lParam)
`
`switch (uMsg)
`{
`
`case WM COMMAND:
`{
`-
`if (LOWORD(wParam) == IDB_DEFAULT)
`{
`
`pIContrast()->put_DefaultContrastLevel();
`SendMessage(m_hwndSlider, TBM_SETPOS, TRUE, OL);
`SetDirty () ;
`
`return (LRESULT) 1;
`
`Effect filters use critical sections internally to protect the global filter state. Effect filters can
`lock a critical section to ensure that data flow through the filter graph is serialized and that the
`global filter state doesn't change while an effect is occurring. DirectShow locks a critical section
`by declaring a CAutolock class object. Typically, effect filters lock the critical section as soon
`as they enter the function that applies the effect. For example, in the following code fragment
`from the Gargle sample, the function that applies the effect is MessltAbout:
`
`CCritSec m_GargleLock; //Declare the critical section data member in the effect
`
`void CGargle,,MessitAbout(PBYTE pb, int cb)
`{
`
`CAutoLock foo(&m_GargleLock);
`
`The put and get methods of the effect properties (for example, put_GargleRate) typically lock
`the critical section so effect values can't change in the middle of an update.
`
`List of DirectShow Effect Filters and Samples
`
`The DirectShow SDK ships with the following effect filters. You can find these filters in the
`Samples directory. All the source code is included.
`
`Contrast: This effect filter adjusts the contrast of the video images sent through it. The filter
`adjusts the contrast by using palettes, because an image's color palette effectively determines
`how the image is interpreted by the display device; that is, how the value 23 (for example)
`maps into an RGB triplet for display. By changing the palette, you can reduce and increase
`
`373
`
`
`
`Filter Developer's Guide
`
`Page 66 of 83
`
`contrast without doing anything to the image pixels themselves. The Filter Graph Editor lists
`this filter as Video Contrast.
`
`EzRGB24: This effect filter modifies decompressed video images sent through it. It creates
`color and image filtering effects through simple techniques such as adjusting the red, green, or
`blue levels (to change the playback color) and by averaging neighboring pixels (to achieve blur
`and embossed (raised) effects). The Filter Graph Editor lists this filter as Image Effects.
`
`Gargle: This effect filter modifies audio data sent through it. A synthesized wave function
`modulates the audio data's amplitude. The secondary wave can be a triangular or square wave,
`and can have different frequencies. At low modulation frequencies it sounds like a tremolo. At
`high modulation frequencies it sounds like a distortion. The Filter Graph Editor lists this filter
`as Gargle.
`
`© 1997 Microsoft Corporation. All rights reserved. Terms of Use.
`
`MQi@[.ji!:M l!i.! 11ij Topic Contents
`
`l@i§il!MM
`
`+Qi§i!.li!:1 1 !1·Hj Topic Contents
`
`l@IJlllMM
`
`Video Renderers
`
`This section describes how to write and use video renderers, both full-screen and custom
`renderers. It discusses how and why to support a full-screen renderer, and how to handle
`notifications, state changes, and dynamic format changes in a custom renderer.
`
`· Full-Screen Video Renderer
`
`· Alternative Video Renderers
`
`© 1997 Microsoft Corporation. All rights reserved. Terms of Use.
`
`MQi@[.ji!:M l!i.! 11ij Topic Contents
`
`l@i§i l!lltiM
`
`Full-Screen Video Renderer
`
`This article explains the logic used by the default Microsoft® IVideoWindow plug-in distributor
`(PID), when an application instructs it to render the video in full-screen mode. Substitute
`renderer filters can use the IVideoWindow PID for communication with applications.
`Developers of substitute renderers should be aware of how this PID searches the filter graph
`for the best means of representing full-screen video, when requested to render in full-screen
`mode.
`
`Contents of this article:
`
`374
`
`
`
`Filter Developer's Guide
`
`Page 67 of 83
`
`• Using the IVideoWindow PID to Implement Full-Screen Support
`• Finding a Filter That Supports Full-Screen Mode
`• Finding a Filter That Can Be Stretched Full-Screen at No Cost
`• Supplying a Full-Screen Renderer Filter
`• Stretching the Output of a Renderer Full-Screen
`• Implications of Full-Screen Support for the Application
`
`Using the IVideoWindow PIO to Implement Full-Screen Support
`
`Microsoft® DirectShow™ implements full-screen support in a number of ways that depend on
`what hardware resources are available. An application can support full-screen video playback
`through the IVideoWindow interface provided by the filter graph manager. An application can
`have its own implementation of full-screen playback, but it can probably make better use of
`resources by using the IVideoWindow implementation.
`
`The IVideoWindow plug-in distributor (PID) tries three different options for implementing full(cid:173)
`screen support when an application requests full-screen mode. The option is typically chosen
`the first time the filter graph enters full-screen mode. While in full-screen mode, no
`IVideoWindow methods can be called (apart from accessing the full-screen property). Any
`attempts to do so will return the VFW E IN FULLSCREEN MODE message. The PID searches
`in the following order for a filter that supports IVideoWindow and that has one of these
`characteristics:
`
`1. The filter supplies full-screen mode directly.
`2. The filter allows its window to be stretched to full screen without penalty.
`3. The filter can be replaced by a full-screen renderer.
`
`If none of these three options are found, the default is to simply stretch the video of a filter
`that supports IVideoWindow to full-screen, ignoring the performance penalties.
`
`Finding a Filter That Supports Full-Screen Mode
`
`The first option is to search for a filter in the filter graph that supports full-screen mode
`directly. When asked to go into full-screen mode, the IVideoWindow PID first scans all filters
`supporting IVideoWindow in the filter graph. The PID calls
`IVideoWindow: :get FullScreenMode on each filter and, if the filter returns E_NOTIMP (the
`default), assumes that the filter has no inherent support for full-screen playback. If the filter
`returns anything else, then that filter becomes the nominated filter for full-screen playback.
`This means that any calls to the filter graph manager to set the full-screen mode on or off will
`be sent directly to that nominated filter. This mechanism allows filters to be extended to
`support full-screen support directly. Most normal window-based renderers do not need to
`support this feature.
`
`Finding a Filter That Can Be Stretched Full-Screen at No Cost
`
`If a full-screen rendering filter can't be found, then the PID tries to find a filter supporting the
`IVideoWindow interface that can have its window stretched full-screen without penalty. The
`PID does this by scanning the list of filters in the filter graph that support IVideoWindow. For
`each filter found, the PID calls IVideoWindow: :GetMaxideallmageSize. If a filter indicates that
`its window can be stretched full-screen at no cost, then that becomes the nominated filter.
`
`If that nominated filter is then requested to render full-screen, the PID resets a number of the
`
`375
`
`
`
`Filter Developer's Guide
`
`Page 68 of 83
`
`filter's !VideoWindow properties and stretches the window to full-screen. This typically means
`setting a null owner, changing the window styles to not show the border or the caption, and
`updating the window position to match the current display size. When full-screen mode is
`switched off, the properties on the filter will be reset to the state prior to the full-screen mode.
`
`Most video renderers supporting !VideoWindow cannot return the maximum ideal image size
`until they have been activated (either paused or running), because that is when they allocate
`their resources. For this reason, when scanning the list of filters while the filter graph is in a
`stopped state, the PID pauses each filter before calling !VideoWindow: :GetMaxldeallmageSize.
`After calling this method, the filter is stopped again.
`
`Supplying a Full-Screen Renderer Filter
`
`If neither of the previous options were successful, then the PID finds the first available filter in
`the filter graph that supports an !VideoWindow interface, and assumes that it is the current
`video renderer filter.
`
`If no filters that support !VideoWindow are available, the call to change to full-screen mode will
`return VFW E NO FULLSCREEN. When asked to change into full-screen mode, the PID stops
`the filter graph, if it is not already stopped, disconnects the current renderer, and reconnects
`the DirectShow full-screen renderer in its place. If the connection succeeds, then the filter
`graph is restored to its original state. When switching out of full-screen mode, the opposite
`occurs. That is, the full-screen renderer is disconnected and the original filter is reconnected.
`The state of the filter graph is likewise restored. The full-screen renderer is a specialized
`renderer that uses the display changing capabilities provided by DirectDraw®. For example, it
`might switch the full-screen display 320 x 240 when it might have been in, for example, 1024
`x 768. By switching to lower resolution modes, it can cheaply implement full-screen rendering
`without having to stretch images.
`
`The full-screen renderer currently implements 320 x 200 x 8/16 bits per pixel, 320 x 240 x
`8/16, 640 x 400 x 8/16, 640 x 400 x 8/16, 640 x 480 x 8/16, 800 x 600 x 8/16, 1024 x
`768 x 8/16, 1152 x 864 x 8/16, and 1280 x 1024 x 8/16 display modes. The Modex renderer
`supports the !FullScreenVideo interface. When the modex renderer is connected, it loads the
`display modes DirectDraw has made available. The number of modes available can be obtained
`through !FullScreenVideo: :CountModes. Information on each mode is available by calling
`!FullScreenVideo: :GetModelnfo and !FullScreenVideo: :IsModeAvailable. An application can
`enable and disable any modes by calling the SetEnabled flag with OATRUE or OAFALSE. The
`current value can be queried for with !FullScreenVideo: :IsModeEnabled.
`
`Another way to set the modes enabled is to use the clip loss factor. This defines the amount of
`video that can be lost when deciding which display mode to use. Assuming the decoder cannot
`compress the video, then playing, for example, an MPEG file that is 352 x 288 pixels into a
`320 x 200 display will lose over 40 percent of the image. The clip loss factor specifies the
`upper range of clipping loss that is permissible. To allow typical MPEG video to be played in
`320 x 200 it defaults to 50 percent. You can set the clip loss factor with
`!FullScreenVideo: :SetClioFactor.
`
`Stretching the Output of a Renderer Full-Screen
`
`After trying the first three options, the final option for implementing full-screen support is to
`pick any filter enabled by !VideoWindow and stretch its window full-screen, regardless of the
`resulting poor performance. Essentially, the first filter in the filter graph that is enabled by the
`IVideoWindow interface becomes the nominated filter. This filter is then used in the same
`manner as if it was a filter that could be stretched full-screen without sacrificing performance
`
`376
`
`
`
`Filter Developer's Guide
`
`Page 69 of 83
`
`(that is, the owner is reset, the styles changed, and the window position changed to match the
`display extents).
`
`The cost of stretching a window full-screen where there is an implicit performance penalty
`varies, depending on the resolution currently displayed. The worst scenario is one in which the
`user is using a relatively high resolution (for example, 1024 x 768) and the images must be
`stretched by the renderer using GD!. This is likely to provide very low frame throughput and is
`used only as a last resort.
`
`Implications of Full-Screen Support for the Application
`
`While the interface exposed to applications is relatively simple, the underlying implementation
`can be more complex. The full-screen renderer has some special properties that application
`developers should be aware of. In particular, the renderer changes display modes only when
`activated (either paused or running). T