I'm new in Android and want to write an App that measure the framerate while playing video. For this purpose I use the MediaPlayer and show it on the SurfaceView. In this constellation, is it even possible to get the needed render statistics to calculate the Framerate? Thanks
2 Answers
The point of MediaPlayer is to conceal the details of video decoding and presentation, so you can't get at all the details. For example, there is no per-frame callback.
One way to approach the problem would be to play the video with MediaPlayer onto a SurfaceTexture, and render each frame onto the SurfaceView's Surface with OpenGL ES. The presentation time stamp of each frame is available from the SurfaceTexture.
Another approach is to use MediaCodec instead of MediaPlayer, giving you full control over the decoding and presentation process. This is more complicated, and gets tricky if the video has audio.
You may also want to consider examining the video file itself with MediaExtractor, and use the first few frames to detect the frame rate.
As noted by @Mick, some videos have a variable frame rate, and you cannot establish a single value for the entire stream. Video captured by screenrecord
is a prime example. In such a case, the best you can do is show the "recent" frame rate, and you have to compute it dynamically (so MediaExtractor won't cut it).

- 51,356
- 5
- 116
- 166
-
I guess you can also show the average frame rate which may be useful also. – Mick Sep 09 '15 at 19:27
-
Thanks for the overview. When using MediaExtractor and MediaCodec could it be better to use the Exoplayer instead? – henchman21 Sep 10 '15 at 07:39
It has been reported (I have not tested myself) that the VideoView's onDraw method will be called when every video frame is written.
This allows you to override and add some code to the onDraw method to note the time each frame is written and to calculate a running fps value.
To allow the onDraw method to be called you have to set a flag:
setWillNotDraw(false)
in your view constructor - see: https://stackoverflow.com/a/17595671/334402
BTW, it is worth being aware that some video will have a variable frame rate. This is usually because they are trying to maximise quality within a given bandwidth budget.
-
It would be inefficient, and rather silly, to update the View every time a new frame of video was sent to the Surface. The only reason `onDraw()` would be called every frame is if somebody were issuing View invalidates for each frame, which would only be useful if the video were being decoded in software and rendered onto the View itself. (Where is this coming from?) – fadden Sep 09 '15 at 18:34
-
Ok - Ill give the OP time to read your comments and then delete this answer if it is wrong. I have not tested it myself but it is fairly commonly reported that this approach works in answers to this type of question. If you take a look at your comments feed you'll see I asked you a question about this in the comment to another answer - I'd be interested in your response if you see it. – Mick Sep 09 '15 at 18:46
-
I saw it (http://stackoverflow.com/questions/23133739/) and responded (SO might not send a notification). The only way `onDraw()` could be used to indicate the frame rate is if VideoView is updating something in its View every frame. Glancing through https://android.googlesource.com/platform/frameworks/base/+/lollipop-mr1-release/core/java/android/widget/VideoView.java , the only use of `draw()` is for subtitles. – fadden Sep 09 '15 at 18:55
-
Thanks - nice clear explanation. BTW - here's an example of onDraw being used for fps calculation: http://stackoverflow.com/q/10210439/334402 - I'd be interested if you are 100% sure this will not work (or maybe I am reading it wrong??) – Mick Sep 09 '15 at 19:00
-
My guess would be that the "third party framework" mentioned in the question is rendering to the View with a software codec. That would get you one invalidate per frame. A question linked from that one (http://stackoverflow.com/questions/13498184/) had a similar answer, but the OP was using a VideoView and apparently didn't get it to work. – fadden Sep 09 '15 at 20:52
-
Yes I saw that one too - I guess it is the up votes for these answers which are confusing as they seem to imply some people were happy with the answer and hence that it maybe worked for them. The SW vs HW codec probably explains this as you suggest and is an interesting point. This comment thread is actually a pretty useful discussion so I'll leave this answer here for a while so long as it does not attract too many down votes!! – Mick Sep 09 '15 at 22:09