I'm using an AVAssetWriter on iOS to encode an MP4 video. I'm currently passing data in with an AVAssetWriterInputPixelBufferAdaptor, but I'm flexible on that front.
How can I specify which of my input frames are key frames?
Currently, I can control the number of key frames (or make all frames key frames) by setting AVVideoMaxKeyFrameIntervalKey, but my encoded video is a straightforward slideshow-with-transitions, and I'd like to ensure key frames at the main images without sacrificing compression.
If you make CMSampleBufferRefs (via CMSampleBufferCreateReadyWithImageBuffer(…) to pass in to your AVAssetWriterInput directly (instead of going through an AVAssetWriterInputPixelBufferAdaptor), you can then use CMSetAttachment(…) to set kCMSampleBufferAttachmentKey_ForceKeyFrame to kCFBooleanTrue on your frame to ensure that it will become a key frame.
A potential downside to moving away from AVAssetWriterInputPixelBufferAdaptor is that you lose the memory efficiency that comes with having a shared pixel buffer pool.
If the memory efficiency is important, you might want to consider looking into VideoToolbox and VTCompressionSession instead. VTCompressionSession is more complex than AVAssetWriter* is, but also exposes the pixel buffer pool that's used internally.
If you do go down this route, you'll want to use the kVTEncodeFrameOptionKey_ForceKeyFrame key set to kCFBooleanTrue as a frame attribute when submitting a frame to VTCompressionSessionEncodeFrame(…) for compression.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With