Configuring Profiles and Other ASF File Properties
Microsoft DirectShow 9.0 |
Configuring Profiles and Other ASF File Properties
The following items describe how to perform various tasks related to the creation of ASF files. Some of the interfaces mentioned in this topic are documented in the Windows Media Format SDK documentation.
Creating a Profile
ASF profiles are discussed in detail in the Windows Media Format SDK; essentially, they describe attributes of a Windows Media Format file such as bit rate, number and type of streams, and compression quality. The filter uses the profile to determine what kind of Windows Media Format file to write, how many input pins it must set up, and what media types they can accept.
To create a custom profile, use the Windows Media Format SDK directly to create a profile manager object by using the WMCreateProfileManager function. Next, create the profile, and pass it to the WM ASF Writer by using the IConfigASFWriter::ConfigureFilterUsingProfile method. This is the only way to configure the filter with a profile that uses the Windows Media Audio and Video 9 Series codecs. System profiles for earlier versions of these codecs can be added by using the IConfigASFWriter::ConfigureFilterUsingProfileGuid method.
You can reset the profile while the filter's input pins are connected, as long as the new profile does not require any additional input pins. For example, if you change the profile from a one-input audio-only profile to a two-input audio and video profile, just the audio pin will be reconnected and no new pin will be created for the video stream.
Adding Metadata
To add metadata to a file, query the WM ASF Writer filter for the IWMHeaderInfo interface. After the filter has been given a profile, use the IWMHeaderInfo interface methods to write the metadata.
Indexing a File
The WM ASF Writer creates temporally indexed files by default. To create a frame-indexed file, use the IConfigAsfWriter::SetIndexMode method to disable all indexing, then create the file. When it is complete, use the Windows Media Format SDK directly to create a frame-based index for the file.
Two-Pass Encoding
Two-pass encoding is supported only on Windows Media codecs of version 8 and later. Put the WM ASF Writer into preprocess mode by calling IConfigAsfWriter2::SetParam and specifying AM_CONFIGASFWRITER_PARAM_MULTIPASS in the dwParam parameter and TRUE in the dwParam1 parameter.
Then run the filter graph. When all the preprocessing passes are done (typically only one preprocessing pass will be performed), the application will receive an EC_PREPROCESS_COMPLETE event from the filter. When this event is received, use IMediaSeeking::SetPositions to reset the stream pointer back to the beginning, and run the filter graph again. After the last pass (typically the second pass), the application will receive an EC_COMPLETE event to signify that the encoding process is complete. If a preprocessing pass is canceled before the EC_PREPROCESS_COMPLETE event is received, call IConfigAsfWriter2::ResetMultiPassState to reset the filter before attempting another preprocessing run.
It is only necessary to set the AM_CONFIGASFWRITER_PARAM_MULTIPASS parameter to FALSE if you want to put the filter out of preprocessing mode completely.
- **Important ** It is the application's responsibility to enable the preprocessing mode based on the profile that will be used for encoding. Some profiles require two-pass encoding; if you attempt to encode a file with such a profile, and do not set AM_CONFIGASFWRITER_PARAM_MULTIPASS to TRUE, an EC_USERABORT error will result. For more information, see the Windows Media Format SDK documentation.
Getting and Setting Buffer Properties at Run Time
In some scenarios, for example if you want to force key-frame insertion when writing a file, an application may need to get or set information about a Windows Media buffer at run time. The WM ASF Reader and WM ASF Writer filters both support a callback mechanism that enables an application to access the INSSBuffer3 interface on each individual media buffer during file reading or file writing. Applications can use this interface to designate specific samples as key frames, set SMPTE time codes, specify interlace settings, or add any type of private data to a stream.
Use the IAMWMBufferPass interface to register for callbacks from the pin that is handling the video stream. The pin will call your IAMWMBufferPassCallback::Notify method for each buffer.
Non-Square Pixels
The WM ASF Writer connects to an upstream filter, such as the DV Decoder, that outputs pixel aspect ratio information. The WM ASF Writer will write this information as data unit extensions for every sample in the file.
When the WM ASF Reader encounters pixel aspect ratio information in the file header or in data unit extensions for the samples, it will offer a VIDEOINFOHEADER2 format as a first choice on its output pin. The dwPictAspectRatioX and dwPictAspectRatioY members of the structure, which describe the video rectangle's aspect ratio, will be correctly adjusted to account for the pixel aspect ratio.
Maintaining Interlaced Format
If you capture interlaced video from a television or a DV camera, you might wish to preserve the original video as independent fields if you expect the encoded file to be played back on a television or other interlaced display device. (Computer monitors are progressive scanning devices.) If you deinterlace a video, and then reinterlace it for playback on a television, some loss of data will be incurred. In an ASF file, interlacing information is stored as data unit extensions that the application applies to each sample using the IAMWMBufferPassCallback method described previously. To encode a file that preserves the original interlace settings, follow these steps:
- Implement a class that supports IAMWMBufferPassCallback and write a Notify function that sets the interlace flags for each sample. This function will be called by the WM ASF Writer before it processes each sample.
// Set to WM_CT_TOP_FIELD_FIRST if that is your format. BYTE flag = WM_CT_INTERLACED | WM_CT_BOTTOM_FIELD_FIRST; HRESULT hr = pNSSBuffer3->SetProperty(WM_SampleExtensionGUID_ContentType, (void*) &flag, WM_SampleExtension_ContentType_Size);
- Set the data unit extensions on the profile before you pass the profile to the filter.
hr = pWMStreamConfig2->AddDataUnitExtension( WM_SampleExtensionGUID_ContentType, WM_SampleExtension_ContentType_Size, NULL, 0 );
- After you configure the filter with the profile, obtain the IWMWriterAdvanced2 interface from the WM ASF Writer and call the SetInputSettings method.
// Must do this first.
hr = pConfigAsfWriter2->ConfigureFilterUsingProfile(pProfile);
CComPtr<IServiceProvider> pProvider; CComPtr<IWMWriterAdvanced2> pWMWA2; hr = pConfigAsfWriter2->QueryInterface( __uuidof(IServiceProvider), (void**)&pProvider); if (SUCCEEDED(hr)) { hr = pProvider->QueryService(IID_IWMWriterAdvanced2, IID_IWMWriterAdvanced2, (void**)&pWMWA2); } BOOL pValue = TRUE; // Set the first parameter to your actual input number. hr = pWMWA2->SetInputSetting(0, g_wszInterlacedCoding, WMT_TYPE_BOOL, (BYTE*) &pValue, sizeof(WMT_TYPE_BOOL));
See Also