gpt4 book ai didi

ios - AVAssetWriter - 设置自定义帧率

转载 作者:行者123 更新时间:2023-11-28 07:32:00 24 4
gpt4 key购买 nike

我正在使用 AVAssetWriter 通过委托(delegate)从 ARSession 写入视频帧。

func session(_ session: ARSession, didUpdate frame: ARFrame)

请参阅下面用于写入图像的代码。

如何根据需要设置自定义帧速率,如 24、30 或 60 等。

在输出设置中,AVVideoExpectedSourceFrameRateKey 的值是 30。但是无论我们给它什么值,在使用 VLC 播放器 -> 媒体信息 -> 编解码器详细信息检查时,始终将“帧速率”设为 60

我应该做哪些更改来设置所需的帧速率?提前致谢。

func writeImage(_ image: CVPixelBuffer, thisTimestamp: TimeInterval) {

guard let videoDirector = videoWriter else { return }

serialQueue.async(execute: {

let scale = CMTimeScale(NSEC_PER_SEC)

if (!self.seenTimestamps.contains(thisTimestamp)) {

self.seenTimestamps.append(thisTimestamp)
let pts = CMTime(value: CMTimeValue((thisTimestamp) * Double(scale)),
timescale: scale)
var timingInfo = CMSampleTimingInfo(duration: kCMTimeInvalid,
presentationTimeStamp: pts,
decodeTimeStamp: kCMTimeInvalid)

var vidInfo:CMVideoFormatDescription! = nil
CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, image, &vidInfo)

var sampleBuffer:CMSampleBuffer! = nil
CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, image, true, nil, nil, vidInfo, &timingInfo, &sampleBuffer)

let imageBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!

if self.videoWriterInput == nil {

let width = CVPixelBufferGetWidth(imageBuffer)
let height = CVPixelBufferGetHeight(imageBuffer)


let numPixels: Double = Double(width * height);
let bitsPerPixel = 11.4;
let bitsPerSecond = Int(numPixels * bitsPerPixel)

// add video input
let outputSettings: [String: Any] = [
AVVideoCodecKey : AVVideoCodecType.h264,
AVVideoWidthKey : width,
AVVideoHeightKey : height,
AVVideoCompressionPropertiesKey : [
AVVideoExpectedSourceFrameRateKey: 30,
AVVideoAverageBitRateKey : bitsPerSecond,
AVVideoMaxKeyFrameIntervalKey : 1
]
]
self.videoWriterInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: outputSettings)
self.videoWriterInput?.expectsMediaDataInRealTime = true
guard let input = self.videoWriterInput else { return }

if videoDirector.canAdd(input) {
videoDirector.add(input)
}
videoDirector.startWriting()
}

let writable = self.canWrite()
if writable, self.sessionAtSourceTime == nil {
let timeStamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
self.sessionAtSourceTime = timeStamp
videoDirector.startSession(atSourceTime: timeStamp)
}

if self.videoWriterInput?.isReadyForMoreMediaData == true {
let appendResult = self.videoWriterInput?.append(sampleBuffer)
if appendResult == false {
printDebug("writer status: \(videoDirector.status.rawValue)")
printDebug("writer error: \(videoDirector.error.debugDescription)")
}
}
}
})
}
func canWrite() -> Bool {
return isRecording && videoWriter?.status == .writing
}

最佳答案

苹果支持的回复:

如果你真的想用 AVAssetWriter 改变电影的帧速率,那么你必须在写出每个视频帧时正确设置时间戳。

一种方法是使用 AVAssetWriterInputPixelBufferAdaptor 对象。例如,您使用 AVAssetWriterInputPixelBufferAdaptor 将打包为 CVPixelBuffer 对象的视频样本附加到单个 AVAssetWriterInput 对象。

初始化代码看起来像这样:

[dictionary setObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(NSString*) kCVPixelBufferPixelFormatTypeKey];

...

AVAssetWriterInputPixelBufferAdaptor *avAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc] initWithAssetWriterInput:assetWriterInput sourcePixelBufferAttributes:dictionary];

然后,要为新电影指定特定的播放帧速率(例如 15 fps),时间戳(表示为 CMTime 结构)应指定为相隔 1/15 秒。这是一个代码片段:

CMTime frameTime = CMTimeMake(1, 15);
result = [avAdaptor appendPixelBuffer:buffer withPresentationTime:frameTime];

另一种方法是使用 CMSampleBufferCreateCopyWithNewTiming 重新定时缓冲区,然后将它们传递给 AVAssetWriter。这是一个粗略的概述:

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

CMSampleBufferGetSampleTimingInfo(existingSampleBuffer, 0, &sampleTimingInfo);

sampleTimingInfo.duration = CMTimeMake(1, 30) // Specify new frame rate.
sampleTimingInfo.presentationTimeStamp = CMTimeAdd(previousPresentationTimeStamp, sampleTimingInfo.duration);
previousPresentationTimeStamp = sampleTimingInfo.presentationTimeStamp;

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

if (status == noErr) {
/* Write your newBuffer here */
}

//////////

我尝试使用“CMSampleBufferCreateCopyWithNewTiming”。 FPS 已正确设置。但是得到了慢动作输出。以下是我的代码。

autoreleasepool {
//set FPS
var sampleTimingInfo: CMSampleTimingInfo = CMSampleTimingInfo(duration: kCMTimeInvalid, presentationTimeStamp: CMTime(), decodeTimeStamp: kCMTimeInvalid)
var newBuffer: CMSampleBuffer! = nil

CMSampleBufferGetSampleTimingInfo(sampleBufferMain, 0, &sampleTimingInfo);

sampleTimingInfo.duration = CMTimeMake(1, 15) // Specify new frame rate.
sampleTimingInfo.presentationTimeStamp = CMTimeAdd(self.previousPresentationTimeStamp, sampleTimingInfo.duration)
self.previousPresentationTimeStamp = sampleTimingInfo.presentationTimeStamp

let status: OSStatus = CMSampleBufferCreateCopyWithNewTiming(kCFAllocatorDefault, sampleBufferMain, 1, &sampleTimingInfo, &newBuffer);

if status == noErr {
let appendResult = self.videoWriterInput?.append(newBuffer)
if appendResult == false {
printError("writer status: \(String(describing: self.videoWriter?.status.rawValue))")
printError("writer error: \(self.videoWriter?.error.debugDescription ?? "")")
}
} else {
print("write error")
}
}

关于ios - AVAssetWriter - 设置自定义帧率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54435281/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com