Microsoft DirectX 8.0 |
This article describes how to use effects and transitions in Microsoft® DirectShow® Editing Services (DES). It contains the following sections.
To add an effect or transition object, perform the following steps.
Call the IAMTimeline::CreateEmptyNode method with a major type of TIMELINE_MAJOR_TYPE_EFFECT or TIMELINE_MAJOR_TYPE_TRANSITION. Effects expose the IAMTimelineEffect interface, and transitions expose the IAMTimelineTrans interface. For more information, see Creating Timeline Objects.
Effect and transition objects are wrappers for subobjects. The subobjects do the real work by implementing a data transform. The effect or transition object uses the subobject to transform the audio or video stream. You can use any one-input Microsoft® DirectX® Transform object as an effect, or any two-input DirectX Transform object as a transition. A DirectShow audio effect filter can serve as an effect in an audio group. DES also provides a special audio effect called the Volume Envelope, which sets the volume. Each object in a timeline can have at most one Volume Envelope effect. Other effects do not have this restriction.
After you create an effect or transition object, call IAMTimelineObj::SetSubObjectGUID with the class identifier (CLSID) of the subobject. Enumerating Effects and Transitions describes how to enumerate the effects and transitions available on the user's system.
Call the IAMTimelineObj::SetStartStop method to set the start and stop times relative to the parent object.
Many effects and transitions support custom properties. Setting Properties on Effects and Transitions describes how to set these properties.
Call one of the following methods on the parent object:
The parent object can have multiple effects and transitions. Effects can overlap on the same object; transitions cannot. For each object, its effects are rendered in the order of their priority, starting from priority zero. (Specify the priority level when you call EffectInsBefore.)
The following code example adds an SMPTE Wipe Transition to a track. It assumes the track is already created.
// IAMTimeline *pTL; // IAMTimelineTrack *pTrack; // Create the transition object. IAMTimelineObj *pTransObj = NULL; hr = pTL->CreateEmptyNode(&pTransObj, TIMELINE_MAJOR_TYPE_TRANSITION); // Set the subobject. hr = pTransObj->SetSubObjectGUID(CLSID_DxtJpeg); // SMPTE Wipe // Set the start and stop times. hr = pTransObj->SetStartStop(50000000, 100000000); // Insert the transition object into the timeline. IAMTimelineTransable *pTransable = NULL; hr = pTrack->QueryInterface(IID_IAMTimelineTransable, (void **)&pTransable); hr = pTransable->TransAdd(pTransObj); hr = pTransObj->Release();
Some effects and transitions take a relatively long time to render. During preview this can cause the video to become choppy or out of sync with the audio. You can increase preview speed by disabling effects or transitions:
When effects are disabled, they are not rendered during preview. When a transition is disabled, it is rendered as a jump cut. The segue between tracks still occurs, but the visual effect is not rendered.
If an effect or transition cannot be rendered, the render engine substitutes a default effect or transition. Call the IAMTimeline::SetDefaultEffect method to set the default effect, and the IAMTimeline::SetDefaultTransition method to set the default transition. If you do not specify a default, or if the one you specify also causes an error, DES uses its own default.
Note You can also improve preview quality by increasing the amount of frame buffering. See IAMTimelineGroup::SetOutputBuffering.
DirectShow provides a system device enumerator for enumerating devices. You can use it to retrieve monikers for effects or transitions installed on the user's system.
The system device enumerator exposes the ICreateDevEnum interface. It returns category enumerators for specified device categories. A category enumerator, in turn, exposes the IEnumMoniker interface and returns monikers for each device in the category. For a detailed discussion of using ICreateDevEnem, see Enumerating Devices and Filters. The following is a brief summary, specific to DirectShow Editing Services.
To enumerate effects or transitions, perform the following steps.
The following code example illustrates these steps.
ICreateDevEnum *pCreateDevEnum; IEnumMoniker *pEm; CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pCreateDevEnum); pCreateDevEnum->CreateClassEnumerator( CLSID_VideoEffects1Category, // Effects category. &pEnumMoniker, 0); // Use CLSID_VideoEffects2Category for transitions. ULONG cFetched; IMoniker *pMoniker; while(S_OK == pEnumMoniker->Next(1, &pMoniker, &cFetched)) { HRESULT hr; IPropertyBag *pBag; hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag); if(SUCCEEDED(hr)) { VARIANT var; var.vt = VT_BSTR; hr = pBag->Read(L"FriendlyName", &var, NULL); if (SUCCEEDED(hr)) { if ( ... ) // Check whether var.bstrVal is the name you want. { VARIANT var2; GUID guid; pBag->Read(L"guid", &var2, NULL); GuidFromString(var2.bstrVal, &guid); SysFreeString(var2.bstrVal); // GUID is now the CLSID for the effect. break; } SysFreeString(var.bstrVal); } pBag->Release(); } pMoniker->Release(); } pEnumMoniker->Release(); pCreateDevEnum->Release();
Many effects and transitions support properties that control their appearance. For example, the Volume Envelope effect has a property that specifies the volume level. Using the IPropertySetter interface, an application can set the value of a property across a range of times.
To set a property, perform the following steps.
The DEXTER_PARAM structure specifies which property is being set. It contains the following members.
If you know the DISPID of the property, you can set the dispID member. Typically, you would set this member to zero and set the Name member to the name of the property.
The DEXTER_VALUE structure specifies the value of a property at a given time. It contains the following members.
If you set the vt member to VT_BSTR, the property setter makes any necessary conversions. For floating-point values, include the leading zero before the decimal place. For example, 0.3, not .3.
The value of a property can change over time, so the IPropertySetter::AddProp method takes a single DEXTER_PARAM structure and a pointer to an array of DEXTER_VALUE structures. The array defines a set of time-based values for the property. The members of the array must be in ascending time order, and the nValues member of the DEXTER_PARAM structure must equal the length of the array.
The following code example creates property data for the SMPTE Wipe transition. It sets the wipe code to 120, which creates an oval wipe. It sets the reference time to zero, indicating the start of the transition.
IPropertySetter *pProp; // Property setter IAMTimelineObj *pTransObj; // Transition object // Create an SMPTE Wipe transition object. (Not shown) CoCreateInstance(CLSID_PropertySetter, NULL, CLSCTX_INPROC_SERVER, IID_IPropertySetter, (void**) &pProp); DEXTER_PARAM param; DEXTER_VALUE *pValue = (DEXTER_VALUE *)CoTaskMemAlloc(sizeof(DEXTER_VALUE)); // Initialize the parameter. param.Name = SysAllocString(L"MaskNum"); param.dispID = 0; param.nValues = 1; // Initialize the value. pValue->v.vt = VT_BSTR; pValue->v.bstrVal = SysAllocString(L"120"); // Oval pValue->rt = 0; pValue->dwInterp = DEXTERF_JUMP; pProp->AddProp(param, pValue); // Free allocated resources. SysFreeString(param.Name); VariantClear(&(pValue->v)); CoTaskMemFree(pValue); // Set the property on the transition. pTransObj->SetPropertySetter(pProp); pProp->Release();
A transition goes from input A to input B, and from time t0 to t1. Therefore, the direction of a transition can mean one of two things:
The first is the input direction, and the second is the progress direction. You can control both directions.
The following diagram illustrates the difference between input direction and progress direction. It shows four variations on a standard SMPTE Wipe transition.
The transition resides on track 1. By default, the wipe goes from left to right and from track 0 to track 1. Swapping inputs causes the wipe to go from track 1 to track 0, but still from left to right. Reversing the progress makes the transition go from right to left. You can combine both, as shown on the far left.
For more information about how DES renders transitions, see The Timeline Model.