[UWP] Camera Preview while recording

David H 1 Reputation point
2019-12-12T20:36:57.57+00:00

Hello,

I'm attempting to work with video capture in a UWP app and am running across an issue when it comes to the preview of the video.

Everything works fine to preview, capture, play back a video if I don't resize the window. If recording is taking place when the visual state manager triggers a change in the layout of the control, my capture element loses the feed from the camera and I cannot get it back while recording. If simply previewing before recording, I can simply restart the preview from the MediaCapture object again as normal. The issue is really just losing the feed while recording if they resize the window.

The process that is being triggered is the parent Grid that contains the capture object is being removed from being the child of one grid and put into another when the screen becomes too small/large enough. I'm assuming the time it's detached from having a parent is why this occurs, but I'm not sure how to work around it. Simple setting the Source of the CaptureElement back to the MediaCapture does not work, and calling StartPreviewAsync() on the MediaCapture does not work while recording. Is there some other way I could go about handling this?

Here's the code I'm using for this. First is the VisualStateManager that triggers the view change. This part is working perfectly. The grids show/hide and the WideViewLayout property on videoControl calls some other code below.  
  
    // The visual state manager. Everything in here seems to be working fine.  Can't seem to figure out how to make XAML work here so the opening tags are removed so they show up. But it's basic Visual state manager code.  
  
        VisualStateManager.VisualStateGroups  
            VisualStateGroup  
                VisualState x:Name="WideLayout"  
                    VisualState.StateTriggers  
                        AdaptiveTrigger MinWindowWidth="1024" /  
                    /VisualState.StateTriggers>  
                    VisualState.Setters>  
                        Setter Target="videoControl.WideViewLayout" Value="True" />  
                        Setter Target="wideViewControl.Visibility" Value="Visible" />  
                        Setter Target="narrowViewControl.Visibility" Value="Collapsed" />  
                    /VisualState.Setters>  
                /VisualState>  
            /VisualStateGroup>  
        /VisualStateManager.VisualStateGroups>  
  
     
    //The grid being moved from one parent grid to another during layout change.  
      
                Grid x:Name="videoCaptureGrid" Grid.Row="1">  
                    Grid.RowDefinitions>  
                        RowDefinition />  
                        RowDefinition Height="Auto" />  
                    Grid.RowDefinitions>  
                    Viewbox VerticalAlignment="Top">  
                        /Grid>  
                            Canvas Grid.Row="1" x:Name="previewCanvas" Width="300" Height="220" Background="Black" HorizontalAlignment="Center" VerticalAlignment="Center">  
                                CaptureElement x:Name="previewElement" Width="300" Height="220" />  
                            /Canvas>  
                          
                    /Viewbox>  
                    ComboBox Grid.Row="1" Background="Black" ItemsSource="{Binding DeviceInformationCollection}" BorderBrush="Black" FontSize="35" Margin="20,3,20,3" DisplayMemberPath="Name"   
                              IsEnabled="{Binding IsCameraOn, Converter={StaticResource boolNegationConverter}}" SelectedItem="{Binding SelectedVideoDevice, Mode=TwoWay}" />  
                /Grid>  
  
  
    //The code moving the grid from one element to another. I think this is where the problem is with it losing the preview, but not sure of another approach to take.  
  
    private void SetupWideViewMode()  
        {  
              narrowVideoElementGrid.Children.Remove(videoCaptureGrid);      
              wideViewControl.Children.Add(videoCaptureGrid);  
              
              Grid.SetRow(videoCaptureGrid, 1);  
              Grid.SetColumn(videoCaptureGrid, 0);  
        }  
  
Please let me know if I can provide any other information.  
  
Thank you!  
Universal Windows Platform (UWP)
{count} votes

1 answer

Sort by: Most helpful
  1. Richard Zhang-MSFT 6,936 Reputation points
    2019-12-16T03:03:55.113+00:00

    Hello,​

    Welcome to our Microsoft Q&A platform!

    I reproduced your problem, the migration of controls on the visual tree may cause the disconnection of mediaCapture and previewElement.

    So before the videoCaptureGrid migration, you need to stop the video preview.

    Here are the variable and methods needed in the operation

    private bool isPreviewing = false;
    
    private async Task StartPreviewAsync()
    {
        try
        {
            mediaCapture = new MediaCapture();
            await mediaCapture.InitializeAsync();
        }
        catch (UnauthorizedAccessException)
        {
            return;
        }
    
        try
        {
            previewElement.Source = mediaCapture;
            await mediaCapture.StartPreviewAsync();
            isPreviewing = true;
        }
        catch (FileLoadException)
        {
    
        }
    }
    private async Task CleanupCameraAsync()
    {
        if (mediaCapture != null)
        {
            if (isPreviewing)
            {
                await mediaCapture.StopPreviewAsync();
            }
    
            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                previewElement.Source = null;
                mediaCapture.Dispose();
                mediaCapture = null;
            });
        }
    
    }
    

    Usage

    private async void SetupWideViewMode()
    {
        await CleanupCameraAsync();
        narrowVideoElementGrid.Children.Remove(videoCaptureGrid);
        wideViewControl.Children.Add(videoCaptureGrid);
    
        Grid.SetRow(videoCaptureGrid, 1);
        Grid.SetColumn(videoCaptureGrid, 0);
        await StartPreviewAsync();
    }
    

    This will restart the preview after moving the Grid.

    Thanks.