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 "QTMovieVisualContext.h"
     28 
     29 #include "QTMovieTask.h"
     30 #include <CVBase.h>
     31 #include <CVHostTime.h>
     32 #include <ImageCompression.h>
     33 #include <Movies.h>
     34 #include <windows.h>
     35 
     36 struct QTCVTimeStamp {
     37     CVTimeStamp t;
     38 };
     39 
     40 class QTMovieVisualContextPriv {
     41 public:
     42     QTMovieVisualContextPriv(QTMovieVisualContext* parent, QTMovieVisualContextClient* client, QTPixelBuffer::Type contextType);
     43     ~QTMovieVisualContextPriv();
     44 
     45     bool isImageAvailableForTime(const QTCVTimeStamp*) const;
     46     QTPixelBuffer imageForTime(const QTCVTimeStamp*);
     47     void task();
     48 
     49     QTVisualContextRef visualContextRef();
     50 
     51     void setMovie(PassRefPtr<QTMovie>);
     52     QTMovie* movie() const;
     53 
     54     static void imageAvailableCallback(QTVisualContextRef visualContext, const CVTimeStamp *timeStamp, void *refCon);
     55 
     56 private:
     57     QTMovieVisualContext* m_parent;
     58     QTMovieVisualContextClient* m_client;
     59     QTVisualContextRef m_visualContext;
     60     RefPtr<QTMovie> m_movie;
     61 
     62 };
     63 
     64 static CFDictionaryRef createPixelBufferOptionsDictionary(QTPixelBuffer::Type contextType)
     65 {
     66     const void* key = kQTVisualContextPixelBufferAttributesKey;
     67     const void* value = QTPixelBuffer::createPixelBufferAttributesDictionary(contextType);
     68     CFDictionaryRef pixelBufferOptions = CFDictionaryCreate(kCFAllocatorDefault, &key, &value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
     69     CFRelease(value);
     70     return pixelBufferOptions;
     71 }
     72 
     73 static CFDictionaryRef pixelBufferCreationOptions(QTPixelBuffer::Type contextType)
     74 {
     75     if (contextType == QTPixelBuffer::ConfigureForCAImageQueue) {
     76         static CFDictionaryRef imageQueueOptions = createPixelBufferOptionsDictionary(contextType);
     77         return imageQueueOptions;
     78     }
     79 
     80     ASSERT(contextType == QTPixelBuffer::ConfigureForCGImage);
     81     static CFDictionaryRef cgImageOptions = createPixelBufferOptionsDictionary(contextType);
     82     return cgImageOptions;
     83 }
     84 
     85 QTMovieVisualContextPriv::QTMovieVisualContextPriv(QTMovieVisualContext* parent, QTMovieVisualContextClient* client, QTPixelBuffer::Type contextType)
     86         : m_parent(parent)
     87         , m_client(client)
     88         , m_visualContext(0)
     89 {
     90     typedef OSStatus ( __cdecl *pfnQTPixelBufferContextCreate)(CFAllocatorRef, CFDictionaryRef, QTVisualContextRef*);
     91     static pfnQTPixelBufferContextCreate pPixelBufferContextCreate = 0;
     92     if (!pPixelBufferContextCreate) {
     93         HMODULE qtmlDLL = ::LoadLibraryW(L"QTMLClient.dll");
     94         if (!qtmlDLL)
     95             return;
     96         pPixelBufferContextCreate = reinterpret_cast<pfnQTPixelBufferContextCreate>(GetProcAddress(qtmlDLL, "QTPixelBufferContextCreate"));
     97         if (!pPixelBufferContextCreate)
     98             return;
     99     }
    100 
    101     OSStatus status = pPixelBufferContextCreate(kCFAllocatorDefault, pixelBufferCreationOptions(contextType), &m_visualContext);
    102     if (status == noErr && m_visualContext)
    103         QTVisualContextSetImageAvailableCallback(m_visualContext, &QTMovieVisualContextPriv::imageAvailableCallback, static_cast<void*>(this));
    104 }
    105 
    106 QTMovieVisualContextPriv::~QTMovieVisualContextPriv()
    107 {
    108     if (m_visualContext)
    109         QTVisualContextSetImageAvailableCallback(m_visualContext, 0, 0);
    110 }
    111 
    112 bool QTMovieVisualContextPriv::isImageAvailableForTime(const QTCVTimeStamp* timeStamp) const
    113 {
    114     if (!m_visualContext)
    115         return false;
    116 
    117     return QTVisualContextIsNewImageAvailable(m_visualContext, reinterpret_cast<const CVTimeStamp*>(timeStamp));
    118 }
    119 
    120 QTPixelBuffer QTMovieVisualContextPriv::imageForTime(const QTCVTimeStamp* timeStamp)
    121 {
    122     QTPixelBuffer pixelBuffer;
    123     if (m_visualContext) {
    124         CVImageBufferRef newImage = 0;
    125         OSStatus status = QTVisualContextCopyImageForTime(m_visualContext, kCFAllocatorDefault, reinterpret_cast<const CVTimeStamp*>(timeStamp), &newImage);
    126         if (status == noErr)
    127             pixelBuffer.adopt(newImage);
    128     }
    129     return pixelBuffer;
    130 }
    131 
    132 void QTMovieVisualContextPriv::task()
    133 {
    134     if (m_visualContext)
    135         QTVisualContextTask(m_visualContext);
    136 }
    137 
    138 QTVisualContextRef QTMovieVisualContextPriv::visualContextRef()
    139 {
    140     return m_visualContext;
    141 }
    142 
    143 void QTMovieVisualContextPriv::setMovie(PassRefPtr<QTMovie> movie)
    144 {
    145     if (movie == m_movie)
    146         return;
    147 
    148     if (m_movie) {
    149         SetMovieVisualContext(m_movie->getMovieHandle(), 0);
    150         m_movie = 0;
    151     }
    152 
    153     if (movie)
    154         OSStatus status = SetMovieVisualContext(movie->getMovieHandle(), m_visualContext);
    155 
    156     m_movie = movie;
    157 }
    158 
    159 QTMovie* QTMovieVisualContextPriv::movie() const
    160 {
    161     return m_movie.get();
    162 }
    163 
    164 void QTMovieVisualContextPriv::imageAvailableCallback(QTVisualContextRef visualContext, const CVTimeStamp *timeStamp, void *refCon)
    165 {
    166     if (!refCon)
    167         return;
    168 
    169     QTMovieVisualContextPriv* vc = static_cast<QTMovieVisualContextPriv*>(refCon);
    170     if (!vc->m_client)
    171         return;
    172 
    173     vc->m_client->imageAvailableForTime(reinterpret_cast<const QTCVTimeStamp*>(timeStamp));
    174 }
    175 
    176 PassRefPtr<QTMovieVisualContext> QTMovieVisualContext::create(QTMovieVisualContextClient* client, QTPixelBuffer::Type contextType)
    177 {
    178     return adoptRef(new QTMovieVisualContext(client, contextType));
    179 }
    180 
    181 QTMovieVisualContext::QTMovieVisualContext(QTMovieVisualContextClient* client, QTPixelBuffer::Type contextType)
    182     : m_private(new QTMovieVisualContextPriv(this, client, contextType))
    183 {
    184 }
    185 
    186 QTMovieVisualContext::~QTMovieVisualContext()
    187 {
    188 }
    189 
    190 bool QTMovieVisualContext::isImageAvailableForTime(const QTCVTimeStamp* timeStamp) const
    191 {
    192     return m_private->isImageAvailableForTime(timeStamp);
    193 }
    194 
    195 QTPixelBuffer QTMovieVisualContext::imageForTime(const QTCVTimeStamp* timeStamp)
    196 {
    197     return m_private->imageForTime(timeStamp);
    198 }
    199 
    200 void QTMovieVisualContext::task()
    201 {
    202     m_private->task();
    203 }
    204 
    205 QTVisualContextRef QTMovieVisualContext::visualContextRef()
    206 {
    207     return m_private->visualContextRef();
    208 }
    209 
    210 void QTMovieVisualContext::setMovie(PassRefPtr<QTMovie> movie)
    211 {
    212     m_private->setMovie(movie);
    213 }
    214 
    215 QTMovie* QTMovieVisualContext::movie() const
    216 {
    217     return m_private->movie();
    218 }
    219 
    220 double QTMovieVisualContext::currentHostTime()
    221 {
    222     return CVGetCurrentHostTime() / CVGetHostClockFrequency();
    223 }
    224