Как накладывать представления на каждый захваченный кадр внутри CVImageBuffer, в режиме реального времени, а не после процесса

Мне удалось установить базовый AVCaptureSession который записывает видео и сохраняет его на устройстве с помощью AVCaptureFileOutputRecordingDelegate. Я просматриваю документы, чтобы понять, как мы можем добавлять наложения статистики поверх видео, которое записывается.

т.е.

enter image description here

Как вы можете видеть в приведенном выше изображении. У меня несколько надписей поверх слоя предварительного просмотра видео. Теперь, когда я сохраняю свой видеовыход, я хотел бы также скомпоновать эти представления на видео.

Что я пробовал до сих пор?

  • Честно говоря, я просто прыгаю в интернете, чтобы найти авторитетный блог, объясняющий, как это можно сделать. Но не удалось его найти.
  • Я прочитал несколько мест, которые можно было бы CALayer как описано в следующем сообщении, создав CALayer и добавив его в качестве подуровня.
  • Но, о чем я хочу сделать MapView поверх записываемого видео. Кроме того, я не ищу захват экрана. Некоторое содержимое на экране не будет частью окончательной записи, поэтому я хочу, чтобы можно было просматривать вишневое представление, которое будет составлено.

Что я ищу?

  1. Направление.
  2. Нет прямого решения
  3. Ссылки на документацию и имена классов. Я должен больше читать об этом.

Прогресс:

Мне удалось понять, что мне нужно получить CVImageBuffer из CMSampleBuffer и нарисовать текст поверх него. Мне все еще неясно, можно ли каким-либо образом наложить MapView на видео, которое записывается.

Ответ 1

Лучший способ помочь вам достичь своей цели - использовать структуру Metal. Использование Metal камеры полезно для минимизации воздействия на устройства ограниченных вычислительных ресурсов. Если вы пытаетесь достичь самого низкого доступа к датчику камеры, использование AVCaptureSession было бы действительно хорошим началом.

Вам нужно захватить данные каждого кадра из CMSampleBuffer (вы правы), а затем преобразовать фрейм в MTLTexture. AVCaptureSession будет постоянно отправлять нам кадры с камеры устройств через обратный вызов делегата.

Все доступные оверлеи также должны быть преобразованы в MTLTextures. Затем вы можете комбинировать все слои MTLTextures с over операцией.

Итак, здесь вы найдете всю необходимую информацию в четырехчастной серии Metal Camera.

И вот ссылка на блог: О композиции в металле.

Кроме того, я хотел бы опубликовать фрагмент кода (работа с AVCaptureSession in Metal):

import Metal

guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
    // Handle an error here.
}

// Texture cache for converting frame images to textures
var textureCache: CVMetalTextureCache?

// 'MTLDevice' for initializing texture cache
var metalDevice = MTLCreateSystemDefaultDevice()

guard
    let metalDevice = metalDevice
    where CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, metalDevice, nil, &textureCache) == kCVReturnSuccess
else {
    // Handle an error (failed to create texture cache)
}

let width = CVPixelBufferGetWidth(imageBuffer)
let height = CVPixelBufferGetHeight(imageBuffer)

var imageTexture: CVMetalTexture?
let result = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, textureCache.takeUnretainedValue(), imageBuffer, nil, pixelFormat, width, height, planeIndex, &imageTexture)

// 'MTLTexture' is in the 'texture' variable now.
guard
    let unwrappedImageTexture = imageTexture,
    let texture = CVMetalTextureGetTexture(unwrappedImageTexture),
    result == kCVReturnSuccess
else {
    throw MetalCameraSessionError.failedToCreateTextureFromImage
}

И здесь вы можете найти окончательный проект на GitHub: MetalRenderCamera