[BUG]Movie texture only decoding every 2nd frame

Ok,
Just tried with:

load_prc_file_data("", "support-threads 1");
load_prc_file_data("", "notify-level-ffmpeg fatal");
load_prc_file_data("", "sync_video 1");

It does work this way, as well as it used to do last fortnight.
Apparently ffmpeg error reporting is screwing up something…

btw. don’t know if this may be related, I recently noticed some cracklings in sounds unrelated to the video (the sounds play in a different task_chain…)

Just to mention, after a few hours working ok, here is a crash that was (sporadically) generated.

Call stack:

time=-1.#QNAN00000000000 ??? !!!

Hmm, I’m still trying to track down a mysterious crash that another user has been reporting to me, and it might be related to yours as well.

Unfortunately, the suspicious non-number in the stack trace doesn’t mean very much, because it’s common for the stack data to become meaningless after a crash. Still, it’s useful to see that the last Panda function before the crash was fetch_packet(). Is this in the child thread, and not in the main thread? Do you have more than one ffmpeg video texture in your game? Did the crash appear immediately after creating the texture, or some time later, after rendering a few frames?

There are a few more possible fixes I’ve recently committed, so if you get a chance to try the latest and see if it helps, I’d appreciate it. In particular, I did find a definite problem with the log message callbacks, so you should be able to turn those back on now and not crash (though you might want them off anyway to avoid the spammage).

David

main thread

two

It appeared a long time (ie 15mn) after creating the texture. But for all the time no video was within the camera frustum… (ie the video are textured on a different region of the scene)

Hmm, that’s very strange–are you absolutely sure about the thread of the crash? Because, other than during initial texture creation, the main thread shouldn’t call into fetch_frame() again–that should only be the child thread. If the main thread really is calling into fetch_frame() 15 minutes after texture creation, that would indeed be a serious error.

Is there more to the stack trace, showing where fetch_frame() had been called from?

David

Just checked in a few more possible fixes, though I admit I’m casting about in the dark here.

David

Sorry, I understood that you were talking about a different thread_chain and since my texture is loaded in the core program actually I don’t know which thread was calling the fetch_frame.

I have no more info than the call stack dump, and for the time being I haven’t been able to reproduce the bug.

BTW. Some pb with the new build

Ah, I understand. OK. In the debugger, there’s a different call stack for each active thread; you can usually tell whether you’re looking at the main thread stack, or some other thread’s stack.

Oops, fixed! Sorry about that.

David

maybe it’s not relevant anymore (simply because a lot of code has changed since then) but just for remembrance could it be something related to post 1 of [ffmpeg/Threading issues in 1.8.0?) ?

one more thing that i noticed that made me go “huh?” at first.

i happened to run across a video which usually plays just fine. but sometimes it “freezes” the picture.

upon investigation with pstats i found that ffmpeg is still decoding all frames + it starts to “seek”.

it some point it simply continues to display the video frames again. and the seek time disappears in pstats.

the beginning or cuts in the movie are common points. i investigated the video bit rates and it seems to occur on I-frames mostly, where the bitrate peaks far beyond the average.

so my conclusion whats going on would be:
panda tells ffmpeg to decode a frame. ffmpeg doesnt finish within the frame’s time. panda tells ffmpeg to display the next frame, ffmpeg seeks forward and is still in a hurry to catch up effectively missing the next frames,too.

skipping a few frames aint that bad. but when a big I-frame is at the beginning of the movie, it sometimes happens to freeze the first video frame for 5 to 10 seconds.

vlc player just skipps one or 2 frames and continues.

any way to improve this behaviour? (i know i shouldnt cut it quite that close with the cpu performance but one keyframe can freeze the entire vid in worst case)

Hmm, that does sound like a bad situation. Not entirely sure how to solve it–one of the problems is that there’s not really a way to seek quickly through a video stream. The fastest way to move from frame 0 to frame 3 is to decode frame 1 and frame 2. (You can get a little bit faster by minimizing the decoding effort of 1 and 2 if you know you won’t be displaying these frames anyway, but this is a challenge to determine in the new dual-threaded implementation.)

But if you’re seeing “seeking” happen in the sub-thread, that’s exactly what’s happening: the sub-thread has determined that it’s fallen behind, and is trying to decode frames quickly to catch up.

Still, there are a few weaknesses in the current implementation. Are you running a looping video? The current implementation doesn’t communicate the loop ahead of time to the sub-thread, so it’s always surprised when it finds it has to decode the first frame again after having finished decoding the last frame. If it knew that ahead of time, it could have frame 0 ready and waiting by the time the main thread asked for it. I could fix that little design weakness without too much trouble, but that won’t help if you’re explicitly seeking the video yourself.

I could also add an option where, instead of discarding the too-old frames, it displayed them anyway. This would mean that instead of a long freeze, you might get a relatively short freeze, then the video would start to play (but it would be a little bit behind). Then it would play a bit faster than normal as it caught up to itself. Would that be an improvement, do you think? The audio would still play at its natural speed.

One easy thing to do right now would be to try to increase the priority of the decoding thread, with the config setting “ffmpeg-thread-priority high”.

Also, you should make sure that you have the latest code (as of last Friday or so). I’ve been making ongoing changes in this system.

David

code is from tuesday. not running looping.

it is not that i require a fix for that.
was just one of the vids and we reencoded it to mpeg2 for better performance on that cpu already.
i was just wondering if that worst-case can be somehow improved in general.

what surprises me is that seeking adds up on top of the regular decoding.
wont the seeking eat into the regular decoding tasks cpu share? like, 2 decoding threads and still no frames displayed?

This impression is due to a bit of a misleading presentation from PStats, I think. In the sub-frame, there’s not a clear definition of what constitutes a “frame”, so it arbitrarily defines that one PStats frame has passed when a single frame from the video stream has been decoded.

This means that you get a fairly constant bar graph for decoding video frames in PStats, and any other work that the thread does (like seeking) appears as additional work on top of that. So when the sub-thread needs to seek a bit, then decode an additional frame, the only visible change in PStats is that there is more additional work in “seek”.

It is a problem if you see many frames go by with lots of seek time. That means the seeks aren’t enough to catch up.

“seek”, by the way, for the most part just means decoding the next frame(s) in a less-precise way so we can catch up to the frame we actually want to display. The video codec doesn’t provide a way to actually seek from one frame to the next without decoding the intervening frames.

David

another very curious “bug” i ran into.

setting
texture-minfilter linear_mipmap_linear
in the config file, and playing videos hammered performance into the ground. i know it is not a bug because panda is just doing as told and creating mipmaps. but it is very hard to track down that issue should you ever encounter it. might be worth a warning/hint message when you use mipmaps and videos

Hmm, it’s a good point. Maybe movie textures shouldn’t automatically respect texture-minfilter, but rather a different variable like movie-minfilter.

David