@@ -308,6 +308,48 @@ def test_hardware_decode_download_preserves_frame_props(is_hw_owned: bool) -> No
308308 assert_video_frame_color_props_match (hw_frame , cpu_frame )
309309
310310
311+ def test_hardware_frame_reformat_matches_downloaded_frame () -> None :
312+ hwdevices_available = av .codec .hwaccel .hwdevices_available ()
313+ if "HWACCEL_DEVICE_TYPE" not in os .environ :
314+ pytest .skip (
315+ "Set the HWACCEL_DEVICE_TYPE to run this test. "
316+ f"Options are { ' ' .join (hwdevices_available )} "
317+ )
318+
319+ hwaccel_device_type = os .environ ["HWACCEL_DEVICE_TYPE" ]
320+ assert hwaccel_device_type in hwdevices_available , (
321+ f"{ hwaccel_device_type } not available"
322+ )
323+
324+ test_video_path = fate_suite ("h264/interlaced_crop.mp4" )
325+ downloaded_frame = decode_first_video_frame (
326+ test_video_path ,
327+ av .codec .hwaccel .HWAccel (
328+ device_type = hwaccel_device_type ,
329+ is_hw_owned = False ,
330+ allow_software_fallback = False ,
331+ ),
332+ )
333+ hw_frame = decode_first_video_frame (
334+ test_video_path ,
335+ av .codec .hwaccel .HWAccel (
336+ device_type = hwaccel_device_type ,
337+ is_hw_owned = True ,
338+ allow_software_fallback = False ,
339+ ),
340+ )
341+ assert downloaded_frame .format .name != hw_frame .format .name # E.g. cuda vs nv12
342+
343+ # Download hw_frame to CPU and ensure the contents match downloaded_frame
344+ sw_format = downloaded_frame .format .name
345+ reformatted_frame = hw_frame .reformat (format = sw_format )
346+ assert reformatted_frame .format .name == downloaded_frame .format .name
347+ assert np .array_equal (
348+ reformatted_frame .to_ndarray (format = sw_format ),
349+ downloaded_frame .to_ndarray (format = sw_format ),
350+ )
351+
352+
311353def decode_first_video_frame (
312354 path : str , hwaccel : av .codec .hwaccel .HWAccel | None = None
313355) -> av .VideoFrame :
0 commit comments