Fundamentals of Audio and Video Programming for Games (Pro-Developer)
In video production, a ProcAmp , or processing amplifier , is a circuit that modifies a video signal to adjust qualities such as image brightness, contrast, or saturation. Some graphics cards are able to make the same types of adjustment using the graphics processing unit (GPU). If your graphics card supports this feature, you can control the image settings through the VMR s IVMRMixerControl9 interface. This feature is demonstrated in the Amplify sample located in the AVBook\bin directory. (See Plate 15.)
Checking for ProcAmp Support
First, check for ProcAmp support on the driver. There are four ProcAmp properties ” brightness, contrast, hue, and saturation ” and the driver may support all, some, or none of them. The following code shows how to check for ProcAmp support.
// Get the ProcAmp settings from the VMR. VMR9ProcAmpControl ProcAmp; ZeroMemory(&ProcAmp, sizeof(VMR9ProcAmpControl)); ProcAmp.dwSize = sizeof(VMR9ProcAmpControl); m_pMixer->GetProcAmpControl(0, &ProcAmp); // Loop through all the properties to see which are supported. VMR9ProcAmpControlFlags ProcAmpFlags[] = { ProcAmpControl9_Brightness, ProcAmpControl9_Contrast, ProcAmpControl9_Hue, ProcAmpControl9_Saturation }; for (int i = 0; i < NUM_PROCAMP_CONTROLS; i++) { VMR9ProcAmpControlFlags prop = ProcAmpFlags[i]; if ((ProcAmp.dwFlags & prop) == prop) { // This ProcAmp property is supported. // Get the current setting for this property. float val; switch (prop) { case ProcAmpControl9_Brightness: val = ProcAmp.Brightness; break; case ProcAmpControl9_Contrast: val = ProcAmp.Contrast; break; case ProcAmpControl9_Hue: val = ProcAmp.Hue; break; case ProcAmpControl9_Saturation: val = ProcAmp.Saturation; break; } // Get the allowable range of values for this property. VMR9ProcAmpControlRange range; ZeroMemory(&range, sizeof(VMR9ProcAmpControlRange)); range.dwSize = sizeof(VMR9ProcAmpControlRange); range.dwProperty = prop; m_pMixer->GetProcAmpControlRange(0, &range); } }
To get the current ProcAmp settings, call IVMRMixerControl9::GetProcAmpControl and pass in a pointer to the VMR9ProcAmpControl structure. You must set the structure s dwSize member equal to the structure size , as shown in the previous code example. Zero out the other structure members . When the method returns, the dwFlags field contains a bitwise OR of all the ProcAmp properties supported by the graphics card (if any). Test for each property using a bitwise AND. The VMR9ProcAmpControl structure also contains a separate field for each ProcAmp value. If the card supports a property, the corresponding field in the structure contains the current value. ProcAmp values are always floats.
The range of values for each property can vary depending on the driver. To get this information, call the GetProcAmpControlRange method. Pass in a pointer to the VMR9ProcAmpControlRange structure, setting the structure s dwSize member equal to the structure size. Specify the property that you are querying in the dwProperty member. When the method returns, the structure contains the minimum, maximum, and default values of the property.
The Amplify sample has a slider control for each ProcAmp property. The slider is enabled if the driver supports the property. Slider positions are expressed as LONG values, so the application maps the ProcAmp values (which are floats) into a range of 1 to 100, although some precision may be lost in the conversion.
Setting ProcAmp Values
To set ProcAmp properties, call the SetProcAmpControl method:
VMR9ProcAmpControl ProcAmp; ZeroMemory(&ProcAmp, sizeof(VMR9ProcAmpControl)); ProcAmp.dwSize = sizeof(VMR9ProcAmpControl); ProcAmp.dwFlags = prop; // This is the property we want to set. // Note: You can combine more than one property with a bitwise OR. // Set the value of the property. switch (prop) { case ProcAmpControl9_Brightness: ProcAmp.Brightness = val; break; case ProcAmpControl9_Contrast: ProcAmp.Contrast = val; break; case ProcAmpControl9_Hue: ProcAmp.Hue = val; break; case ProcAmpControl9_Saturation: ProcAmp.Saturation = val; break; } hr = m_pMixer->SetProcAmpControl(0, &ProcAmp);
Set the dwSize member of the VMR9ProcAmpControl structure equal to the structure size before calling the method. Use the dwFlags member to indicate which ProcAmp properties you are changing. The example shown here sets only one property, but you can set several properties at once by combining the flags with a bitwise OR. For each property, set the new value in the corresponding structure member.