Qt iOS: how to return QVideoFrame with type GLText

2019-09-08 04:35发布

问题:

I'm trying to capture camera output frame and process it further in GPU pipeline. For this reason returing frame as a GPU texture is the best option. After inheriting from QVideoFilterRunnable class received by run method QVideoFrame objects has type which is not equal to QAbstractVideoBuffer::GLTextureHandle. It's equal to NoHandle and I need to do map/unmap and load texture manually by glTexImage, which is not good for performance. Is there any control options that can be used to return texture name?

Some notes:

  • Looks good on Android. Returned frame is texture so this works like a charm:

    QVideoFrame* input = ...;
    GLuint texture = input->handle().toUInt(); 
    f->glBindTexture(GL_TEXTURE_2D, texture);
    
  • It's possible in general, there is iOS texture cache feature:

    CVPixelBufferRef pixelBuffer = ...;
    CVOpenGLESTextureCacheCreateTextureFromImage(..., pixelBuffer, ..., &textureRef);
    texture = CVOpenGLESTextureGetName(textureRef);
    

回答1:

CVPixelBufferRef can be created manually (I do need to use map still):

frame.map(QAbstractVideoBuffer::ReadOnly);

CVPixelBufferRef x;
CVPixelBufferCreateWithBytes(
    kCFAllocatorDefault,
    frame.size().width(),
    frame.size().height(),
    kCVPixelFormatType_32BGRA,
    frame.bits(),
    frame.bytesPerLine(),
    nullptr, // releaseCallback
    nullptr, // releaseRefCon
    nullptr, // pixelBufferAttributes
    &x
);

Use value of CVPixelBufferRef pointer to create cache texture:

CVOpenGLESTextureRef texRef;
CVOpenGLESTextureCacheCreateTextureFromImage(
    kCFAllocatorDefault,
    textureCache,
    x,
    NULL, // texture attributes
    GL_TEXTURE_2D,
    GL_RGBA, // opengl format
    inputW,
    inputH,
    inputPixelFormat,
    GL_UNSIGNED_BYTE,
    0,
    &texRef
);

Getting texture name:

inputTexId = CVOpenGLESTextureGetName(texRef);