이 문서에서는 IMediaEncodingProperties 인터페이스를 사용하여 카메라 미리 보기 스트림 및 캡처된 사진 및 비디오의 해상도 및 프레임 속도를 설정하는 방법을 보여 줍니다. 또한 미리 보기 스트림의 가로 세로 비율이 캡처된 미디어의 가로 세로 비율과 일치하는지 확인하는 방법도 보여줍니다.
카메라 프로필은 카메라의 스트림 속성을 검색하고 설정하기 위한 더 간단하고 높은 수준의 메커니즘을 제공하지만 모든 디바이스에서 지원되지는 않습니다. 자세한 내용은 카메라 프로필을 참조하세요.
미리 보기 및 캡처 스트림이 독립적인지 확인
일부 디바이스에서는 미리 보기 및 캡처 스트림 모두에 동일한 하드웨어 핀이 사용됩니다. 이러한 디바이스에서 형식, 해상도 및 프레임 속도와 같은 인코딩 속성을 설정하면 둘 다에 영향을 줍니다. 캡처 및 미리 보기에 서로 다른 하드웨어 핀을 사용하는 디바이스에서는 각 스트림에 대해 독립적으로 속성을 설정할 수 있습니다. 다음 코드를 사용하여 미리 보기 및 캡처 스트림이 독립적인지 확인합니다. 다음은 스트림이 공유되거나 독립적인 경우 앱의 동작을 전환하는 데 사용할 수 있는 부울 전역 변수를 설정하는 예제입니다.
if (m_mediaCapture.MediaCaptureSettings.VideoDeviceCharacteristic == VideoDeviceCharacteristic.AllStreamsIdentical ||
m_mediaCapture.MediaCaptureSettings.VideoDeviceCharacteristic == VideoDeviceCharacteristic.PreviewRecordStreamsIdentical)
{
m_captureAndPreviewStreamsIdentical = true;
}
미디어 인코딩 속성 도우미 클래스
IMediaEncodingProperties 인터페이스의 기능을 래핑하는 간단한 도우미 클래스를 만들면 특정 조건을 충족하는 인코딩 속성 집합을 더 쉽게 선택할 수 있습니다. 이 도우미 클래스는 인코딩 속성 기능의 다음 동작으로 인해 특히 유용합니다.
비고
VideoDeviceController.GetAvailableMediaStreamProperties 메서드는 VideoRecord 또는 Photo와 같은 MediaStreamType 열거형의 멤버를 사용하고 캡처한 사진 또는 비디오의 해상도와 같은 스트림 인코딩 설정을 전달하는 ImageEncodingProperties 또는 VideoEncodingProperties 개체의 목록을 반환합니다. GetAvailableMediaStreamProperties를 호출한 결과에는 지정된 MediaStreamType 값에 관계없이 ImageEncodingProperties 또는 VideoEncodingProperties가 포함될 수 있습니다. 이러한 이유로 항상 반환된 각 값의 형식을 확인하고 속성 값에 액세스하기 전에 해당 형식으로 캐스팅해야 합니다.
아래에 정의된 도우미 클래스는 앱 코드가 두 형식을 구분할 필요가 없도록 ImageEncodingProperties 또는 VideoEncodingProperties 에 대한 형식 검사 및 캐스팅을 처리합니다. 이 외에도 도우미 클래스는 속성의 가로 세로 비율, 프레임 속도(비디오 인코딩 속성에만 해당) 및 UI에서 인코딩 속성을 쉽게 표시할 수 있는 친숙한 이름을 노출합니다.
class StreamPropertiesHelper
{
private IMediaEncodingProperties _properties;
public StreamPropertiesHelper(IMediaEncodingProperties properties)
{
if (properties == null)
{
throw new ArgumentNullException(nameof(properties));
}
// This helper class only uses ImageEncodingProperties or VideoEncodingProperties
if (!(properties is ImageEncodingProperties) && !(properties is VideoEncodingProperties))
{
throw new ArgumentException("Argument is of the wrong type. Required: " + typeof(ImageEncodingProperties).Name
+ " or " + typeof(VideoEncodingProperties).Name + ".", nameof(properties));
}
// Store the actual instance of the IMediaEncodingProperties for setting them later
_properties = properties;
}
public uint Width
{
get
{
if (_properties is ImageEncodingProperties)
{
return (_properties as ImageEncodingProperties).Width;
}
else if (_properties is VideoEncodingProperties)
{
return (_properties as VideoEncodingProperties).Width;
}
return 0;
}
}
public uint Height
{
get
{
if (_properties is ImageEncodingProperties)
{
return (_properties as ImageEncodingProperties).Height;
}
else if (_properties is VideoEncodingProperties)
{
return (_properties as VideoEncodingProperties).Height;
}
return 0;
}
}
public uint FrameRate
{
get
{
if (_properties is VideoEncodingProperties)
{
if ((_properties as VideoEncodingProperties).FrameRate.Denominator != 0)
{
return (_properties as VideoEncodingProperties).FrameRate.Numerator /
(_properties as VideoEncodingProperties).FrameRate.Denominator;
}
}
return 0;
}
}
public double AspectRatio
{
get { return Math.Round((Height != 0) ? (Width / (double)Height) : double.NaN, 2); }
}
public IMediaEncodingProperties EncodingProperties
{
get { return _properties; }
}
public string GetFriendlyName(bool showFrameRate = true)
{
if (_properties is ImageEncodingProperties ||
!showFrameRate)
{
return Width + "x" + Height + " [" + AspectRatio + "] " + _properties.Subtype;
}
else if (_properties is VideoEncodingProperties)
{
return Width + "x" + Height + " [" + AspectRatio + "] " + FrameRate + "FPS " + _properties.Subtype;
}
return String.Empty;
}
}
사용 가능한 스트림 속성 목록 가져오기
앱의 MediaCapture 개체에 대한 VideoDeviceController를 가져오고 GetAvailableMediaStreamProperties를 호출하고 MediaStreamType 값, VideoPreview, VideoRecord 또는 Photo 중 하나를 전달하여 캡처 디바이스에 사용할 수 있는 스트림 속성 목록을 가져옵니다. 이 예제에서는 이 문서의 앞에 정의된 StreamPropertiesHelper 개체 목록이 GetAvailableMediaStreamProperties에서 반환된 각 IMediaEncodingProperties 값에 대해 만들어집니다. 다음은 해상도를 기준으로 반환된 속성을 정렬한 다음 프레임 속도에 따라 정렬하는 예제입니다.
앱에 특정 해상도 또는 프레임 속도 요구 사항이 있는 경우 프로그래밍 방식으로 미디어 인코딩 속성 집합을 선택할 수 있습니다. 일반적인 카메라 앱은 대신 UI에서 사용 가능한 속성 목록을 노출하고 사용자가 원하는 설정을 선택할 수 있도록 합니다. 목록의 StreamPropertiesHelper 개체 목록에 있는 각 항목에 대해 ComboBoxItem이 만들어집니다. 콘텐츠는 도우미 클래스에서 반환된 친숙한 이름으로 설정되고 태그는 도우미 클래스 자체로 설정되므로 나중에 연결된 인코딩 속성을 검색하는 데 사용할 수 있습니다. 그런 다음 각 ComboBoxItem 이 UI에 정의된 ComboBox 에 추가됩니다.
private void bGetStreamProperties_Click(object sender, RoutedEventArgs e)
{
// Query all properties of the specified stream type
IEnumerable<StreamPropertiesHelper> allStreamProperties =
m_mediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoRecord).Select(x => new StreamPropertiesHelper(x));
// Order them by resolution then frame rate
allStreamProperties = allStreamProperties.OrderByDescending(x => x.Height * x.Width).ThenByDescending(x => x.FrameRate);
// Populate the combo box with the entries
foreach (var property in allStreamProperties)
{
ComboBoxItem comboBoxItem = new ComboBoxItem();
comboBoxItem.Content = property.GetFriendlyName();
comboBoxItem.Tag = property;
cbStreamProperties.Items.Add(comboBoxItem);
}
}
원하는 스트림 속성 설정
SetMediaStreamPropertiesAsync를 호출하고 사진, 비디오 또는 미리 보기 속성을 설정해야 하는지 여부를 나타내는 MediaStreamType 값을 전달하여 원하는 인코딩 속성을 사용하도록 비디오 디바이스 컨트롤러에 지시합니다. 이 예제에서는 이전 섹션의 예제에서 채워진 ComboBox 를 사용합니다. 여기서 미디어 스트림 속성은 선택한 항목의 태그 속성에서 검색됩니다.
private async void bSetStreamProperties_Click(object sender, RoutedEventArgs e)
{
if (m_exclusiveCameraAccess)
{
var selectedItem = cbStreamProperties.SelectedItem as ComboBoxItem;
var encodingProperties = (selectedItem.Tag as StreamPropertiesHelper).EncodingProperties;
await m_mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoPreview, encodingProperties);
}
}
미디어 스트림 속성을 변경하려면 앱이 캡처 디바이스를 단독으로 제어해야 합니다.
미리 보기 및 캡처 스트림의 가로 세로 비율 일치
일반적인 카메라 앱은 사용자가 비디오 또는 사진 캡처 해상도를 선택할 수 있는 UI를 제공하지만 프로그래밍 방식으로 미리 보기 해상도를 설정합니다. 앱에 가장 적합한 미리 보기 스트림 해상도를 선택하기 위한 몇 가지 전략이 있습니다.
사용 가능한 가장 높은 미리 보기 해상도를 선택하여 UI 프레임워크가 미리 보기의 필요한 크기 조정을 수행할 수 있도록 합니다.
미리 보기가 최종 캡처된 미디어에 가장 가까운 표현을 표시하도록 캡처 해상도에 가장 가까운 미리 보기 해상도를 선택합니다.
필요한 것보다 더 이상 픽셀이 미리 보기 스트림 파이프라인을 통과하지 않도록 CaptureElement 의 크기에 가장 가까운 미리 보기 해상도를 선택합니다.
비고
일부 디바이스에서는 카메라의 미리 보기 스트림 및 캡처 스트림에 대해 다른 가로 세로 비율을 설정할 수 있습니다. 이 불일치로 인한 프레임 자르기로 인해 미리 보기에 표시되지 않은 캡처된 미디어에 콘텐츠가 표시되어 부정적인 사용자 환경이 발생할 수 있습니다. 미리 보기 및 캡처 스트림에 대해 작은 허용 범위 내에서 동일한 가로 세로 비율을 사용하는 것이 좋습니다. 가로 세로 비율이 밀접하게 일치하는 한 캡처 및 미리 보기에 대해 완전히 다른 해상도를 사용하도록 설정하는 것은 괜찮습니다.
사진 또는 비디오 캡처 스트림이 미리 보기 스트림의 가로 세로 비율과 일치하는지 확인하기 위해 이 예제에서는 VideoDeviceController.GetMediaStreamProperties 를 호출하고 VideoPreview 열거형 값을 전달하여 미리 보기 스트림에 대한 현재 스트림 속성을 요청합니다. 다음으로, 작은 가로 세로 비율 허용 범위가 정의되어, 미리 보기 스트림과 정확히 일치하지 않더라도 가까운 비율을 포함할 수 있게 합니다. 다음으로 가로 세로 비율이 미리 보기 스트림의 정의된 허용 범위 내에 있는 StreamPropertiesHelper 개체가 선택됩니다.
// Query all properties of the specified stream type
IEnumerable<StreamPropertiesHelper> allVideoProperties =
m_mediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoRecord).Select(x => new StreamPropertiesHelper(x));
// Query the current preview settings
StreamPropertiesHelper previewProperties = new StreamPropertiesHelper(m_mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview));
// Get all formats that have the same-ish aspect ratio as the preview
// Allow for some tolerance in the aspect ratio comparison
const double ASPECT_RATIO_TOLERANCE = 0.015;
var matchingFormats = allVideoProperties.Where(x => Math.Abs(x.AspectRatio - previewProperties.AspectRatio) < ASPECT_RATIO_TOLERANCE);
// Order them by resolution then frame rate
allVideoProperties = matchingFormats.OrderByDescending(x => x.Height * x.Width).ThenByDescending(x => x.FrameRate);
// Clear out old entries and populate the video combo box with new matching entries
cbStreamProperties.Items.Clear();
foreach (var property in allVideoProperties)
{
ComboBoxItem comboBoxItem = new ComboBoxItem();
comboBoxItem.Content = property.GetFriendlyName();
comboBoxItem.Tag = property;
cbStreamProperties.Items.Add(comboBoxItem);
}
SnippetMatchPreviewAspectRatio (스니펫 일치 미리보기 종횡비)
Windows developer