@@ -21,7 +21,7 @@ supported_np_pix_fmts = {
2121 " gbrp14be" , " gbrp14le" , " gbrp16be" , " gbrp16le" , " gbrpf32be" , " gbrpf32le" , " gray" ,
2222 " gray16be" , " gray16le" , " gray8" , " grayf32be" , " grayf32le" , " nv12" , " pal8" , " rgb24" ,
2323 " rgb48be" , " rgb48le" , " rgb8" , " rgba" , " rgba64be" , " rgba64le" , " yuv420p" ,
24- " yuv422p10le" , " yuv444p" , " yuv444p16be" , " yuv444p16le" , " yuva444p16be" ,
24+ " yuv420p10le " , " yuv422p10le" , " yuv444p" , " yuv444p16be" , " yuv444p16le" , " yuva444p16be" ,
2525 " yuva444p16le" , " yuvj420p" , " yuvj444p" , " yuyv422" ,
2626}
2727
@@ -321,7 +321,7 @@ cdef class VideoFrame(Frame):
321321 import numpy as np
322322
323323 # check size
324- if frame.format.name in {" yuv420p" , " yuvj420p" , " yuyv422" , " yuv422p10le" }:
324+ if frame.format.name in {" yuv420p" , " yuvj420p" , " yuyv422" , " yuv420p10le " , " yuv422p10le" }:
325325 assert frame.width % 2 == 0 , " the width has to be even for this pixel format"
326326 assert frame.height % 2 == 0 , " the height has to be even for this pixel format"
327327
@@ -407,6 +407,16 @@ cdef class VideoFrame(Frame):
407407 useful_array(frame.planes[1 ]),
408408 useful_array(frame.planes[2 ]),
409409 ]).reshape(- 1 , frame.width)
410+ if frame.format.name == " yuv420p10le" :
411+ # Read planes as uint16:
412+ y = useful_array(frame.planes[0 ], 2 , " uint16" ).reshape(frame.height, frame.width)
413+ u = useful_array(frame.planes[1 ], 2 , " uint16" ).reshape(frame.height // 2 , frame.width // 2 )
414+ v = useful_array(frame.planes[2 ], 2 , " uint16" ).reshape(frame.height // 2 , frame.width // 2 )
415+ u_full = np.repeat(np.repeat(u, 2 , axis = 1 ), 2 , axis = 0 )
416+ v_full = np.repeat(np.repeat(u, 2 , axis = 1 ), 2 , axis = 0 )
417+ if channel_last:
418+ return np.stack([y, u_full, v_full], axis = 2 )
419+ return np.stack([y, u_full, v_full], axis = 0 )
410420 if frame.format.name == " yuv422p10le" :
411421 # Read planes as uint16 at their original width
412422 y = useful_array(frame.planes[0 ], 2 , " uint16" ).reshape(frame.height, frame.width)
@@ -652,6 +662,28 @@ cdef class VideoFrame(Frame):
652662 copy_array_to_plane(flat[u_start:v_start], frame.planes[1 ], 1 )
653663 copy_array_to_plane(flat[v_start:], frame.planes[2 ], 1 )
654664 return frame
665+ elif format == " yuv420p10le" :
666+ if not isinstance (array, np.ndarray) or array.dtype != np.uint16:
667+ raise ValueError (" Array must be uint16 type" )
668+
669+ # Convert to channel-first if needed:
670+ if channel_last and array.shape[2 ] == 3 :
671+ array = np.moveaxis(array, 2 , 0 )
672+ elif not (array.shape[0 ] == 3 ):
673+ raise ValueError (" Array must have shape (3, height, width) or (height, width, 3)" )
674+
675+ height, width = array.shape[1 :]
676+ if width % 2 != 0 or height % 2 != 0 :
677+ raise ValueError (" Width and height must be even" )
678+
679+ frame = VideoFrame(width, height, format)
680+ copy_array_to_plane(array[0 ], frame.planes[0 ], 2 )
681+ # Subsample U and V by taking every other row and column:
682+ u = array[1 , ::2 , ::2 ].copy() # Need copy to ensure C-contiguous
683+ v = array[2 , ::2 , ::2 ].copy() # Need copy to ensure C-contiguous
684+ copy_array_to_plane(u, frame.planes[1 ], 2 )
685+ copy_array_to_plane(v, frame.planes[2 ], 2 )
686+ return frame
655687 elif format == " yuv422p10le" :
656688 if not isinstance (array, np.ndarray) or array.dtype != np.uint16:
657689 raise ValueError (" Array must be uint16 type" )
0 commit comments