AVAssetWriter AVVideoExpectedSourceFrameRateKey (frame rate) ignored

可紊 提交于 2019-11-27 07:18:42

问题


Me and my team are trying to re-encode a video file to a more "gify" feeling by changing the video frame rate. We are using the following properties for the AVAssetWriterInput:

let videoSettings:[String:Any] = [
            AVVideoCodecKey: AVVideoCodecH264,
            AVVideoHeightKey: videoTrack.naturalSize.height,
            AVVideoWidthKey: videoTrack.naturalSize.width,
            AVVideoCompressionPropertiesKey: [AVVideoExpectedSourceFrameRateKey: NSNumber(value: 12)]                                         
        ]

But the output video keep playing in the normal frame rate (played using AVPlayer).

What is the right way to reduce video frame rate? (12 for example).

Any help in the right direction would be HIGHLY approcated. We stuck. Best regards, Roi


回答1:


You can control the timing of each sample you append to your AVAssetWriterInput directly with CMSampleBufferCreateCopyWithNewTiming.

You need to adjust the timing in the CMSampleTimingInfo you provide. Retrieve current timing info with CMSampleBufferGetOutputSampleTimingInfoArray and just go over the duration of each sample and calculate the correct duration to get 12 frames per second and adjust presentation and decode timestamps to match this new duration. You then make your copy and feed it to your writer's input.

Let's say you have existingSampleBuffer:

CMSampleBufferRef sampleBufferToWrite = NULL;
CMSampleTimingInfo sampleTimingInfo = {0};

CMSampleBufferGetSampleTimingInfo(existingSampleBuffer, 0, &sampleTimingInfo);

// modify duration & presentationTimeStamp
sampleTimingInfo.duration = CMTimeMake(1, 12) // or whatever frame rate you desire
sampleTimingInfo.presentationTimeStamp = CMTimeAdd(previousPresentationTimeStamp, sampleTimingInfo.duration);
previousPresentationTimeStamp = sampleTimingInfo.presentationTimeStamp; // should be initialised before passing here the first time

OSStatus status = CMSampleBufferCreateCopyWithNewTiming(kCFAllocatorDefault, existingSampleBuffer, 1, &sampleTimingInfo, &sampleBufferToWrite);

if (status == noErr) {
    // you can write sampleBufferToWrite
}

I'm making some assumptions in this code:

  • SampleBuffer contains only one sample
  • SampleBuffer contains uncompressed video (otherwise, you need to handle decodeTimeStamp as well)


来源:https://stackoverflow.com/questions/49235811/avassetwriter-avvideoexpectedsourceframeratekey-frame-rate-ignored

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!