前言
正文
ios中視頻流渲染有三種方法:
AVCaptureVideoPreviewLayer:視頻采集時回顯使用的圖層揣钦, 調用簡單移层,功能較少。
AVSampleBufferDisplayLayer:CPU渲染yuv數據也可直接渲染壓縮的視頻數據憔鬼,小巧方便龟劲,功能比較豐富,可操作性強轴或。
openGl:GPU渲染昌跌,功能強大,性能卓越照雁,使用復雜蚕愤。
本文主要介紹AVSampleBufferDisplayLayer,demo分為兩個類,大屏和小屏,小屏繼承自大屏類.
openGl推薦參考:落影l(fā)oyinglin
創(chuàng)建渲染圖層
- (void)createLayer
{
if (!self.buffer_layer)
{
self.buffer_layer = [[AVSampleBufferDisplayLayer alloc]init];
self.buffer_layer.frame = self.bounds;
self.buffer_layer.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
/*!
@constant AVLayerVideoGravityResizeAspect 根據圖像像素比例 繪制圖像 圖像會填充不滿圖層size
@abstract Preserve aspect ratio; fit within layer bounds.
@constant AVLayerVideoGravityResizeAspectFill 根據像素比例 填充圖層 畫面會超出圖層size
@abstract Preserve aspect ratio; fill layer bounds.
@constant AVLayerVideoGravityResize 拉伸 用這個自適應不同size圖層最好
@abstract Stretch to fill layer bounds.
*/
self.buffer_layer.videoGravity = AVLayerVideoGravityResizeAspect;
//不透明
self.buffer_layer.opaque = YES;
[self.layer addSublayer:self.buffer_layer];
}
else
{
[CATransaction begin];
[CATransaction setDisableActions:YES];
self.buffer_layer.bounds = self.qlframe;
self.buffer_layer.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
[CATransaction commit];
}
}
播放
#pragma mark - play
// 每來一幀數據進行緩存, 從后臺模式返回后, 重啟layer
- (void)play:(CMSampleBufferRef)buffer
{
if (buffer)
{
[_buffer_layer enqueueSampleBuffer:buffer];
if (_buffer_layer.status == AVQueuedSampleBufferRenderingStatusFailed)
{
//后臺喚醒重啟渲染層
if (-11847 == _buffer_layer.error.code)
{
NSLog(@"11111");
[self rebuildSampleBufferDisplayLayer];
}
else
{
[self rebuildSampleBufferDisplayLayer];
NSLog(@"%s 第%d行 %@",__func__,__LINE__,_buffer_layer.error.description);
}
}
}
}
#pragma mark - 重啟渲染layer
- (void)rebuildSampleBufferDisplayLayer
{
[self remove_layer];
[self createLayer];
}
- (void)remove_layer
{
if (self.buffer_layer)
{
[self.buffer_layer stopRequestingMediaData];
[self.buffer_layer removeFromSuperlayer];
self.buffer_layer = nil;
}
}
小屏
小屏的切換和拖拽功能只是添加了兩個手勢
- (instancetype)initWithFrame:(CGRect)frame and_touchBlock:(touchBlock)touch_block and_panBlcok:(panblock)pan_block
{
if (self = [super initWithFrame:frame and_touchBlock:touch_block and_panBlcok:pan_block])
{
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
[self addGestureRecognizer:tap];
UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
[self addGestureRecognizer:pan];
}
return self;
}
- (void)tap:(UITapGestureRecognizer*)tap
{
// 切換大小屏時,在此block內 調用flushAndRemoveImage 清除緩存
self.touch_block();
}
- (void)pan:(UIPanGestureRecognizer*)pan
{
self.pan_block(pan);
}
最后
demo地址
下一篇:音頻采集播放與編解碼
歡迎交流指正