从AVPlayerItemVideoOutput获取浮动支持的IOSurface

时间:2014-11-25 23:54:31

标签: objective-c macos opengl avfoundation

我有一个10位的ProRes4444文件,我正在渲染到CAOpenGLLayer,因此我可以在播放期间对其进行一些处理。但是,由于这是一个10位视频,我希望获得一个具有完整10位(或更多,因此浮动背景)的IOSurface,因此任何处理都可以使用全彩色。不幸的是,我无法弄清楚如何在纹理中获得更高的颜色深度。

这是我在设置过程中所拥有的:

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

kCVPixelBufferPixelFormatTypeKey设置为kCVPixelFormatType_128RGBAFloat会使解码器崩溃,并在日志中打印出以下内容:

[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
...

kCVPixelBufferIOSurfacePropertiesKey字典中添加任何内容似乎都没有做任何事情。然后,实际绘制东西:

- (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_RGBAGL_FLOAT会导致10008错误。

即使媒体本身的颜色深度超过10位,也无法直接使用它?

0 个答案:

没有答案
相关问题