经过一周的奋斗,我决定寻求帮助:
我尝试了两种方法:
简单地将样本排入队列(因为这是一个实时流,帧定期进入):
- (void)drawSample:(CMSampleBufferRef)sample {
CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sample, YES);
CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
if (CMSampleBufferIsValid(sample)) {
NSLog(@"Valid sample: %@", sample);
}
else {
NSLog(@"Invalid sample: %@", sample);
}
[self.videoLayer enqueueSampleBuffer:sample];
[self.videoLayer setNeedsDisplay];
if (self.colorIndex > 255) {
self.colorIndex = 0;
}
self.videoLayer.backgroundColor = [UIColor colorWithWhite:self.colorIndex / 255.0f alpha:1.0f].CGColor;
self.colorIndex += 1;
}
使用这种方法,不会显示任何框架(为了调试目的,我添加了背景颜色更改代码,这样可以正常工作)。
第二种方法是将帧显示为来自无约束源(尽管仍然使用相同的直播流)。
- (void)drawSample:(CMSampleBufferRef)sample {
CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sample, YES);
CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
if (CMSampleBufferIsValid(sample)) {
NSLog(@"Valid sample");
}
else {
NSLog(@"Invalid sample: %@", sample);
}
[self.videoLayer requestMediaDataWhenReadyOnQueue:self.dispatchQueue usingBlock: ^{
while( [_videoLayer isReadyForMoreMediaData] )
{
if (CMSampleBufferIsValid(sample)) {
[_videoLayer enqueueSampleBuffer:sample];
CFRelease(sample);
}
else {
NSLog(@"Invalid sample inside block: %@", sample);
}
}
NSLog(@"Layer isn't ready");
}];
}
还没有工作。通过这种方法,我有两个问题:
如果我在块中添加CFRelease(sample);
,应用程序将崩溃。启用Zombie Objects后,我收到错误消息:
[Not A Type release]: message sent to deallocated instance 0x7fc6426a2120
我应该将CMSampleBufferRef对象存储在容器中并检索AVSampleBufferDisplayLayer的请求媒体块吗?
如果我不在块内添加CFRelease(sample);
,则只会显示第一帧,并且应用程序最终会因内存警告而崩溃(显然)。
知道我做错了吗?
注意:我已经看过"直接访问媒体编码和解码"来自2014年WWDC的视频,我似乎正在做正确的事情。我已经创建了视频格式描述,用NAL单元中的长度代码替换了起始代码,并成功创建了CMSampleBuffer。