예제 #1
0
static CGImageRef CreateCGImageFromPixelBuffer(QTPixelBuffer buffer)
{
#if USE(ACCELERATED_COMPOSITING)
    CGDataProviderRef provider = 0;
    CGColorSpaceRef colorSpace = 0;
    CGImageRef image = 0;

    size_t bitsPerComponent = 0;
    size_t bitsPerPixel = 0;
    CGImageAlphaInfo alphaInfo = kCGImageAlphaNone;
        
    if (buffer.pixelFormatIs32BGRA()) {
        bitsPerComponent = 8;
        bitsPerPixel = 32;
        alphaInfo = (CGImageAlphaInfo)(kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little);
    } else if (buffer.pixelFormatIs32ARGB()) {
        bitsPerComponent = 8;
        bitsPerPixel = 32;
        alphaInfo = (CGImageAlphaInfo)(kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big);
    } else {
        // All other pixel formats are currently unsupported:
        ASSERT_NOT_REACHED();
    }

    CGDataProviderDirectAccessCallbacks callbacks = {
        &QTPixelBuffer::dataProviderGetBytePointerCallback,
        &QTPixelBuffer::dataProviderReleaseBytePointerCallback,
        &QTPixelBuffer::dataProviderGetBytesAtPositionCallback,
        &QTPixelBuffer::dataProviderReleaseInfoCallback,
    };
    
    // Colorspace should be device, so that Quartz does not have to do an extra render.
    colorSpace = CGColorSpaceCreateDeviceRGB();
    require(colorSpace, Bail);
            
    provider = CGDataProviderCreateDirectAccess(buffer.pixelBufferRef(), buffer.dataSize(), &callbacks);
    require(provider, Bail);

    // CGDataProvider does not retain the buffer, but it will release it later, so do an extra retain here:
    QTPixelBuffer::retainCallback(buffer.pixelBufferRef());
        
    image = CGImageCreate(buffer.width(), buffer.height(), bitsPerComponent, bitsPerPixel, buffer.bytesPerRow(), colorSpace, alphaInfo, provider, 0, false, kCGRenderingIntentDefault);
 
Bail:
    // Once the image is created we can release our reference to the provider and the colorspace, they are retained by the image
    if (provider)
        CGDataProviderRelease(provider);
    if (colorSpace)
        CGColorSpaceRelease(colorSpace);
 
    return image;
#else
    return 0;
#endif
}
예제 #2
0
void MediaPlayerPrivateQuickTimeVisualContext::paint(GraphicsContext* p, const IntRect& r)
{
    MediaRenderingMode currentMode = currentRenderingMode();

    if (currentMode == MediaRenderingNone)
        return;

    if (currentMode == MediaRenderingSoftwareRenderer && !m_visualContext)
        return;

    QTPixelBuffer buffer = m_visualContext->imageForTime(0);
    if (buffer.pixelBufferRef()) {
#if USE(ACCELERATED_COMPOSITING)
        if (m_qtVideoLayer) {
            // We are probably being asked to render the video into a canvas, but
            // there's a good chance the QTPixelBuffer is not ARGB and thus can't be
            // drawn using CG.  If so, fire up an ICMDecompressionSession and convert
            // the current frame into something which can be rendered by CG.
            if (!buffer.pixelFormatIs32ARGB() && !buffer.pixelFormatIs32BGRA()) {
                // The decompression session will only decompress a specific pixelFormat
                // at a specific width and height; if these differ, the session must be
                // recreated with the new parameters.
                if (!m_decompressionSession || !m_decompressionSession->canDecompress(buffer))
                    m_decompressionSession = QTDecompressionSession::create(buffer.pixelFormatType(), buffer.width(), buffer.height());
                buffer = m_decompressionSession->decompress(buffer);
            }
        }
#endif
        CGImageRef image = CreateCGImageFromPixelBuffer(buffer);

        CGContextRef context = p->platformContext();
        CGContextSaveGState(context);
        CGContextTranslateCTM(context, r.x(), r.y());
        CGContextTranslateCTM(context, 0, r.height());
        CGContextScaleCTM(context, 1, -1);
        CGContextDrawImage(context, CGRectMake(0, 0, r.width(), r.height()), image);
        CGContextRestoreGState(context);

        CGImageRelease(image);
    }
    paintCompleted(*p, r);
}