Reputation: 583
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?
Upvotes: 2
Views: 2922
Reputation: 278
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)
Upvotes: 0
Reputation: 1143
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...
Upvotes: 0
Reputation: 583
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);
Upvotes: 2
Reputation: 13317
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.
Upvotes: 1