44 #include "qt7backend.h" |
44 #include "qt7backend.h" |
45 |
45 |
46 #include "qt7playercontrol.h" |
46 #include "qt7playercontrol.h" |
47 #include "qt7movieviewrenderer.h" |
47 #include "qt7movieviewrenderer.h" |
48 #include "qt7playersession.h" |
48 #include "qt7playersession.h" |
|
49 #include "qt7ciimagevideobuffer.h" |
49 #include <QtCore/qdebug.h> |
50 #include <QtCore/qdebug.h> |
50 #include <QtCore/qcoreevent.h> |
51 #include <QtCore/qcoreevent.h> |
51 #include <QtCore/qcoreapplication.h> |
52 #include <QtCore/qcoreapplication.h> |
52 |
53 |
53 #include <QtMultimedia/qabstractvideobuffer.h> |
54 #include <qabstractvideobuffer.h> |
54 #include <QtMultimedia/qabstractvideosurface.h> |
55 #include <qabstractvideosurface.h> |
55 #include <QtMultimedia/qvideosurfaceformat.h> |
56 #include <qvideosurfaceformat.h> |
56 |
57 |
|
58 #include <QuartzCore/CIFilter.h> |
|
59 #include <QuartzCore/CIVector.h> |
57 |
60 |
58 QT_USE_NAMESPACE |
61 QT_USE_NAMESPACE |
59 |
62 |
60 class NSBitmapVideoBuffer : public QAbstractVideoBuffer |
63 class NSBitmapVideoBuffer : public QAbstractVideoBuffer |
61 { |
64 { |
110 } |
113 } |
111 |
114 |
112 - (HiddenQTMovieView *) initWithRenderer:(QT7MovieViewRenderer *)renderer; |
115 - (HiddenQTMovieView *) initWithRenderer:(QT7MovieViewRenderer *)renderer; |
113 - (void) setRenderer:(QT7MovieViewRenderer *)renderer; |
116 - (void) setRenderer:(QT7MovieViewRenderer *)renderer; |
114 - (void) setDrawRect:(const QRect &)rect; |
117 - (void) setDrawRect:(const QRect &)rect; |
|
118 - (CIImage *) view:(QTMovieView *)view willDisplayImage:(CIImage *)img; |
115 @end |
119 @end |
116 |
120 |
117 @implementation HiddenQTMovieView |
121 @implementation HiddenQTMovieView |
118 |
122 |
119 - (HiddenQTMovieView *) initWithRenderer:(QT7MovieViewRenderer *)renderer |
123 - (HiddenQTMovieView *) initWithRenderer:(QT7MovieViewRenderer *)renderer |
160 { |
164 { |
161 // This method is called from QTMovieView just |
165 // This method is called from QTMovieView just |
162 // before the image will be drawn. |
166 // before the image will be drawn. |
163 Q_UNUSED(view); |
167 Q_UNUSED(view); |
164 if (m_renderer) { |
168 if (m_renderer) { |
165 NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img]; |
|
166 CGRect bounds = [img extent]; |
169 CGRect bounds = [img extent]; |
167 int w = bounds.size.width; |
170 int w = bounds.size.width; |
168 int h = bounds.size.height; |
171 int h = bounds.size.height; |
169 |
172 |
170 // Swap red and blue (same as QImage::rgbSwapped, but without copy) |
173 QVideoFrame frame; |
171 uchar *data = [bitmap bitmapData]; |
174 |
172 //qDebug() << data << w << h; |
175 QAbstractVideoSurface *surface = m_renderer->surface(); |
173 int bytesPerLine = [bitmap bytesPerRow]; |
176 if (!surface || !surface->isActive()) |
174 for (int i=0; i<h; ++i) { |
177 return img; |
175 quint32 *p = (quint32*)data; |
178 |
176 data += bytesPerLine; |
179 if (surface->surfaceFormat().handleType() == QAbstractVideoBuffer::CoreImageHandle) { |
177 quint32 *end = p + w; |
180 //surface supports rendering of opengl based CIImage |
178 while (p < end) { |
181 frame = QVideoFrame(new QT7CIImageVideoBuffer(img), QSize(w,h), QVideoFrame::Format_RGB32 ); |
179 *p = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00); |
182 } else { |
180 p++; |
183 //Swap R and B colors |
181 } |
184 CIFilter *colorSwapFilter = [CIFilter filterWithName: @"CIColorMatrix" keysAndValues: |
182 } |
185 @"inputImage", img, |
183 |
186 @"inputRVector", [CIVector vectorWithX: 0 Y: 0 Z: 1 W: 0], |
184 QVideoFrame frame( new NSBitmapVideoBuffer(bitmap), QSize(w,h), QVideoFrame::Format_RGB32 ); |
187 @"inputGVector", [CIVector vectorWithX: 0 Y: 1 Z: 0 W: 0], |
185 |
188 @"inputBVector", [CIVector vectorWithX: 1 Y: 0 Z: 0 W: 0], |
186 //static int i=0; |
189 @"inputAVector", [CIVector vectorWithX: 0 Y: 0 Z: 0 W: 1], |
187 //i++; |
190 @"inputBiasVector", [CIVector vectorWithX: 0 Y: 0 Z: 0 W: 0], |
188 //QImage img([bitmap bitmapData], w, h, QImage::Format_RGB32); |
191 nil]; |
189 //img.save(QString("img%1.jpg").arg(i)); |
192 CIImage *img = [colorSwapFilter valueForKey: @"outputImage"]; |
190 |
193 NSBitmapImageRep *bitmap =[[NSBitmapImageRep alloc] initWithCIImage:img]; |
191 [bitmap release]; |
194 //requesting the bitmap data is slow, |
|
195 //but it's better to do it here to avoid blocking the main thread for a long. |
|
196 [bitmap bitmapData]; |
|
197 frame = QVideoFrame(new NSBitmapVideoBuffer(bitmap), QSize(w,h), QVideoFrame::Format_RGB32 ); |
|
198 [bitmap release]; |
|
199 } |
192 |
200 |
193 if (m_renderer) |
201 if (m_renderer) |
194 m_renderer->renderFrame(frame); |
202 m_renderer->renderFrame(frame); |
195 } |
203 } |
196 |
204 |
263 m_movieView = movieView; |
272 m_movieView = movieView; |
264 [movieView setControllerVisible:NO]; |
273 [movieView setControllerVisible:NO]; |
265 } |
274 } |
266 |
275 |
267 [movieView setMovie:(QTMovie*)m_movie]; |
276 [movieView setMovie:(QTMovie*)m_movie]; |
268 //[movieView setDrawRect:QRect(QPoint(0,0), m_nativeSize)]; |
277 [movieView setDrawRect:QRect(QPoint(0,0), m_nativeSize)]; |
269 } |
278 } |
270 |
279 |
271 if (m_surface && !m_nativeSize.isEmpty()) { |
280 if (m_surface && !m_nativeSize.isEmpty()) { |
272 QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32); |
281 bool coreImageFrameSupported = !m_surface->supportedPixelFormats(QAbstractVideoBuffer::CoreImageHandle).isEmpty() && |
|
282 !m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).isEmpty(); |
|
283 |
|
284 QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32, |
|
285 coreImageFrameSupported ? QAbstractVideoBuffer::CoreImageHandle : QAbstractVideoBuffer::NoHandle); |
273 |
286 |
274 if (m_surface->isActive() && m_surface->surfaceFormat() != format) { |
287 if (m_surface->isActive() && m_surface->surfaceFormat() != format) { |
275 qDebug() << "Surface format was changed, stop the surface."; |
288 qDebug() << "Surface format was changed, stop the surface."; |
276 m_surface->stop(); |
289 m_surface->stop(); |
277 } |
290 } |
282 qDebug() << "failed to start video surface" << m_surface->error(); |
295 qDebug() << "failed to start video surface" << m_surface->error(); |
283 } |
296 } |
284 } |
297 } |
285 } |
298 } |
286 |
299 |
287 void QT7MovieViewRenderer::setEnabled(bool) |
|
288 { |
|
289 } |
|
290 |
|
291 void QT7MovieViewRenderer::setMovie(void *movie) |
300 void QT7MovieViewRenderer::setMovie(void *movie) |
292 { |
301 { |
293 if (movie == m_movie) |
302 if (movie == m_movie) |
294 return; |
303 return; |
295 |
304 |
296 QMutexLocker locker(&m_mutex); |
305 QMutexLocker locker(&m_mutex); |
297 m_movie = movie; |
306 m_movie = movie; |
298 setupVideoOutput(); |
307 setupVideoOutput(); |
299 } |
308 } |
300 |
309 |
|
310 void QT7MovieViewRenderer::updateNaturalSize(const QSize &newSize) |
|
311 { |
|
312 if (m_nativeSize != newSize) { |
|
313 m_nativeSize = newSize; |
|
314 setupVideoOutput(); |
|
315 } |
|
316 } |
|
317 |
301 QAbstractVideoSurface *QT7MovieViewRenderer::surface() const |
318 QAbstractVideoSurface *QT7MovieViewRenderer::surface() const |
302 { |
319 { |
303 return m_surface; |
320 return m_surface; |
304 } |
321 } |
305 |
322 |
317 setupVideoOutput(); |
334 setupVideoOutput(); |
318 } |
335 } |
319 |
336 |
320 void QT7MovieViewRenderer::renderFrame(const QVideoFrame &frame) |
337 void QT7MovieViewRenderer::renderFrame(const QVideoFrame &frame) |
321 { |
338 { |
322 { |
339 |
323 QMutexLocker locker(&m_mutex); |
340 QMutexLocker locker(&m_mutex); |
324 m_currentFrame = frame; |
341 m_currentFrame = frame; |
325 } |
342 |
326 |
343 if (!m_pendingRenderEvent) |
327 qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority); |
344 qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority); |
|
345 |
|
346 m_pendingRenderEvent = true; |
328 } |
347 } |
329 |
348 |
330 bool QT7MovieViewRenderer::event(QEvent *event) |
349 bool QT7MovieViewRenderer::event(QEvent *event) |
331 { |
350 { |
332 if (event->type() == QEvent::User) { |
351 if (event->type() == QEvent::User) { |
333 QMutexLocker locker(&m_mutex); |
352 QMutexLocker locker(&m_mutex); |
|
353 m_pendingRenderEvent = false; |
334 if (m_surface->isActive()) |
354 if (m_surface->isActive()) |
335 m_surface->present(m_currentFrame); |
355 m_surface->present(m_currentFrame); |
336 } |
356 } |
337 |
357 |
338 return QT7VideoRendererControl::event(event); |
358 return QT7VideoRendererControl::event(event); |