[camera_windows] Set device media type for video preview explicitly (#7447)
Fixes preview aspect ratio on Windows on some webcams (See https://github.com/flutter/flutter/issues/122966).
Before (main branch 7c1a05c8b12274e940e39adcb42896a32f57df32):
![image](https://github.com/user-attachments/assets/cca93da9-dd94-486e-930f-5c5aa73922a9)
After:
![image](https://github.com/user-attachments/assets/05c5c460-21ed-40d8-93eb-1e75da7c929c)
diff --git a/packages/camera/camera_windows/CHANGELOG.md b/packages/camera/camera_windows/CHANGELOG.md
index 3479db4..8fe3c0d 100644
--- a/packages/camera/camera_windows/CHANGELOG.md
+++ b/packages/camera/camera_windows/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.2.6+1
+
+* Fixes black bars on camera preview [#122966](https://github.com/flutter/flutter/issues/122966).
+
## 0.2.6
* Reverts streaming frame support, as the implementation was incorrect and never
diff --git a/packages/camera/camera_windows/pubspec.yaml b/packages/camera/camera_windows/pubspec.yaml
index ae13369..a2a9efb 100644
--- a/packages/camera/camera_windows/pubspec.yaml
+++ b/packages/camera/camera_windows/pubspec.yaml
@@ -2,7 +2,7 @@
description: A Flutter plugin for getting information about and controlling the camera on Windows.
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_windows
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
-version: 0.2.6
+version: 0.2.6+1
environment:
sdk: ^3.3.0
diff --git a/packages/camera/camera_windows/windows/capture_controller.cpp b/packages/camera/camera_windows/windows/capture_controller.cpp
index 44df843..44675da 100644
--- a/packages/camera/camera_windows/windows/capture_controller.cpp
+++ b/packages/camera/camera_windows/windows/capture_controller.cpp
@@ -467,10 +467,15 @@
return hr;
}
+ return FindBaseMediaTypesForSource(source.Get());
+}
+
+HRESULT CaptureControllerImpl::FindBaseMediaTypesForSource(
+ IMFCaptureSource* source) {
// Find base media type for previewing.
if (!FindBestMediaType(
(DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_VIDEO_PREVIEW,
- source.Get(), base_preview_media_type_.GetAddressOf(),
+ source, base_preview_media_type_.GetAddressOf(),
GetMaxPreviewHeight(), &preview_frame_width_,
&preview_frame_height_)) {
return E_FAIL;
@@ -479,8 +484,8 @@
// Find base media type for record and photo capture.
if (!FindBestMediaType(
(DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_VIDEO_RECORD,
- source.Get(), base_capture_media_type_.GetAddressOf(), 0xffffffff,
- nullptr, nullptr)) {
+ source, base_capture_media_type_.GetAddressOf(), 0xffffffff, nullptr,
+ nullptr)) {
return E_FAIL;
}
@@ -566,15 +571,30 @@
HRESULT hr = S_OK;
+ ComPtr<IMFCaptureSource> source;
+ hr = capture_engine_->GetSource(&source);
+ if (FAILED(hr)) {
+ return OnPreviewStarted(GetCameraResult(hr),
+ "Failed to get capture engine source");
+ }
+
if (!base_preview_media_type_) {
// Enumerates mediatypes and finds media type for video capture.
- hr = FindBaseMediaTypes();
+ hr = FindBaseMediaTypesForSource(source.Get());
if (FAILED(hr)) {
return OnPreviewStarted(GetCameraResult(hr),
"Failed to initialize video preview");
}
}
+ hr = source->SetCurrentDeviceMediaType(
+ (DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_VIDEO_PREVIEW,
+ base_preview_media_type_.Get());
+ if (FAILED(hr)) {
+ return OnPreviewStarted(GetCameraResult(hr),
+ "Failed to set video preview output format");
+ }
+
texture_handler_->UpdateTextureSize(preview_frame_width_,
preview_frame_height_);
diff --git a/packages/camera/camera_windows/windows/capture_controller.h b/packages/camera/camera_windows/windows/capture_controller.h
index 8dd5414..2280cb3 100644
--- a/packages/camera/camera_windows/windows/capture_controller.h
+++ b/packages/camera/camera_windows/windows/capture_controller.h
@@ -181,6 +181,10 @@
// for preview and video capture.
HRESULT FindBaseMediaTypes();
+ // Enumerates video_sources media types and finds out best resolution
+ // for a given source.
+ HRESULT FindBaseMediaTypesForSource(IMFCaptureSource* source);
+
// Stops preview. Called internally on camera reset and dispose.
HRESULT StopPreview();
diff --git a/packages/camera/camera_windows/windows/test/capture_controller_test.cpp b/packages/camera/camera_windows/windows/test/capture_controller_test.cpp
index aa0b546..98e7758 100644
--- a/packages/camera/camera_windows/windows/test/capture_controller_test.cpp
+++ b/packages/camera/camera_windows/windows/test/capture_controller_test.cpp
@@ -153,6 +153,15 @@
MockAvailableMediaTypes(engine, capture_source.Get(), mock_preview_width,
mock_preview_height);
+ EXPECT_CALL(
+ *capture_source.Get(),
+ SetCurrentDeviceMediaType(
+ Eq((DWORD)
+ MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_VIDEO_PREVIEW),
+ _))
+ .Times(1)
+ .WillOnce(Return(S_OK));
+
EXPECT_CALL(*engine, StartPreview()).Times(1).WillOnce(Return(S_OK));
// Called by destructor