11

I'm working with AVFoundation for capturing and recording audio. There are some issues I don't quite understand.

Basically I want to capture audio from AVCaptureSession and write it using AVWriter, however I need some shifting in the timestamp of the CMSampleBuffer I get from AVCaptureSession. I read documentation of CMSampleBuffer I see two different term of timestamp: 'presentation timestamp' and 'output presentation timestamp'. What the different of the two ?

Let say I get a CMSampleBuffer (for audio) instance from AVCaptureSession, and I want to write it to a file using AVWriter, what function should I use to 'inject' a CMTime to the buffer in order to set the presentation timestamp of it in the resulting file ?

Thanks.

night_coder
  • 305
  • 6
  • 8

2 Answers2

6

Use the CMSampleBufferGetPresentationTimeStamp, that is the time when the buffer is captured and should be "presented" at when played back to be in sync. To quote session 520 at WWDC 2012: "Presentation time is the time at which the first sample in the buffer was picked up by the microphone".

If you start the AVWriter with

[videoWriter startWriting];
[videoWriter startSessionAtSourceTime:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)];

and then append samples with

if(videoWriterInput.readyForMoreMediaData) [videoWriterInput appendSampleBuffer:sampleBuffer];

the frames in the finished video will be consistent with CMSampleBufferGetPresentationTimeStamp (I have checked). If you want to modify the time when adding samples you have to use AVAssetWriterInputPixelBufferAdaptor

Sten
  • 3,624
  • 1
  • 27
  • 26
  • Why are you asking a question when you are not interested in the answer? – Sten Feb 14 '13 at 11:17
  • I need to set timestamp of CMSampleBuffer because I want to sometime pause the recording of a session. I ended up using CMSampleBufferCreateCopyWithNewTiming. I wonder if there's a direct way to inject the timestamp of existing buffer so I don't need to copy it. – night_coder Feb 17 '13 at 10:52
  • 2
    I can't use AVAssetWriterInputPixelBufferAdaptor since it only works for video stream. – night_coder Feb 17 '13 at 14:14
6

Chunk of sample code from here: http://www.gdcl.co.uk/2013/02/20/iPhone-Pause.html CMSampleBufferRef sample - is your sampleBuffer, CMSampleBufferRef sout your output. NewTimeStamp is your time stamp.

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);
Laz
  • 538
  • 7
  • 12