We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I'm using Processing to make a small app. I want to display and edit text overlays on top of a video file - similar to subtitles. For that, I want to be able to jump a paused video to a specific timecode and display the video frame at that time. Unfortunately, this doesn't seem to work.
So if I make something like this:
movie.pause();
movie.jump(30);
movie.read();
The video will NOT show the frame at second 30, but whatever frame was on the screen before the jump. If I jump around in the video the same frame keeps being displayed until I hit play.
Is there a workaround for this?
Answers
Can you post your code showing your approach? It will also allow to reproduce your issue.
Kf
@Krystman -- Keep in mind that:
...doesn't do anything on-screen. This line has to run before the screen updates:
See for example the basic movie example sketch:
Depending on where you are triggering the pause, you may need to either move it in
draw()
before theimage()
call or (if you are doing it inkeyPressed()
etc.) you may need to callredraw()
.I'm sorry, I presumed it was a known issue. Here is sample code illustrating the problem:
Clicking with the mouse will NOT show random frames from the video.
@Krystman --
I'm not sure, but I believe that you need to be playing in order for jump to take effect on the next frame -- otherwise you have specified a new time position, but the movie is paused so it hasn't loaded the frame yet.
Here is an example, adding a revised version of your mousePressed function to the bottom of the standard Processing Example for a video loop. Note that play is called before and pause is called after the new random frame has been loaded.
@jeremydouglass sounds like a bug in the video library if that's the case.
@neilcsmith_net -- I honestly can't tell from the reference page or example.
However, code examples seem to indicate the need to play/jump/pause:
Whether a bug or feature request, it certainly seems reasonable to expect that
jump()
would update the current image, even while a movie is paused. Perhaps someone working with this wants to submit an issue to Processing-Video?Why should images stop coming when playback is paused?! It would make more sense to follow the underlying GStreamer behaviour and emit all frame update events, so that jump() works as expected. If you don't do that, pause() is just another form of stop().
I'm not familiar w/ GStreamer's features at all.
Video library is merely a wrapper for GStreamer.
And its pause() method temporarily halts the playback to spare CPU.
AFAIK, after stop(), resume isn't possible anymore. At least for library Minim. :P
A quick inspection on the source file, the difference between pause and stop is that stop calls jump(0) and resets a boolean field differently: https://github.com/processing/processing-video/blob/master/src/processing/video/Movie.java
From the source, I can't tell much about the behavior of jump() in regards to returning data. Maybe @codeanticode could comment on this?
Kf
GStreamer is already doing this though - it will only trigger an update if the image changes, eg. through jump(). The video library seems to be filtering events when paused, which won't actually save any CPU time.
That's good to hear! So video library demands a refactoring in its logic. :P
Well, video library requires lots of refactoring! GStreamer 1.x would be good for a start :-)
I also have a feature request: a new callback event for when video reaches its playback end. $-)
I second that feature as well.
Kf
:-bd
Regardless, I've already have a hack for the eosEvent() internal method: :ar!
https://forum.Processing.org/two/discussion/14990/movie-begin-and-end-events#Item_1
@jeremydouglass - aren't all these in the issue queue already?! They're just not being addressed. If anyone wants to take a lead on updating the library then I'm happy to help out (I'm the GStreamer 1.x bindings maintainer).
@GoToLoop - nice hack! If that's called directly from the GStreamer thread (probably is), be careful about concurrency issues using that approach though.
@neilcsmith_net -- re:
Really?
When I searched open issues for "jump" and "pause" I also didn't see any bug or enhancement request describing jump not updating the current frame while paused.
When I searched open issues for "callback" "end" "stop" and "done" I didn't see any open issue requesting a new callback event for when video reaches the end.
However, I didn't read through the complete list of open issues. Maybe they are in there somewhere but described using different terms.
The EOS and GStreamer 1.x things are there. You're right that the OP's jump / pause issue isn't listed. Still doesn't change the fact the library has not seen any development for ~18 months. :-S
AFAIK, that's the same Thread which calls back movieEvent().8-XOn 2nd look within internal initSink():
https://GitHub.com/processing/processing-video/blob/master/src/processing/video/Movie.java#L785-#L790
The Thread responsible for eosEvent() callback is whatever Bus.EOS's is. b-(
For movieEvent()'s Thread, it's either BufferDataAppSink.Listener or RGBDataAppSink.Listener I guess:
https://GitHub.com/processing/processing-video/blob/master/src/processing/video/Movie.java#L754-#L773
Method invokeEvent() which is called back by 1 of those 2 Listener classes above is
synchronized
.While eosEvent() by Bus.EOS isn't: 8-|
https://GitHub.com/processing/processing-video/blob/master/src/processing/video/Movie.java#L854-#L871
synchronized
, it shouldn't cause any concurrency problems.@GoToLoop - er, no! Threads don't work like that. However, my point was not about what the library is doing. It's that the eos method in your code may be called at the same time as the animation thread is calling draw(). If you're reading or writing any of the same variables within both draw() and your eos method code you have a potential issue.
You mean these statements?
Field ended got no problem. I guess you mean
frameRate(1);
It doesn't mutate sketch's canvas in any significant way.
Therefore it's safe to call outside the "Animation Thread".
As an answerer of this forum, I've seen lotsa folks doing drawing commands outside the "Animation Thread". I guess I see 1 at least once for each 2 weeks. @-)
But I'm confident frameRate() is safe when called outside the "Animation Thread".
Most of what may happen is some innocuous race condition if more than 1 Thread invokes it at the same time. ;;)
Well, as I had stated, I dunno the specifics of GStreamer.
And thus I dunno how many threads are created by it. 8-|
The only thing I know is that if we place
println( Thread.currentThread() );
inside movieEvent(), the answer isn't "Animation Thread". [-(I don't mean any particular statements, just that the approach needs to be thought through. I'm also talking about threads in general - nothing specific to GStreamer.
In your example, you can't guarantee when the change to ended will be "seen" by the animation thread. In theory it could be never. And you have no idea whether any renderers implementation of frameRate() is thread safe, although the JOGL ones might be.
Lots of none drawing code isn't safe to blindly use, and race conditions are almost never innocuous. They cause weird crashes and bugs. The sort that don't show up when testing, just at the important times! ;-)
This is mostly irrelevant! In Processing by default draw() is called back at about 60 FPS.
If I change some field outside the "Animation Thread", if it takes at most 2 FPS to be "felt" for the latter, it won't make much visually difference. ~:>
In my Processing experience w/ concurrency, Java has never failed to update the actual field when it was changed by some foreign Thread. >:/
And for some exotic reason I really need it to be updated ASAP, I can always declare the target field w/
volatile
. \m/By the looks of it it should merely change some bunch of internal fields.
And it ended up that way when I just looked that up right now:
https://GitHub.com/processing/processing/blob/master/core/src/processing/core/PSurfaceNone.java#L245-L249
I fail to see how changing those 2 fields could crash the renderer. :-@
Although I agree there's a chance for the values stored in those 2 fields ending up not matching if a race condition happens.
But still, frameRate() is mostly invoked within setup().
No sketch keeps mutating its FPS all the time after all, much less in multiple threads. :P
In Processing is just the opposite! Most of them won't be visually realized by the user watching an animation. 1 or 2 FPS w/ slightly wrong, not fully updated state aren't that serious. :ar!
Having said that, there are race conditions which crash a sketch code, especially now in version 3! :-&
Any drawing commands which mutate the pixels of the PGraphics main canvas crash P3 and can corrupt it under P2 & P1 if they are run outside the "Animation Thread"!!! :-SS
In addition to those, if more than 1 Thread relies on any color-related function, like color(), fill(), stroke(), background(), for the same PGraphics object, the results are gonna get corrupted if they happen at the same time!
Those 2 situations above are the only dangerous race conditions that I know for sure are problematic in Processing.
I know what you're warning us about are general Java protocols for concurrency safety.
But I don't believe they apply much for Processing API in general. >-)
... and some people still believe the world is flat! ;-) In the past I've had stuff run for hours or days before it blew up. Trying to help you, but arguing with a brick wall is no fun. So, good luck with it.
On a more relevant note, if someone is going to take the initiative on the video library, PM me.