88pytestmark = pytest .mark .unit
99
1010
11- def make_settings (index = 0 , fps = 30.0 , properties = None ):
12- """Minimal settings object compatible with CameraBackend usage."""
11+ def make_settings (index = 0 , fps = 30.0 , properties = None , * , width = 0 , height = 0 , backend = "opencv" , name = "Test" ):
12+ """Minimal settings object compatible with OpenCVCameraBackend usage."""
1313 if properties is None :
1414 properties = {}
15- return SimpleNamespace (index = index , fps = fps , properties = properties )
15+ return SimpleNamespace (
16+ index = index ,
17+ fps = fps ,
18+ properties = properties ,
19+ width = width ,
20+ height = height ,
21+ backend = backend ,
22+ name = name ,
23+ )
24+
1625
26+ def test_requested_resolution_precedence_property_over_width_height ():
27+ settings = make_settings (
28+ properties = {"resolution" : (800 , 600 )},
29+ width = 1280 ,
30+ height = 720 ,
31+ )
32+ backend = ob .OpenCVCameraBackend (settings )
33+ assert backend ._get_requested_resolution () == (800 , 600 )
1734
18- def test_parse_resolution_defaults_and_invalid_values ():
19- backend = ob .OpenCVCameraBackend (make_settings (properties = {}))
20- assert backend ._parse_resolution (None ) == (720 , 540 )
21- assert backend ._parse_resolution ([1280 , 720 ]) == (1280 , 720 )
22- assert backend ._parse_resolution (("1920" , "1080" )) == (1920 , 1080 )
23- assert backend ._parse_resolution (("bad" , 123 )) == (720 , 540 )
24- assert backend ._parse_resolution ("nope" ) == (720 , 540 )
35+
36+ def test_requested_resolution_uses_width_height_when_no_property_resolution ():
37+ settings = make_settings (
38+ properties = {},
39+ width = 1280 ,
40+ height = 720 ,
41+ )
42+ backend = ob .OpenCVCameraBackend (settings )
43+ assert backend ._get_requested_resolution () == (1280 , 720 )
44+
45+
46+ def test_requested_resolution_defaults_when_no_request ():
47+ settings = make_settings (properties = {}, width = 0 , height = 0 )
48+ backend = ob .OpenCVCameraBackend (settings )
49+ assert backend ._get_requested_resolution () == (720 , 540 )
2550
2651
2752def test_try_open_windows_fallback_to_msmf (monkeypatch , fake_capture_factory ):
@@ -68,7 +93,7 @@ def fake_videocapture(index, flag):
6893
6994 monkeypatch .setattr (ob .cv2 , "VideoCapture" , fake_videocapture )
7095
71- settings = make_settings (index = 0 , fps = 30.0 , properties = {"alt_index_probe" : True })
96+ settings = make_settings (index = 0 , fps = 30.0 , properties = {"opencv" : { " alt_index_probe" : True } })
7297 backend = ob .OpenCVCameraBackend (settings )
7398 backend .open ()
7499
@@ -145,7 +170,6 @@ def test_configure_capture_sets_resolution_and_fps_non_faststart_windows(monkeyp
145170 backend ._configure_capture ()
146171
147172 assert backend .actual_resolution == (800 , 600 )
148- assert settings .properties ["resolution" ] == (800 , 600 )
149173 assert backend .actual_fps is not None
150174 assert isinstance (backend .actual_fps , float )
151175
@@ -157,18 +181,20 @@ def test_configure_capture_fast_start_does_not_force_resolution(monkeypatch, fak
157181 cap .props [ob .cv2 .CAP_PROP_FRAME_WIDTH ] = 1920.0
158182 cap .props [ob .cv2 .CAP_PROP_FRAME_HEIGHT ] = 1080.0
159183
160- settings = make_settings (index = 0 , fps = 30.0 , properties = {"resolution" : (1280 , 720 ), "opencv" : {"fast_start" : True }})
184+ settings = make_settings (
185+ index = 0 ,
186+ fps = 30.0 ,
187+ properties = {"resolution" : (1280 , 720 ), "opencv" : {"fast_start" : True }},
188+ )
161189 backend = ob .OpenCVCameraBackend (settings )
162190 backend ._capture = cap
163191
164192 backend ._configure_capture ()
165193
166- assert backend .actual_resolution == (1920 , 1080 )
194+ # Fast-start still applies requested resolution, just without verification
195+ assert backend .actual_resolution == (1280 , 720 )
167196
168- # Fast-start does not configure the camera; it only reports the current mode.
169- # Keep "resolution" as the requested intent (do not overwrite with observed values).
170- # Settings are applied later when user clicks "Apply settings" in the UI,
171- # so it's important not to overwrite them here.
197+ # Requested intent must remain unchanged
172198 assert settings .properties ["resolution" ] == (1280 , 720 )
173199
174200
@@ -181,9 +207,7 @@ def test_configure_capture_applies_only_safe_numeric_properties(monkeypatch, fak
181207 fps = 30.0 ,
182208 properties = {
183209 "resolution" : (640 , 480 ),
184- "api" : "ANY" ,
185- "fast_start" : False ,
186- "alt_index_probe" : False ,
210+ "opencv" : {"api" : "ANY" , "fast_start" : False , "alt_index_probe" : False },
187211 str (int (getattr (ob .cv2 , "CAP_PROP_GAIN" , 14 ))): 7 ,
188212 "999" : 123 ,
189213 "not-a-number" : 1 ,
@@ -213,3 +237,20 @@ def test_close_and_stop_release_capture(fake_capture_factory):
213237 backend .stop ()
214238 assert backend ._capture is None
215239 assert cap2 .released is True
240+
241+
242+ def test_configure_capture_uses_width_height_when_no_legacy_resolution (monkeypatch , fake_capture_factory ):
243+ monkeypatch .setattr (ob .platform , "system" , lambda : "Windows" )
244+
245+ cap = fake_capture_factory (opened = True , backend_name = "DSHOW" )
246+ cap .props [ob .cv2 .CAP_PROP_FRAME_WIDTH ] = 640.0
247+ cap .props [ob .cv2 .CAP_PROP_FRAME_HEIGHT ] = 480.0
248+ cap .props [ob .cv2 .CAP_PROP_FPS ] = 30.0
249+
250+ settings = make_settings (index = 0 , fps = 30.0 , properties = {}, width = 1024 , height = 768 )
251+ backend = ob .OpenCVCameraBackend (settings )
252+ backend ._capture = cap
253+
254+ backend ._configure_capture ()
255+
256+ assert backend .actual_resolution == (1024 , 768 )
0 commit comments