Microsoft UWP MediaPlayer Example throws Memory AccessViolationException - c#

The following code sample from Microsoft is causing an external exception when used against UWP version 1903 Build 18362 and Nuget package Win2d 1.25.0
The memory access violation happens on mediaPlayer.CopyFrameToVideoSurface(inputBitmap);
And it happens no matter what video the MediaPlayer is trying to play.
The example_video.mkv file in the Assets folder is the file sample_640x360.mkv from this video sample page. Ultimately I tried multiple file formats both local and streaming, and it didn't change the exception being thrown.
Also I tried locking the CanvasDevice as is seen by the CanvasLock which is commented out, but that also changed nothing.
The Fatal Exception Thrown:
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
MainPage.xaml.cs:
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
using Microsoft.Graphics.Canvas.UI.Xaml;
using System;
using Windows.Graphics.Display;
using Windows.Graphics.Imaging;
using Windows.Media.Core;
using Windows.Media.Playback;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace MediaPlayerTest
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
MediaPlayer mediaPlayer;
SoftwareBitmap frameServerDest;
CanvasImageSource canvasImageSource;
public MainPage()
{
this.InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
mediaPlayer = new MediaPlayer();
mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
mediaPlayer.VideoFrameAvailable += mediaPlayer_VideoFrameAvailable;
mediaPlayer.IsVideoFrameServerEnabled = true;
mediaPlayer.Play();
}
// FROM: https://learn.microsoft.com/en-us/windows/uwp/audio-video-camera/play-audio-and-video-with-mediaplayer#use-mediaplayer-in-frame-server-mode
private async void mediaPlayer_VideoFrameAvailable(MediaPlayer sender, object args)
{
CanvasDevice canvasDevice = CanvasDevice.GetSharedDevice();
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
if (frameServerDest == null)
{
// FrameServerImage in this example is a XAML image control
frameServerDest = new SoftwareBitmap(BitmapPixelFormat.Rgba8, (int)FrameServerImage.Width, (int)FrameServerImage.Height, BitmapAlphaMode.Ignore);
}
if (canvasImageSource == null)
{
canvasImageSource = new CanvasImageSource(canvasDevice, (int)FrameServerImage.Width, (int)FrameServerImage.Height, DisplayInformation.GetForCurrentView().LogicalDpi);//96);
FrameServerImage.Source = canvasImageSource;
}
using (CanvasBitmap inputBitmap = CanvasBitmap.CreateFromSoftwareBitmap(canvasDevice, frameServerDest))
using (CanvasDrawingSession ds = canvasImageSource.CreateDrawingSession(Windows.UI.Colors.Black))
{
// CanvasLock lk = canvasDevice.Lock();
mediaPlayer.CopyFrameToVideoSurface(inputBitmap);
// lk.Dispose();
var gaussianBlurEffect = new GaussianBlurEffect
{
Source = inputBitmap,
BlurAmount = 5f,
Optimization = EffectOptimization.Speed
};
ds.DrawImage(gaussianBlurEffect);
}
});
}
}
}
MainPage.xaml:
<Page
x:Class="MediaPlayerTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MediaPlayerTest"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Button Content="Play Video" FontSize="40" HorizontalAlignment="Left" Height="78" Margin="156,110,0,0" VerticalAlignment="Top" Width="288" Click="Button_Click"/>
<Image x:Name="FrameServerImage" Height="360" Width="640" Margin="156,246,704,0" VerticalAlignment="Top"/>
</Grid>
</Page>

Related

UWP: use 1 MediaSource for several Players

I have some uwp application, where several videos are played simultaneously. I thought it might be a good idea to use 1 media source to improve performance. But I'm not sure why this idea doesn't work.
MainPage.xaml:
<Page
x:Class="UWP_OneMediaSourceForSeveralPlayers.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UWP_OneMediaSourceForSeveralPlayers"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
Loaded="Page_Loaded">
<StackPanel Orientation="Vertical" Background="Yellow" Height="400" Width="200">
<MediaPlayerElement x:Name="Player1" Height="200" Width="200" />
<MediaPlayerElement x:Name="Player2" Height="200" Width="200" />
</StackPanel>
</Page>
MainPage.xaml.cs:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Media.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace UWP_OneMediaSourceForSeveralPlayers
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
var uri = new Uri(BaseUri, "/Assets/Videos/video.mp4");
var mediaSource = MediaSource.CreateFromUri(uri);
Player1.Source = mediaSource;
Player2.Source = mediaSource;
Player1.MediaPlayer.Play();
Player2.MediaPlayer.Play();
}
}
}
That's what I see:
So, looks like the first video is loaded. But not the second...
NOW question: why I can not use 1 media source for 2 players? How to make it work? Or do you have any other idea how to run the same file in several players?
P.S. creating 2 media sources from URI is not a good solution for me, because my app can have a lot (10+) videos running at the same time. If I create a media source for each player it will hurt performance.
So what you can actually do here is share a MediaPlayer between the two MediaPlayerElement instance.
private void Page_Loaded(object sender, RoutedEventArgs e)
{
var uri = new Uri(BaseUri, "/Assets/Videos/video.mp4");
var mediaSource = MediaSource.CreateFromUri(uri);
var player = new MediaPlayer
{
Source = new MediaPlaybackItem(mediaSource)
};
Player1.SetMediaPlayer(player);
Player2.SetMediaPlayer(player);
player.Play();
}
If you don't require the transport controls from MediaPlayerElement, it's probably better to use MediaPlayerPresenter instead.

XAML changing the source path of an svg

I'm trying to implement an application that requests weather data from OWM (OpenWeatherMap) and displays the temperature as well as an weather icon fitting the weather outside. OWM provides icon ids for the fitting icon. You can then access those icons over a specific web path. Displaying those icons in my app worked well. Because the icons provided by OWM have got a low resolution I decided to use vector graphics, that I saved in the application directory. Displaying those vector graphics directly using this code
<Image Source="Assets/WeatherIcons/01d.svg" Height="300" HorizontalAlignment="Right"/>
works just fine. But I want to adjust the used source depending on the, by OWM provided, icon id.
My Code at the moment looks like this:
MainPage.xaml:
<Page
x:Class="starting.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:starting"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="Black"
PointerPressed="WakeUp">
<StackPanel x:Name="WeatherInformation"
Visibility="Collapsed">
<Image x:Name="WeatherIcon"
Height="300"
HorizontalAlignment="Right"/>
<TextBlock Foreground="White"
TextAlignment="Center">
<Run x:Name="Temperature" FontSize="90"/>
<LineBreak/>
<Run x:Name="WeatherDescription" FontSize="50"/>
</TextBlock>
</StackPanel>
</Grid>
</Page>
MainPage.xaml.cs:
using System;
using System.Globalization;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media.Imaging;
namespace starting
{
public sealed partial class MainPage : Page
{
private DispatcherTimer modeTimer = new DispatcherTimer();
public MainPage()
{
this.InitializeComponent();
updateWeather(this, this);
modeTimer.Tick += new EventHandler<object>(Sleep);
modeTimer.Interval = new TimeSpan(0, 1, 0);
DispatcherTimer updateWeatherTimer = new DispatcherTimer();
updateWeatherTimer.Tick += new EventHandler<object>(updateWeather);
updateWeatherTimer.Interval= new TimeSpan(0, 30, 0);
updateWeatherTimer.Start();
}
private void updateWeather(object sender, object e)
{
WeatherApp.WeatherAPI myWeatherApi = new WeatherApp.WeatherAPI("Friedrichshafen,de");
OpenWeatherMapType.WeatherStream data = myWeatherApi.GetForecast();
WeatherIcon.Source = new BitmapImage(new Uri("ms-appx:///Assets/WeatherIcons/" + data.Weather[0].Icon + ".svg"));
Temperature.Text = Math.Round(data.Main.Temp).ToString() + "°C";
WeatherDescription.Text = data.Weather[0].Description;
}
private void Sleep(object sender, object e)
{
StandByTime.Visibility = Visibility.Visible;
ActiveTime.Visibility = Visibility.Collapsed;
WeatherInformation.Visibility = Visibility.Collapsed;
modeTimer.Stop();
}
private void WakeUp(object sender, PointerRoutedEventArgs e)
{
StandByTime.Visibility = Visibility.Collapsed;
ActiveTime.Visibility = Visibility.Visible;
WeatherInformation.Visibility = Visibility.Visible;
modeTimer.Start();
}
}
}
When I start the application there is no sign of an weather icon showing up. How's that possible?
It seems to be working fine like this:
MainPage.xaml:
<Page>
<Grid>
<Image Height="300">
<Image.Source>
<SvgImageSource x:Name="WeatherIconSource"/>
</Image.Source>
</Image>
</Grid>
</Page>
MainPage.xaml.cs:
private void updateWeather(object sender, object e)
{
WeatherApp.WeatherAPI myWeatherApi = new WeatherApp.WeatherAPI("Friedrichshafen,de");
OpenWeatherMapType.WeatherStream data = myWeatherApi.GetForecast();
WeatherIconSource.UriSource = new Uri("ms-appx:///Assets/WeatherIcons/" + data.Weather[0].Icon + ".svg");
}

I get error: name cannot be found in the name scope of - When moving from page to page in an MVVMLight application

I have an MVVMLight multi-page application which has two pages, I can navigate from one page to the other by clicking the respective buttons.
In the second page, I have a loader animation that is triggered every time something is typed in a textBox field. Everything is working fine; from the first page I can go to the second page then you type something in the textBox and the animation starts. The problem is that if I go to the second page, then I go back to the first page and then I go to the second page again and type something in the textBox I get an error that says that the name of the loader doesn't exist, the funny thing is that I don't get this error until I leave the page and come back.
Any idea why the animation stops working after leaving the page and coming back?
EDIT: Here is the link to a complete project.
https://www.dropbox.com/sh/yf87shw5rzxtxen/AAClTesIGpLKl6IzV-6pjfEfa?dl=0
To replicate error do the following...
Download and open application.
Go to page 2.
Type something in the textBox (animation should start).
Go back to page 1, do nothing.
Go to page 2 again and try typing something in the textBox (you should see the error here).
Error:
Additional information: 'rectangleLoader' name cannot be found in the name scope of 'TwoViews.Views.SecondView'.
XAML
<UserControl x:Class="TwoViews.Views.SecondView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid>
<Rectangle x:Name="rectangleLoader" Fill="#FFB2B2FF" HorizontalAlignment="Left" Height="19" Margin="26,89,0,0" VerticalAlignment="Top" Width="248"/>
<TextBox x:Name="textBoxFileName"
HorizontalAlignment="Left"
Height="35" Width="180"
Margin="26,125,0,0"
VerticalAlignment="Top"
Text="{Binding InputFileNameChanged, UpdateSourceTrigger=PropertyChanged}" FontSize="18"/>
</Grid>
</UserControl>
SecondView.xaml.cs
namespace TwoViews.Views
{
public partial class SecondView : UserControl
{
private Storyboard loaderStoryboard;
public SecondView()
{
InitializeComponent();
Messenger.Default.Register<MessageSearchStatus>(this, messageSearchStatus => ReceivedSearchStatus(messageSearchStatus));
/// Animation for loader
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 100;
myDoubleAnimation.To = 0;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(.1));
myDoubleAnimation.AutoReverse = true;
myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
loaderStoryboard = new Storyboard();
loaderStoryboard.Children.Add(myDoubleAnimation);
Storyboard.SetTargetName(myDoubleAnimation, rectangleLoader.Name);
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.WidthProperty));
}
private void ReceivedSearchStatus(MessageSearchStatus message)
{
loaderStoryboard.Begin(this, true);
}
/// I manually stop the animation before going to other screens
private void stopAnimation_Click(object sender, System.Windows.RoutedEventArgs e)
{
loaderStoryboard.Stop(this);
}
}
}
ViewModel
namespace TwoViews.ViewModels
{
public class SecondViewModel : ViewModelBase
{
private string _inputFileName;
public string InputFileNameChanged
{
get { return _inputFileName; }
set {
// send message to start animation everytime the textBox changes
Messenger.Default.Send<MessageSearchStatus>(new MessageSearchStatus { isSearchingFile = true });
}
}
}
}
Please note that in my code I'm not showing the code that stops the animation.
Again, the animation works fine until the user leaves the page where the animation is and comes back.
Thanks!
FYI - The issue appeared to be the Storyboard I was using with the animation. Removed the Storyboard and everything work fine.
SecondView.xaml.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using System;
using System.Windows.Input;
using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Threading;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Collections.Specialized;
using System.Linq;
using System.Windows.Shapes;
using TwoViews.Models;
using System.Windows.Media;
namespace TwoViews.Views
{
public partial class SecondView : UserControl
{
private DoubleAnimation myDoubleAnimation;
public SecondView()
{
InitializeComponent();
Messenger.Default.Register<MessageSearchStatus>(this, messageSearchStatus => ReceivedSearchStatus(messageSearchStatus));
/// Animation for loader
myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 100;
myDoubleAnimation.To = 0;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(.1));
myDoubleAnimation.AutoReverse = true;
myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
}
private void ReceivedSearchStatus(MessageSearchStatus message)
{
rectangleLoader.BeginAnimation(Rectangle.WidthProperty, myDoubleAnimation);
}
private void stopAnimation_Click(object sender, System.Windows.RoutedEventArgs e)
{
rectangleLoader.BeginAnimation(Rectangle.WidthProperty, null);
}
}
}

How to switch images in a C# WPF application?

I am trying to make an application that switches between an image of the heads sign of a coin and the tails side of a coin. However, every time I press either the "heads" button or the "tails" button, an error occurs. How can I fix my code so that the image successfully switches?
XAML:
<Window x:Class="HeadsOrTails.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:HeadsOrTails"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Image
x:Name="coinImage"
HorizontalAlignment="Center"
Height="100"
Margin="43,10,374,209"
VerticalAlignment="Center"
Width="100"
Loaded="Image_Loaded"/>
<Button x:Name="tailsButton" Content="Show Tails" HorizontalAlignment="Center" Height="40" Margin="190,214,197,65" VerticalAlignment="Center" Width="130" Click="tailsButton_Click"/>
<Button x:Name="headsButton" Content="Show Heads" HorizontalAlignment="Center" Height="40" Margin="43,214,344,65" VerticalAlignment="Center" Width="130" Click="headsButton_Click"/>
<Button x:Name="exitButton" Content="Exit" HorizontalAlignment="Center" Height="40" Margin="339,214,48,65" VerticalAlignment="Center" Width="130" Click="exitButton_Click"/>
</Grid>
</Window>
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Media;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace HeadsOrTails
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Image_Loaded(object sender, RoutedEventArgs e)
{
}
private void tailsButton_Click(object sender, RoutedEventArgs e)
{
//create a second bitmap image (tails)
BitmapImage c = new BitmapImage();
c.BeginInit();
c.UriSource = new Uri(#"C:\Users\Raymond\Documents\Visual Studio 2015\Projects\HeadsOrTails\tails.jpg");
c.EndInit();
var image = sender as Image;
image.Source = c;
}
private void headsButton_Click(object sender, RoutedEventArgs e)
{
//create the new bitmap image (heads)
BitmapImage b = new BitmapImage();
b.BeginInit();
b.UriSource = new Uri(#"C:\Users\Raymond\Documents\Visual Studio 2015\Projects\HeadsOrTails\heads.jpg");
b.EndInit();
var image = sender as Image;
image.Source = b;
}
private void exitButton_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
}
You can't use the sender argument, because that's the Button, not the Image control.
Use the coinImage member instead:
private void headsButton_Click(object sender, RoutedEventArgs e)
{
coinImage.Source = new BitmapImage(new Uri(#"C:\Users\Raymond Karrenbauer\Documents\Visual Studio 2015\Projects\HeadsOrTails\heads.jpg"));
}
private void tailsButton_Click(object sender, RoutedEventArgs e)
{
coinImage.Source = new BitmapImage(new Uri(#"C:\Users\Raymond Karrenbauer\Documents\Visual Studio 2015\Projects\HeadsOrTails\tails.jpg"));
}
Besides that, you should add both image files to your Visual Studio project, set their Build Action to Resource and access them by a Resource File Pack URI. This way you wouldn't have to deal with absolute file paths:
private void headsButton_Click(object sender, RoutedEventArgs e)
{
coinImage.Source = new BitmapImage(new Uri("pack://application:,,,/heads.jpg"));
}
private void tailsButton_Click(object sender, RoutedEventArgs e)
{
coinImage.Source = new BitmapImage(new Uri("pack://application:,,,/tails.jpg"));
}
You may then also add the BitmapImages as XAML Resources:
<Window ...>
<Window.Resources>
<BitmapImage x:Key="heads" UriSource="heads.png"/>
<BitmapImage x:Key="tails" UriSource="tails.png"/>
</Window.Resources>
...
</Window>
And use them like this:
private void headsButton_Click(object sender, RoutedEventArgs e)
{
coinImage.Source = (ImageSource)Resources["heads"];
}
private void tailsButton_Click(object sender, RoutedEventArgs e)
{
coinImage.Source = (ImageSource)Resources["tails"];
}
Clemens is absolutely right, and his second alternative is far superior because it doesn't re-load the bitmaps each time you flip them. However if I may suggest an even better alternative (IMHO) to what you're doing, instead of changing the Source of the coinImage each time, you might instead want to have two Images, for example, coinHeadsImage and coinTailsImage, and flip their respective Visibility properties in those Click handlers. Wrap both Images in their own common Grid so that they are overlapping in the visual tree. I'm not 100% certain, but I believe changing the Visibility of the Images would be more efficient speed-wise than setting the Source property, and either way, it would be better architecture because you could bind the Visibility properties directly to a hypothetical IsHeads property in your code-behind or view model, using appropriate converters of course.
Also, any time you use the as syntax, you generally should check the result for null. Unlike a simple type cast, you won't get an exception if the object cannot covert to the desired type when you use as. Had you checked for null you would have caught your error there.

KinectColorViewer SDK 1.7

I'm trying to make KinectColorViewer to work with SDK 1.7 but without success. I can display video picture only if I manually copy pixels from camera to Image element.
I have the following XAML:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:k="http://schemas.microsoft.com/kinect/2013"
xmlns:WpfViewers="clr-namespace:Microsoft.Samples.Kinect.WpfViewers;assembly=Microsoft.Samples.Kinect.WpfViewers" x:Class="KinectD.Camera"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="500"
Title="Camera">
<Grid>
<k:KinectUserViewer k:KinectRegion.KinectRegion="{Binding ElementName=kinectRegion}" Height="100" HorizontalAlignment="Center" VerticalAlignment="Top" />
<k:KinectSensorChooserUI HorizontalAlignment="Center" VerticalAlignment="Top" x:Name="sensorChooserUi" />
<k:KinectRegion x:Name="kinectRegion">
<Grid>
<k:KinectCircleButton Label="Menu" HorizontalAlignment="Right" Height="200" VerticalAlignment="Top" Click="MenuButtonOnClick" >
<StackPanel>
<Image Source="Images/smile.png" Height="30"/>
</StackPanel>
</k:KinectCircleButton>
</Grid>
</k:KinectRegion>
<WpfViewers:KinectColorViewer HorizontalAlignment="Left" Height="240" Margin="10,10,0,0" VerticalAlignment="Top" Width="320" Kinect="{Binding ElementName=sensorChooserUi, Mode=OneWay, Path=Kinect}"/>
</Grid>
And XAML.CS:
public partial class Camera : Page
{
#region "Kinect"
private KinectSensorChooser sensorChooser;
#endregion
public Camera()
{
this.InitializeComponent();
// initialize the sensor chooser and UI
this.sensorChooser = new KinectSensorChooser();
//Assign the sensor chooser with the sensor chooser from the mainwindow.
//We are reusing the sensorchoosing declared in the first window that can in contact with kinect
this.sensorChooser = Generics.GlobalKinectSensorChooser;
//subscribe to the sensorChooserOnKinectChanged event
this.sensorChooser.KinectChanged += SensorChooserOnKinectChanged;
//Assign Kinect Sensorchooser to the sensorchooser we got from our static class
this.sensorChooserUi.KinectSensorChooser = sensorChooser;
// Bind the sensor chooser's current sensor to the KinectRegion
var regionSensorBinding = new Binding("Kinect") { Source = this.sensorChooser };
BindingOperations.SetBinding(this.kinectRegion, KinectRegion.KinectSensorProperty, regionSensorBinding);
}
private void SensorChooserOnKinectChanged(object sender, KinectChangedEventArgs args)
{
bool error = false;
if (args.OldSensor != null)
{
try
{
args.OldSensor.DepthStream.Range = DepthRange.Default;
args.OldSensor.SkeletonStream.EnableTrackingInNearRange = false;
args.OldSensor.DepthStream.Disable();
args.OldSensor.SkeletonStream.Disable();
args.OldSensor.ColorStream.Disable();
}
catch (InvalidOperationException)
{
// KinectSensor might enter an invalid state while enabling/disabling streams or stream features.
// E.g.: sensor might be abruptly unplugged.
error = true;
}
}
if (args.NewSensor != null)
{
try
{
args.NewSensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
args.NewSensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
args.NewSensor.SkeletonStream.Enable();
}
catch (InvalidOperationException)
{
error = true;
// KinectSensor might enter an invalid state while enabling/disabling streams or stream features.
// E.g.: sensor might be abruptly unplugged.
}
}
if (!error)
kinectRegion.KinectSensor = args.NewSensor;
}
private void MenuButtonOnClick(object sender, RoutedEventArgs e)
{
//Unsubscribe to the sensorchooser's event SensorChooseronkinectChanged
this.sensorChooser.KinectChanged -= SensorChooserOnKinectChanged;
(Application.Current.MainWindow.FindName("_mainFrame") as Frame).Source = new Uri("MainMenu.xaml", UriKind.Relative);
}
}
In tutorial I was following (http://channel9.msdn.com/Series/KinectQuickstart/Camera-Fundamentals) instructor just drops KinectColorViewer to a screen, sets path and it's working.
The KinectColorViewer available in the KinectWpfViewers assembly is used in the "Kinect Explorer" example, and that is the best place to see how it is used and behaves. From this example you will find that the proper way to initialize the viewer in the XAML and the bindings that are necessary.
From the code you posted, you appear to binding the Kinect itself (a reference to the hardware) to the KinectColorViewer, which is not what it is expecting. You need to be setting a reference to a KinectSensorManager class, which is part of the KinectWpfViewers assembly.
Here is a simplified XAML with a KinectColorViewer
<Window x:Class="Microsoft.Samples.Kinect.KinectExplorer.KinectWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Microsoft.Samples.Kinect.KinectExplorer"
xmlns:kt="clr-namespace:Microsoft.Samples.Kinect.WpfViewers;assembly=Microsoft.Samples.Kinect.WpfViewers"
Title="Kinect Explorer" Width="812" Height="768">
<Grid>
<kt:KinectColorViewer x:Name="ColorViewer" KinectSensorManager="{Binding KinectSensorManager}" CollectFrameRate="True" RetainImageOnSensorChange="True" />
</Grid>
</Window>
Then you XAML.CS constructor will look something similar to:
public KinectWindow()
{
this.viewModel = new KinectWindowViewModel();
// The KinectSensorManager class is a wrapper for a KinectSensor that adds
// state logic and property change/binding/etc support, and is the data model
// for KinectDiagnosticViewer.
this.viewModel.KinectSensorManager = new KinectSensorManager();
Binding sensorBinding = new Binding("KinectSensor");
sensorBinding.Source = this;
BindingOperations.SetBinding(this.viewModel.KinectSensorManager, KinectSensorManager.KinectSensorProperty, sensorBinding);
// Attempt to turn on Skeleton Tracking for each Kinect Sensor
this.viewModel.KinectSensorManager.SkeletonStreamEnabled = true;
this.DataContext = this.viewModel;
InitializeComponent();
}
Review the "Kinect Explorer" example for complete details.
I had the same problem with using KinectSensorManager. It turns out you need to call to Microsoft.Samples.Kinect.Wpf.Viewers and not just the kinect.dll, kinect.toolkit.dll, and kinect.controls.dll.
However, when I implemented KinectSensorManager, then the KinectUI and SensorChooser stopped working on my xaml interface.

Categories