iOS10 中的 AVSampleBufferDisplayLayer 不再渲染帧
AVSampleBufferDisplayLayer not rendering frames anymore in iOS10
以下设置一直在所有最近的 iOS 版本上运行,直到 iOS10:
我正在使用 AVSampleBufferDisplayLayer
从自定义来源渲染原始帧。
我使用 CVPixelBufferPoolCreate
设置了一个像素缓冲池,并按照 Apple 的指示将 kCVPixelBufferIOSurfacePropertiesKey
设置为 @{}
。
我使用 CVPixelBufferPoolCreatePixelBuffer
从池中获取像素缓冲区,然后使用 CVPixelBufferLockBaseAddress
和 CVPixelBufferUnlockBaseAddress
.
将我的数据复制到缓冲区
我的原始帧使用 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);
pixelBuffer
是 CVPixelBufferRef
类型,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:您可能想尝试一下,看看它是否也能解决您的问题。
以下设置一直在所有最近的 iOS 版本上运行,直到 iOS10:
我正在使用 AVSampleBufferDisplayLayer
从自定义来源渲染原始帧。
我使用 CVPixelBufferPoolCreate
设置了一个像素缓冲池,并按照 Apple 的指示将 kCVPixelBufferIOSurfacePropertiesKey
设置为 @{}
。
我使用 CVPixelBufferPoolCreatePixelBuffer
从池中获取像素缓冲区,然后使用 CVPixelBufferLockBaseAddress
和 CVPixelBufferUnlockBaseAddress
.
我的原始帧使用 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);
pixelBuffer
是 CVPixelBufferRef
类型,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:您可能想尝试一下,看看它是否也能解决您的问题。