5

次の行を実行して、Web カメラのプレビューを取得します。

...
public MediaCapture VideoCaptureSource { get; set; }
var cameras = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);

if (cameras.Count == 1)
{
  settings = new MediaCaptureInitializationSettings { VideoDeviceId = cameras[0].Id };
}
else
{
  settings = new MediaCaptureInitializationSettings { VideoDeviceId = cameras[1].Id };
}

await _mediaCapture.InitializeAsync(settings);
VideoCaptureSource = _mediaCapture;
await VideoCaptureSource.StartPreviewAsync();
...

ここに私のXAMLがあります:

<Canvas Width="640" Height="360">
  <CaptureElement Source="{Binding VideoCaptureSource}" Visibility="{Binding VideoCaptureVisibility}" Width="640" Height="360" />
  <Image Source="{Binding CaptureImageSource}" Visibility="{Binding CaptureImageVisibility, FallbackValue=Collapsed}" Width="640" Height="360" />
</Canvas>

StartPreviewAsyn() メソッドを呼び出すまで、すべて正常に動作します。残念ながら、「要求された操作で予期しないエラーが発生しました」というあまり役に立たないエラー メッセージしか表示されません。ローカル マシンとシミュレーターでコードを実行しようとしました。誰かが私が間違っていることを知っていますか?

環境は Windows 8.1、Caliburn.Micro、ZXing.Net 0.12.0.0、VS 2013

4

1 に答える 1

3

私は最近同じ問題に遭遇しました。正しい順序でプレビュー ストリームを初期化、設定、および開始する必要があるため、ビデオ ソースのバインドは非常に難しいようです。添付プロパティを使用して問題を修正しました。

/// <summary>
/// This utility class provides an attached property that enables us to
/// bind the source of a <see cref="CaptureElement"/>.
/// </summary>
public static class VideoSourceBinding {

    public static MediaCapture GetVideoSource(DependencyObject obj) {
        return (MediaCapture) obj.GetValue(VideoSourceProperty);
    }

    public static void SetVideoSource(DependencyObject obj,
            MediaCapture value) {
        obj.SetValue(VideoSourceProperty, value);
    }

    public static readonly DependencyProperty VideoSourceProperty
        = DependencyProperty.RegisterAttached("VideoSource",
        typeof(MediaCapture),
        typeof(VideoSourceBinding),
        new PropertyMetadata(null, onVideoSourcePropertyChanged));

    private static async void onVideoSourcePropertyChanged(
            DependencyObject d, DependencyPropertyChangedEventArgs e) {
        Debug.Assert(d is CaptureElement);
        Debug.Assert(e.Property == VideoSourceBinding.VideoSourceProperty);

        CaptureElement preview = d as CaptureElement;

        if (d != null) {
            if (preview.Source != null) {
                // If another camera was attached before, stop it.
                await preview.Source.StopPreviewAsync();
            }

            try {
                preview.Source = (MediaCapture) e.NewValue;
            } catch {
                // The property change occurred before the the video source
                // was properly initialised. In this case, we ignore the
                // change and wait for the source to fire the event again
                // once the initialisation was completed.
                // Important: The source must actually change in order for
                // the event to be fired (the attached property will detect
                // if the same object was re-set) and ignore this.
                preview.Source = null;
            }

            if (preview.Source != null) {
                // Start the preview stream.
                await preview.Source.StartPreviewAsync();
            }
        }
    }
}

ビデオ ソースは次のようにバインドされます。

<CaptureElement u:VideoSourceBinding.VideoSource="{Binding VideoCapture}" />

ビュー モデルで行う順序は重要であることに注意してください。

public class ViewModel : Screen {
    // Note: The sample uses a Caliburn Micro base class - this is, however, not
    // a requirement.

    public MediaCapture VideoCapture {
        get;
        private set;
    }

    /// <summary>
    /// Starts the video preview.
    /// </summary>
    /// <remarks>
    /// Call this method whenever it is necessary to (re-) start the preview, eg
    /// if the page is activated or if the settings have changed.
    /// </remarks>
    private async void startVideo() {
        var captureSettings = new MediaCaptureInitializationSettings() {
            StreamingCaptureMode = StreamingCaptureMode.Video
        };
        // Set a NEW MediaCapture! Do not re-use the old one, because the property 
        // change event of the attached property will not fire otherwise.
        this.VideoCapture = new MediaCapture();
        await this.videoCapture.InitializeAsync(captureSettings);
        // Notify the UI about a new video source AFTER the initialisation completed. It 
        // is important to await the initialisation here.
        this.NotifyOfPropertyChange(() => this.VideoCapture);
    }
}
于 2013-12-28T12:09:05.087 に答える