## Using the CTransformFilter and CTransInPlaceFilter Transform Base Classes

This article describes the classes provided for creating a transform filter. It is background information that you should read before reading the article Creating a Transform Filter, which walks through the steps of creating a transform filter.

Contents of this article:

- Introducing the CTransformFilter and CTransInPlaceFilter Classes
- What the Derived Class Must Provide
- A Sample Transform Filter Declaration

Introducing the CTransformFilter and CTransInPlaceFilter Classes

The easiest solution for writing a transform filter is to use the transform filter classes, which work well for most types of transform filters. Typically, a noncopying transform filter is derived from the CTransInPlaceFilter class and its associated pin classes; a copy transform filter is derived from the CTransformFilter filter class and its associated pin classes.

Transform filter classes are hierarchical, with the transform-inplace classes at the bottom of the hierarchy tree. CTransInPlaceFilter is derived from CTransformFilter, which is derived from CBaseFilter, as shown in the following illustration.

The CTransInPlaceInputPin class is derived from the CTransformInputPin class. The CTransformInputPin class is derived from the CBaseInputPin class, as shown in the following illustration.

The CTransInPlaceOutputPin class is derived from the CTransformOutputPin class. The CTransformOutputPin class is derived from the CBaseOutputPin class, as shown in the following illustration.

Copy transform and transform-inplace classes share many features, because the transform-inplace classes derive almost all member functions from the copy transform classes. The principal additions made by the transform classes over the base classes is that all required pin member functions are implemented—so for default implementation, you need only to derive a main filter class (from CTransInPlaceFilter or CTransformFilter).

What the Derived Class Must Provide

The derived filter class must provide a few member functions, typically to:

- Determine if the filter accepts the media type.
- Specify the count and size of any required allocators (for copy transforms only).
- Provide the transform functionality of the filter.

All derived filter classes must implement a static CFactoryTemplate::CreateInstance function. You can also choose to override the CBaseFilter::GetSetupData member function to make your filter self-registering. Beyond this, your classes must override a few member functions in the transform base classes. For more information about instantiating the filter, see Creating a Transform Filter.

If your derived filter class is based on the CTransformFilter class, you must override the following member functions.

Member function | Description
Transform | Implement transform.
CheckInputType | Verify support of media type.
CheckTransform | Verify support for transforming this type (for debugging builds only).
DecideBufferSize | Set size and count when copying.
GetMediaType | Suggest media types for the output pin.

If your derived filter class is based on the CTransInPlaceFilter class, override the following member functions.

Member function | Description
Transform | Implement transform.
CheckInputType | 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 CompleteConnect, 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:

Member function | Reason to override
NonDelegatingQueryInterface | 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.
CompleteConnect | To perform some action at the end of connection (such as reconnecting the input pin).
SetMediaType | To be notified when the media type has been set.
StartStreaming | To be notified when entering the streaming state.
StopStreaming | To be notified when exiting the streaming state.
AlterQuality | To do anything with quality-control messages other than passing them on.

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.

    // CNullNull
    //
    class CNullNull
        : public CTransInPlaceFilter
    {

    public:

        static CUnknown *CreateInstance(LPUNKNOWN punk, HRESULT *phr);

        DECLARE_IUNKNOWN;

        LPAMOVIESETUP_FILTER GetSetupData()
        {
            return &sudNullNull;
        }

    private:

        // Constructor - just calls the base class constructor
        CNullNull(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr)
            : CTransInPlaceFilter (tszName, punk, CLSID_NullNull, phr)
        { }

        // Overrides the PURE virtual Transform of CTransInPlaceFilter base class
        // This is where the "real work" is done by altering *pSample.
        // We do the Null transform by leaving it alone.
        HRESULT Transform(IMediaSample *pSample){ return NOERROR; }

        // We accept any input type.  We'd return S_FALSE for any we didn't like.
        HRESULT CheckInputType(const CMediaType* mtIn) { return S_OK; }
    };

This example illustrates the basic member functions required in the base class:

CreateInstance | Needed by every filter so that it can be instantiated as a COM object.
GetSetupData | Overrides CBaseFilter::GetSetupData 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.
CNullNull | Class constructor, which typically just calls the base class constructor.
Transform | Overrides CTransInPlaceFilter::Transform and does the main work of CNullNull, which in this case is nothing.
CheckInputType | Overrides CTransInPlaceFilter::CheckInputType 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.

Note that, strictly speaking, GetSetupData is required only if you want your filter to be self-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.