Discover and select camera capabilities with camera profiles

This article discusses how to use camera profiles to discover and manage the capabilities of different video capture devices. This includes tasks such as selecting profiles that support specific resolutions or frame rates, profiles that support simultaneous access to multiple cameras, and profiles that support HDR.

Note

This article builds on concepts and code discussed in Basic photo, video, and audio capture with MediaCapture, which describes the steps for implementing basic photo and video capture. It is recommended that you familiarize yourself with the basic media capture pattern in that article before moving on to more advanced capture scenarios. The code in this article assumes that your app already has an instance of MediaCapture that has been properly initialized.

 

About camera profiles

Cameras on different devices support different capabilities including the set of supported capture resolutions, frame rate for video captures, and whether HDR or variable frame rate captures are supported. The Universal Windows Platform (UWP) media capture framework stores this set of capabilities in a MediaCaptureVideoProfileMediaDescription. A camera profile, represented by a MediaCaptureVideoProfile object, has three collections of media descriptions; one for photo capture, one for video capture, and another for video preview.

Before initializing your MediaCapture object, you can query the capture devices on the current device to see what profiles are supported. When you select a supported profile, you know that the capture device supports all of the capabilities in the profile's media descriptions. This eliminates the need for a trial and error approach to determining which combinations of capabilities are supported on a particular device.

var mediaInitSettings = new MediaCaptureInitializationSettings { VideoDeviceId = cameraDevice.Id };

The code examples in this article replace this minimal initialization with the discovery of camera profiles supporting various capabilities, which are then used to initialize the media capture device.

Find a video device that supports camera profiles

Before searching for supported camera profiles, you should find a capture device that supports the use of camera profiles. The GetVideoProfileSupportedDeviceIdAsync helper method defined in the example below uses the DeviceInformation.FindAllAsync method to retrieve a list of all available video capture devices. It loops through all of the devices in the list, calling the static method, IsVideoProfileSupported, for each device to see if it supports video profiles. Also, the EnclosureLocation.Panel property for each device, allowing you to specify whether you want a camera on the front or back of the device.

If a device that supports camera profiles is found on the specified panel, the Id value, containing the device's ID string, is returned.

public async Task<string> GetVideoProfileSupportedDeviceIdAsync(Windows.Devices.Enumeration.Panel panel)
{
    string deviceId = string.Empty;

    // Finds all video capture devices
    DeviceInformationCollection devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
    
    foreach (var device in devices)
    {
        // Check if the device on the requested panel supports Video Profile
        if (MediaCapture.IsVideoProfileSupported(device.Id) && device.EnclosureLocation.Panel == panel)
        {
            // We've located a device that supports Video Profiles on expected panel
            deviceId = device.Id;
            break;
        }
    }

    return deviceId;
}

If the device ID returned from the GetVideoProfileSupportedDeviceIdAsync helper method is null or an empty string, there is no device on the specified panel that supports camera profiles. In this case, you should initialize your media capture device without using profiles.

string videoDeviceId = await GetVideoProfileSupportedDeviceIdAsync(Windows.Devices.Enumeration.Panel.Back);

if (string.IsNullOrEmpty(videoDeviceId))
{
    // No devices on the specified panel support video profiles. .
    return;
}

Select a profile based on supported resolution and frame rate

To select a profile with particular capabilities, such as with the ability to achieve a particular resolution and frame rate, you should first call the helper method defined above to get the ID of a capture device that supports using camera profiles.

Create a new MediaCaptureInitializationSettings object, passing in the selected device ID. Next, call the static method MediaCapture.FindAllVideoProfiles to get a list of all camera profiles supported by the device.

This example uses a Linq query method, included in the using System.Linq namespace, to select a profile that contains a SupportedRecordMediaDescription object where the Width, Height, and FrameRate properties match the requested values. If a match is found, VideoProfile and RecordMediaDescription of the MediaCaptureInitializationSettings are set to the values from the anonymous type returned from the Linq query. If no match is found, the default profile is used.


var mediaInitSettings = new MediaCaptureInitializationSettings { VideoDeviceId = videoDeviceId };

IReadOnlyList<MediaCaptureVideoProfile> profiles = MediaCapture.FindAllVideoProfiles(videoDeviceId);

var match = (from profile in profiles
             from desc in profile.SupportedRecordMediaDescription
             where desc.Width == 640 && desc.Height == 480 && Math.Round(desc.FrameRate) == 30
             select new { profile, desc }).FirstOrDefault();

if (match != null)
{
    mediaInitSettings.VideoProfile = match.profile;
    mediaInitSettings.RecordMediaDescription = match.desc;
}
else
{
    // Could not locate a WVGA 30FPS profile, use default video recording profile
    mediaInitSettings.VideoProfile = profiles[0];
}

After you populate the MediaCaptureInitializationSettings with your desired camera profile, you simply call InitializeAsync on your media capture object to configure it to the desired profile.

await _mediaCapture.InitializeAsync(mediaInitSettings);

Use media frame source groups to get profiles

Starting with Windows 10, version 1803, you can use the MediaFrameSourceGroup class to get camera profiles with specific capabilities before initializing the MediaCapture object. Frame source groups allow device manufacturers to represent groups of sensors or capture capabilities as a single virtual device. This enables computational photography scenarios such as using depth and color cameras together, but can also be used to select camera profiles for simple capture scenarios. For more information on using MediaFrameSourceGroup, see Process media frames with MediaFrameReader.

The example method below shows how to use MediaFrameSourceGroup objects to find a camera profile that supports a known video profile, such as one that supports HDR or variable photo sequence. First, call MediaFrameSourceGroup.FindAllAsync to get a list of all media frame source groups available on the current device. Loop through each source group and call MediaCapture.FindKnownVideoProfiles to get a list of all of the video profiles for the current source group that support the specified profile, in this case HDR with WCG photo. If a profile that meets the criteria is found, create a new MediaCaptureInitializationSettings object and set the VideoProfile to the select profile and the VideoDeviceId to the Id property of the current media frame source group. So, for example, you could pass the value KnownVideoProfile.HdrWithWcgVideo into this method to get media capture settings that support HDR video. Pass KnownVideoProfile.VariablePhotoSequence to get settings that support variable photo sequence.

private async Task<MediaCaptureInitializationSettings> GetKnownVideoProfile(KnownVideoProfile knownVideoProfile)
{
    IReadOnlyList<MediaFrameSourceGroup> sourceGroups = await MediaFrameSourceGroup.FindAllAsync();
    MediaCaptureInitializationSettings settings = null;

    foreach (MediaFrameSourceGroup sg in sourceGroups)
    {
        // Find a device that support VariablePhotoSequence
        IReadOnlyList<MediaCaptureVideoProfile> profileList = MediaCapture.FindKnownVideoProfiles(
                                      sg.Id,
                                      knownVideoProfile); // e.g. KnownVideoProfile.HdrWithWcgVideo

        if (profileList.Count > 0)
        {
            settings = new MediaCaptureInitializationSettings();
            settings.VideoProfile = profileList[0];
            settings.VideoDeviceId = sg.Id;
            break;
        }
    }
    return settings;

    
}

Use known profiles to find a profile that supports HDR video (legacy technique)

Note

The APIs described in this section are deprecated starting with Windows 10, version 1803. See the previous section, Use media frame source groups to get profiles.

Selecting a profile that supports HDR begins like the other scenarios. Create a MediaCaptureInitializationSettings and a string to hold the capture device ID. Add a boolean variable that will track whether HDR video is supported.

MediaCaptureInitializationSettings mediaInitSettings = new MediaCaptureInitializationSettings();
string videoDeviceId = string.Empty;
bool HdrVideoSupported = false;

Use the GetVideoProfileSupportedDeviceIdAsync helper method defined above to get the device ID for a capture device that supports camera profiles.

// Select the first video capture device found on the back of the device
videoDeviceId = await GetVideoProfileSupportedDeviceIdAsync(Windows.Devices.Enumeration.Panel.Back);

if (string.IsNullOrEmpty(videoDeviceId))
{
    // No devices on the specified panel support video profiles. .
    return;
}

The static method MediaCapture.FindKnownVideoProfiles returns the camera profiles supported by the specified device that is categorized by the specified KnownVideoProfile value. For this scenario, the VideoRecording value is specified to limit the returned camera profiles to ones that support video recording.

Loop through the returned list of camera profiles. For each camera profile, loop through each VideoProfileMediaDescription in the profile checking to see if the IsHdrVideoSupported property is true. After a suitable media description is found, break out of the loop and assign the profile and description objects to the MediaCaptureInitializationSettings object.

IReadOnlyList<MediaCaptureVideoProfile> profiles =
    MediaCapture.FindKnownVideoProfiles(videoDeviceId, KnownVideoProfile.VideoRecording);

// Walk through available profiles, look for first profile with HDR supported Video Profile
foreach (MediaCaptureVideoProfile profile in profiles)
{
    IReadOnlyList<MediaCaptureVideoProfileMediaDescription> recordMediaDescription =
        profile.SupportedRecordMediaDescription;
    foreach (MediaCaptureVideoProfileMediaDescription videoProfileMediaDescription in recordMediaDescription)
    {
        if (videoProfileMediaDescription.IsHdrVideoSupported)
        {
            // We've located the profile and description for HDR Video, set profile and flag
            mediaInitSettings.VideoProfile = profile;
            mediaInitSettings.RecordMediaDescription = videoProfileMediaDescription;
            HdrVideoSupported = true;
            break;
        }
    }

    if (HdrVideoSupported)
    {
        // Profile with HDR support found. Stop looking.
        break;
    }
}

Determine if a device supports simultaneous photo and video capture

Many devices support capturing photos and video simultaneously. To determine if a capture device supports this, call MediaCapture.FindAllVideoProfiles to get all of the camera profiles supported by the device. Use a link query to find a profile that has at least one entry for both SupportedPhotoMediaDescription and SupportedRecordMediaDescription which means that the profile supports simultaneous capture.

var simultaneousPhotoAndVideoSupported = false;

IReadOnlyList<MediaCaptureVideoProfile> profiles = MediaCapture.FindAllVideoProfiles(videoDeviceId);

var match = (from profile in profiles
             where profile.SupportedPhotoMediaDescription.Any() &&
             profile.SupportedRecordMediaDescription.Any()
             select profile).FirstOrDefault();

if (match != null)
{
    // Simultaneous photo and video supported
    simultaneousPhotoAndVideoSupported = true;
}
else
{
    // Simultaneous photo and video not supported
    simultaneousPhotoAndVideoSupported = false;
}

You can refine this query to look for profiles that support specific resolutions or other capabilities in addition to simultaneous video record. You can also use the MediaCapture.FindKnownVideoProfiles and specify the BalancedVideoAndPhoto value to retrieve profiles that support simultaneous capture, but querying all profiles will provide more complete results.