【问题标题】:Failure to append frames to video file using AVAssetWriterVideoInput. Fails with undocumented error -12738 at the end无法使用 AVAssetWriterVideoInput 将帧附加到视频文件。失败,最后出现未记录的错误 -12738
【发布时间】:2017-01-27 04:05:31
【问题描述】:

我正在使用 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 失败,显然在任何 documentation 上都找不到,正如所有苹果文档所预期的那样。

另外,我怀疑这是一个未知错误,原因很简单,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

I have a sample code here 如果你想检查问题。该代码准备拍摄 4K 视频。如果您的设备无法执行此操作,请将行 AVCaptureSessionPreset3840x2160 更改为 AVCaptureSessionPresetHighinsideProcessadorVideo.m`。示例代码从视频流中裁剪出一个矩形,并对其应用漫画效果。 谢谢

【问题讨论】:

  • 你在打电话给startSessionAtSourceTime吗?
  • 这个问题和你的另一个问题stackoverflow.com/a/41207678/22147类似吗?
  • 抱歉延迟回答这个问题:不。试过了。问题仍然存在。
  • @RhythmicFistman - 我已经为此开了一个赏金 -
  • 由于常规文档没有提供有关此错误代码的线索,我怀疑该错误来自另一个例程(而不是 appendSampleBuffer)。您是否查看过其他可能导致问题的原因?是否有可能您的内存不足?您正在写入现有文件夹吗?您有权访问此文件夹吗?您正在追加,它是否已经有数据?等等。

标签: ios avfoundation avassetwriter avassetwriterinput


【解决方案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;

【讨论】:

    猜你喜欢
    • 2012-08-25
    • 2019-11-09
    • 2021-06-22
    • 2015-07-16
    • 1970-01-01
    • 2016-07-08
    • 2023-03-12
    • 1970-01-01
    • 2019-03-02
    相关资源
    最近更新 更多