Home | History | Annotate | Download | only in win
      1 /*
      2  * Copyright (C) 2007, 2008, 2009, 2010 Apple, Inc.  All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 #include "config.h"
     26 
     27 #include "QTPixelBuffer.h"
     28 
     29 #include <CFNumber.h>
     30 #include <CFString.h>
     31 #include <CGColorSpace.h>
     32 #include <CGImage.h>
     33 #include <CVPixelBuffer.h>
     34 #include <QuickDraw.h>
     35 #include <memory.h>
     36 
     37 static OSStatus SetNumberValue(CFMutableDictionaryRef inDict, CFStringRef inKey, SInt32 inValue)
     38 {
     39     CFNumberRef number;
     40 
     41     number = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &inValue);
     42     if (!number)
     43         return coreFoundationUnknownErr;
     44 
     45     CFDictionarySetValue(inDict, inKey, number);
     46     CFRelease(number);
     47 
     48     return noErr;
     49 }
     50 
     51 CFDictionaryRef QTPixelBuffer::createPixelBufferAttributesDictionary(QTPixelBuffer::Type contextType)
     52 {
     53     static const CFStringRef kDirect3DCompatibilityKey = CFSTR("Direct3DCompatibility");
     54 
     55     CFMutableDictionaryRef pixelBufferAttributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
     56     if (contextType == QTPixelBuffer::ConfigureForCAImageQueue) {
     57         // Ask for D3D compatible pixel buffers so no further work is needed.
     58         CFDictionarySetValue(pixelBufferAttributes, kDirect3DCompatibilityKey, kCFBooleanTrue);
     59     } else {
     60         // Use the k32BGRAPixelFormat, as QuartzCore will be able to use the pixels directly,
     61         // without needing an additional copy or rendering pass.
     62         SetNumberValue(pixelBufferAttributes, kCVPixelBufferPixelFormatTypeKey, k32BGRAPixelFormat);
     63 
     64         // Set kCVPixelBufferBytesPerRowAlignmentKey to 16 to ensure that each row of pixels
     65         // starts at a 16 byte aligned address for most efficient data reading.
     66         SetNumberValue(pixelBufferAttributes, kCVPixelBufferBytesPerRowAlignmentKey, 16);
     67         CFDictionarySetValue(pixelBufferAttributes, kCVPixelBufferCGImageCompatibilityKey, kCFBooleanTrue);
     68     }
     69     return pixelBufferAttributes;
     70 }
     71 
     72 QTPixelBuffer::QTPixelBuffer()
     73     : m_pixelBuffer(0)
     74 {
     75 }
     76 
     77 QTPixelBuffer::QTPixelBuffer(const QTPixelBuffer& p)
     78     : m_pixelBuffer(p.m_pixelBuffer)
     79 {
     80     CVPixelBufferRetain(m_pixelBuffer);
     81 }
     82 
     83 QTPixelBuffer::QTPixelBuffer(CVPixelBufferRef ref)
     84     : m_pixelBuffer(ref)
     85 {
     86     CVPixelBufferRetain(m_pixelBuffer);
     87 }
     88 
     89 QTPixelBuffer::~QTPixelBuffer()
     90 {
     91     clear();
     92 }
     93 
     94 QTPixelBuffer& QTPixelBuffer::operator=(const QTPixelBuffer& p)
     95 {
     96     set(p.m_pixelBuffer);
     97     return *this;
     98 }
     99 
    100 void QTPixelBuffer::set(CVPixelBufferRef ref)
    101 {
    102     CVPixelBufferRetain(ref);
    103     CVPixelBufferRelease(m_pixelBuffer);
    104     m_pixelBuffer = ref;
    105 }
    106 
    107 CVPixelBufferRef QTPixelBuffer::pixelBufferRef()
    108 {
    109     return m_pixelBuffer;
    110 }
    111 
    112 void QTPixelBuffer::adopt(CVPixelBufferRef ref)
    113 {
    114     if (ref == m_pixelBuffer)
    115         return;
    116     CVPixelBufferRelease(m_pixelBuffer);
    117     m_pixelBuffer = ref;
    118 }
    119 
    120 void QTPixelBuffer::clear()
    121 {
    122     CVPixelBufferRelease(m_pixelBuffer);
    123     m_pixelBuffer = 0;
    124 }
    125 
    126 CVReturn QTPixelBuffer::lockBaseAddress()
    127 {
    128     return CVPixelBufferLockBaseAddress(m_pixelBuffer, 0);
    129 }
    130 
    131 CVReturn QTPixelBuffer::unlockBaseAddress()
    132 {
    133     return CVPixelBufferUnlockBaseAddress(m_pixelBuffer, 0);
    134 }
    135 
    136 void* QTPixelBuffer::baseAddress()
    137 {
    138     return CVPixelBufferGetBaseAddress(m_pixelBuffer);
    139 }
    140 
    141 size_t QTPixelBuffer::width() const
    142 {
    143     return CVPixelBufferGetWidth(m_pixelBuffer);
    144 }
    145 
    146 size_t QTPixelBuffer::height() const
    147 {
    148     return CVPixelBufferGetHeight(m_pixelBuffer);
    149 }
    150 
    151 unsigned long QTPixelBuffer::pixelFormatType() const
    152 {
    153     return CVPixelBufferGetPixelFormatType(m_pixelBuffer);
    154 }
    155 
    156 bool QTPixelBuffer::pixelFormatIs32ARGB() const
    157 {
    158     return CVPixelBufferGetPixelFormatType(m_pixelBuffer) == k32ARGBPixelFormat;
    159 }
    160 
    161 bool QTPixelBuffer::pixelFormatIs32BGRA() const
    162 {
    163     return CVPixelBufferGetPixelFormatType(m_pixelBuffer) == k32BGRAPixelFormat;
    164 }
    165 
    166 size_t QTPixelBuffer::bytesPerRow() const
    167 {
    168     return CVPixelBufferGetBytesPerRow(m_pixelBuffer);
    169 }
    170 
    171 size_t QTPixelBuffer::dataSize() const
    172 {
    173     return CVPixelBufferGetDataSize(m_pixelBuffer);
    174 }
    175 
    176 bool QTPixelBuffer::isPlanar() const
    177 {
    178     return CVPixelBufferIsPlanar(m_pixelBuffer);
    179 }
    180 
    181 size_t QTPixelBuffer::planeCount() const
    182 {
    183     return CVPixelBufferGetPlaneCount(m_pixelBuffer);
    184 }
    185 
    186 size_t QTPixelBuffer::widthOfPlane(size_t plane) const
    187 {
    188     return CVPixelBufferGetWidthOfPlane(m_pixelBuffer, plane);
    189 }
    190 
    191 size_t QTPixelBuffer::heightOfPlane(size_t plane) const
    192 {
    193     return CVPixelBufferGetHeightOfPlane(m_pixelBuffer, plane);
    194 }
    195 
    196 void* QTPixelBuffer::baseAddressOfPlane(size_t plane) const
    197 {
    198     return CVPixelBufferGetBaseAddressOfPlane(m_pixelBuffer, plane);
    199 }
    200 
    201 size_t QTPixelBuffer::bytesPerRowOfPlane(size_t plane) const
    202 {
    203     return CVPixelBufferGetBytesPerRowOfPlane(m_pixelBuffer, plane);
    204 }
    205 
    206 void QTPixelBuffer::getExtendedPixels(size_t* left, size_t* right, size_t* top, size_t* bottom) const
    207 {
    208     return CVPixelBufferGetExtendedPixels(m_pixelBuffer, left, right, top, bottom);
    209 }
    210 
    211 CFDictionaryRef QTPixelBuffer::attachments() const
    212 {
    213     return CVBufferGetAttachments(m_pixelBuffer, kCVAttachmentMode_ShouldPropagate);
    214 }
    215 
    216 void QTPixelBuffer::retainCallback(void* refcon)
    217 {
    218     CVPixelBufferRetain(static_cast<CVPixelBufferRef>(refcon));
    219 }
    220 
    221 void QTPixelBuffer::releaseCallback(void* refcon)
    222 {
    223     CVPixelBufferRelease(static_cast<CVPixelBufferRef>(refcon));
    224 }
    225 
    226 void QTPixelBuffer::imageQueueReleaseCallback(unsigned int type, uint64_t id, void* refcon)
    227 {
    228     CVPixelBufferRelease(static_cast<CVPixelBufferRef>(refcon));
    229 }
    230 
    231 void QTPixelBuffer::dataProviderReleaseBytePointerCallback(void* refcon, const void* pointer)
    232 {
    233     CVPixelBufferUnlockBaseAddress(static_cast<CVPixelBufferRef>(refcon), 0);
    234 }
    235 
    236 const void* QTPixelBuffer::dataProviderGetBytePointerCallback(void* refcon)
    237 {
    238     CVPixelBufferLockBaseAddress(static_cast<CVPixelBufferRef>(refcon), 0);
    239     return CVPixelBufferGetBaseAddress(static_cast<CVPixelBufferRef>(refcon));
    240 }
    241 
    242 size_t QTPixelBuffer::dataProviderGetBytesAtPositionCallback(void* refcon, void* buffer, size_t position, size_t count)
    243 {
    244     char* data = (char*)CVPixelBufferGetBaseAddress(static_cast<CVPixelBufferRef>(refcon));
    245     size_t size = CVPixelBufferGetDataSize(static_cast<CVPixelBufferRef>(refcon));
    246     if (size - position < count)
    247         count = size - position;
    248 
    249     memcpy(buffer, data+position, count);
    250     return count;
    251 }
    252 
    253 void QTPixelBuffer::dataProviderReleaseInfoCallback(void* refcon)
    254 {
    255     CVPixelBufferRelease(static_cast<CVPixelBufferRef>(refcon));
    256 }
    257