How can ffmpeg be made as efficient as Android's built-in video viewer?


Staff member
I have a project based off of <a href="" rel="nofollow"></a>, which uses an older copy of the ffmpeg libraries from <a href="" rel="nofollow"></a>. Within the C++ code in this project we have the following lines of code:

        unsigned long long current = GetCurrentTimeInNanoseconds();
        avcodec_decode_video(pCodecCtx, pFrame, &amp;frameFinished,, packet.size);
        __android_log_print(ANDROID_LOG_DEBUG, "getFrame&gt;&gt;&gt;&gt;", "decode video time: %llu", (GetCurrentTimeInNanoseconds() - current)/1000000);

This code continually reports between 60 and 90 ms to decode each frame on an Xperia Ion, using a 1280x720 h264 source video file. Other processing to get the frame out to the screen takes an average of 30ms more with very little variation. This leads to frame rates of 10-11fps.

Ignoring that other processing, a decode that takes an average of 75ms would result in 13fps. However, when I browse my SD card and click on that mp4 file to open it in the native viewer, it shows at a full 30fps. Further, when I open a 1920x1080 version of the same mp4 in the native viewer it also runs at a full 30fps without stutter or lag. This implies (to my novice eye) that something is very very wrong, as the hardware is obviously capable of decoding many times faster.

What flags or options can be passed to avcode_decode_video to optimize decode speed to match that of the native viewer? Can optimizations be made elsewhere to optimize speed further? Is there a reason that the native viewer can decode almost an order of magnitude faster (taking into account the 1920x1080 source results)?


The answer below is very helpful, but is not practical for me at this time. In the mean time I have managed to decrease decoding time by 70% with some optimal encoding flags found through many many hours of trial and error. Here are the ffmpeg arguments I'm using for encoding in case it helps anyone else who stumbles across this post:

        ffmpeg.exe -i "#inputFilePath#" -c:v libx264 -preset veryslow -g 2 -y -s 910x512 -b 5000k -minrate 2000k -maxrate 8000k -pix_fmt yuv420p -tune fastdecode -coder 0 -flags -loop -profile:v main -x264-params subme=5:ref=4 "#ouputFilePath#"

With these settings ffmpeg is decoding frames in 20-25 seconds, though with the sws_scale and then writing out to the texture I'm still hovering at ~22 FPS on an Xperia Ion at a lower resolution than I'd like.