Используя буферы OpenGL

Эта статья описывает методы, которые Ваш исходный объект видеоданных должен реализовать для использования OpenGL для iChat Theater. Считайте Установку Источника Видеоданных для того, как установить исходный объект видеоданных прежде, чем считать эту статью. Если Ваш источник видеоданных использует пиксельные буферы, читайте Используя Пиксельные Буферы.

Получение формата видео

Ваш исходный объект видеоданных должен реализовать getOpenGLBufferContext:pixelFormat: IMVideoDataSource метод протокола для возврата контекста OpenGL и формата пикселя для видеоконтента. IMAVManager возразите нуждается в этой информации, чтобы должным образом вывести на экран и передать видео.

- (void)getOpenGLBufferContext:(CGLContextObj *)contextOut pixelFormat:(CGLPixelFormatObj *)pixelFormatOut {
    *contextOut = context;
    *pixelFormatOut = pixelFormat;
}

Как правило, контекст и объекты формата пикселя создаются и сохраняются исходным объектом видеоданных в определяемом инициализаторе. Этот фрагмент кода создает контекст OpenGL и объект формата пикселя:

        long npix = 0;
        CGLPixelFormatAttribute attributes[] = {
            kCGLPFADoubleBuffer,
            kCGLPFAColorSize, 24,
            0
        };
        CGLChoosePixelFormat(attributes, &pixelFormat, (void*)&npix);
        CGLCreateContext(pixelFormat, [[self openGLContext] CGLContextObj], &context);

Рендеринг видеокадров

Ваш исходный объект видеоданных должен реализовать renderIntoOpenGLBuffer:onScreen:forTime: IMVideoDataSource метод протокола для рендеринга содержания OpenGL в буфере. Мгновенная платформа сообщения указывает экран при вызове renderIntoOpenGLBuffer:onScreen:forTime: метод, таким образом, может быть более эффективно, когда компьютер имеет многократные видеокарты.

Обратите внимание на то, что OpenGL не ориентирован на многопотоковое исполнение поэтому, если Вы представляете к дисплею и буферу одновременно, необходимо использовать макросы OpenGL для рендеринга в двух различных контекстах — контексте по умолчанию для дисплея и альтернативном контексте для буфера — как описано в Улучшающейся Производительности в Руководстве по программированию OpenGL для Mac.

Эта реализация renderIntoOpenGLBuffer:onScreen:forTime: метод в NSView разделите на подклассы использует макросы OpenGL для рендеринга в переданном буфере OpenGL использования альтернативного контекста:

 
- (BOOL) renderIntoOpenGLBuffer:(CVOpenGLBufferRef)buffer onScreen:(int *)screenInOut forTime:(CVTimeStamp*)timeStamp {
    // We ignore the timestamp, signifying that we're providing content for 'now'.
    // Make sure we agree on the screen ID.
    CGLContextObj cgl_ctx = _alternateContext;
    CGLGetVirtualScreen(cgl_ctx, screenInOut);
 
    // Attach the OpenGLBuffer and render into the _alternateContext.
    if (CVOpenGLBufferAttach(buffer, _alternateContext, 0, 0, *screenInOut) == kCVReturnSuccess) {
        // In case the buffers have changed in size, reset the viewport.
        CGRect cleanRect = CVImageBufferGetCleanRect(buffer);
        glViewport(CGRectGetMinX(cleanRect), CGRectGetMinY(cleanRect), CGRectGetWidth(cleanRect), CGRectGetHeight(cleanRect));
 
        // Render
        [self _renderInContext:_alternateContext];
        return YES;
    } else {
        // This should never happen.  The safest thing to do if it does is return
        // 'NO' (signifying that the frame has not changed).
        return NO;
    }

_renderInContext: метод в примере кода делает фактический рендеринг с помощью предоставленного контекста и также вызывается drawRect: метод как показано в этом фрагменте кода:

 
- (void) _renderInContext:(CGLContextObj)cgl_ctx {
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
 
    /* ... */
}
 
- (void) drawRect:(NSRect)rect {
    // Render in the normal context.
    [self _renderInContext:[[self openGLContext] CGLContextObj]];

См. Руководство по программированию OpenGL для Mac для получения дополнительной информации об использовании OpenGL.