WinUI uygulamasında MediaCapture için biçim, çözünürlük ve kare hızı ayarlama

Bu makalede, kamera önizleme akışının ve yakalanan fotoğrafların ve videoların çözünürlüğünü ve kare hızını ayarlamak için IMediaEncodingProperties arabiriminin nasıl kullanılacağı gösterilmektedir. Ayrıca önizleme akışının en boy oranının yakalanan medyayla eşleştiğinden nasıl emin olunduğunu da gösterir.

Kamera profilleri, kameranın akış özelliklerini bulmak ve ayarlamak için daha basit, daha üst düzey bir mekanizma sunar, ancak tüm cihazlar için desteklenmez. Daha fazla bilgi için bkz . Kamera profilleri.

Önizleme ve yakalama akışlarının bağımsız olup olmadığını belirleme

Bazı cihazlarda, hem önizleme hem de yakalama akışları için aynı donanım pini kullanılır. Bu cihazlarda, bir cihazda biçim, çözünürlük ve kare hızı gibi kodlama özelliklerini ayarlamak her ikisini de etkiler. Yakalama ve önizleme için farklı donanım pin'leri kullanan cihazlarda özellikler her akış için bağımsız olarak ayarlanabilir. Önizleme ve yakalama akışlarının bağımsız olup olmadığını belirlemek için aşağıdaki kodu kullanın. Bu örnek, akışların paylaşılması veya bağımsız olması durumunda uygulamanın davranışını değiştirmek için kullanılabilecek boole genel değişkenini ayarlar.

if (m_mediaCapture.MediaCaptureSettings.VideoDeviceCharacteristic == VideoDeviceCharacteristic.AllStreamsIdentical ||
    m_mediaCapture.MediaCaptureSettings.VideoDeviceCharacteristic == VideoDeviceCharacteristic.PreviewRecordStreamsIdentical)
{
    m_captureAndPreviewStreamsIdentical = true;
}

Medya kodlama özellikleri yardımcı sınıfı

IMediaEncodingProperties arabiriminin işlevselliğini sarmalayan basit bir yardımcı sınıfı oluşturmak, belirli ölçütleri karşılayan bir dizi kodlama özelliği seçmeyi kolaylaştırır. Bu yardımcı sınıfı, kodlama özellikleri özelliğinin aşağıdaki davranışı nedeniyle özellikle yararlıdır:

Uyarı

VideoDeviceController.GetAvailableMediaStreamProperties yöntemi, VideoKayıt veya Fotoğraf gibi MediaStreamType numaralandırmasının bir üyesini alır ve yakalanan fotoğraf veya videonun çözünürlüğü gibi akış kodlama ayarlarını aktaran ImageEncodingProperties veya VideoEncodingProperties nesnelerinin listesini döndürür. GetAvailableMediaStreamProperties çağrısının sonuçları, hangi MediaStreamType değerinin belirtildiğine bakılmaksızın ImageEncodingProperties veya VideoEncodingProperties içerebilir. Bu nedenle, özellik değerlerinden herhangi birine erişmeye çalışmadan önce her zaman döndürülen her değerin türünü denetlemeniz ve uygun türe dönüştürmeniz gerekir.

Aşağıda tanımlanan yardımcı sınıfı ImageEncodingProperties veya VideoEncodingProperties için tür denetimini ve atamayı işler, böylece uygulama kodunuzun iki türü ayırt etmesine gerek yoktur. Buna ek olarak, yardımcı sınıf, özelliklerin en boy oranı, kare hızı (yalnızca video kodlama özellikleri için) ve kodlama özelliklerini kullanıcı arabiriminizde görüntülemeyi kolaylaştıran kolay bir isim sunar.

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;
    }

}

Kullanılabilir akış özelliklerinin listesini alma

Uygulamanızın MediaCapture nesnesi için VideoDeviceController'ı alıp GetAvailableMediaStreamProperties çağrısı yaparak ve MediaStreamType değerlerinden birini(VideoPreview, VideoRecord veya Photo) geçirerek yakalama cihazının kullanılabilir akış özelliklerinin listesini alın. Bu örnekte, daha önce bu makalede tanımlanan StreamPropertiesHelper nesnelerinin listesi, GetAvailableMediaStreamProperties'ten döndürülen IMediaEncodingProperties değerlerinin her biri için oluşturulur. Bu örnek, döndürülen özellikleri önce çözümlemeye ve ardından kare hızına göre sıralar.

Uygulamanızın belirli çözünürlük veya kare hızı gereksinimleri varsa, program aracılığıyla bir dizi medya kodlama özelliği seçebilirsiniz. Tipik bir kamera uygulaması bunun yerine kullanıcı arabirimindeki kullanılabilir özelliklerin listesini kullanıma sunar ve kullanıcının istediği ayarları seçmesine izin verir. Listedeki StreamPropertiesHelper nesneleri listesindeki her öğe için bir ComboBoxItem oluşturulur. İçerik, yardımcı sınıf tarafından döndürülen dostane ada ayarlanır ve etiket, daha sonra ilişkili kodlama özelliklerini almak için kullanılabilmesi amacıyla yardımcı sınıfın kendisine atanır. Her ComboBoxItem daha sonra kullanıcı arabiriminde tanımlanan bir ComboBox'a eklenir.

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);
    }
}

İstenen akış özelliklerini ayarlama

Fotoğraf, video veya önizleme özelliklerinin ayarlanıp ayarlanmayacağını belirten MediaStreamType değerini geçirerek SetMediaStreamPropertiesAsync çağrısı yaparak video cihaz denetleyicisine istediğiniz kodlama özelliklerini kullanmasını söyleyin. Bu örnekte, medya akışı özelliklerinin seçili öğeden etiket özelliğinden alındığı önceki bölümde yer alan örnekte doldurulan ComboBox kullanılır.

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);
    }
}

Medya akışı özelliklerini değiştirmek için uygulamanızın yakalama cihazı için özel denetime sahip olması gerektiğini unutmayın.

Önizleme ve yakalama akışlarının en boy oranını eşleştirin

Tipik bir kamera uygulaması, kullanıcının video veya fotoğraf yakalama çözünürlüğünü seçmesi için kullanıcı arabirimi sağlar ancak önizleme çözünürlüğünü program aracılığıyla ayarlar. Uygulamanız için en iyi önizleme akışı çözünürlüğünü seçmek için birkaç farklı strateji vardır:

  • Kullanılabilir en yüksek önizleme çözünürlüğünü seçerek kullanıcı arabirimi çerçevesinin önizleme için gerekli ölçeklendirmeyi gerçekleştirmesini sağlayın.

  • Yakalama çözünürlüğüne en yakın önizleme çözünürlüğünü seçerek önizlemenin yakalanan son medyaya en yakın gösterimi görüntülemesini sağlayın.

  • CaptureElement boyutuna en yakın önizleme çözünürlüğünü seçin, böylece gereğinden fazla piksel önizleme akış hattından geçmesin.

Uyarı

Bazı cihazlarda kameranın önizleme akışı ve yakalama akışı için farklı bir en boy oranı ayarlamak mümkündür. Bu uyumsuzluğun neden olduğu çerçeve kırpması, yakalanan medyada içeriğin önizlemede görünmemesiyle sonuçlanabilir ve bu da olumsuz bir kullanıcı deneyimine neden olabilir. Önizleme ve yakalama akışları için küçük bir tolerans penceresinde aynı en boy oranını kullanmanız kesinlikle önerilir. En boy oranı yakından eşleştikçe yakalama ve önizleme için tamamen farklı çözünürlüklerin etkinleştirilmesi sorun değildir.

Fotoğraf veya video yakalama akışlarının önizleme akışının en boy oranıyla eşleştiğinden emin olmak için bu örnekte VideoDeviceController.GetMediaStreamProperties çağrılır ve önizleme akışı için geçerli akış özelliklerini istemek üzere VideoPreview sabit listesi değerini geçirir. Bundan sonra, önizleme akışıyla tam olarak aynı olmayan en boy oranlarını yakın oldukları sürece ekleyebilmemiz için küçük bir en boy oranı tolerans penceresi tanımlanır. Ardından, en boy oranının önizleme akışının tanımlı tolerans aralığı içinde olduğu StreamPropertiesHelper nesneleri seçilir.

// 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);
}

SnippetEşleşmeÖnizlemeEnBoyOranı