Skip to content

Conversation

zhitaop
Copy link
Contributor

@zhitaop zhitaop commented Apr 17, 2025

Description of Change

  • Fixes [BUG] CameraView App crashes when switching camera on Windows #2559:

    Root cause :
    In CameraProvider.windows.cs, only one instance of MediaCapture is instantiated when iterating through the videoCaptureSourceGroup. This causes only the first mediaCapture.InitializeCameraForCameraView() to be successful. Wrong camera meta data from the first camera, such as the supported resolutions, are added to the subsequent CameraInfos (i.e. all subsequent CameraInfo contains metadata from the first CameraInfo). This causes the following exception when the camera is being updated with incorrect resolution:

    System.Runtime.InteropServices.COMException (0xC00D36B4): The data specified for the media type is invalid, inconsistent, or not supported by this object.
    The data specified for the media type is invalid, inconsistent, or not supported by this object.
    at CommunityToolkit.Maui.Core.CameraManager.PlatformUpdateResolution(Size resolution, CancellationToken token)

    Code changes:

    • Instantiate new MediaCapture in each iteration and properly dispose it after use
  • Enhancement: refactor camera refresh logic

    Root cause:
    Multiple calls to CameraProvider.RefreshAvailableCameras() are scattered throughout the camera initialization code (i.e.in CameraManager.ConnectCamera, CameraManager.StartCameraPreview, CameraManager.UpdateResolution), which are unnecessary as the available cameras are unlikely to change during initialization, and also time consuming especially on Windows as it needs to initialize MediaCapture.

    In Addition, consumers of the camera view may also call RefreshAvailableCameras() (e.g. to populate the list for camera switcher), usually at the same time when the camera view itself is initializing , resulting in more redundant code execution.

    Code changes:

    • Add new properties and methods to CameraProvider:
      • internal: refreshTask and PlatformRefreshAvailableCameras()
      • public: InitializeAsync()
    • move camera refresh logic to PlatformRefreshAvailableCameras .
    • The refreshTask is reused for both initialization and refresh, ensuring only one refresh operation runs at a time.
    • InitializeAsync() only refreshes the cameras if the camera provide has not been initialized, i.e. the refreshTask is not completed successfully
    • RefreshAvailableCameras() only refreshes the cameras if the refresh task is not currently in progress, i.e. refreshTask is null or is completed (could be completed successfully, faulted or canceled)
    • Remove all RefreshAvailableCameras() calls in CameraManager and CameraViewHandler. Instead, call InitializeAsync() in CameraManager.ConnectCamera to ensure available cameras are initialized.

    Example usage by consumer:

// Initialization logic for camera view view model
public async Task InitializeAsync()
{
  await cameraProvider.InitializeAsync(CancellationToken.None); 
  Cameras = cameraProvider.AvailableCameras ?? [];
}

// Method to force camera to refresh. Can be used when cameras are changed, e.g. external usb camera is added
async Task RefreshCameras(CancellationToken token) => await cameraProvider.RefreshAvailableCameras(token);
  • Enhancements in CameraViewPage and CameraViewViewModel:
    • Add camera switcher on the camera view page
    • Make Cameras observable in the view model, and make sure it's assigned after the CameraProvider is initialized so that camera list is not empty.

Linked Issues

PR Checklist

  • Has a linked Issue, and the Issue has been approved(bug) or Championed (feature/proposal)
  • Has tests (if omitted, state reason in description)
  • Has samples (if omitted, state reason in description)
  • Rebased on top of main at time of PR
  • Changes adhere to coding standard
  • Documentation created or updated: https://github.com/MicrosoftDocs/CommunityToolkit/pulls

Additional information

* Add automatic initialization in CameraProvider
* Remove unnecessary refresh cameras calls in CameraManager
* Add camera switcher in camera sample page
@VR-Architect
Copy link

Any guess when this will deploy to main? Hoping it fixes some issues I have with Windows camera.

@bijington
Copy link
Contributor

Any guess when this will deploy to main? Hoping it fixes some issues I have with Windows camera.

Perhaps you could help us and test this branch on your machine to see if it helps?

@VR-Architect
Copy link

Any guess when this will deploy to main? Hoping it fixes some issues I have with Windows camera.

Perhaps you could help us and test this branch on your machine to see if it helps?

I would love to help but don't know how do download the branch to test. Let me Google it.

* Unbind ProcessCameraProvider when dispose
@dotnet-policy-service dotnet-policy-service bot added stale The author has not responded in over 30 days help wanted This proposal has been approved and is ready to be implemented labels Jun 25, 2025
@ruc12127
Copy link

I have tested the CommunityToolkitSampleApp using https://github.com/zhitaop/CommunityToolkitMaui/tree/fix/camera-provider-refresh branch on Surface Book 3 (Windows 10). The camera switcher is working as expected without any crashes.

@zhitaop
Copy link
Contributor Author

zhitaop commented Jul 16, 2025

Hi @bijington, could this PR be assigned for review soon? As mentioned in #2634 (comment), the branch has been tested that it does solve the original crash issue.

@bijington
Copy link
Contributor

Hi @bijington, could this PR be assigned for review soon? As mentioned in #2634 (comment), the branch has been tested that it does solve the original crash issue.

I've added some comments I didn't have a chance to take a look on a laptop so I'll try and do a more in depth check later in the week

@zhitaop zhitaop requested a review from bijington July 24, 2025 02:58
@bijington
Copy link
Contributor

Sorry it's taken time to get to this. I'll try and sort it tomorrow or next week

@vovanb
Copy link

vovanb commented Aug 5, 2025

I this it is same issue with recent code on Android

@Copilot Copilot AI review requested due to automatic review settings August 20, 2025 04:32
Copilot

This comment was marked as outdated.

@zhitaop
Copy link
Contributor Author

zhitaop commented Aug 20, 2025

Hi @bijington, I've addressed some of your comments and provide explanation for others, could you please take a look again? Thanks!

@dotnet-policy-service dotnet-policy-service bot removed the stale The author has not responded in over 30 days label Aug 20, 2025
@bijington
Copy link
Contributor

Sorry things became really busy and then I went on vacation. I return at the weekend so I've added a reminder to take a look at this next week for you.

bijington
bijington previously approved these changes Aug 28, 2025
Copy link
Contributor

@bijington bijington left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zhitaop apologies for the delay in reviewing this. It looks good to me now!

@TheCodeTraveler TheCodeTraveler added pending documentation This feature requires documentation breaking change This label is used for PRs that include a breaking change and removed help wanted This proposal has been approved and is ready to be implemented labels Aug 28, 2025
…avoid async/await race conditions, Implement `IDisplosable`
@TheCodeTraveler TheCodeTraveler added the approved This Proposal has been approved and is ready to be added to the Toolkit label Aug 28, 2025
@TheCodeTraveler
Copy link
Collaborator

Thanks @zhitaop! This is a breaking change that requires the docs to be updated before we can merge the PR: https://github.com/MicrosoftDocs/CommunityToolkit/pulls

@bijington - could you work with @zhitaop on the updating the docs?

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes a critical CameraView crash on Windows when switching cameras and implements significant camera provider enhancements. The crash was caused by reusing a single MediaCapture instance across multiple cameras, leading to incorrect metadata assignment and resolution conflicts.

Key changes:

  • Fixed Windows MediaCapture disposal and instantiation to prevent camera switching crashes
  • Refactored camera initialization logic to reduce redundant refresh calls and improve performance
  • Enhanced sample app with camera switcher UI and improved initialization patterns

Reviewed Changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
CameraProvider.windows.cs Fixed MediaCapture lifecycle management by creating new instances per camera and proper disposal
CameraProvider.shared.cs Added thread-safe initialization logic with semaphore and task management
ICameraProvider.shared.cs Extended interface with InitializeAsync method and IsInitialized property
CameraManager.*.cs Removed redundant RefreshAvailableCameras calls and consolidated initialization logic
CameraViewHandler.shared.cs Simplified connection logic by removing duplicate camera provider refresh
Sample app files Enhanced UI with camera picker and improved initialization patterns

Comment on lines +63 to +64
refreshAvailableCamerasTask?.Dispose();
refreshAvailableCamerasTask = null;
Copy link
Preview

Copilot AI Aug 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting the task reference to null after disposing it creates a potential race condition. If another thread is checking refreshAvailableCamerasTask?.IsCompletedSuccessfully in the IsInitialized property while disposal is happening, it could access a disposed task. Consider setting the reference to null before disposing, or use a different synchronization approach.

Suggested change
refreshAvailableCamerasTask?.Dispose();
refreshAvailableCamerasTask = null;
var task = refreshAvailableCamerasTask;
refreshAvailableCamerasTask = null;
task?.Dispose();

Copilot uses AI. Check for mistakes.

@zhitaop
Copy link
Contributor Author

zhitaop commented Sep 1, 2025

@TheCodeTraveler Thanks for the review and code update! I have raised a PR to update the documentation: MicrosoftDocs/CommunityToolkit#593

@TheCodeTraveler TheCodeTraveler added the needs discussion Discuss it on the next Monthly standup label Sep 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved This Proposal has been approved and is ready to be added to the Toolkit breaking change This label is used for PRs that include a breaking change needs discussion Discuss it on the next Monthly standup pending documentation This feature requires documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] CameraView App crashes when switching camera on Windows
7 participants