音视频硬编码

AVAssetWriterInputPixelBufferAda

2018-11-15  本文已影响0人  王沐凡

在我们使用AVAssetWriter的时候,经常会用到AVAssetWriterInputPixelBufferAdaptor这个类,从字义上来理解,它是一个输入的像素缓冲适配器,看起来就像你电脑的电源适配器一样。我们来看一下apple官网对它的解释:

A buffer used to append video samples packaged as pixel buffers to a single asset writer input.

apple的解释是,它是一个缓冲区,作为assetWriter的输入,用于把缓冲池中的像素打包追加到视频样本上。这样解释,是不是很清晰了?

那么,为什么要使用它呢?
举例来说,当我们要将摄像头获取的原数据(一般是CMSampleBufferRef)写入文件的时候,需要将CMSampleBufferRef转成CVPixelBuffer,而这个转换是在CVPixelBufferPool中完成的

CVPixelBufferRef newPixelBuffer = NULL;
CVPixelBufferPoolCreatePixelBuffer(NULL, self.inputPixelBufferAdptor.pixelBufferPool, &newPixelBuffer);

AVAssetWriterInputPixelBufferAdaptor的实例提供了一个CVPixelBufferPool,可用于分配像素缓冲区来写入输出数据。 使用它提供的像素缓冲池进行缓冲区分配通常比使用额外创建的缓冲区更有效。这是官方的说法,不建议我们另行创建一个CVPixelBufferPool来使用。

下面仔细来研究一下AVAssetWriterInputPixelBufferAdaptor这个类:
它有三个重要的属性:

@property (nonatomic, readonly) AVAssetWriterInput *assetWriterInput;
@property (nonatomic, readonly, nullable) NSDictionary<NSString *, id> *sourcePixelBufferAttributes;
@property (nonatomic, readonly, nullable) CVPixelBufferPoolRef pixelBufferPool;

首先,每个AVAssetWriterInputPixelBufferAdaptor都包含一个assetWriterInput,用于接收缓冲区中的数据,并且AVAssetWriterInput有一个很重要的属性readyForMoreMediaData,这是一个键值观察属性,它会经常地异步地在NO和YES之间变换,来标识现在缓冲区中的数据是否已经处理完成。通过判断这个属性,我们可以向AVAssetWriterInputPixelBufferAdaptor中添加数据以进行处理。

if (self.inputPixelBufferAdptor.assetWriterInput.isReadyForMoreMediaData ) {
    BOOL success = [self.inputPixelBufferAdptor appendPixelBuffer:newPixelBuffer withPresentationTime:self.currentSampleTime];
    if (!success) {
        NSLog(@"append pixel buffer failed");
       }
}

再来说一下第二个属性sourcePixelBufferAttributes:
它是输入像素源的一些属性,一般由CVPixelBufferPool提供,比如像素宽高,色彩空间等

NSDictionary* sourcePixelBufferAttributesDictionary =
    @{
      (NSString*)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_32BGRA),
      (NSString*)kCVPixelBufferWidthKey:@(self.currentVideoDimensions.width),
      (NSString*)kCVPixelBufferHeightKey:@(self.currentVideoDimensions.height),
      (NSString*)kCVPixelFormatOpenGLESCompatibility:@(1)
      };

与之对应的,是编码输出属性,这个属性在AVAssetWriterInput里,我们上面说过,每个AVAssetWriterInputPixelBufferAdaptor都包含一个assetWriterInput。输出属性包括输出码率,帧率,最大I帧间隔,编码方式,输出分辨率以及填充模式,方向等。

    NSDictionary* compressionProperties =
    @{
      AVVideoAverageBitRateKey:@(bitsPerSecond),
      AVVideoExpectedSourceFrameRateKey:@(30),
      AVVideoMaxKeyFrameIntervalKey:@(30),
      AVVideoProfileLevelKey:AVVideoProfileLevelH264BaselineAutoLevel
      };

    NSDictionary* outputSettings =
    @{
      AVVideoCodecKey:type,
      AVVideoWidthKey:@480,
      AVVideoHeightKey:@640,
      AVVideoScalingModeKey:AVVideoScalingModeResizeAspect,
      AVVideoCompressionPropertiesKey:compressionProperties
      };

这些是视频的主要参数,当然还有音频的,比如采样率,声道,编码方式,输出码率等。可以对比demo进行查看。

对于第三个属性CVPixelBufferPoolRef,上面有说过,它是处理像素的缓冲区,我们一般会使用它将CMSampleBufferRef生成CVPixelBufferRef

哈勒,关于AVAssetWriterInputPixelBufferAdaptor的常见用法就说到这里,如果这篇文章对您有所帮助,请点击下面的支持,非常感谢~ 点击支持后,会有demo的下载链接。

【Light & Shallow】(https://github.com/RonbeKing/Light-Shallow)
若您喜欢demo,还请点击star,能让更多的同学看到,共同探讨,指正,拜谢!

上一篇下一篇

猜你喜欢

热点阅读