-
Notifications
You must be signed in to change notification settings - Fork 111
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use of video_set_callbacks #17
Comments
It should work, but I could not test all bindings and especially callbacks which can be trickier to automatically convert from C to python. If you found a solution, please post it here. |
I imagine there is a magic function somewhere that does the trick... But i didn't found it. |
Started playing with this today and it turns out that the ctypes callback definition for See Once I started using the correct definition I was able to set the pointer to the buffer I allocated as the documentation instructed:
With chroma No actual locking is being done, which may or may not be a problem (because GIL?) :) Also writing the images in the display callback is a bad idea, but good enough to show this works. import vlc
import ctypes
import time
import sys
from PIL import Image
pl = vlc.MediaPlayer('videofile.mp4')
VIDEOWIDTH = 1920
VIDEOHEIGHT = 1080
# size in bytes when RV32
size = VIDEOWIDTH * VIDEOHEIGHT * 4
# allocate buffer
buf = (ctypes.c_ubyte * size)()
# get pointer to buffer
buf_p = ctypes.cast(buf, ctypes.c_void_p)
# global frame (or actually displayed frame) counter
framenr = 0
# vlc.CallbackDecorators.VideoLockCb is incorrect
CorrectVideoLockCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p))
@CorrectVideoLockCb
def _lockcb(opaque, planes):
print("lock", file=sys.stderr)
planes[0] = buf_p
@vlc.CallbackDecorators.VideoDisplayCb
def _display(opaque, picture):
print("display {}".format(framenr))
global framenr
if framenr % 24 == 0:
# shouldn't do this here! copy buffer fast and process in our own thread, or maybe cycle
# through a couple of buffers, passing one of them in _lockcb while we read from the other(s).
img = Image.frombuffer("RGBA", (VIDEOWIDTH, VIDEOHEIGHT), buf, "raw", "BGRA", 0, 1)
img.save('img{}.png'.format(framenr))
framenr += 1
vlc.libvlc_video_set_callbacks(pl, _lockcb, None, _display, None)
pl.video_set_format("RV32", VIDEOWIDTH, VIDEOHEIGHT, VIDEOWIDTH * 4)
pl.play()
time.sleep(10) |
The unlock definition also seemed incorrect. This works: CorrectVideoUnlockCb = ctypes.CFUNCTYPE(
ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p)) I am by no means experienced with Also now with proper lock on with buf1_lock:
ctypes.memmove(buf2, buf1, size)
img = Image.frombuffer("RGBA", (VIDEOWIDTH, VIDEOHEIGHT), buf2, "raw", "BGRA", 0, 1)
img.save('img{}.png'.format(framenr)) Seems to work great! I am planning to use it for something totally different than the (slow) PIL saving, but this proofs the concept nicely. |
I get bus error (core dumped) when I run the following code.. What would be the issue? `import vlc vlcInstance = vlc.Instance() VIDEOWIDTH = 1920 size = VIDEOWIDTH * VIDEOHEIGHT * 4 buf = (ctypes.c_ubyte * size)() buf_p = ctypes.cast(buf, ctypes.c_void_p) framenr = 0 CorrectVideoLockCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p)) @CorrectVideoLockCb @vlc.CallbackDecorators.VideoDisplayCb vlc.libvlc_video_set_callbacks(player, _lockcb, None, _display, None) player.play() |
how to add this code in class python ? |
Here you are working with All this is not in the scope of this issue and I suggest you read up on python in general and Also, since this issue is closed I assume the bug is fixed and you don't need the code you pasted. |
Many thanks. You have indicated the right path for me. I found what I need. |
Great! Can you please share this version of the code? |
Everything you need is in this thread, however if it helps you I dug up the code from when I worked on this and added the relevant part to a gist https://gist.github.com/daniel5gh/36f6a802451c02d3434f9aab730c1828 |
Thank you very much for the gist :) |
I do not see the reason for the VideoUnlockCb patching, since it is correctly defined in the vlc module. And I just committed a fix for the |
The code in the gist is a direct copy of the code I wrote back in 2017
Absolutely! Looking at it again, it might be better to keep references to the callback functions on the surface instance itself. In my code the user of Surface did that to prevent python GC from deleting those while they were still referenced by the player. I was just being pragmatic back then and I have limited experience with this, but should there be some I just ran into this GC deletion because I created the callback function in the scope/closure of |
Yes, keeping reference of the callbacks could be done at the module level, but it introduces complexity (and I imagine corner cases) so for the moment, I chose the easy path for me. I prepared the code (which I would put in the |
I approve and left some small comments on the gist. |
Is there anyway to reduce CPU usage for the following code ? Any other efficient way to convert it to opencv ? Can't we do it directly without using PIL ?
|
I don't know, I suggest you ask on stack overflow, this seems off topic for this issue. |
as_np = np.ndarray(shape=(VIDEOHEIGHT, VIDEOWIDTH, 4), dtype=np.ubyte, buffer=buf) 30% of CPU processing down :-) |
@rho-sk |
Hello,
i have been trying to get images frame per frame from an rtsp stream.
I can get the stream in vlc window, but i cannot get the frame data.
I read that i should use the video_set_callbacks function; however, instance crash if i set a callback.
This is a part of the code I've been using :
Did i do something wrong ? Or maybe it isn't supported in the python binding ?
Thanks !
The text was updated successfully, but these errors were encountered: