MAC - AVAssetReader для TRIM - чтение образцов вне порядка
Я пытаюсь прочитать и записать образцы из видеофайла в определенной начальной и конечной точках обрезки видео. Я использую AVAssetReader и AVAssetWriter.
Используемая здесь логика -
ШАГ А:
- Создайте экземпляр средства чтения ресурсов с указанным ресурсом.
- Установите временной диапазон для считывателя согласно начальной и конечной точкам. (Например, начальная точка = 5, конечная точка = 15, длина файла = 55 с)
- Начните читать образцы.
- Получите точную временную отметку образца относительно начальной точки, которую мы передали.
- Сохраните отметку времени образца, которая является точной с начальной точкой (может быть 5,13 или около того). Скажи та = 5,13
- Выпустите читателя.
ШАГ Б:
- Создайте новый экземпляр читателя с указанным ресурсом.
- Установите временной диапазон для считывателя согласно начальной и конечной точкам. (Например, начальная точка = 5, конечная точка = 15, длина файла = 55 с)
- Начните читать образцы.
- Создайте новый буфер семплов с информацией о времени семплов, измененной как (отметка времени буфера семплов t1- ta, полученная из STEP A) - Это начинает запись с 0 (отметка времени буфера семплов t2- ta, выбранная из STEP A) (отметка времени T3 буфера семплов - та извлекается из ШАГА А) и так до конечной точки.
- Выпустите читателя.
Пример кода для того же:
ШАГ А:
while ([assetWriterInput isReadyForMoreMediaData] )
{
CMSampleBufferRef sampleBuffer = [assetReaderOutput copyNextSampleBuffer];
if (sampleBuffer != NULL)
{
CMTime originalTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
float time = CMTimeGetSeconds( originalTime );
// This is where we store the time stamp
fTimeTange = time;
[HelpMethods setCorrectEditTime:fTimeTange]; // This is stored globally
// This is to release the readers and writers and start a fresh call with the stored time stamp ta
[delegate resetTimeRange];
return;
}
}
ШАГ Б:
while ([assetWriterInput isReadyForMoreMediaData] )
{
CMSampleBufferRef sampleBuffer = [assetReaderOutput copyNextSampleBuffer];
if (sampleBuffer != NULL)
{
CMSampleBufferRef finalBuffer = sampleBuffer;
CMSampleBufferRef newSampleBuffer;
CMSampleTimingInfo sampleTimingInfo;
CMTime cmm1 = CMSampleBufferGetOutputDuration(sampleBuffer);
CMTime originalTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
float time = CMTimeGetSeconds( originalTime );
// This is a helper method to get the stored ta at STEP A
fTimeTange = [HelpMethods getCorrectEditTime];
sampleTimingInfo.duration = cmm1;
float milliseconds = (time - fTimeTange) * 600;
NSLog( @"Timestamp in milliseconds = %f", milliseconds );
sampleTimingInfo.presentationTimeStamp = CMTimeMake(milliseconds, 600);
sampleTimingInfo.decodeTimeStamp = kCMTimeInvalid;
CMSampleBufferCreateCopyWithNewTiming(kCFAllocatorDefault,
sampleBuffer,
1,
&sampleTimingInfo,
&newSampleBuffer);
finalBuffer = newSampleBuffer;
BOOL success = YES;
success = [assetWriterInput appendSampleBuffer:finalBuffer];
CFRelease(sampleBuffer);
sampleBuffer = NULL;
}
Так как временные метки образцов читаются не по порядку, мы получаем ошибку
"(kFigFormatWriterError_InvalidTimestamp) (временная метка декодирования меньше временной метки декодирования предыдущего образца)"
и значения меток времени -
- Отметка времени в миллисекундах = 0,000000
- Отметка времени в миллисекундах = 79,999924
- Отметка времени в миллисекундах = 39.999962
- Отметка времени в миллисекундах = 119,999886
- Отметка времени в миллисекундах = 200.000092
- Метка времени в миллисекундах = 160.000137
- Метка времени в миллисекундах = 280.000031
- Отметка времени в миллисекундах = 240,000061
- Отметка времени в миллисекундах = 319,999969
- Отметка времени в миллисекундах = 399,999908
- Отметка времени в миллисекундах = 359,999939 и т. Д.
Любые манипуляции с марками презентации приводят к неправильному чтению образцов.
Выискивая способ преодолеть это не по порядку, читая метки времени. Пожалуйста, дайте знать.
Спасибо заранее, Чампа