Я делаю обработку видео в реальном времени на iOS со скоростью 120 кадров в секунду и хочу сначала предварительно обработать изображение на графическом процессоре (сокращение, преобразование цвета и т.д., которые недостаточно быстры для процессора) и более поздний постпроцессный фрейм на CPU с использованием OpenCV.
Какой самый быстрый способ обмена каналами камеры между GPU и CPU с помощью Metal?
Другими словами, труба будет выглядеть так:
CMSampleBufferRef -> MTLTexture or MTLBuffer -> OpenCV Mat
Я конвертирую CMSampleBufferRef → MTLTexture следующим образом
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
// textureRGBA
{
size_t width = CVPixelBufferGetWidth(pixelBuffer);
size_t height = CVPixelBufferGetHeight(pixelBuffer);
MTLPixelFormat pixelFormat = MTLPixelFormatBGRA8Unorm;
CVMetalTextureRef texture = NULL;
CVReturn status = CVMetalTextureCacheCreateTextureFromImage(NULL, _textureCache, pixelBuffer, NULL, pixelFormat, width, height, 0, &texture);
if(status == kCVReturnSuccess) {
textureBGRA = CVMetalTextureGetTexture(texture);
CFRelease(texture);
}
}
После того, как мой металлический шейдер завершен, я конвертирую MTLTexture в OpenCV
cv::Mat image;
...
CGSize imageSize = CGSizeMake(drawable.texture.width, drawable.texture.height);
int imageByteCount = int(imageSize.width * imageSize.height * 4);
int mbytesPerRow = 4 * int(imageSize.width);
MTLRegion region = MTLRegionMake2D(0, 0, int(imageSize.width), int(imageSize.height));
CGSize resSize = CGSizeMake(drawable.texture.width, drawable.texture.height);
[drawable.texture getBytes:image.data bytesPerRow:mbytesPerRow fromRegion:region mipmapLevel:0];
Некоторые наблюдения:
1) К сожалению, MTLTexture.getBytes
кажется дорогим (копирование данных с GPU на CPU?) и занимает около 5 мс на моем iphone 5S, что слишком много при обработке со скоростью ~ 100 кадров в секунду
2) Я заметил, что некоторые люди используют MTLBuffer вместо MTLTexture со следующим методом: metalDevice.newBufferWithLength(byteCount, options: .StorageModeShared)
(см. Производительность записи памяти - Общая память процессора GPU)
Однако CMSampleBufferRef
и сопутствующий CVPixelBufferRef
управляется CoreVideo - это предположение.