Mac OS X Reference Library Apple Developer
Search

Classes/QT/VisualContext/QTVisualContextKit.m

//---------------------------------------------------------------------------
//
//  File: QTVisualContextKit.m
//
//  Abstract: Utility class for maintaining a QT visual context
//           
//  Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
//  Computer, Inc. ("Apple") in consideration of your agreement to the
//  following terms, and your use, installation, modification or
//  redistribution of this Apple software constitutes acceptance of these
//  terms.  If you do not agree with these terms, please do not use,
//  install, modify or redistribute this Apple software.
//  
//  In consideration of your agreement to abide by the following terms, and
//  subject to these terms, Apple grants you a personal, non-exclusive
//  license, under Apple's copyrights in this original Apple software (the
//  "Apple Software"), to use, reproduce, modify and redistribute the Apple
//  Software, with or without modifications, in source and/or binary forms;
//  provided that if you redistribute the Apple Software in its entirety and
//  without modifications, you must retain this notice and the following
//  text and disclaimers in all such redistributions of the Apple Software. 
//  Neither the name, trademarks, service marks or logos of Apple Computer,
//  Inc. may be used to endorse or promote products derived from the Apple
//  Software without specific prior written permission from Apple.  Except
//  as expressly stated in this notice, no other rights or licenses, express
//  or implied, are granted by Apple herein, including but not limited to
//  any patent rights that may be infringed by your derivative works or by
//  other works in which the Apple Software may be incorporated.
//  
//  The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
//  MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
//  THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
//  FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
//  OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
//  
//  IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
//  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//  INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
//  MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
//  AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
//  STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
//  POSSIBILITY OF SUCH DAMAGE.
// 
//  Copyright (c) 2008 Apple Inc., All rights reserved.
//
//---------------------------------------------------------------------------
 
//---------------------------------------------------------------------------
 
#import "AlertPanelKit.h"
#import "QTVisualContextKit.h"
 
//---------------------------------------------------------------------------
 
//---------------------------------------------------------------------------
 
struct QTVisualContextAttributes
{
    GLuint              width;          // Width of the pixel buffer
    GLuint              height;         // Height of the pixel buffer
    QTVisualContextRef  context;        // Pixel buffer or texture visual context
};
 
typedef struct QTVisualContextAttributes   QTVisualContextAttributes;
 
//---------------------------------------------------------------------------
 
//---------------------------------------------------------------------------
 
#pragma mark -- Set Dictionary Values --
 
//---------------------------------------------------------------------------
 
//---------------------------------------------------------------------------
 
static BOOL DictionarySetValue( CFMutableDictionaryRef dict, CFStringRef key, SInt32 value )
{
    BOOL         setNumber = NO;
    CFNumberRef  number    = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value);
    
    if ( number!= NULL )
    {
        CFDictionarySetValue( dict, key, number );
 
        CFRelease( number );
        
        setNumber = YES;
    } // if
    
    return setNumber;
} // DictionarySetValue
 
//---------------------------------------------------------------------------
 
static inline BOOL DictionarySetPixelBufferPixelFormatType( CFMutableDictionaryRef dict )
{
    BOOL setPixelBufferOptions = NO;
    
    #if __BIG_ENDIAN__
        setPixelBufferOptions = DictionarySetValue( dict, kCVPixelBufferPixelFormatTypeKey, k32ARGBPixelFormat );
    #else
        setPixelBufferOptions = DictionarySetValue( dict, kCVPixelBufferPixelFormatTypeKey, k32BGRAPixelFormat );
    #endif
    
    return  setPixelBufferOptions;
} // DictionarySetPixelBufferPixelFormatType
 
//---------------------------------------------------------------------------
 
static inline BOOL DictionarySetPixelBufferSize(    const GLuint            width,
                                                    const GLuint            height,
                                                    CFMutableDictionaryRef  dict )
{
    BOOL setSize = NO;
 
    setSize = DictionarySetValue( dict, kCVPixelBufferWidthKey, width );
    setSize = setSize && DictionarySetValue( dict, kCVPixelBufferHeightKey, height );
    
    return setSize;
} // DictionarySetPixelBufferSize
 
//---------------------------------------------------------------------------
 
static inline BOOL DictionarySetPixelBufferBytesPerRowAlignment( CFMutableDictionaryRef dict )
{
    BOOL setAlignment = NO;
    
    setAlignment = DictionarySetValue( dict, kCVPixelBufferBytesPerRowAlignmentKey, 1 );
    
    return  setAlignment;
} // DictionarySetPixelBufferSize
 
//---------------------------------------------------------------------------
 
static inline void DictionarySetPixelBufferOpenGLCompatibility( CFMutableDictionaryRef dict )
{
    CFDictionarySetValue(dict, kCVPixelBufferOpenGLCompatibilityKey, kCFBooleanTrue);
} // DictionarySetPixelBufferOpenGLCompatibility
 
//---------------------------------------------------------------------------
 
static BOOL DictionarySetPixelBufferOptions(    const GLuint            width,
                                                const GLuint            height,
                                                CFMutableDictionaryRef *pixelBufferOptions )
{
    BOOL  setPixelBufferOptions = NO;
    
    CFMutableDictionaryRef  pixelBufferDict
                                = CFDictionaryCreateMutable(    kCFAllocatorDefault, 
                                                                0,
                                                                &kCFTypeDictionaryKeyCallBacks,
                                                                &kCFTypeDictionaryValueCallBacks );
 
    if ( pixelBufferDict != NULL )
    {
        if ( DictionarySetPixelBufferPixelFormatType( pixelBufferDict ) )
        {
            if ( DictionarySetPixelBufferSize( width, height, pixelBufferDict ) )
            {
                if ( DictionarySetPixelBufferBytesPerRowAlignment( pixelBufferDict ) )
                {
                    DictionarySetPixelBufferOpenGLCompatibility( pixelBufferDict );
                    
                    *pixelBufferOptions = pixelBufferDict;
                    
                    setPixelBufferOptions = YES;
                } // if
            } // if
        } // if
    } // if
    
    return  setPixelBufferOptions;
} // DictionarySetPixelBufferOptions
 
//---------------------------------------------------------------------------
 
//---------------------------------------------------------------------------
 
#pragma mark
 
//---------------------------------------------------------------------------
 
//---------------------------------------------------------------------------
 
@implementation QTVisualContextKit
 
//---------------------------------------------------------------------------
 
#pragma mark -- Initialize QT Visual Context --
 
//---------------------------------------------------------------------------
 
- (CFMutableDictionaryRef) initQTVisualContextOptions
{
    CFMutableDictionaryRef  visualContextOptions = NULL;
    CFMutableDictionaryRef  pixelBufferOptions   = NULL;
                                                   
    BOOL  setPixelBufferOptions = DictionarySetPixelBufferOptions(  visualContext->width, 
                                                                    visualContext->height,
                                                                    &pixelBufferOptions );
    
    if ( pixelBufferOptions != NULL )
    {
        if ( setPixelBufferOptions )
        {
            visualContextOptions = CFDictionaryCreateMutable(   kCFAllocatorDefault, 
                                                                0,
                                                                &kCFTypeDictionaryKeyCallBacks,
                                                                &kCFTypeDictionaryValueCallBacks );
            if ( visualContextOptions != NULL )
            {
                // set the pixel image attributes for the visual context
                
                CFDictionarySetValue(visualContextOptions,
                                     kQTVisualContextPixelBufferAttributesKey,
                                     pixelBufferOptions);
            } // if
        } // if
            
        CFRelease( pixelBufferOptions );
    } // if
    
    return  visualContextOptions;
} // initQTVisualContextOptions
 
//---------------------------------------------------------------------------
 
- (BOOL) initQTPixelBufferContext
{
    BOOL  visualContextIsValid = NO;
 
    CFMutableDictionaryRef visualContextOptions = [self initQTVisualContextOptions];
    
    if ( visualContextOptions != NULL )
    {
        CFAllocatorRef  allocator = kCFAllocatorDefault;
        
        OSStatus err = QTPixelBufferContextCreate(  allocator,
                                                    visualContextOptions,
                                                    &visualContext->context);
 
        if ( err == noErr )
        {
            visualContextIsValid = YES;
        } // if
        
        CFRelease( visualContextOptions );
    } // if
    
    return visualContextIsValid;
} // initQTPixelBufferContext
 
//---------------------------------------------------------------------------
 
- (BOOL) initQTOpenGLTextureContext:(NSOpenGLContext *)theOpenGLContext
                        pixelFormat:(NSOpenGLPixelFormat *)theOpenGLPixelFormat
 
{
    BOOL  visualContextIsValid = NO;
 
    if ( ( theOpenGLContext != nil ) && ( theOpenGLPixelFormat != nil ) )
    {
        CFAllocatorRef     allocator      = kCFAllocatorDefault;
        CGLContextObj      cglContext     = (CGLContextObj)[theOpenGLContext CGLContextObj];
        CGLPixelFormatObj  cglPixelFormat = (CGLPixelFormatObj)[theOpenGLPixelFormat CGLPixelFormatObj];
        CFDictionaryRef    dictAttribs    = NULL;
 
        // Creates a new OpenGL texture context for a specified OpenGL context and pixel format
        
        OSStatus err = QTOpenGLTextureContextCreate(    allocator,                  // an allocator to Create functions
                                                        cglContext,                 // the OpenGL context
                                                        cglPixelFormat,             // pixelformat object that specifies 
                                                                                    // buffer types and other attributes 
                                                                                    // of the context
                                                        dictAttribs,                // a CF Dictionary of attributes
                                                        &visualContext->context );  // returned OpenGL texture context
        
        if ( err == noErr )
        {
            visualContextIsValid = YES;
        } // if
    } // if
    
    return  visualContextIsValid;
} // initQTOpenGLTextureContext
 
//---------------------------------------------------------------------------
 
- (BOOL) initQTVisualContext:(QTVisualContextType)theQTVisualContextType
                    context:(NSOpenGLContext *)theOpenGLContext
                    pixelFormat:(NSOpenGLPixelFormat *)theOpenGLPixelFormat
{
    BOOL visualContextIsValid = NO;
    
    switch( theQTVisualContextType )
    {
        case kQTPixelBufferContext:
            visualContextIsValid = [self initQTPixelBufferContext];
            break;
            
        case kQTOpenGLTextureContext:
        default:
            visualContextIsValid = [self initQTOpenGLTextureContext:theOpenGLContext 
                                                        pixelFormat:theOpenGLPixelFormat];
    } // switch
    
    return  visualContextIsValid;
} // initQTVisualContext
 
//---------------------------------------------------------------------------
//
// Designated initializer
//
//---------------------------------------------------------------------------
 
- (id) initQTVisualContextWithSize:(NSSize)theSize
                            type:(QTVisualContextType)theQTVisualContextType
                            context:(NSOpenGLContext *)theOpenGLContext
                            pixelFormat:(NSOpenGLPixelFormat *)theOpenGLPixelFormat
{
    self = [super initMemoryWithType:kMemAlloc size:sizeof(QTVisualContextAttributes)];
    
    if ( self )
    {
        visualContext = (QTVisualContextAttributesRef)[self pointer];
        
        if ( [self isPointerValid] )
        {
            visualContext->width  = (GLuint)theSize.width;
            visualContext->height = (GLuint)theSize.height;
 
            BOOL visualContextIsValid = [self initQTVisualContext:theQTVisualContextType 
                                                            context:theOpenGLContext 
                                                            pixelFormat:theOpenGLPixelFormat];
            
            if ( !visualContextIsValid )
            {
                [[AlertPanelKit withTitle:@"QTVisualContext Kit" 
                                  message:@"Failure Obtaining a Visual Context"
                                     exit:YES] displayAlertPanel];
            } // if
        } // if
        else
        {
            [[AlertPanelKit withTitle:@"QTVisualContext Kit" 
                              message:@"Failure Allocating Memory For Attributes"
                                 exit:YES] displayAlertPanel];
        } // else
    } // if
    
    return self;
} // initQTVisualContextWithSize
 
//---------------------------------------------------------------------------
 
#pragma mark -- Cleanup all the Resources --
 
//---------------------------------------------------------------------------
 
- (void) dealloc 
{
    if ( visualContext->context != NULL )
    {
        QTVisualContextRelease( visualContext->context );
        
        visualContext->context = NULL;
    } // if
 
    [super dealloc];
} // dealloc
 
//---------------------------------------------------------------------------
 
#pragma mark -- Utilities --
 
//---------------------------------------------------------------------------
 
- (BOOL) isValidVisualContext
{
    return  ( visualContext->context != NULL );
} // isValidVisualContext
 
//---------------------------------------------------------------------------
 
- (BOOL) isNewImageAvailable:(const CVTimeStamp *)theTimeStamp 
{
    BOOL newImageAvailable = NO;
    
    newImageAvailable 
        = QTVisualContextIsNewImageAvailable(   visualContext->context, 
                                                theTimeStamp );
    
    return  newImageAvailable; 
} // isNewImageAvailable
 
//---------------------------------------------------------------------------
//
// Get a "frame" (image image) from the Visual Context, indexed by the 
// provided time.
//
//---------------------------------------------------------------------------
 
- (CVImageBufferRef) copyImageForTime:(const CVTimeStamp *)theTimeStamp
{
    CVImageBufferRef  imageBuffer = NULL;
    CFAllocatorRef    allocator   = kCFAllocatorDefault;
    
    OSStatus status = QTVisualContextCopyImageForTime(  visualContext->context, 
                                                        allocator, 
                                                        theTimeStamp, 
                                                        &imageBuffer );
                                                        
    if ( ( status != noErr ) && ( imageBuffer != NULL ) )
    {
        CFRelease( imageBuffer );
        
        imageBuffer = NULL;
    } // if
    
    return  imageBuffer;
} // copyImageForTime
 
//---------------------------------------------------------------------------
 
- (BOOL) setMovie:(QTMovie *)theQTMovie
{
    BOOL  movieIsSet = NO;
    Movie movie      = [theQTMovie quickTimeMovie];
    
    if ( ( movie != NULL ) && ( *movie != NULL ) )
    {
        OSStatus status = SetMovieVisualContext(movie, visualContext->context);
        
        if ( status == noErr )
        {
            movieIsSet = YES;
        } // if
    } // if
    
    return  movieIsSet;
} // setMovie
 
//---------------------------------------------------------------------------
//
// Give time to the Visual Context so it can release internally held 
// resources for later re-use this function should be called in every 
// rendering pass, after old images have been released, new images 
// have been used and all rendering has been flushed to the screen.
//
//---------------------------------------------------------------------------
 
- (void) task
{
    QTVisualContextTask( visualContext->context );
} // task
 
//---------------------------------------------------------------------------
 
@end
 
//---------------------------------------------------------------------------
 
//---------------------------------------------------------------------------



Last updated: 2009-04-07

Did this document help you? Yes It's good, but... Not helpful...