Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct
Any way QMovie (or somthing else in Qt) can tell the frames per second of an animated GIF file?
I have been using QMovie movie->setSpeed(frame_to_frame_in_ms). But I may have animated GIFs that are 5 and others that are 15 frames per second. I can keep track which is which, but I would much rather call a Qt method that would return this information. Is there such a thing. I have looked, but have not found any such method.
Check out "QMovie::nextFrameDelay() ":http://qt-project.org/doc/qt-4.8/qmovie.html#nextFrameDelay
Yes, but I always got zero out of that method call. I assumed it was telling me "how long until the next frame". Zero was probably correct. As I was in a method that gets called when a new frame is displayed.
What I want to know is what to set the QMovie speed to. That's before I start playing the Animated GIF. Or maybe I'm not using QMovie::nextFrameDelay() correctly.
There must be a way of looking at the file and figuring this out. I tried a Unix "strings" on the file but did not see any clear text that resembled frame rate. There must be some hint as to the frame rate. I know when I use Unix mplayer utility it always plays back at the correct frame rate.
Actually, doesn't setSpeed() take a percentage of the rate of speed? (100 = normal speed, 50 = half speed, 200 = double speed, etc.)? The animated gif should just play at its set speed by default.
You could just calculate the elapsed speed between frames yourself if you already have a slot being triggered by the QMovie's frameChanged() signal, I suppose.
Edit: Just now remembered you said you could track this, yourself...
I'm not sure of your use case, but if you're trying to normalize different FPS GIFs so that they play back at a constant rate, you could always use a QTimer and just increment to the next frame manually with "jumpToNextFrame(),":/doc/qt-4.8/qmovie.html#jumpToNextFrame rather than relying on the QMovie to play it back automatically.
Well, I'm the 3rd person to work on this. When I got the code someone had already set up many of QMovie's parameters (pardon my pseudo code):
Then, because we are playing back a voice audio file using Qt-unsupported hardware we need to keep the QMovie tied very close to the real time clock. So we use Qt QElapsedTimer.elapsed() and adjusted the QMovie speed:
@play_back_speed = frame_interval_in_ms;@
if(QElapsedTimer.elapsed() < frame_interval_in_ms)
Note, the code is more complex. That is, we don't bounce the speed around as the above pseudo code suggests. But it is the basic idea.
Why QMovie is not tracked by Qt better I can not say. All I know is w/o adjusting QMovie according to QElapsedTimer.elapsed() the animation tends to drift rather badly on our target hardware (500MHz MIPS processor).
As you can see, w/o knowing before hand what the FPS is, we really don't have a hope of staying in sync with the audio. So, the name of the file and the FPS information has to be carefully kept together on some *.ini file. I just thought that was problematic and sought to improve on the situation by pulling the FPS information out of the Animated GIF where I am sure it can be found.
There's an inherent problem with asking for a FPS rate for an animated GIF using QMovie. Primarily, I can see an issue because there is no guarantee that an animated GIF has a constant frame rate. Each frame has its own delay time, so there's not one global constant that can be returned.
Perhaps you could load the image with a QImageReader, step through each frame and query its nextFrameDelay before displaying the image. Thus you could profile the GIF beforehand.
Again, though, I'd double check the speed property. "setSpeed()":/doc/qt-4.8/qmovie.html#speed-prop isn't documented to do what you say it does.
bq. Perhaps you could load the image with a QImageReader, step through each frame and query its nextFrameDelay before displaying the image. Thus you could profile the GIF beforehand.
We create the Animated GIFs in house using PhotoShop. I think I later used gifsicle which, if I remember right, reported each frame had been set to 70ms/frame.
bq. Each frame has its own delay time, so there’s not one global constant that can be returned.
Speaking of frame time, I have come to understand that (by definition or by design) Animated GIFs only have a 10ms frame to frame granulatity? If true, then exactly what is PhotoShop doing when offering to make a 15 frames per second Animated GIF? Note that 1000ms/S divided by 15frames/S is 66.67ms/frame. The difference between that and the nearest multiple of 10ms is 3.33ms/frame. That's about a 5% error!
If this is really true, then the best frames per second chose near 15 would be 14. There the error is only about 2%.
bq. Again, though, I’d double check the speed property. setSpeed() isn’t documented to do what you say it does.
Hum, I do think we are changing the playback speed as we go through the Animated GIF. This should be simple enough to test. I can simply comment out the adjustment and see if all "goes south".
But I wonder, maybe our problems are all because of the Animated GIF period granularity restriction. That is, we get a sound file and an Animated GIF from the art group. If they think they are rendering at 15 FPS but are actually rendering at 14.29 FPS, it wouldn't be long before the Animated GIF would lead the sound.
Keep in mind that gifs were never meant as high-performance animation tools, and that they were first designed about 25 years ago. They gave a quick way to do animations, but were never by any means designed for sync sound applications.
Have you considered pre combining your animations and sound into more suitable formats (mpg, etc.)? It seems like you're trying to push a technology into a use that it was not designed for an, as such, are spending more effort in overcoming those limitations than you should have to.
Totally agree. But I'm not paying the bills.
Comes down to this. The "bill payer" wants instant feed back on a Qt button push. The video/sound hardware lags about 1.5 seconds behind the call to the driver. So we are forced to do something purely in software.