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博客

posted @ 2021-10-21 15:01  零度不冷  阅读(350)  评论(0)    收藏  举报