Как установить временную метку 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);