MTLTexture для CVPixelBuffer - PullRequest
       20

MTLTexture для CVPixelBuffer

0 голосов
/ 31 марта 2020

У меня есть MTLTexture, сгенерированная из ARMatteGenerator, которую я хотел бы перенести в OpenGL.

Я не очень разбираюсь в Objective- C, поэтому могу допускать очевидные ошибки для других ...

Я видел this , который создает металлическую текстуру из пиксельного буфера, но мне нужно было бы сделать это наоборот: связать PixelBuffer с уже существующей MTLTexture - в объективе C -.

Моя цель - использовать его со слоем OpenGL.

Я нашел метод, который превращает текстуру MTL в NSData *:

- (NSData*) getTextureBytes:(id<MTLTexture>)texture
{

    int bytesPerPixel = 4;
    int width = (int) texture.width;
    int height = (int) texture.height;

    NSMutableData *mFramebuffer = [NSMutableData dataWithLength:width*height*bytesPerPixel];

    [texture getBytes:(void*)mFramebuffer.mutableBytes
           bytesPerRow:width*bytesPerPixel
         bytesPerImage:width*height*bytesPerPixel
            fromRegion:MTLRegionMake2D(0, 0, width, height)
           mipmapLevel:0
                 slice:0];

    return [NSData dataWithData:mFramebuffer];
}

Но тогда я не знаю, как получить ссылку на CVPixelBuffer.

Я немного сбит с толку относительно того, как я должен действовать ...

Лучший ,

P

  • РЕДАКТИРОВАТЬ *

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

Мой _updateMatteTextures выглядит следующим образом:

 - (void) _updateMatteTextures:(id<MTLCommandBuffer>) commandBuffer {
if(self.currentDrawable && _session.currentFrame.capturedImage){

        alphaTexture = [matteDepthTexture  generateMatteFromFrame:_session.currentFrame commandBuffer:commandBuffer];
        dilatedDepthTexture = [matteDepthTexture generateDilatedDepthFromFrame:_session.currentFrame commandBuffer:commandBuffer];

        // ===============================================================
        int bytesPerPixel = 4;
        int width = (int) alphaTexture.width;
        int height = (int) alphaTexture.height;

        CVReturn err = noErr;

        err = CVPixelBufferCreateWithBytes(kCFAllocatorDefault,
                                     width,
                                     height,
                                     formatInfo.cvPixelFormat,
                                     alphaTexture,
                                     width * bytesPerPixel,
                                     stillImageDataReleaseCallback,
                                     alphaTexture,
                                     NULL,
                                     &alphaTextureGLES);


        if (err != kCVReturnSuccess) {

               if(err == kCVReturnInvalidPixelFormat){
                   NSLog(@"Invalid pixel format");
               }

               if(err == kCVReturnInvalidPixelBufferAttributes){
                   NSLog(@"Invalid pixel buffer attributes");
               }

               if(err == kCVReturnInvalidSize){
                   NSLog(@"invalid size");
               }

               if(err == kCVReturnPixelBufferNotOpenGLCompatible){
                   NSLog(@"not opengl compatible");
               }

        }else{
            NSLog(@"ok CVPixelBufferCreateWithBytes SUCCESS");
        }


        // correct wrapping and filtering
        glBindTexture(CVOpenGLESTextureGetTarget(alphaTextureGLES), CVOpenGLESTextureGetName(alphaTextureGLES));
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glBindTexture(CVOpenGLESTextureGetTarget(alphaTextureGLES), 0);




    }else{
        return;
    }

Я пытался использовать магазин с результатом CVPixelBufferCreateWithBytes в CVPixelBufferRef, с тем же успехом (черная текстура):

    if(self.currentDrawable && _session.currentFrame.capturedImage){

        alphaTexture = [matteDepthTexture  generateMatteFromFrame:_session.currentFrame commandBuffer:commandBuffer];
        dilatedDepthTexture = [matteDepthTexture generateDilatedDepthFromFrame:_session.currentFrame commandBuffer:commandBuffer];

        // ===============================================================
        int bytesPerPixel = 4;
        int width = (int) alphaTexture.width;
        int height = (int) alphaTexture.height;

        CVReturn err = noErr;

        err = CVPixelBufferCreateWithBytes(kCFAllocatorDefault,
                                     width,
                                     height,
                                     formatInfo.cvPixelFormat,
                                     alphaTexture,
                                     width * bytesPerPixel,
                                     stillImageDataReleaseCallback,
                                     alphaTexture,
                                     NULL,
                                     &pixel_bufferAlpha);

        if (err != kCVReturnSuccess) {

               if(err == kCVReturnInvalidPixelFormat){
                   NSLog(@"Invalid pixel format");
               }

               if(err == kCVReturnInvalidPixelBufferAttributes){
                   NSLog(@"Invalid pixel buffer attributes");
               }

               if(err == kCVReturnInvalidSize){
                   NSLog(@"invalid size");
               }

               if(err == kCVReturnPixelBufferNotOpenGLCompatible){
                   NSLog(@"not opengl compatible");
               }

        }else{
            NSLog(@"ok CVPixelBufferCreateWithBytes SUCCESS");
        }


        CVPixelBufferLockBaseAddress(pixel_bufferAlpha, 0);

        err = noErr;
        err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                           _videoTextureAlphaCache,
                                                           pixel_bufferAlpha,
                                                           nil,
                                                           GL_TEXTURE_2D,
                                                           formatInfo.glInternalFormat,
                                                           CVPixelBufferGetWidth(pixel_bufferAlpha),
                                                           CVPixelBufferGetHeight(pixel_bufferAlpha),
                                                           formatInfo.glFormat,
                                                           formatInfo.glType,
                                                           0,
                                                           &alphaTextureGLES);

        if (err != kCVReturnSuccess) {
            CVBufferRelease(alphaTextureGLES);

            if(err == kCVReturnInvalidPixelFormat){
                NSLog(@"Invalid pixel format");
            }

            if(err == kCVReturnInvalidPixelBufferAttributes){
                NSLog(@"Invalid pixel buffer attributes");
            }

            if(err == kCVReturnInvalidSize){
                NSLog(@"invalid size");
            }

            if(err == kCVReturnPixelBufferNotOpenGLCompatible){
                NSLog(@"not opengl compatible");
            }

        }

        // clear texture cache
        CVOpenGLESTextureCacheFlush(_videoTextureAlphaCache, 0);


        // correct wrapping and filtering
        glBindTexture(CVOpenGLESTextureGetTarget(alphaTextureGLES), CVOpenGLESTextureGetName(alphaTextureGLES));
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glBindTexture(CVOpenGLESTextureGetTarget(alphaTextureGLES), 0);
        CVPixelBufferUnlockBaseAddress(pixel_bufferAlpha, 0);




    }else{
        return;
    }

С:

CVPixelBufferRef pixel_bufferAlpha;
    CVOpenGLESTextureCacheRef _videoTextureAlphaCache;
void stillImageDataReleaseCallback(void *releaseRefCon, const void *baseAddress)
{
    free((void *)baseAddress);
}

Не уверен, что я здесь не так делаю.

...