Не удалось добавить кадры в видеофайл с помощью AVAssetWriterVideoInput. Сбой с недокументированной ошибкой -12738 в конце
Я использую AVAssetWriterVideoInput для добавления буферов в файл. У меня есть этот код:
if ( _assetWriter.status == AVAssetWriterStatusWriting ) {
// If the asset writer status is writing, append sample buffer to its corresponding asset writer input
if (mediaType == AVMediaTypeVideo) {
if (_assetWriterVideoInput.readyForMoreMediaData) {
if (![_assetWriterVideoInput appendSampleBuffer:sampleBuffer]) {
NSLog(@"error: %@", [_assetWriter.error localizedFailureReason]);
NSLog(@"error: %@", [_assetWriter.error localizedRecoveryOptions]);
NSLog(@"error: %@", [_assetWriter.error localizedDescription]);
NSLog(@"error: %@", [_assetWriter.error domain]);
NSLog(@"error: %@", [_assetWriter.error userInfo]);
} else
NSLog(@"frame saved");
}
}
эта линия
if (![_assetWriterVideoInput appendSampleBuffer:sampleBuffer]) {
не удается с unknown error
и код -12738
это, очевидно, не найдено ни в одной документации, как и ожидалось со всеми документами Apple.
Кроме того, я сомневаюсь, что это неизвестная ошибка по той простой причине, что внутри AVFoundation много кодов для неизвестных ошибок и если система выбирает код -12738
он, очевидно, знает больше, чем говорит, что он неизвестен.
Глядя на сохраняемый файл, он остается 0 мегабайт, потому что буфер / кадр не сохраняется.
это AVAssetWriterVideoInput
был создан так:
CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(currentFormatDescription);
NSUInteger numPixels = dimensions.width * dimensions.height;
NSUInteger bitsPerSecond;
// Assume that lower-than-SD resolutions are intended for streaming, and use a lower bitrate
NSUInteger bitsPerPixel = 11.4; // This bitrate matches the quality produced by AVCaptureSessionPresetHigh.
bitsPerSecond = numPixels * bitsPerPixel;
NSDictionary *videoCompressionSettings = @{AVVideoCodecKey : AVVideoCodecH264,
AVVideoWidthKey : @(dimensions.width),
AVVideoHeightKey : @(dimensions.height),
AVVideoCompressionPropertiesKey : @{ AVVideoAverageBitRateKey : @(bitsPerSecond),
AVVideoMaxKeyFrameIntervalKey : @(30)} };
if ([_assetWriter canApplyOutputSettings:videoCompressionSettings forMediaType:AVMediaTypeVideo])
{
// Intialize asset writer video input with the above created settings dictionary
_assetWriterVideoInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoCompressionSettings];
_assetWriterVideoInput.expectsMediaDataInRealTime = YES;
и буфер, когда он добавлен, имеет следующие характеристики:
CMSampleBuffer 0x1009e12a0 retainCount: 1 allocator: 0x1b762cbb8
invalid = NO
dataReady = YES
makeDataReadyCallback = 0x0
makeDataReadyRefcon = 0x0
formatDescription = <CMVideoFormatDescription 0x170443210 [0x1b762cbb8]> {
mediaType:'vide'
mediaSubType:'BGRA'
mediaSpecific: {
codecType: 'BGRA' dimensions: 1920 x 1080
}
extensions: {<CFBasicHash 0x17087c2c0 [0x1b762cbb8]>{type = immutable dict, count = 2,
entries =>
0 : <CFString 0x1b1c6d460 [0x1b762cbb8]>{contents = "Version"} = <CFNumber 0xb000000000000022 [0x1b762cbb8]>{value = +2, type = kCFNumberSInt32Type}
2 : <CFString 0x1b1c6d3e0 [0x1b762cbb8]>{contents = "CVBytesPerRow"} = <CFNumber 0xb00000000001e002 [0x1b762cbb8]>{value = +7680, type = kCFNumberSInt32Type}
}
}
}
sbufToTrackReadiness = 0x0
numSamples = 1
sampleTimingArray[1] = {
{PTS = {290309939228910/1000000000 = 290309.939}, DTS = {INVALID}, duration = {INVALID}},
}
imageBuffer = 0x170321180
У меня есть пример кода здесь, если вы хотите проверить проблему. Этот код готов снимать видео в 4K. Изменить линию AVCaptureSessionPreset3840x2160
AVCaptureSessionPresetHighinside
ProcessadorVideo.m`, если ваше устройство не может этого сделать. Пример кода обрезает прямоугольник из видеопотока и применяет к нему комический эффект. Спасибо
1 ответ
Я попробовал ваш образец, но не смог воспроизвести ошибку -12783. Однако я получил еще одну ошибку -12780. Я использовал iPhone 6s, так что не уверен, что это связано с этим.
В любом случае я мог бы исправить ошибку -12780. Вы столкнулись с этой проблемой из-за старой отметки времени. Я добавил несколько журналов в ваше приложение для отладки. Увидеть ниже
2017-01-26 15: 00: 35.809590 NotWriting [16829: 3116125] начиная с 401051199680537 2017-01-26 15: 00: 35.809986 NotWriting [16829: 3116125] добавление видеобуфера с отметкой времени 401051199680537 2017-01-26 15:00: 35.810008 NotWriting [16829: 3116125] presentationTimeStamp меньше, чем отметка времени последнего кадра, поэтому, вероятно, произойдет сбой 2017-01-26 15: 00: 35.815605 Ошибка NotWriting [16829: 3116125]: произошла неизвестная ошибка (-12780)
Когда вы пишете буфер, вы должны убедиться, что отметка времени представления больше, чем последний записанный вами кадр, иначе запись не удастся. Вы можете добавить проверку со следующей логикой:
CMTime presentationTimeStamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
if(CMTIME_COMPARE_INLINE(presentationTimeStamp, <=, lastpresentationTimeStamp))
{
NSLog(@"presentationTimeStamp is less than last frame timestamp, So rejecting frame");
return;
}
lastpresentationTimeStamp = presentationTimeStamp;