Skip to content

Commit d979acb

Browse files
waderWyattBlue
authored andcommitted
Add yuv422p support for video frame to_ndarray and from_ndarray
1 parent 6a0cf68 commit d979acb

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

av/video/frame.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,13 @@ 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 {
453+
"yuv420p",
454+
"yuvj420p",
455+
"yuyv422",
456+
"yuv422p10le",
457+
"yuv422p",
458+
}:
453459
assert frame.width % 2 == 0, (
454460
"the width has to be even for this pixel format"
455461
)
@@ -563,7 +569,7 @@ def to_ndarray(self, channel_last=False, **kwargs):
563569
return array
564570

565571
# special cases
566-
if frame.format.name in {"yuv420p", "yuvj420p"}:
572+
if frame.format.name in {"yuv420p", "yuvj420p", "yuv422p"}:
567573
return np.hstack(
568574
[
569575
useful_array(frame.planes[0]),
@@ -1022,6 +1028,19 @@ def from_ndarray(array, format="rgb24", channel_last=False):
10221028
copy_array_to_plane(flat[u_start:v_start], frame.planes[1], 1)
10231029
copy_array_to_plane(flat[v_start:], frame.planes[2], 1)
10241030
return frame
1031+
elif format == "yuv422p":
1032+
check_ndarray(array, "uint8", 2)
1033+
check_ndarray_shape(array, array.shape[0] % 4 == 0)
1034+
check_ndarray_shape(array, array.shape[1] % 2 == 0)
1035+
1036+
frame = VideoFrame(array.shape[1], array.shape[0] // 2, format)
1037+
u_start = frame.width * frame.height
1038+
v_start = u_start + u_start // 2
1039+
flat = array.reshape(-1)
1040+
copy_array_to_plane(flat[0:u_start], frame.planes[0], 1)
1041+
copy_array_to_plane(flat[u_start:v_start], frame.planes[1], 1)
1042+
copy_array_to_plane(flat[v_start:], frame.planes[2], 1)
1043+
return frame
10251044
elif format == "yuv422p10le":
10261045
if not isinstance(array, np.ndarray) or array.dtype != np.uint16:
10271046
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)