@@ -20,9 +20,9 @@ supported_np_pix_fmts = {
2020 " gbrapf32be" , " gbrapf32le" , " gbrp" , " gbrp10be" , " gbrp10le" , " gbrp12be" , " gbrp12le" ,
2121 " gbrp14be" , " gbrp14le" , " gbrp16be" , " gbrp16le" , " gbrpf32be" , " gbrpf32le" , " gray" ,
2222 " gray16be" , " gray16le" , " gray8" , " grayf32be" , " grayf32le" , " nv12" , " pal8" , " rgb24" ,
23- " rgb48be" , " rgb48le" , " rgb8" , " rgba" , " rgba64be" , " rgba64le" , " yuv420p" , " yuv444p " ,
24- " yuv444p16be " , " yuv444p16le " , " yuva444p16be " , " yuva444p16le " , " yuvj420p " ,
25- " yuvj444p" , " yuyv422" ,
23+ " rgb48be" , " rgb48le" , " rgb8" , " rgba" , " rgba64be" , " rgba64le" , " yuv420p" ,
24+ " yuv422p10le " , " yuv444p " , " yuv444p16be " , " yuv444p16le " , " yuva444p16be " ,
25+ " yuva444p16le " , " yuvj420p " , " yuvj444p" , " yuyv422" ,
2626}
2727
2828cdef VideoFrame alloc_video_frame():
@@ -322,7 +322,7 @@ cdef class VideoFrame(Frame):
322322 import numpy as np
323323
324324 # check size
325- if frame.format.name in {" yuv420p" , " yuvj420p" , " yuyv422" }:
325+ if frame.format.name in {" yuv420p" , " yuvj420p" , " yuyv422" , " yuv422p10le " }:
326326 assert frame.width % 2 == 0 , " the width has to be even for this pixel format"
327327 assert frame.height % 2 == 0 , " the height has to be even for this pixel format"
328328
@@ -408,6 +408,18 @@ cdef class VideoFrame(Frame):
408408 useful_array(frame.planes[1 ]),
409409 useful_array(frame.planes[2 ]),
410410 ]).reshape(- 1 , frame.width)
411+ if frame.format.name == " yuv422p10le" :
412+ # Read planes as uint16 at their original width
413+ y = useful_array(frame.planes[0 ], 2 , " uint16" ).reshape(frame.height, frame.width)
414+ u = useful_array(frame.planes[1 ], 2 , " uint16" ).reshape(frame.height, frame.width // 2 )
415+ v = useful_array(frame.planes[2 ], 2 , " uint16" ).reshape(frame.height, frame.width // 2 )
416+
417+ # Double the width of U and V by repeating each value
418+ u_full = np.repeat(u, 2 , axis = 1 )
419+ v_full = np.repeat(v, 2 , axis = 1 )
420+ if channel_last:
421+ return np.stack([y, u_full, v_full], axis = 2 )
422+ return np.stack([y, u_full, v_full], axis = 0 )
411423 if frame.format.name == " pal8" :
412424 image = useful_array(frame.planes[0 ]).reshape(frame.height, frame.width)
413425 palette = np.frombuffer(frame.planes[1 ], " i4" ).astype(" >i4" ).reshape(- 1 , 1 ).view(np.uint8)
@@ -641,6 +653,28 @@ cdef class VideoFrame(Frame):
641653 copy_array_to_plane(flat[u_start:v_start], frame.planes[1 ], 1 )
642654 copy_array_to_plane(flat[v_start:], frame.planes[2 ], 1 )
643655 return frame
656+ elif format == " yuv422p10le" :
657+ if not isinstance (array, np.ndarray) or array.dtype != np.uint16:
658+ raise ValueError (" Array must be uint16 type" )
659+
660+ # Convert to channel-first if needed
661+ if channel_last and array.shape[2 ] == 3 :
662+ array = np.moveaxis(array, 2 , 0 )
663+ elif not (array.shape[0 ] == 3 ):
664+ raise ValueError (" Array must have shape (3, height, width) or (height, width, 3)" )
665+
666+ height, width = array.shape[1 :]
667+ if width % 2 != 0 or height % 2 != 0 :
668+ raise ValueError (" Width and height must be even" )
669+
670+ frame = VideoFrame(width, height, format)
671+ copy_array_to_plane(array[0 ], frame.planes[0 ], 2 )
672+ # Subsample U and V by taking every other column
673+ u = array[1 , :, ::2 ].copy() # Need copy to ensure C-contiguous
674+ v = array[2 , :, ::2 ].copy() # Need copy to ensure C-contiguous
675+ copy_array_to_plane(u, frame.planes[1 ], 2 )
676+ copy_array_to_plane(v, frame.planes[2 ], 2 )
677+ return frame
644678 elif format == " yuyv422" :
645679 check_ndarray(array, " uint8" , 3 )
646680 check_ndarray_shape(array, array.shape[0 ] % 2 == 0 )
0 commit comments