Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I want to fill the pixel data of an empty
QVideoFrame
instance. In PySide6, the
bits(0)
method returns a memory view and I can directly modify it by slicing and assigning. But in PyQt6,
sip.voidptr
is returned instead and I can't figure out how should I deal with it!
I am not really familiar with Python C bindings. Is there any way to easily access the memory using
voidptr
? Thanks in advance!
Edit 1
Here is a sample code.
from PyQt6 import QtCore, QtMultimedia
pfmt = QtMultimedia.QVideoFrameFormat.PixelFormat.Format_Y8
ffmt = QtMultimedia.QVideoFrameFormat(QtCore.QSize(1280, 1024), pfmt)
vf = QtMultimedia.QVideoFrame(ffmt)
vf.map(QtMultimedia.QVideoFrame.MapMode.ReadWrite)
# Data manipulation should come here.
vf.unmap()
Edit 2
Ok, I found out that voidptr
can be converted to an array by passing the size of the video frame.
In the comment location of the code above,
>>> size = vf.bytesPerLine(0)*vf.height()
>>> vf.bits(0).asarray(size)
PyQt6.sip.array(unsigned char, 1310720)
Modifying a single pixel works fine.
>>> arr = vf.bits(0).asarray(vf.bytesPerLine(0)*vf.height())
>>> arr[0]
>>> arr[0] = 255
>>> arr[0]
But assigning the bytes to sip.array
raised error.
>>> data = bytes(255 for _ in range(size))
>>> arr[:] = data
TypeError: can only assign another array of unsigned char to the slice
Answers in another question raised same error.
–
–
Thanks to @musicamante I managed to find the solution. It seems that voidptr
can be directly accessed to write the bytes, provided that its size is known. QVideoFrame.bits()
returns voidptr
with unknown size (perhaps it is a bug of PyQt) so I had to manually set the size from QVideoFrame.mappedBytes
.
Here is the full code:
from PyQt6 import QtCore, QtMultimedia
pfmt = QtMultimedia.QVideoFrameFormat.PixelFormat.Format_Y8
ffmt = QtMultimedia.QVideoFrameFormat(QtCore.QSize(1280, 1024), pfmt)
vf = QtMultimedia.QVideoFrame(ffmt)
vf.map(QtMultimedia.QVideoFrame.MapMode.ReadWrite)
ptr = frame.bits(0)
ptr.setsize(frame.mappedBytes(0))
ptr[:] = bytes(255 for _ in range(size))
vf.unmap()
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.