SampleBufferDisplayLayer 使用示例
首先看一下SampleBufferView 的定义
#ifndef SampleBufferView_h
#define SampleBufferView_h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface SFSampleBufferView : UIView
- (void)displayPixelBuffer:(CVPixelBufferRef )pixelBuffer;
@end
#endif /* SFSampleBufferView_h */
接下来看下 SampleBufferView 的实现
#import <Foundation/Foundation.h>
#import "SFSampleBufferView.h"
@interface SFSampleBufferView()
{
AVSampleBufferDisplayLayer *_sbdLayer; // layer
CVPixelBufferRef _pixelBuffer; // 需要保存以恶搞 pixelbuffer ref
}
@end
@implementation SFSampleBufferView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// 初始化 AVSampleBufferDisplayLayer
_sbdLayer = [[AVSampleBufferDisplayLayer alloc] init];
_sbdLayer.frame = frame;
_sbdLayer.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
_sbdLayer.videoGravity = AVLayerVideoGravityResizeAspect;
_sbdLayer.opaque = YES;
_sbdLayer.backgroundColor = [UIColor blackColor].CGColor;
// 作为子layer添加到视图的layer
[self.layer addSublayer:_sbdLayer];
}
return self;
}
-(void)setFrame:(CGRect)frame
{
[super setFrame:frame];
[_sbdLayer setFrame:frame];
}
- (void)displayPixelBuffer:(CVPixelBufferRef )pixelBuffer
{
if(!pixelBuffer)
{
return;
}
@synchronized (self) {
if(_pixelBuffer)
{
CFRelease(_pixelBuffer);
_pixelBuffer = nil;
}
_pixelBuffer = CVPixelBufferRetain(pixelBuffer);
}
// 设置时间
CMSampleTimingInfo timing = {kCMTimeInvalid, kCMTimeInvalid, kCMTimeInvalid};
// 获取图像信息
CMVideoFormatDescriptionRef videoInfo = NULL;
OSStatus result = CMVideoFormatDescriptionCreateForImageBuffer(NULL, pixelBuffer, &videoInfo);
NSParameterAssert(result == 0 && videoInfo != NULL);
// 转换成 CMSampleBuffer
CMSampleBufferRef sampleBuffer = NULL;
result = CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, true, NULL, NULL, videoInfo, &timing, &sampleBuffer);
NSParameterAssert(result == 0 && sampleBuffer != NULL);
CFRelease(videoInfo);
// 设置立即显示
CFArrayRef attechments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, YES);
CFMutableDictionaryRef dict = (CFMutableDictionaryRef) CFArrayGetValueAtIndex(attechments, 0);
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
// 推送到queue
[self enqueueSampleBuffer:sampleBuffer toLayer:_sbdLayer];
CFRelease(sampleBuffer);
}
- (void) enqueueSampleBuffer:(CMSampleBufferRef)sampleBuffer toLayer:(AVSampleBufferDisplayLayer *)layer
{
if(sampleBuffer)
{
CFRetain(sampleBuffer);
[layer enqueueSampleBuffer:sampleBuffer];
CFRelease(sampleBuffer);
// 出错了的话,需要flush 一下layer
if(layer.status == AVQueuedSampleBufferRenderingStatusFailed)
{
NSLog(@"ERROR : %@", layer.error);
[_sbdLayer flush];
}
}
}
参考地址: 在iOS端使用AVSampleBufferDisplayLayer进行视频渲染_fernandowei的博客-CSDN博客

浙公网安备 33010602011771号