Enhance poor performance of decoding audio with MediaExtractor and MediaCodec to PCM
Current situation
It takes 30 seconds for decoding a mp3 (file size: 4 MB, bit rate: 128 kbps, length: 4 minutes) file to PCM using MediaExtractor and MediaCodec, this is unbearable for user experience.
Problem
MediaExtractorcan only read samples byadvance()and reads 418 bytes in a single step.MediaCodec’s input buffer and output buffer lock the current thread on executing.
Real-world example:
4 MB file leads to 1,048,576 x 2 (input/output buffer) execution by MediaCodec which means 2,097,152 times thread locks. Of course we cannot have a good performance.
Solution
The goal is to reduce MediaCodec execution counts by collecting enough samples by MediaExtractor in memory then feeding it to MediaCodec. We can expect performance enhancement.
96% faster
If I collect 524,288 bytes (0.5 MB) for MediaCodec’s input buffer instead of just-in-time’s 418 bytes, now it’s 96% faster.
HUGE.
Sample code:
Brief description:
inputFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, DECODE_INPUT_SIZE);for setting input buffer’s size- collect samples from
MediaExtractorand feed samples toMediaCodeconMediaCodec’sonInputBufferAvailable()callback - decode to PCM on
MediaCodec’sonOutputBufferAvailable()callback - store decoded samples on
mDecodedSamples