我运行以下行来预览我的网络摄像头:
...
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() - Method之前,一切正常。不幸的是,我只收到一条不太有用的错误消息:“请求的操作中发生意外错误。” 我试图在我的本地机器和模拟器上运行代码。有谁知道我做错了什么?
环境是Windows 8.1,Caliburn.Micro,ZXing.Net 0.12.0.0,VS 2013
答案 0 :(得分: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);
}
}