MediaFormat.KEY_I_FRAME_INTERVAL only takes an integer value, and I assume this is what controls how frequent the encoder generates an I-frame right? So does that mean if I am using MediaCodec I cannot possibly generate I-frames more frequently?
-
Here's [a link](https://stackoverflow.com/a/58933377/10960892) to my answer to similar question: – puksec Nov 19 '19 at 11:51
-
Here's a link to my answer to the similar question: https://stackoverflow.com/a/58933377/10960892 – puksec Nov 19 '19 at 11:52
4 Answers
I finally found a workaround for this issue!
Insert the following code before a key frame is needed, then it will generate a key frame on the next available frame.
Bundle b = new Bundle();
b.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
encoder.setParameters(b);

- 503
- 1
- 5
- 19
You can probably work around this by scaling your timestamps. If you e.g. multiply the timestamps by 2 when inputting them into the encoder, and then divide by 2 on the timestamps you get on the output buffers from the encoder, you should be able to get an I-frame interval of half a second. Then you also need to halve the bitrate (and frame rate) to make it match. This isn't ideal of course, but should allow you to get the right effect.

- 12,983
- 2
- 39
- 62
The documentation says that:
A zero value means a stream containing all key frames is requested.
So all what you need is:
MediaFormat format = MediaFormat.createVideoFormat(...);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 0);
It works for some devices, but for some devices (Nexus 6p for example) it produces exception:
E/ACodec: [OMX.qcom.video.encoder.avc] configureCodec returning error -1010
E/ACodec: signalError(omxError 0x80001001, internalError -1010)
E/MediaCodec: Codec reported err 0xfffffc0e, actionCode 0, while in state 3
E/MediaCodec: configure failed with err 0xfffffc0e, resetting...

- 1,134
- 1
- 12
- 19
KEY_I_FRAME_INTERVAL can also receive float since Android 7.1.
Therefore is now possible to do something like this :
val mediaFormat: MediaFormat = MediaFormat.createVideoFormat(VIDEO_MIME_TYPE, 480, 640)
// 30 Frames per second
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30)
// 1 second between key frames!
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1)
// 0.3 seconds between key frame!
mediaFormat.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 0.3F)

- 278
- 1
- 6
- 18