标签: cvpixelbuffer

调整 CVPixelBuffer 的大小

我正在尝试将 CVPixelBuffer 大小调整为 128x128。我正在使用 750x750 的分辨率。我目前正在使用 CVPixelBuffer 创建一个新的 CGImage,调整大小然后转换回 CVPixelBuffer。这是我的代码:

func getImageFromSampleBuffer (buffer:CMSampleBuffer) -> UIImage? {
    if let pixelBuffer = CMSampleBufferGetImageBuffer(buffer) {
        let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
        let context = CIContext()
        let imageRect = CGRect(x: 0, y: 0, width: 128, height: 128)

        if let image = context.createCGImage(ciImage, from: imageRect) {
            let t = CIImage(cgImage: image)
            let new = t.applying(transformation)
            context.render(new, to: pixelBuffer)

            return UIImage(cgImage: image, scale: UIScreen.main.scale, orientation: .right)
        }

    }

    return nil
}
Run Code Online (Sandbox Code Playgroud)

我还尝试缩放 CIImage 然后转换它:

let t = …
Run Code Online (Sandbox Code Playgroud)

core-image ios swift cvpixelbuffer swift3

6
推荐指数
1
解决办法
9718
查看次数

如何裁剪和翻转 CVPixelBuffer 并返回 CVPixelBuffer?

我正在制作一个快速的视频应用程序。

在我的应用程序中,我需要裁剪和水平翻转 CVPixelBuffer 并返回类型也是 CVPixelBuffer 的结果。

我尝试了几件事。

首先,我使用了“CVPixelBufferCreateWithBytes”

func resizePixelBuffer(_ pixelBuffer: CVPixelBuffer, destSize: CGSize) 
-> CVPixelBuffer? 
{

  CVPixelBufferLockAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: O))

  let baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer)
  let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)
  let pixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer)
  let width = CVPixelBufferGetWidth(pixelBuffer)
  let height = CVPixelBufferGetHeight(pixelBuffer)

  var destPixelBuffer: CVPixelBuffer?

  let topMargin = (height - destsize.height) / 2
  let leftMargin = (width - destsize.width) / 2 * 4   // bytesPerPixel
  let offset = topMargin * bytesPerRow + leftMargin

  CVPixelBufferCreateWithBytes(kCFAllocatorDefault, 
                               destSize.width, 
                               destSize.height, 
                               pixelFormat, 
                               baseAddress.advanced(by: offset),
                               bytesPerRow, 
                               nil, nil, …
Run Code Online (Sandbox Code Playgroud)

crop cgimage ciimage swift cvpixelbuffer

6
推荐指数
1
解决办法
2386
查看次数

swift - CGImage 到 CVPixelBuffer

如何快速将 a 转换CGImage为 a CVPixelBuffer

我知道有很多问题试图做相反的事情,还有一些客观的 C 答案,比如这个,但我无法让它们迅速工作。这是我最接近的:

func pixelBufferFromCGImage(image: CGImage) -> CVPixelBuffer {
    var pxbuffer: CVPixelBuffer? = nil
    let options: NSDictionary = [:]

    let width =  image.width
    let height = image.height
    let bytesPerRow = image.bytesPerRow

    let dataFromImageDataProvider = image.dataProvider!.data
    let x = CFDataGetBytePtr(dataFromImageDataProvider)

    CVPixelBufferCreateWithBytes(
        kCFAllocatorDefault,
        width,
        height,
        kCVPixelFormatType_32ARGB,
        CFDataGetBytePtr(dataFromImageDataProvider),
        bytesPerRow,
        nil,
        nil,
        options,
        &pxbuffer
    )
    return pxbuffer!;
}
Run Code Online (Sandbox Code Playgroud)

(这不会编译,因为CVPixelBufferCreateWithBytesUnsafeMutablePointer 除外,并且CFDataGetBytePtr(dataFromImageDataProvider)UnsafePointer<UIint8>!

cgimage swift cvpixelbuffer

5
推荐指数
1
解决办法
3515
查看次数

金属渲染循环优化

我正在寻找有关如何正确实现 Metal 渲染循环的一些指导。我的渲染循环正在从AVPlayer.

这是我当前的实现:

  1. A以60hzCVDisplayLink查询播放器的频率。AVPlayerItemVideoOutput如果存在新帧,则会将其捕获/保存*作为它将渲染到的CVPixelBufferRef属性。MTKView(此时,先前捕获的视频帧被释放)。
  2. 我的MTKView设置是用isPausedenableSetNeedsDisplayto NO。换句话说,内部定时器的任务MTKView是定期调用其drawRect方法。
  3. drawRect首先将新到达的 * 转换CVPixelBuffer为 a MTLTexture,然后发生一堆渲染阶段。
  4. 最后,我在方法presentDrawable结束时调用drawRect

*注意:对 的互斥访问由和CVPixelBufferRef配对控制 。dispatch_semaphore_waitdispatch_semaphore_signal

这是正确的做事方式吗? 尽管偶尔会丢失一些帧,但它看起来性能相当不错。在时间方面,Metal 的 Xcode 分析告诉我,我的MTLCommandBuffer运行时间通常不到 3 毫秒。

话虽如此,我看到了一些替代的可能性:

  • 放弃CVDisplayLink实现并获取其中的框架drawRect
  • 反转渲染过程;首先在方法中显示先前捕获的帧并渲染,然后显示 Metal 命令缓冲区并立即调用。之后,捕获下一个视频帧并在下一次调用之前运行它的渲染阶段(在退出之前这样做吗?)。MTLTexturedrawRectcommitpresentDrawabledrawRectdrawRect

另一个问题: …

drawrect avplayer metal cvpixelbuffer metalkit

5
推荐指数
0
解决办法
894
查看次数

创建宽度倍数为 90 的 CVPixelBuffer 时,每行字节数错误

我正在处理从网络接收的原始 yuv420 双平面帧数据,需要创建 CVPixelBuffer 以便将其处理为 Core Image 以及使用 AVAssetWriter 写入磁盘。

当我尝试使用下面的代码创建一个宽度为 120、240 或 480 的 CVPixelBuffer 时,它会分配内存并为两个平面创建一个具有正确 bytePerRow 值的正确 CVPixelBuffer(例如宽度 120 会产生 120 bytePerRow 的值)。

但是,当我输入宽度为 90、180 或 360 的帧时,它会产生错误的 bytePerRow,例如帧宽度为 180 时为 192 bytePerRow。这会导致稍后在 CoreImage 或 AVAssetWriter 中绘制的问题。

请参阅下面的代码来创建 CVPixelBuffer。

CGSize frameSize = CGSizeMake(180,240);
CVPixelBufferRef pixelBuffer = NULL;
NSDictionary *pixelAttributes = @{(id)kCVPixelBufferIOSurfaceOpenGLESFBOCompatibilityKey : (id)kCFBooleanTrue,
                                  (id)kCVPixelBufferIOSurfaceCoreAnimationCompatibilityKey : (id)kCFBooleanTrue,     
                                  (id)kCVPixelBufferIOSurfaceOpenGLESTextureCompatibilityKey : (id)kCFBooleanTrue,     
                                  (id)kCVPixelBufferOpenGLESCompatibilityKey: (id)kCFBooleanTrue};

CVReturn result = CVPixelBufferCreate(NULL, frameSize.width, frameSize.height, kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, (__bridge CFDictionaryRef _Nullable)(pixelAttributes), &pixelBuffer);
Run Code Online (Sandbox Code Playgroud)

请注意,我无法使用 CVPixelBufferCreateWithPlanarBytes,这会迫使我自己分配内存,并在稍后与 Core Image 一起使用时导致内存泄漏,这不是此问题的主题。

objective-c core-image avfoundation ios cvpixelbuffer

5
推荐指数
1
解决办法
1839
查看次数

旋转 CMSampleBuffer/CVPixelBuffer

我目前正在尝试通过首先将其转换为 CVPixelBuffer 然后使用 vImageRotate90_ARGB8888 来转换缓冲区来更改 CMSampleBuffer 的方向。我的代码的问题是当 vImageRotate90_ARGB8888 执行时,它立即崩溃。我知道有答案(比如这个这个),但是所有这些解决方案在我的情况下都不起作用,我真的找不到任何类型的错误,或者想不出任何会导致这种行为的东西。我当前的代码如下:

- (CVPixelBufferRef)rotateBuffer:(CMSampleBufferRef)sampleBuffer {
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(pixelBuffer, 0);

size_t bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer);
size_t width = CVPixelBufferGetWidth(pixelBuffer);
size_t height = CVPixelBufferGetHeight(pixelBuffer);
size_t currSize = bytesPerRow * height * sizeof(unsigned char);
size_t bytesPerRowOut = 4 * height * sizeof(unsigned char);

OSType pixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer);

void *baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer);
unsigned char *outPixelData = (unsigned char *)malloc(currSize);

vImage_Buffer sourceBuffer = {baseAddress, height, width, bytesPerRow};
vImage_Buffer destinationBuffer = {outPixelData, width, height, …
Run Code Online (Sandbox Code Playgroud)

objective-c ios accelerate-framework cmsamplebuffer cvpixelbuffer

5
推荐指数
0
解决办法
3149
查看次数

从 SCNView 录制视频的最快方法

我有 SCNView,屏幕中间有一些对象,用户可以旋转它、缩放等。

我想在视频中记录所有这些动作并实时添加一些声音。另外,我只想记录SCNView的中间部分(例如SCNView框架是375x812,但我只想中间375x375,没有顶部和底部边框)。我还想在视频捕获的同时将其显示在屏幕上。

我当前的变体是:

func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) {
    DispatchQueue.main.async {
        if let metalLayer = self.sceneView.layer as? CAMetalLayer, let texture = metalLayer.currentSceneDrawable?.texture, let pixelBufferPool = self.pixelBufferPool {
            //1
            var maybePixelBuffer: CVPixelBuffer? = nil
            let status  = CVPixelBufferPoolCreatePixelBuffer(nil, pixelBufferPool, &maybePixelBuffer)

            guard let pixelBuffer = maybePixelBuffer else { return }

            CVPixelBufferLockBaseAddress(pixelBuffer, [])

            let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)
            let region = MTLRegionMake2D(Int(self.fieldOfView.origin.x * UIScreen.main.scale),
                                         Int(self.fieldOfView.origin.y * UIScreen.main.scale),
                                         Int(self.fieldOfView.width * UIScreen.main.scale),
                                         Int(self.fieldOfView.height * UIScreen.main.scale))

            let pixelBufferBytes = CVPixelBufferGetBaseAddress(pixelBuffer)!
            texture.getBytes(pixelBufferBytes, …
Run Code Online (Sandbox Code Playgroud)

ios avassetwriter scenekit metal cvpixelbuffer

5
推荐指数
1
解决办法
1069
查看次数

如何将现有 OpenGL 纹理转换为金属纹理

我正在为 Motion 和 FCP X 开发一些 FxPlug 插件。最终,我想让它们在 Metal 中渲染,因为 Apple 正在弃用 OpenGL。

我目前正在使用 CoreImage,虽然我已经能够使用 CoreImage 功能在 FxPlug SDK 之外进行 Metal 处理,但 FxPlug 只向我提供帧作为 OpenGL 纹理。我尝试将其传递到 CoreImage 过滤器中,但最终收到此错误:

Cannot render image (with an input GL texture) using a metal-DG context.
Run Code Online (Sandbox Code Playgroud)

经过一番研究,我发现我应该使用 CVPixelBuffers 在两者之间共享纹理,但是在尝试使用这种方法编写代码一段时间后,我开始相信这是一种 WRITE 的方式(如从头开始创建)到共享缓冲区,但不在之间进行转换。虽然这可能不正确,但我无法找到一种方法来使现有的 GL 纹理存在于 CVPixelBuffer 中。

TL;DR:我已经找到了从 CVPixelBuffer 获取生成的 Metal 或 OpenGL 纹理的方法,但我找不到从现有 OpenGL 纹理创建 CVPixelBuffer 的方法。我并不打算采用这种方法,因为我的最终目标是简单地从 OpenGL 转换为 Metal,然后再转换回 OpenGL(理想情况下以有效的方式)。

还有其他人找到了将 FxPlug 与 Metal 一起使用的方法吗?有没有好方法从 OpenGL 纹理转换为 Metal/CVPixelBuffer?

opengl core-image metal cvpixelbuffer

5
推荐指数
1
解决办法
1761
查看次数

如何在 Swift 中直接从 CIImage 而不是 UIImage 制作 CVPixelBuffer ?

我正在通过 iPhone 摄像头录制经过过滤的视频,在录制时将 CIImage 实时转换为 UIImage 时,CPU 使用率大幅增加。我制作 CVPixelBuffer 的缓冲区函数使用了 UIImage,到目前为止,它需要我进行此转换。如果可能的话,我想创建一个采用 CIImage 的缓冲函数,这样我就可以跳过从 UIImage 到 CIImage 的转换。我认为这会给我录制视频时的性能带来巨大的提升,因为 CPU 和 GPU 之间不会有任何交接。

这就是我现在所拥有的。在我的 captureOutput 函数中,我从 CIImage 创建了一个 UIImage,它是过滤后的图像。我使用 UIImage 从缓冲区函数创建一个 CVPixelBuffer,并将其附加到 assetWriter 的 pixelBufferInput:

let imageUI = UIImage(ciImage: ciImage)

let filteredBuffer:CVPixelBuffer? = buffer(from: imageUI)

let success = self.assetWriterPixelBufferInput?.append(filteredBuffer!, withPresentationTime: self.currentSampleTime!)
Run Code Online (Sandbox Code Playgroud)

我使用 UIImage 的缓冲函数:

func buffer(from image: UIImage) -> CVPixelBuffer? {
    let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
    var pixelBuffer : CVPixelBuffer?
    let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(image.size.width), Int(image.size.height), kCVPixelFormatType_32ARGB, attrs, …
Run Code Online (Sandbox Code Playgroud)

uiimage avassetwriter ciimage swift cvpixelbuffer

5
推荐指数
2
解决办法
6623
查看次数

在 iOS 中用 Swift 绘制/编辑 CVPixelBuffer 的正确方法

是否有一种标准的高性能方法可以快速编辑/绘制 CVImageBuffer/CVPixelBuffer?

我在网上找到的所有视频编辑演示都将绘图(矩形或文本)覆盖在屏幕上,并且不直接编辑 CVPixelBuffer。

更新我尝试使用 CGContext 但保存的视频不显示上下文绘图

private var adapter: AVAssetWriterInputPixelBufferAdaptor?

extension TrainViewController: CameraFeedManagerDelegate {
    
    func didOutput(sampleBuffer: CMSampleBuffer) {

        let time = CMTime(seconds: timestamp - _time, preferredTimescale: CMTimeScale(600))
        let pixelBuffer: CVPixelBuffer? = CMSampleBufferGetImageBuffer(sampleBuffer)

        guard let context = CGContext(data: CVPixelBufferGetBaseAddress(pixelBuffer),
                                  width: width,
                                  height: height,
                                  bitsPerComponent: 8,
                                  bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer),
                                  space: colorSpace,
                                  bitmapInfo: alphaInfo.rawValue)
        else {
          return nil
        }

        context.setFillColor(red: 1, green: 0, blue: 0, alpha: 1.0)
        context.fillEllipse(in: CGRect(x: 0, y: 0, width: width, height: height))
        context.flush()

        adapter?.append(pixelBuffer, withPresentationTime: time)


    }
}
Run Code Online (Sandbox Code Playgroud)

opencv image ios swift cvpixelbuffer

5
推荐指数
1
解决办法
1953
查看次数