From a642ac226a74363d68d96540be8f5b763fa1601c Mon Sep 17 00:00:00 2001 From: z-khan Date: Mon, 21 Apr 2025 15:22:27 +1000 Subject: [PATCH 1/6] add "bgra64" pixel format added "bgra64be", "bgra64le" pixel formats to VideoFrame.from_numpy() --- av/video/frame.pyx | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/av/video/frame.pyx b/av/video/frame.pyx index 785603a1a..4e8482210 100644 --- a/av/video/frame.pyx +++ b/av/video/frame.pyx @@ -16,7 +16,7 @@ cdef object _cinit_bypass_sentinel supported_np_pix_fmts = { "abgr", "argb", "bayer_bggr16be", "bayer_bggr16le", "bayer_bggr8", "bayer_gbrg16be", "bayer_gbrg16le", "bayer_gbrg8", "bayer_grbg16be", "bayer_grbg16le", "bayer_grbg8", - "bayer_rggb16be", "bayer_rggb16le", "bayer_rggb8", "bgr24", "bgr8", "bgra", + "bayer_rggb16be", "bayer_rggb16le", "bayer_rggb8", "bgr24", "bgr8", "bgra", "bgra64be", "bgra64le", "gbrapf32be", "gbrapf32le", "gbrp", "gbrp10be", "gbrp10le", "gbrp12be", "gbrp12le", "gbrp14be", "gbrp14le", "gbrp16be", "gbrp16le", "gbrpf32be", "gbrpf32le", "gray", "gray16be", "gray16le", "gray8", "grayf32be", "grayf32le", "nv12", "pal8", "rgb24", @@ -370,6 +370,8 @@ cdef class VideoFrame(Frame): "rgba": (4, "uint8"), "rgba64be": (8, "uint16"), "rgba64le": (8, "uint16"), + "bgra64be": (8, "uint16"), + "bgra64le": (8, "uint16"), "yuv444p": (1, "uint8"), "yuv444p16be": (2, "uint16"), "yuv444p16le": (2, "uint16"), @@ -467,43 +469,58 @@ cdef class VideoFrame(Frame): if not width: width = array.shape[1] - if format in ("rgb24", "bgr24"): + if format in {"rgb24", "bgr24"}: check_ndarray(array, "uint8", 3) check_ndarray_shape(array, array.shape[2] == 3) if array.strides[1:] != (3, 1): raise ValueError("provided array does not have C_CONTIGUOUS rows") + linesizes = (array.strides[0], ) + elif format in {"rgb48le", "rgb48be", "bgr48le", "bgr48be"}: + check_ndarray(array, "uint16", 3) + check_ndarray_shape(array, array.shape[2] == 3) + if array.strides[1:] != (6, 2): + raise ValueError("provided array does not have C_CONTIGUOUS rows") linesizes = (array.strides[0], ) - elif format in ("rgba", "bgra"): + elif format in {"rgba", "bgra", "argb", "abgr"}: check_ndarray(array, "uint8", 3) check_ndarray_shape(array, array.shape[2] == 4) if array.strides[1:] != (4, 1): raise ValueError("provided array does not have C_CONTIGUOUS rows") linesizes = (array.strides[0], ) - elif format in ("gray", "gray8", "rgb8", "bgr8"): + elif format in {"rgba64le", "rgba64be", "bgra64le", "bgra64be"}: + check_ndarray(array, "uint16", 3) + check_ndarray_shape(array, array.shape[2] == 4) + if array.strides[1:] != (8, 2): + raise ValueError("provided array does not have C_CONTIGUOUS rows") + linesizes = (array.strides[0], ) + elif format in {"gray", "gray8", "rgb8", "bgr8","bayer_bggr8", "bayer_rggb8", "bayer_gbrg8", "bayer_grbg8"}: check_ndarray(array, "uint8", 2) if array.strides[1] != 1: raise ValueError("provided array does not have C_CONTIGUOUS rows") linesizes = (array.strides[0], ) - elif format in ("yuv420p", "yuvj420p", "nv12"): + elif format in {"gray16le", "gray16be", "bayer_rggb16le", "bayer_gbrg16le", "bayer_grbg16le","bayer_bggr16be", "bayer_rggb16be", "bayer_gbrg16be", "bayer_grbg16be"}: + check_ndarray(array, "uint16", 2) + if array.strides[1] != 2: + raise ValueError("provided array does not have C_CONTIGUOUS rows") + linesizes = (array.strides[0], ) + elif format in {"grayf32le", "grayf32be"}: + check_ndarray(array, "float32", 2) + if array.strides[1] != 4: + raise ValueError("provided array does not have C_CONTIGUOUS rows") + linesizes = (array.strides[0], ) + elif format in {"yuv420p", "yuvj420p", "nv12"}: check_ndarray(array, "uint8", 2) check_ndarray_shape(array, array.shape[0] % 3 == 0) check_ndarray_shape(array, array.shape[1] % 2 == 0) height = height // 6 * 4 if array.strides[1] != 1: raise ValueError("provided array does not have C_CONTIGUOUS rows") - if format in ("yuv420p", "yuvj420p"): + if format in {"yuv420p", "yuvj420p"}: # For YUV420 planar formats, the UV plane stride is always half the Y stride. linesizes = (array.strides[0], array.strides[0] // 2, array.strides[0] // 2) else: # Planes where U and V are interleaved have the same stride as Y. linesizes = (array.strides[0], array.strides[0]) - elif format in {"bayer_bggr8", "bayer_rggb8", "bayer_gbrg8", "bayer_grbg8","bayer_bggr16le", "bayer_rggb16le", "bayer_gbrg16le", "bayer_grbg16le","bayer_bggr16be", "bayer_rggb16be", "bayer_gbrg16be", "bayer_grbg16be"}: - check_ndarray(array, "uint8" if format.endswith("8") else "uint16", 2) - - if array.strides[1] != (1 if format.endswith("8") else 2): - raise ValueError("provided array does not have C_CONTIGUOUS rows") - - linesizes = (array.strides[0],) else: raise ValueError(f"Conversion from numpy array with format `{format}` is not yet supported") @@ -723,7 +740,7 @@ cdef class VideoFrame(Frame): frame = VideoFrame(array.shape[1], array.shape[0], format) copy_array_to_plane(byteswap_array(array, format.endswith("be")), frame.planes[0], 6) return frame - elif format in {"rgba64be", "rgba64le"}: + elif format in {"rgba64be", "rgba64le", "bgra64be", "bgra64le"}: check_ndarray(array, "uint16", 3) check_ndarray_shape(array, array.shape[2] == 4) frame = VideoFrame(array.shape[1], array.shape[0], format) From f811683dfd4a12b718318bb323b52466a6ff1df9 Mon Sep 17 00:00:00 2001 From: z-khan Date: Mon, 21 Apr 2025 15:35:22 +1000 Subject: [PATCH 2/6] fix bgr48 pixel formats --- av/video/frame.pyx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/av/video/frame.pyx b/av/video/frame.pyx index 4e8482210..04a14fd8b 100644 --- a/av/video/frame.pyx +++ b/av/video/frame.pyx @@ -16,7 +16,7 @@ cdef object _cinit_bypass_sentinel supported_np_pix_fmts = { "abgr", "argb", "bayer_bggr16be", "bayer_bggr16le", "bayer_bggr8", "bayer_gbrg16be", "bayer_gbrg16le", "bayer_gbrg8", "bayer_grbg16be", "bayer_grbg16le", "bayer_grbg8", - "bayer_rggb16be", "bayer_rggb16le", "bayer_rggb8", "bgr24", "bgr8", "bgra", "bgra64be", "bgra64le", + "bayer_rggb16be", "bayer_rggb16le", "bayer_rggb8", "bgr24", "bgr48be", "bgr48le", "bgr8", "bgra", "bgra64be", "bgra64le", "gbrapf32be", "gbrapf32le", "gbrp", "gbrp10be", "gbrp10le", "gbrp12be", "gbrp12le", "gbrp14be", "gbrp14le", "gbrp16be", "gbrp16le", "gbrpf32be", "gbrpf32le", "gray", "gray16be", "gray16le", "gray8", "grayf32be", "grayf32le", "nv12", "pal8", "rgb24", @@ -342,6 +342,8 @@ cdef class VideoFrame(Frame): "bayer_rggb16le": (2, "uint16"), "bayer_rggb16be": (2, "uint16"), "bgr24": (3, "uint8"), + "bgr48be": (6, "uint16"), + "bgr48le": (6, "uint16"), "bgr8": (1, "uint8"), "bgra": (4, "uint8"), "gbrapf32be": (4, "float32"), @@ -734,7 +736,7 @@ cdef class VideoFrame(Frame): elif format in {"argb", "rgba", "abgr", "bgra"}: check_ndarray(array, "uint8", 3) check_ndarray_shape(array, array.shape[2] == 4) - elif format in {"rgb48be", "rgb48le"}: + elif format in {"rgb48be", "rgb48le","bgr48be", "bgr48le"}: check_ndarray(array, "uint16", 3) check_ndarray_shape(array, array.shape[2] == 3) frame = VideoFrame(array.shape[1], array.shape[0], format) From 9ff1fb688450b40254e5ea0281821106234b6cf9 Mon Sep 17 00:00:00 2001 From: z-khan Date: Wed, 23 Apr 2025 17:52:20 +1000 Subject: [PATCH 3/6] add tests ndarray and memory shares tests for bgr48, bgra64, bayer8, bayer16 add other missing tests for gray16, grayf32 --- tests/test_videoframe.py | 218 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) diff --git a/tests/test_videoframe.py b/tests/test_videoframe.py index 9327a4ccd..34e03fc61 100644 --- a/tests/test_videoframe.py +++ b/tests/test_videoframe.py @@ -284,6 +284,25 @@ def test_ndarray_rgba_align() -> None: assert frame.format.name == format assertNdarraysEqual(frame.to_ndarray(), array) +def test_ndarray_bayer8() -> None: + array = numpy.random.randint(0, 256, size=(480, 640), dtype=numpy.uint8) + for format in ("bayer_bggr8", "bayer_gbrg8", "bayer_grbg8", "bayer_rggb8"): + frame = VideoFrame.from_ndarray(array, format=format) + assert format in av.video.frame.supported_np_pix_fmts + assert frame.width == 640 and frame.height == 480 + assert frame.format.name == format + assertNdarraysEqual(frame.to_ndarray(), array) + + +def test_ndarray_bayer16() -> None: + array = numpy.random.randint(0, 65536, size=(480, 640), dtype=numpy.uint16) + for format in ("bayer_bggr16be", "bayer_bggr16le", "bayer_gbrg16be", "bayer_gbrg16le", "bayer_grbg16be", "bayer_grbg16le", "bayer_rggb16be", "bayer_rggb16le"): + frame = VideoFrame.from_ndarray(array, format=format) + assert format in av.video.frame.supported_np_pix_fmts + assert frame.width == 640 and frame.height == 480 + assert frame.format.name == format + assertNdarraysEqual(frame.to_ndarray(), array) + def test_ndarray_gbrp() -> None: array = numpy.random.randint(0, 256, size=(480, 640, 3), dtype=numpy.uint8) @@ -571,6 +590,17 @@ def test_ndarray_rgb48be() -> None: assertPixelValue16(frame.planes[0], array[0][0][0], "big") +def test_ndarray_bgr48be() -> None: + array = numpy.random.randint(0, 65536, size=(480, 640, 3), dtype=numpy.uint16) + frame = VideoFrame.from_ndarray(array, format="bgr48be") + assert frame.width == 640 and frame.height == 480 + assert frame.format.name == "bgr48be" + assertNdarraysEqual(frame.to_ndarray(), array) + + # check endianness by examining blue value of first pixel + assertPixelValue16(frame.planes[0], array[0][0][0], "big") + + def test_ndarray_rgb48le() -> None: array = numpy.random.randint(0, 65536, size=(480, 640, 3), dtype=numpy.uint16) frame = VideoFrame.from_ndarray(array, format="rgb48le") @@ -582,6 +612,17 @@ def test_ndarray_rgb48le() -> None: assertPixelValue16(frame.planes[0], array[0][0][0], "little") +def test_ndarray_bgr48le() -> None: + array = numpy.random.randint(0, 65536, size=(480, 640, 3), dtype=numpy.uint16) + frame = VideoFrame.from_ndarray(array, format="bgr48le") + assert frame.width == 640 and frame.height == 480 + assert frame.format.name == "bgr48le" + assertNdarraysEqual(frame.to_ndarray(), array) + + # check endianness by examining blue value of first pixel + assertPixelValue16(frame.planes[0], array[0][0][0], "little") + + def test_ndarray_rgb48le_align() -> None: array = numpy.random.randint(0, 65536, size=(238, 318, 3), dtype=numpy.uint16) frame = VideoFrame.from_ndarray(array, format="rgb48le") @@ -593,6 +634,17 @@ def test_ndarray_rgb48le_align() -> None: assertPixelValue16(frame.planes[0], array[0][0][0], "little") +def test_ndarray_bgr48le_align() -> None: + array = numpy.random.randint(0, 65536, size=(238, 318, 3), dtype=numpy.uint16) + frame = VideoFrame.from_ndarray(array, format="bgr48le") + assert frame.width == 318 and frame.height == 238 + assert frame.format.name == "bgr48le" + assertNdarraysEqual(frame.to_ndarray(), array) + + # check endianness by examining blue value of first pixel + assertPixelValue16(frame.planes[0], array[0][0][0], "little") + + def test_ndarray_rgba64be() -> None: array = numpy.random.randint(0, 65536, size=(480, 640, 4), dtype=numpy.uint16) frame = VideoFrame.from_ndarray(array, format="rgba64be") @@ -604,6 +656,17 @@ def test_ndarray_rgba64be() -> None: assertPixelValue16(frame.planes[0], array[0][0][0], "big") +def test_ndarray_bgra64be() -> None: + array = numpy.random.randint(0, 65536, size=(480, 640, 4), dtype=numpy.uint16) + frame = VideoFrame.from_ndarray(array, format="bgra64be") + assert frame.width == 640 and frame.height == 480 + assert frame.format.name == "bgra64be" + assertNdarraysEqual(frame.to_ndarray(), array) + + # check endianness by examining blue value of first pixel + assertPixelValue16(frame.planes[0], array[0][0][0], "big") + + def test_ndarray_rgba64le() -> None: array = numpy.random.randint(0, 65536, size=(480, 640, 4), dtype=numpy.uint16) frame = VideoFrame.from_ndarray(array, format="rgba64le") @@ -615,6 +678,17 @@ def test_ndarray_rgba64le() -> None: assertPixelValue16(frame.planes[0], array[0][0][0], "little") +def test_ndarray_bgra64le() -> None: + array = numpy.random.randint(0, 65536, size=(480, 640, 4), dtype=numpy.uint16) + frame = VideoFrame.from_ndarray(array, format="bgra64le") + assert frame.width == 640 and frame.height == 480 + assert frame.format.name == "bgra64le" + assertNdarraysEqual(frame.to_ndarray(), array) + + # check endianness by examining blue value of first pixel + assertPixelValue16(frame.planes[0], array[0][0][0], "little") + + def test_ndarray_rgb8() -> None: array = numpy.random.randint(0, 256, size=(480, 640), dtype=numpy.uint8) frame = VideoFrame.from_ndarray(array, format="rgb8") @@ -709,6 +783,42 @@ def test_shares_memory_gray8() -> None: assertNdarraysEqual(frame.to_ndarray(), array) +def test_shares_memory_gray16() -> None: + array = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) + frame = VideoFrame.from_numpy_buffer(array, "gray16") + assertNdarraysEqual(frame.to_ndarray(), array) + + array[...] = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) + assertNdarraysEqual(frame.to_ndarray(), array) + + array = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) + array = array[:, :300] + assert not array.data.c_contiguous + frame = VideoFrame.from_numpy_buffer(array, "gray16") + assertNdarraysEqual(frame.to_ndarray(), array) + + array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) + assertNdarraysEqual(frame.to_ndarray(), array) + + +def test_shares_memory_grayf32() -> None: + array = numpy.random.rand(357, 318).astype(numpy.float32) + frame = VideoFrame.from_numpy_buffer(array, "grayf32") + assertNdarraysEqual(frame.to_ndarray(), array) + + array[...] = numpy.random.rand(357, 318).astype(numpy.float32) + assertNdarraysEqual(frame.to_ndarray(), array) + + array = numpy.random.rand(357, 318).astype(numpy.float32) + array = array[:, :300] + assert not array.data.c_contiguous + frame = VideoFrame.from_numpy_buffer(array, "grayf32") + assertNdarraysEqual(frame.to_ndarray(), array) + + array[...] = numpy.random.rand(*array.shape).astype(numpy.float32) + assertNdarraysEqual(frame.to_ndarray(), array) + + def test_shares_memory_rgb8() -> None: array = numpy.random.randint(0, 256, size=(357, 318), dtype=numpy.uint8) frame = VideoFrame.from_numpy_buffer(array, "rgb8") @@ -781,6 +891,30 @@ def test_shares_memory_rgb24() -> None: assertNdarraysEqual(frame.to_ndarray(), array) +def test_shares_memory_rgb48() -> None: + array = numpy.random.randint(0, 65536, size=(357, 318, 3), dtype=numpy.uint16) + frame = VideoFrame.from_numpy_buffer(array, "rgb48") + assertNdarraysEqual(frame.to_ndarray(), array) + + # overwrite the array, the contents thereof + array[...] = numpy.random.randint(0, 65536, size=(357, 318, 3), dtype=numpy.uint16) + # Make sure the frame reflects that + assertNdarraysEqual(frame.to_ndarray(), array) + + # repeat the test, but with an array that is not fully contiguous, though the + # pixels in a row are + array = numpy.random.randint(0, 65536, size=(357, 318, 3), dtype=numpy.uint16) + array = array[:, :300, :] + assert not array.data.c_contiguous + frame = VideoFrame.from_numpy_buffer(array, "rgb48") + assertNdarraysEqual(frame.to_ndarray(), array) + + # overwrite the array, the contents thereof + array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) + # Make sure the frame reflects that + assertNdarraysEqual(frame.to_ndarray(), array) + + def test_shares_memory_rgba() -> None: array = numpy.random.randint(0, 256, size=(357, 318, 4), dtype=numpy.uint8) frame = VideoFrame.from_numpy_buffer(array, "rgba") @@ -805,6 +939,68 @@ def test_shares_memory_rgba() -> None: assertNdarraysEqual(frame.to_ndarray(), array) +def test_shares_memory_rgba64() -> None: + array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) + frame = VideoFrame.from_numpy_buffer(array, "rgba64") + assertNdarraysEqual(frame.to_ndarray(), array) + + # overwrite the array, the contents thereof + array[...] = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) + # Make sure the frame reflects that + assertNdarraysEqual(frame.to_ndarray(), array) + + # repeat the test, but with an array that is not fully contiguous, though the + # pixels in a row are + array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) + array = array[:, :300, :] + assert not array.data.c_contiguous + frame = VideoFrame.from_numpy_buffer(array, "rgba64") + assertNdarraysEqual(frame.to_ndarray(), array) + + # overwrite the array, the contents thereof + array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) + # Make sure the frame reflects that + assertNdarraysEqual(frame.to_ndarray(), array) + + +def test_shares_memory_bayer8() -> None: + for format in ("bayer_rggb8", "bayer_bggr8", "bayer_grbg8", "bayer_gbrg8"): + array = numpy.random.randint(0, 256, size=(357, 318), dtype=numpy.uint8) + frame = VideoFrame.from_numpy_buffer(array, format) + assertNdarraysEqual(frame.to_ndarray(), array) + + array[...] = numpy.random.randint(0, 256, size=(357, 318), dtype=numpy.uint8) + assertNdarraysEqual(frame.to_ndarray(), array) + + array = numpy.random.randint(0, 256, size=(357, 318), dtype=numpy.uint8) + array = array[:, :300] + assert not array.data.c_contiguous + frame = VideoFrame.from_numpy_buffer(array, format) + assertNdarraysEqual(frame.to_ndarray(), array) + + array[...] = numpy.random.randint(0, 256, size=array.shape, dtype=numpy.uint8) + assertNdarraysEqual(frame.to_ndarray(), array) + + +def test_shares_memory_bayer16() -> None: + for format in ("bayer_rggb16", "bayer_bggr16", "bayer_grbg16", "bayer_gbrg16"): + array = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) + frame = VideoFrame.from_numpy_buffer(array, format) + assertNdarraysEqual(frame.to_ndarray(), array) + + array[...] = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) + assertNdarraysEqual(frame.to_ndarray(), array) + + array = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) + array = array[:, :300] + assert not array.data.c_contiguous + frame = VideoFrame.from_numpy_buffer(array, format) + assertNdarraysEqual(frame.to_ndarray(), array) + + array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) + assertNdarraysEqual(frame.to_ndarray(), array) + + def test_shares_memory_yuv420p() -> None: array = numpy.random.randint(0, 256, size=(512 * 6 // 4, 256), dtype=numpy.uint8) frame = VideoFrame.from_numpy_buffer(array, "yuv420p") @@ -960,6 +1156,28 @@ def test_shares_memory_bgra() -> None: # Make sure the frame reflects that assertNdarraysEqual(frame.to_ndarray(), array) +def test_shares_memory_bgra64() -> None: + array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) + frame = VideoFrame.from_numpy_buffer(array, "bgra64") + assertNdarraysEqual(frame.to_ndarray(), array) + + # overwrite the array, the contents thereof + array[...] = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) + # Make sure the frame reflects that + assertNdarraysEqual(frame.to_ndarray(), array) + + # repeat the test, but with an array that is not fully contiguous, though the + # pixels in a row are + array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) + array = array[:, :300, :] + assert not array.data.c_contiguous + frame = VideoFrame.from_numpy_buffer(array, "bgra64") + assertNdarraysEqual(frame.to_ndarray(), array) + + # overwrite the array, the contents thereof + array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) + # Make sure the frame reflects that + assertNdarraysEqual(frame.to_ndarray(), array) def test_reformat_pts() -> None: frame = VideoFrame(640, 480, "rgb24") From 235d3c0f1f5a81d4bf29b30e5f6eddd91614d6d2 Mon Sep 17 00:00:00 2001 From: z-khan Date: Wed, 23 Apr 2025 18:21:42 +1000 Subject: [PATCH 4/6] fix endianness specify endianness with format name in tests --- tests/test_videoframe.py | 185 ++++++++++++++++++++------------------- 1 file changed, 95 insertions(+), 90 deletions(-) diff --git a/tests/test_videoframe.py b/tests/test_videoframe.py index 34e03fc61..95504ecab 100644 --- a/tests/test_videoframe.py +++ b/tests/test_videoframe.py @@ -784,39 +784,41 @@ def test_shares_memory_gray8() -> None: def test_shares_memory_gray16() -> None: - array = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) - frame = VideoFrame.from_numpy_buffer(array, "gray16") - assertNdarraysEqual(frame.to_ndarray(), array) - - array[...] = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) - assertNdarraysEqual(frame.to_ndarray(), array) - - array = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) - array = array[:, :300] - assert not array.data.c_contiguous - frame = VideoFrame.from_numpy_buffer(array, "gray16") - assertNdarraysEqual(frame.to_ndarray(), array) - - array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) - assertNdarraysEqual(frame.to_ndarray(), array) + for format in ("gray16be", "gray16le"): + array = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) + frame = VideoFrame.from_numpy_buffer(array, format) + assertNdarraysEqual(frame.to_ndarray(), array) + + array[...] = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) + assertNdarraysEqual(frame.to_ndarray(), array) + + array = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) + array = array[:, :300] + assert not array.data.c_contiguous + frame = VideoFrame.from_numpy_buffer(array, format) + assertNdarraysEqual(frame.to_ndarray(), array) + + array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) + assertNdarraysEqual(frame.to_ndarray(), array) def test_shares_memory_grayf32() -> None: - array = numpy.random.rand(357, 318).astype(numpy.float32) - frame = VideoFrame.from_numpy_buffer(array, "grayf32") - assertNdarraysEqual(frame.to_ndarray(), array) - - array[...] = numpy.random.rand(357, 318).astype(numpy.float32) - assertNdarraysEqual(frame.to_ndarray(), array) - - array = numpy.random.rand(357, 318).astype(numpy.float32) - array = array[:, :300] - assert not array.data.c_contiguous - frame = VideoFrame.from_numpy_buffer(array, "grayf32") - assertNdarraysEqual(frame.to_ndarray(), array) - - array[...] = numpy.random.rand(*array.shape).astype(numpy.float32) - assertNdarraysEqual(frame.to_ndarray(), array) + for format in ("grayf32be", "grayf32le"): + array = numpy.random.rand(357, 318).astype(numpy.float32) + frame = VideoFrame.from_numpy_buffer(array, format) + assertNdarraysEqual(frame.to_ndarray(), array) + + array[...] = numpy.random.rand(357, 318).astype(numpy.float32) + assertNdarraysEqual(frame.to_ndarray(), array) + + array = numpy.random.rand(357, 318).astype(numpy.float32) + array = array[:, :300] + assert not array.data.c_contiguous + frame = VideoFrame.from_numpy_buffer(array, format) + assertNdarraysEqual(frame.to_ndarray(), array) + + array[...] = numpy.random.rand(*array.shape).astype(numpy.float32) + assertNdarraysEqual(frame.to_ndarray(), array) def test_shares_memory_rgb8() -> None: @@ -891,28 +893,29 @@ def test_shares_memory_rgb24() -> None: assertNdarraysEqual(frame.to_ndarray(), array) -def test_shares_memory_rgb48() -> None: - array = numpy.random.randint(0, 65536, size=(357, 318, 3), dtype=numpy.uint16) - frame = VideoFrame.from_numpy_buffer(array, "rgb48") - assertNdarraysEqual(frame.to_ndarray(), array) - - # overwrite the array, the contents thereof - array[...] = numpy.random.randint(0, 65536, size=(357, 318, 3), dtype=numpy.uint16) - # Make sure the frame reflects that - assertNdarraysEqual(frame.to_ndarray(), array) - - # repeat the test, but with an array that is not fully contiguous, though the - # pixels in a row are - array = numpy.random.randint(0, 65536, size=(357, 318, 3), dtype=numpy.uint16) - array = array[:, :300, :] - assert not array.data.c_contiguous - frame = VideoFrame.from_numpy_buffer(array, "rgb48") - assertNdarraysEqual(frame.to_ndarray(), array) - - # overwrite the array, the contents thereof - array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) - # Make sure the frame reflects that - assertNdarraysEqual(frame.to_ndarray(), array) +def test_shares_memory_rgb48() -> None: + for format in ("rgb48be", "rgb48le"): + array = numpy.random.randint(0, 65536, size=(357, 318, 3), dtype=numpy.uint16) + frame = VideoFrame.from_numpy_buffer(array, format) + assertNdarraysEqual(frame.to_ndarray(), array) + + # overwrite the array, the contents thereof + array[...] = numpy.random.randint(0, 65536, size=(357, 318, 3), dtype=numpy.uint16) + # Make sure the frame reflects that + assertNdarraysEqual(frame.to_ndarray(), array) + + # repeat the test, but with an array that is not fully contiguous, though the + # pixels in a row are + array = numpy.random.randint(0, 65536, size=(357, 318, 3), dtype=numpy.uint16) + array = array[:, :300, :] + assert not array.data.c_contiguous + frame = VideoFrame.from_numpy_buffer(array, format) + assertNdarraysEqual(frame.to_ndarray(), array) + + # overwrite the array, the contents thereof + array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) + # Make sure the frame reflects that + assertNdarraysEqual(frame.to_ndarray(), array) def test_shares_memory_rgba() -> None: @@ -939,27 +942,28 @@ def test_shares_memory_rgba() -> None: assertNdarraysEqual(frame.to_ndarray(), array) -def test_shares_memory_rgba64() -> None: - array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) - frame = VideoFrame.from_numpy_buffer(array, "rgba64") - assertNdarraysEqual(frame.to_ndarray(), array) - - # overwrite the array, the contents thereof - array[...] = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) - # Make sure the frame reflects that - assertNdarraysEqual(frame.to_ndarray(), array) - - # repeat the test, but with an array that is not fully contiguous, though the - # pixels in a row are - array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) - array = array[:, :300, :] - assert not array.data.c_contiguous - frame = VideoFrame.from_numpy_buffer(array, "rgba64") - assertNdarraysEqual(frame.to_ndarray(), array) - - # overwrite the array, the contents thereof - array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) - # Make sure the frame reflects that +def test_shares_memory_rgba64() -> None: + for format in ("rgba64be", "rgba64le"): + array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) + frame = VideoFrame.from_numpy_buffer(array, format) + assertNdarraysEqual(frame.to_ndarray(), array) + + # overwrite the array, the contents thereof + array[...] = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) + # Make sure the frame reflects that + assertNdarraysEqual(frame.to_ndarray(), array) + + # repeat the test, but with an array that is not fully contiguous, though the + # pixels in a row are + array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) + array = array[:, :300, :] + assert not array.data.c_contiguous + frame = VideoFrame.from_numpy_buffer(array, format) + assertNdarraysEqual(frame.to_ndarray(), array) + + # overwrite the array, the contents thereof + array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) + # Make sure the frame reflects that assertNdarraysEqual(frame.to_ndarray(), array) @@ -983,7 +987,7 @@ def test_shares_memory_bayer8() -> None: def test_shares_memory_bayer16() -> None: - for format in ("bayer_rggb16", "bayer_bggr16", "bayer_grbg16", "bayer_gbrg16"): + for format in ("bayer_rggb16be","bayer_rggb16le", "bayer_bggr16be", "bayer_bggr16le", "bayer_grbg16be", "bayer_grbg16le", "bayer_gbrg16be", "bayer_gbrg16le"): array = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) frame = VideoFrame.from_numpy_buffer(array, format) assertNdarraysEqual(frame.to_ndarray(), array) @@ -1157,22 +1161,23 @@ def test_shares_memory_bgra() -> None: assertNdarraysEqual(frame.to_ndarray(), array) def test_shares_memory_bgra64() -> None: - array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) - frame = VideoFrame.from_numpy_buffer(array, "bgra64") - assertNdarraysEqual(frame.to_ndarray(), array) - - # overwrite the array, the contents thereof - array[...] = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) - # Make sure the frame reflects that - assertNdarraysEqual(frame.to_ndarray(), array) - - # repeat the test, but with an array that is not fully contiguous, though the - # pixels in a row are - array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) - array = array[:, :300, :] - assert not array.data.c_contiguous - frame = VideoFrame.from_numpy_buffer(array, "bgra64") - assertNdarraysEqual(frame.to_ndarray(), array) + for format in ("bgra64be","bgra64le"): + array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) + frame = VideoFrame.from_numpy_buffer(array, format) + assertNdarraysEqual(frame.to_ndarray(), array) + + # overwrite the array, the contents thereof + array[...] = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) + # Make sure the frame reflects that + assertNdarraysEqual(frame.to_ndarray(), array) + + # repeat the test, but with an array that is not fully contiguous, though the + # pixels in a row are + array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) + array = array[:, :300, :] + assert not array.data.c_contiguous + frame = VideoFrame.from_numpy_buffer(array, format) + assertNdarraysEqual(frame.to_ndarray(), array) # overwrite the array, the contents thereof array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) From e7d2b9d9f266953d7615d4e0130130578c9c7a45 Mon Sep 17 00:00:00 2001 From: z-khan Date: Wed, 23 Apr 2025 19:11:26 +1000 Subject: [PATCH 5/6] remove shares memory tests for some formats The returned array need to be compared with original array after byteswap depending on the system byte order and format byte order. Since no such share memory tests exist for previous formats ending with "le" or "be", I'm removing these tests. --- tests/test_videoframe.py | 130 --------------------------------------- 1 file changed, 130 deletions(-) diff --git a/tests/test_videoframe.py b/tests/test_videoframe.py index 95504ecab..04d014660 100644 --- a/tests/test_videoframe.py +++ b/tests/test_videoframe.py @@ -783,44 +783,6 @@ def test_shares_memory_gray8() -> None: assertNdarraysEqual(frame.to_ndarray(), array) -def test_shares_memory_gray16() -> None: - for format in ("gray16be", "gray16le"): - array = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) - frame = VideoFrame.from_numpy_buffer(array, format) - assertNdarraysEqual(frame.to_ndarray(), array) - - array[...] = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) - assertNdarraysEqual(frame.to_ndarray(), array) - - array = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) - array = array[:, :300] - assert not array.data.c_contiguous - frame = VideoFrame.from_numpy_buffer(array, format) - assertNdarraysEqual(frame.to_ndarray(), array) - - array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) - assertNdarraysEqual(frame.to_ndarray(), array) - - -def test_shares_memory_grayf32() -> None: - for format in ("grayf32be", "grayf32le"): - array = numpy.random.rand(357, 318).astype(numpy.float32) - frame = VideoFrame.from_numpy_buffer(array, format) - assertNdarraysEqual(frame.to_ndarray(), array) - - array[...] = numpy.random.rand(357, 318).astype(numpy.float32) - assertNdarraysEqual(frame.to_ndarray(), array) - - array = numpy.random.rand(357, 318).astype(numpy.float32) - array = array[:, :300] - assert not array.data.c_contiguous - frame = VideoFrame.from_numpy_buffer(array, format) - assertNdarraysEqual(frame.to_ndarray(), array) - - array[...] = numpy.random.rand(*array.shape).astype(numpy.float32) - assertNdarraysEqual(frame.to_ndarray(), array) - - def test_shares_memory_rgb8() -> None: array = numpy.random.randint(0, 256, size=(357, 318), dtype=numpy.uint8) frame = VideoFrame.from_numpy_buffer(array, "rgb8") @@ -893,31 +855,6 @@ def test_shares_memory_rgb24() -> None: assertNdarraysEqual(frame.to_ndarray(), array) -def test_shares_memory_rgb48() -> None: - for format in ("rgb48be", "rgb48le"): - array = numpy.random.randint(0, 65536, size=(357, 318, 3), dtype=numpy.uint16) - frame = VideoFrame.from_numpy_buffer(array, format) - assertNdarraysEqual(frame.to_ndarray(), array) - - # overwrite the array, the contents thereof - array[...] = numpy.random.randint(0, 65536, size=(357, 318, 3), dtype=numpy.uint16) - # Make sure the frame reflects that - assertNdarraysEqual(frame.to_ndarray(), array) - - # repeat the test, but with an array that is not fully contiguous, though the - # pixels in a row are - array = numpy.random.randint(0, 65536, size=(357, 318, 3), dtype=numpy.uint16) - array = array[:, :300, :] - assert not array.data.c_contiguous - frame = VideoFrame.from_numpy_buffer(array, format) - assertNdarraysEqual(frame.to_ndarray(), array) - - # overwrite the array, the contents thereof - array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) - # Make sure the frame reflects that - assertNdarraysEqual(frame.to_ndarray(), array) - - def test_shares_memory_rgba() -> None: array = numpy.random.randint(0, 256, size=(357, 318, 4), dtype=numpy.uint8) frame = VideoFrame.from_numpy_buffer(array, "rgba") @@ -942,31 +879,6 @@ def test_shares_memory_rgba() -> None: assertNdarraysEqual(frame.to_ndarray(), array) -def test_shares_memory_rgba64() -> None: - for format in ("rgba64be", "rgba64le"): - array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) - frame = VideoFrame.from_numpy_buffer(array, format) - assertNdarraysEqual(frame.to_ndarray(), array) - - # overwrite the array, the contents thereof - array[...] = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) - # Make sure the frame reflects that - assertNdarraysEqual(frame.to_ndarray(), array) - - # repeat the test, but with an array that is not fully contiguous, though the - # pixels in a row are - array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) - array = array[:, :300, :] - assert not array.data.c_contiguous - frame = VideoFrame.from_numpy_buffer(array, format) - assertNdarraysEqual(frame.to_ndarray(), array) - - # overwrite the array, the contents thereof - array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) - # Make sure the frame reflects that - assertNdarraysEqual(frame.to_ndarray(), array) - - def test_shares_memory_bayer8() -> None: for format in ("bayer_rggb8", "bayer_bggr8", "bayer_grbg8", "bayer_gbrg8"): array = numpy.random.randint(0, 256, size=(357, 318), dtype=numpy.uint8) @@ -986,25 +898,6 @@ def test_shares_memory_bayer8() -> None: assertNdarraysEqual(frame.to_ndarray(), array) -def test_shares_memory_bayer16() -> None: - for format in ("bayer_rggb16be","bayer_rggb16le", "bayer_bggr16be", "bayer_bggr16le", "bayer_grbg16be", "bayer_grbg16le", "bayer_gbrg16be", "bayer_gbrg16le"): - array = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) - frame = VideoFrame.from_numpy_buffer(array, format) - assertNdarraysEqual(frame.to_ndarray(), array) - - array[...] = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) - assertNdarraysEqual(frame.to_ndarray(), array) - - array = numpy.random.randint(0, 65536, size=(357, 318), dtype=numpy.uint16) - array = array[:, :300] - assert not array.data.c_contiguous - frame = VideoFrame.from_numpy_buffer(array, format) - assertNdarraysEqual(frame.to_ndarray(), array) - - array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) - assertNdarraysEqual(frame.to_ndarray(), array) - - def test_shares_memory_yuv420p() -> None: array = numpy.random.randint(0, 256, size=(512 * 6 // 4, 256), dtype=numpy.uint8) frame = VideoFrame.from_numpy_buffer(array, "yuv420p") @@ -1160,29 +1053,6 @@ def test_shares_memory_bgra() -> None: # Make sure the frame reflects that assertNdarraysEqual(frame.to_ndarray(), array) -def test_shares_memory_bgra64() -> None: - for format in ("bgra64be","bgra64le"): - array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) - frame = VideoFrame.from_numpy_buffer(array, format) - assertNdarraysEqual(frame.to_ndarray(), array) - - # overwrite the array, the contents thereof - array[...] = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) - # Make sure the frame reflects that - assertNdarraysEqual(frame.to_ndarray(), array) - - # repeat the test, but with an array that is not fully contiguous, though the - # pixels in a row are - array = numpy.random.randint(0, 65536, size=(357, 318, 4), dtype=numpy.uint16) - array = array[:, :300, :] - assert not array.data.c_contiguous - frame = VideoFrame.from_numpy_buffer(array, format) - assertNdarraysEqual(frame.to_ndarray(), array) - - # overwrite the array, the contents thereof - array[...] = numpy.random.randint(0, 65536, size=array.shape, dtype=numpy.uint16) - # Make sure the frame reflects that - assertNdarraysEqual(frame.to_ndarray(), array) def test_reformat_pts() -> None: frame = VideoFrame(640, 480, "rgb24") From 6470421b9aaad4b028988ee8a064794ebde1677e Mon Sep 17 00:00:00 2001 From: WyattBlue Date: Wed, 23 Apr 2025 17:10:43 -0400 Subject: [PATCH 6/6] format --- tests/test_videoframe.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/test_videoframe.py b/tests/test_videoframe.py index 04d014660..26549b31b 100644 --- a/tests/test_videoframe.py +++ b/tests/test_videoframe.py @@ -284,6 +284,7 @@ def test_ndarray_rgba_align() -> None: assert frame.format.name == format assertNdarraysEqual(frame.to_ndarray(), array) + def test_ndarray_bayer8() -> None: array = numpy.random.randint(0, 256, size=(480, 640), dtype=numpy.uint8) for format in ("bayer_bggr8", "bayer_gbrg8", "bayer_grbg8", "bayer_rggb8"): @@ -296,7 +297,16 @@ def test_ndarray_bayer8() -> None: def test_ndarray_bayer16() -> None: array = numpy.random.randint(0, 65536, size=(480, 640), dtype=numpy.uint16) - for format in ("bayer_bggr16be", "bayer_bggr16le", "bayer_gbrg16be", "bayer_gbrg16le", "bayer_grbg16be", "bayer_grbg16le", "bayer_rggb16be", "bayer_rggb16le"): + for format in ( + "bayer_bggr16be", + "bayer_bggr16le", + "bayer_gbrg16be", + "bayer_gbrg16le", + "bayer_grbg16be", + "bayer_grbg16le", + "bayer_rggb16be", + "bayer_rggb16le", + ): frame = VideoFrame.from_ndarray(array, format=format) assert format in av.video.frame.supported_np_pix_fmts assert frame.width == 640 and frame.height == 480