• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
createPixelBufferOptionsDictionary(QTPixelBuffer::Type contextType)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 
pixelBufferCreationOptions(QTPixelBuffer::Type contextType)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 
QTMovieVisualContextPriv(QTMovieVisualContext * parent,QTMovieVisualContextClient * client,QTPixelBuffer::Type contextType)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 
~QTMovieVisualContextPriv()106 QTMovieVisualContextPriv::~QTMovieVisualContextPriv()
107 {
108     if (m_visualContext)
109         QTVisualContextSetImageAvailableCallback(m_visualContext, 0, 0);
110 }
111 
isImageAvailableForTime(const QTCVTimeStamp * timeStamp) const112 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 
imageForTime(const QTCVTimeStamp * timeStamp)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 
task()132 void QTMovieVisualContextPriv::task()
133 {
134     if (m_visualContext)
135         QTVisualContextTask(m_visualContext);
136 }
137 
visualContextRef()138 QTVisualContextRef QTMovieVisualContextPriv::visualContextRef()
139 {
140     return m_visualContext;
141 }
142 
setMovie(PassRefPtr<QTMovie> movie)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 
movie() const159 QTMovie* QTMovieVisualContextPriv::movie() const
160 {
161     return m_movie.get();
162 }
163 
imageAvailableCallback(QTVisualContextRef visualContext,const CVTimeStamp * timeStamp,void * refCon)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 
create(QTMovieVisualContextClient * client,QTPixelBuffer::Type contextType)176 PassRefPtr<QTMovieVisualContext> QTMovieVisualContext::create(QTMovieVisualContextClient* client, QTPixelBuffer::Type contextType)
177 {
178     return adoptRef(new QTMovieVisualContext(client, contextType));
179 }
180 
QTMovieVisualContext(QTMovieVisualContextClient * client,QTPixelBuffer::Type contextType)181 QTMovieVisualContext::QTMovieVisualContext(QTMovieVisualContextClient* client, QTPixelBuffer::Type contextType)
182     : m_private(new QTMovieVisualContextPriv(this, client, contextType))
183 {
184 }
185 
~QTMovieVisualContext()186 QTMovieVisualContext::~QTMovieVisualContext()
187 {
188 }
189 
isImageAvailableForTime(const QTCVTimeStamp * timeStamp) const190 bool QTMovieVisualContext::isImageAvailableForTime(const QTCVTimeStamp* timeStamp) const
191 {
192     return m_private->isImageAvailableForTime(timeStamp);
193 }
194 
imageForTime(const QTCVTimeStamp * timeStamp)195 QTPixelBuffer QTMovieVisualContext::imageForTime(const QTCVTimeStamp* timeStamp)
196 {
197     return m_private->imageForTime(timeStamp);
198 }
199 
task()200 void QTMovieVisualContext::task()
201 {
202     m_private->task();
203 }
204 
visualContextRef()205 QTVisualContextRef QTMovieVisualContext::visualContextRef()
206 {
207     return m_private->visualContextRef();
208 }
209 
setMovie(PassRefPtr<QTMovie> movie)210 void QTMovieVisualContext::setMovie(PassRefPtr<QTMovie> movie)
211 {
212     m_private->setMovie(movie);
213 }
214 
movie() const215 QTMovie* QTMovieVisualContext::movie() const
216 {
217     return m_private->movie();
218 }
219 
currentHostTime()220 double QTMovieVisualContext::currentHostTime()
221 {
222     return CVGetCurrentHostTime() / CVGetHostClockFrequency();
223 }
224