如何为AVWriter写入设置CMSampleBuffer的时间戳

时间:2013-02-09 09:18:05

标签: ios avfoundation audio-recording cmsamplebufferref core-media

我正在使用AVFoundation捕获和录制音频。有些问题我不太明白。

基本上我想从AVCaptureSession捕获音频并使用AVWriter编写它,但是我需要在从AVCaptureSession获得的CMSampleBuffer的时间戳中进行一些转换。我阅读了CMSampleBuffer的文档。我看到两个不同的时间戳术语:'presentation timestamp'和'output presentation timestamp'。这两者有什么不同?

假设我从AVCaptureSession获取CMSampleBuffer(用于音频)实例,并且我想使用AVWriter将其写入文件,我应该使用什么函数将CMTime“注入”到缓冲区以设置演示时间戳在结果文件中?

感谢。

2 个答案:

答案 0 :(得分:6)

使用CMSampleBufferGetPresentationTimeStamp,即捕获缓冲区的时间,并在播放时同步时“显示”。引用WWDC 2012上的会议520:“演示时间是麦克风拾取缓冲区中第一个样本的时间”。

如果您使用

启动AVWriter
[videoWriter startWriting];
[videoWriter startSessionAtSourceTime:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)];

然后用

附加样本
if(videoWriterInput.readyForMoreMediaData) [videoWriterInput appendSampleBuffer:sampleBuffer];

完成的视频中的帧将与CMSampleBufferGetPresentationTimeStamp一致(我已经检查过)。如果要修改添加样本的时间,则必须使用AVAssetWriterInputPixelBufferAdaptor

答案 1 :(得分:6)

来自此处的示例代码块:http://www.gdcl.co.uk/2013/02/20/iPhone-Pause.html CMSampleBufferRef示例 - 是您的sampleBuffer,CMSampleBufferRef sout您的输出。 NewTimeStamp是你的时间戳。

CMItemCount count;
CMTime newTimeStamp = CMTimeMake(YOURTIME_GOES_HERE);
CMSampleBufferGetSampleTimingInfoArray(sample, 0, nil, &count);
CMSampleTimingInfo* pInfo = malloc(sizeof(CMSampleTimingInfo) * count);
CMSampleBufferGetSampleTimingInfoArray(sample, count, pInfo, &count);
for (CMItemCount i = 0; i < count; i++)
{
    pInfo[i].decodeTimeStamp = newTimeStamp; // kCMTimeInvalid if in sequence
    pInfo[i].presentationTimeStamp = newTimeStamp;

}
CMSampleBufferRef sout;
CMSampleBufferCreateCopyWithNewTiming(kCFAllocatorDefault, sample, count, pInfo, &sout);
free(pInfo);