def qvideoframe_from_yuv420p(data_address: int, width: int, height: int) -> QVideoFrame:
""" Construct a QVideoFrame from a YUV420P data buffer."""
format = QVideoFrameFormat(QSize(width, height), QVideoFrameFormat.PixelFormat.Format_YUV420P)
frame = QVideoFrame(format)
if not frame.map(QVideoFrame.MapMode.WriteOnly):
print("Failed to map QVideoFrame")
return frame
# if the mapped bytes is equal to the expceted size of the YUV420P data, then we can copy the data directly
if frame.mappedBytes(0) + frame.mappedBytes(1) + frame.mappedBytes(2) == width * height * 3 // 2:
data_offset = 0
for i in range(frame.planeCount()):
nbytes = frame.mappedBytes(i)
ctypes.memmove(
(ctypes.c_ubyte * nbytes).from_buffer(frame.bits(i)),
data_address + data_offset,
nbytes
)
data_offset += nbytes
frame.unmap()
return frame
# if the mapped bytes is not equal to the expceted size of the YUV420P data, then we need to copy the data line by line
else:
y_bytes_per_line = frame.bytesPerLine(0)
uv_bytes_per_line = frame.bytesPerLine(1)
y_stride = width
uv_stride = y_stride // 2
y_size = width * height
uv_size = y_size // 4
y_src = data_address
u_src = y_src + y_size
v_src = u_src + uv_size
y_dst = frame.bits(0)
u_dst = frame.bits(1)
v_dst = frame.bits(2)
line_size = min(y_stride, y_bytes_per_line)
for i in range(height):
ctypes.memmove(
(ctypes.c_ubyte * y_bytes_per_line).from_buffer(y_dst, i*y_bytes_per_line),
y_src,
line_size
)
y_src += y_stride
line_size = min(uv_stride, uv_bytes_per_line)
for i in range(height//2):
ctypes.memmove(
(ctypes.c_ubyte * uv_bytes_per_line).from_buffer(u_dst, i*uv_bytes_per_line),
u_src,
line_size
)
u_src += uv_stride
ctypes.memmove(
(ctypes.c_ubyte * uv_bytes_per_line).from_buffer(v_dst, i*uv_bytes_per_line),
v_src,
line_size
)
v_src += uv_stride
frame.unmap()
return frame
YUV420P数据转换成QVideoFrame
来自
标签:
发表回复