iOS10 中的 AVSampleBufferDisplayLayer 不再渲染帧

AVSampleBufferDisplayLayer not rendering frames anymore in iOS10

以下设置一直在所有最近的 iOS 版本上运行,直到 iOS10:

我正在使用 AVSampleBufferDisplayLayer 从自定义来源渲染原始帧。

我使用 CVPixelBufferPoolCreate 设置了一个像素缓冲池,并按照 Apple 的指示将 kCVPixelBufferIOSurfacePropertiesKey 设置为 @{}

我使用 CVPixelBufferPoolCreatePixelBuffer 从池中获取像素缓冲区,然后使用 CVPixelBufferLockBaseAddressCVPixelBufferUnlockBaseAddress.

将我的数据复制到缓冲区

我的原始帧使用 NV12 格式 kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange

这是一个代码片段,展示了我如何将像素缓冲区转换为 CMSampleBufferRef 并将其排入显示层:

  CMSampleTimingInfo sampleTimeinfo{
      CMTimeMake(duration.count(), kOneSecond.count()),
      kCMTimeInvalid,
      kCMTimeInvalid};

  CMFormatDescriptionRef formatDescription = nullptr;
  CMVideoFormatDescriptionCreateForImageBuffer(nullptr, pixelBuffer, &formatDescription);

  CMSampleBufferRef sampleBuffer = nullptr;
  CMSampleBufferCreateForImageBuffer(
          nullptr, pixelBuffer, true, nullptr, nullptr, formatDescription, &sampleTimeinfo, &sampleBuffer));


  CFArrayRef attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, YES);
  const CFIndex numElementsInArray = CFArrayGetCount(attachmentsArray);

  for (CFIndex i = 0; i < numElementsInArray; ++i) {
    CFMutableDictionaryRef attachments = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachmentsArray, i);
    CFDictionarySetValue(attachments, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
  }

  if ([avfDisplayLayer_ isReadyForMoreMediaData]) {
    [avfDisplayLayer_ enqueueSampleBuffer:sampleBuffer];
  }

  CFRelease(sampleBuffer);
  CFRelease(formatDescription);

pixelBufferCVPixelBufferRef 类型,avfDisplayLayer_ AVSampleBufferDisplayLayer.

下一个片段展示了我如何构建显示层:

  avfDisplayLayer_ = [[AVSampleBufferDisplayLayer alloc] init];
  avfDisplayLayer_.videoGravity = AVLayerVideoGravityResizeAspectFill;

我没有收到任何警告或错误消息,显示层状态未指示失败并且 isReadyForMoreMediaData 正在返回 true。

问题是我的相框没有显示在屏幕上。我还在显示层上设置了背景色,只是为了确保层的合成正确(确实如此)。

iOS10 中一定有关于 AVSampleBufferDisplayLayer 的更改,但我无法弄清楚它是什么。

事实证明,使用 iOS10,CMSampleTimingInfo 的值显然被更严格地解析。

为了使渲染再次正常工作,将上面的代码更改为以下代码:

  CMSampleTimingInfo sampleTimeinfo{
      CMTimeMake(duration.count(), kOneSecond.count()),
      kCMTimeZero,
      kCMTimeInvalid};

请注意 presentationTimeStamp 字段的 kCMTimeZero

@Sterling Archer:您可能想尝试一下,看看它是否也能解决您的问题。