Я получаю данные в формате jpeg через одноранговое устройство iOS. Обрабатываю и отображаю с помощью CoreImage и Metal + MTKView следующим образом. Я получаю данные в формате jpeg и конвертирую их в CIImage. Затем я применяю соответствующее преобразование к CIImage и визуализирую его в CVPixelBuffer. Затем я отображаю этот CVPixelBuffer в MTKView через сквозные шейдеры (обработка металлов и MTKView не используют ciContext, который используется частью кода CIImage). Затем я конвертирую буфер пикселей в YUV, выполняю некоторую обработку изображений и также отображаю эти данные в MTKView. Проблема в том, что иногда он становится слишком медленным и медленным. Есть ли в приведенном ниже коде узкие места, вызванные использованием CoreImage и Metal? Как сделать этот конвейер лучше?
private func handleImageData(_ data:Data) {
DispatchQueue.main.async {
if let image = CIImage(data: data) {
self.displayImage(image)
}
}
}
private func displayImage(_ image:CIImage) {
let transformFilter = CIFilter(name: "CIAffineTransform")!
transformFilter.setValue(image, forKey: "inputImage")
transformFilter.setValue(NSValue(cgAffineTransform: self.framesTransform), forKey: "inputTransform")
let sourceImage = transformFilter.value(forKey: "outputImage") as! CIImage
//Render CIImage to pixel buffer
var pixelBuffer:CVPixelBuffer? = nil
CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, self.ciPixelBufferPool!, &pixelBuffer)
if let pixBuf = pixelBuffer {
self.ciContext.render(sourceImage, to: pixBuf)
self.displayPixelBufferOnMTKView(pixBuf)
//Convert the pixel buffer to YUV as some filters operate only on YUV
if let yuvPixelBuffer = self.rgb2yuvFrameRenderer?.copyRenderedPixelBuffer(pixBuf) {
self.processYUVPixelBuffer(yuvPixelBuffer)
}
}
}
Вот код шейдера Metal:
// Compute kernel
kernel void kernelRGBtoYUV(texture2d<half, access::read> inputTexture [[ texture(0) ]],
texture2d<half, access::write> textureY [[ texture(1) ]],
texture2d<half, access::write> textureCbCr [[ texture(2) ]],
constant ColorConversion &colorConv [[ buffer(0) ]],
uint2 gid [[thread_position_in_grid]])
{
// Make sure we don't read or write outside of the texture
if ((gid.x >= inputTexture.get_width()) || (gid.y >= inputTexture.get_height())) {
return;
}
float3 inputColor = float3(inputTexture.read(gid).rgb);
float3 yuv = colorConv.matrix*inputColor + colorConv.offset;
half4 uv = half4(yuv.gbrr);
textureY.write(half(yuv.x), gid);
if (gid.x % 2 == 0 && gid.y % 2 == 0) {
textureCbCr.write(uv, uint2(gid.x / 2, gid.y / 2));
}
}
CVPixelBuffer
s? Например, вы можете визуализироватьCIImage
прямо в виде (view.currentDrawable.texture
). - person Frank Schlegel   schedule 06.08.2019CIColorKernel
, тогда вам не нужно будет выполнять рендеринг вCVPixelBuffer
между ними. - person Frank Schlegel   schedule 07.08.2019