Getting IOSurface with float support from AVPlayerItemVideoOutput

I have a 10-bit ProRes4444 file that I transfer to CAOpenGLLayer, so I can do some processing on it during playback. However, since this is a 10-bit video, I would like to get an IOSurface with a full 10-bit (or more, therefore, floating point) so that any processing has a full color to work. Unfortunately, I cannot figure out how to get this higher color depth in my texture.

Here is what I have during setup:

NSDictionary *pixelBufferAttributes = @{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA),
                                        (id)kCVPixelBufferIOSurfacePropertiesKey: @{(id)kCVPixelBufferIOSurfacePropertiesKey: @(kCVPixelFormatType_128RGBAFloat)}, // doesn't appear to do anything
                                        (id)kCVPixelBufferOpenGLCompatibilityKey: @YES};

Setting kCVPixelBufferPixelFormatTypeKeyto kCVPixelFormatType_128RGBAFloatcauses the decoder to fail with the following printed in the log:

[15:58:12.307] <<<< VMC >>>> vmc2PostDecodeError: posting DecodeError (-12905) -- PTS was 0.000 = 0/1
[15:58:14.248] <<<< VMC >>>> vmc2PostDecodeError: posting DecodeError (-12905) -- PTS was 0.000 = 0/1
[15:58:14.253] <<<< VMC >>>> vmc2PostDecodeError: posting DecodeError (-12905) -- PTS was 0.050 = 50000000/1000000000
...

Adding nothing to a kCVPixelBufferIOSurfacePropertiesKeydict is not like anything. Then, to draw the material:

- (void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
{
    // Set the current context to the one given to us.
    CGLSetCurrentContext(glContext);


    glEnable(GL_TEXTURE_RECTANGLE_ARB);


    CMTime outputItemTime = [videoOutput itemTimeForHostTime:timeInterval];

    if ([videoOutput hasNewPixelBufferForItemTime:outputItemTime]) {
        CVPixelBufferRef pixelBuffer = NULL;
        pixelBuffer = [videoOutput copyPixelBufferForItemTime:outputItemTime itemTimeForDisplay:NULL];

        if (lastPixelBuffer) CVPixelBufferRelease(lastPixelBuffer);
        lastPixelBuffer = pixelBuffer;
        NSLog(@"New Frame at %f", CMTimeGetSeconds(outputItemTime));
    }

    if (lastPixelBuffer) {
        IOSurfaceRef newSurface = CVPixelBufferGetIOSurface(lastPixelBuffer);

        if (currentSurface != newSurface && newSurface) {
//            IOSurfaceDecrementUseCount(currentSurface); // crashes
            currentSurface = newSurface;
//            IOSurfaceIncrementUseCount(currentSurface); // crashes
            GLsizei texWidth = (int) IOSurfaceGetWidth(currentSurface);
            GLsizei texHeight = (int) IOSurfaceGetHeight(currentSurface);
            NSLog(@"Copying %f", CMTimeGetSeconds(outputItemTime));


            if (!videoTextureName) {
                GLuint name;
                glGenTextures(1, &name);
                videoTextureName = name;
            }

            GLenum anError = glGetError( );
            if (anError != GL_NO_ERROR) {
                NSLog(@"get context error=%x", anError);
            }

            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, videoTextureName);
            GetError(); // prints glGetError

            CGLError error = CGLTexImageIOSurface2D(glContext, GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, texWidth, texHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, currentSurface, 0);
            if (error != kCGLNoError) {
                NSLog(@"Consumer CGLTexImageIOSurface2D error: %d[%x]", error, error);
            } else {
                NSLog(@"No CGL error creating texture");
            }
            GetError();

            glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
        }
    }

    // more stuff here...

    if (videoTextureName)
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, videoTextureName);

    glBegin(GL_QUADS);

    glTexCoord2f(0, 1080); glVertex2f(-1, -1);
    glTexCoord2f(0, 0); glVertex2f(-1, 1);
    glTexCoord2f(2048, 0); glVertex2f(1, 1);
    glTexCoord2f(2048, 1080); glVertex2f(1, -1);

    glEnd();

    glDisable(GL_TEXTURE_RECTANGLE_ARB);

    [super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:timeInterval displayTime:timeStamp];
}

CGLTexImageIOSurface2D GL_RGBA GL_FLOAT 10008.

, 10- , ?

+4

All Articles