Skip to content

Commit 32b1f24

Browse files
committed
Add yuv422p support for video frame to_ndarray and from_ndarray
1 parent 6a0cf68 commit 32b1f24

File tree

2 files changed

+23
-2
lines changed

2 files changed

+23
-2
lines changed

av/video/frame.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ def to_ndarray(self, channel_last=False, **kwargs):
449449
import numpy as np
450450

451451
# check size
452-
if frame.format.name in {"yuv420p", "yuvj420p", "yuyv422", "yuv422p10le"}:
452+
if frame.format.name in {"yuv420p", "yuvj420p", "yuyv422", "yuv422p10le", "yuv422p"}:
453453
assert frame.width % 2 == 0, (
454454
"the width has to be even for this pixel format"
455455
)
@@ -563,7 +563,7 @@ def to_ndarray(self, channel_last=False, **kwargs):
563563
return array
564564

565565
# special cases
566-
if frame.format.name in {"yuv420p", "yuvj420p"}:
566+
if frame.format.name in {"yuv420p", "yuvj420p", "yuv422p"}:
567567
return np.hstack(
568568
[
569569
useful_array(frame.planes[0]),
@@ -1022,6 +1022,19 @@ def from_ndarray(array, format="rgb24", channel_last=False):
10221022
copy_array_to_plane(flat[u_start:v_start], frame.planes[1], 1)
10231023
copy_array_to_plane(flat[v_start:], frame.planes[2], 1)
10241024
return frame
1025+
elif format == "yuv422p":
1026+
check_ndarray(array, "uint8", 2)
1027+
check_ndarray_shape(array, array.shape[0] % 4 == 0)
1028+
check_ndarray_shape(array, array.shape[1] % 2 == 0)
1029+
1030+
frame = VideoFrame(array.shape[1], array.shape[0] // 2, format)
1031+
u_start = frame.width * frame.height
1032+
v_start = u_start + u_start // 2
1033+
flat = array.reshape(-1)
1034+
copy_array_to_plane(flat[0:u_start], frame.planes[0], 1)
1035+
copy_array_to_plane(flat[u_start:v_start], frame.planes[1], 1)
1036+
copy_array_to_plane(flat[v_start:], frame.planes[2], 1)
1037+
return frame
10251038
elif format == "yuv422p10le":
10261039
if not isinstance(array, np.ndarray) or array.dtype != np.uint16:
10271040
raise ValueError("Array must be uint16 type")

tests/test_videoframe.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,14 @@ def test_ndarray_yuv420p() -> None:
648648
assertNdarraysEqual(frame.to_ndarray(), array)
649649

650650

651+
def test_ndarray_yuv422p() -> None:
652+
array = numpy.random.randint(0, 256, size=(960, 640), dtype=numpy.uint8)
653+
frame = VideoFrame.from_ndarray(array, format="yuv422p")
654+
assert frame.width == 640 and frame.height == 480
655+
assert frame.format.name == "yuv422p"
656+
assertNdarraysEqual(frame.to_ndarray(), array)
657+
658+
651659
def test_ndarray_yuv420p_align() -> None:
652660
array = numpy.random.randint(0, 256, size=(357, 318), dtype=numpy.uint8)
653661
frame = VideoFrame.from_ndarray(array, format="yuv420p")

0 commit comments

Comments
 (0)