Skip to content

Commit fb43dfc

Browse files
CarlosRDominWyattBlue
authored andcommitted
Apply reformat shortcut to hardware frames too
1 parent 41441a5 commit fb43dfc

2 files changed

Lines changed: 55 additions & 0 deletions

File tree

av/video/reformatter.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,19 @@ def _reformat(
291291
frame = frame_sw
292292
src_format = cython.cast(lib.AVPixelFormat, frame.ptr.format)
293293

294+
# Check for shortcut again, in case dst_format matches the downloaded frame's sw_format
295+
if (
296+
dst_format == src_format
297+
and width == frame.ptr.width
298+
and height == frame.ptr.height
299+
and dst_colorspace == src_colorspace
300+
and src_color_range == dst_color_range
301+
and not set_dst_color_trc
302+
and not set_dst_color_primaries
303+
):
304+
frame._init_user_attributes()
305+
return frame
306+
294307
if self.ptr == cython.NULL:
295308
self.ptr = sws_alloc_context()
296309
if self.ptr == cython.NULL:

tests/test_decode.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
311353
def decode_first_video_frame(
312354
path: str, hwaccel: av.codec.hwaccel.HWAccel | None = None
313355
) -> av.VideoFrame:

0 commit comments

Comments
 (0)