YUV420P数据转换成QVideoFrame

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


已发布

分类

来自

标签:

评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注