Как установить временную метку CMSampleBuffer для записи AVWriter

Я работаю с AVFoundation для захвата и записи аудио. Есть некоторые проблемы, которые я не совсем понимаю.

По сути, я хочу захватывать звук из AVCaptureSession и записывать его с помощью AVWriter, однако мне нужно немного сместить временную метку CMSampleBuffer, которую я получаю из AVCaptureSession. Я читаю документацию CMSampleBuffer и вижу два разных термина временной метки: "временная метка представления" и "временная метка презентации". Что отличается от двух?

Допустим, я получаю экземпляр CMSampleBuffer (для аудио) из AVCaptureSession и хочу записать его в файл с помощью AVWriter, какую функцию я должен использовать, чтобы "вставить" CMTime в буфер, чтобы установить его временную метку представления в результирующий файл?

Благодарю.

2 ответа

Используйте CMSampleBufferGetPresentationTimeStamp, то есть время, когда буфер захвачен и должен быть "представлен" при воспроизведении для синхронизации. Процитируем сессию 520 на WWDC 2012: "Время представления - это время, когда микрофон взял первую выборку в буфере".

Если вы запустите AVWriter с

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

а затем добавить образцы с

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

кадры в готовом видео будут соответствовать CMSampleBufferGetPresentationTimeStamp (я проверял). Если вы хотите изменить время добавления образцов, вы должны использовать AVAssetWriterInputPixelBufferAdaptor

Кусок примера кода отсюда: http://www.gdcl.co.uk/2013/02/20/iPhone-Pause.html Пример CMSampleBufferRef - это ваш sampleBuffer, CMSampleBufferRef следит за вашим выводом. 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);
Другие вопросы по тегам