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

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

т.е.

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

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

  • Честно говоря, я просто прыгаю в Интернете, чтобы найти авторитетный блог, объясняющий, как это можно сделать. Но найти не удалось.
  • Я прочитал несколько мест, где можно создать текстовые слои, как описано в следующем посте, создав 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

Другие вопросы по тегам