qtmobility/plugins/multimedia/qt7/qt7movieviewrenderer.mm
changeset 14 6fbed849b4f4
parent 11 06b8e2af4411
--- a/qtmobility/plugins/multimedia/qt7/qt7movieviewrenderer.mm	Fri Jun 11 14:26:25 2010 +0300
+++ b/qtmobility/plugins/multimedia/qt7/qt7movieviewrenderer.mm	Wed Jun 23 19:08:38 2010 +0300
@@ -46,14 +46,17 @@
 #include "qt7playercontrol.h"
 #include "qt7movieviewrenderer.h"
 #include "qt7playersession.h"
+#include "qt7ciimagevideobuffer.h"
 #include <QtCore/qdebug.h>
 #include <QtCore/qcoreevent.h>
 #include <QtCore/qcoreapplication.h>
 
-#include <QtMultimedia/qabstractvideobuffer.h>
-#include <QtMultimedia/qabstractvideosurface.h>
-#include <QtMultimedia/qvideosurfaceformat.h>
+#include <qabstractvideobuffer.h>
+#include <qabstractvideosurface.h>
+#include <qvideosurfaceformat.h>
 
+#include <QuartzCore/CIFilter.h>
+#include <QuartzCore/CIVector.h>
 
 QT_USE_NAMESPACE
 
@@ -112,6 +115,7 @@
 - (HiddenQTMovieView *) initWithRenderer:(QT7MovieViewRenderer *)renderer;
 - (void) setRenderer:(QT7MovieViewRenderer *)renderer;
 - (void) setDrawRect:(const QRect &)rect;
+- (CIImage *) view:(QTMovieView *)view willDisplayImage:(CIImage *)img;
 @end
 
 @implementation HiddenQTMovieView
@@ -162,34 +166,38 @@
     // before the image will be drawn.
     Q_UNUSED(view);
     if (m_renderer) {
-        NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img];
         CGRect bounds = [img extent];
         int w = bounds.size.width;
         int h = bounds.size.height;
 
-        // Swap red and blue (same as QImage::rgbSwapped, but without copy)
-        uchar *data = [bitmap bitmapData];
-        //qDebug() << data << w << h;
-        int bytesPerLine = [bitmap bytesPerRow];
-        for (int i=0; i<h; ++i) {
-            quint32 *p = (quint32*)data;
-            data += bytesPerLine;
-            quint32 *end = p + w;
-            while (p < end) {
-                *p = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
-                p++;
-            }
+        QVideoFrame frame;
+
+        QAbstractVideoSurface *surface = m_renderer->surface();
+        if (!surface || !surface->isActive())
+            return img;
+
+        if (surface->surfaceFormat().handleType() == QAbstractVideoBuffer::CoreImageHandle) {
+            //surface supports rendering of opengl based CIImage
+            frame = QVideoFrame(new QT7CIImageVideoBuffer(img), QSize(w,h), QVideoFrame::Format_RGB32 );
+        } else {
+            //Swap R and B colors
+            CIFilter *colorSwapFilter = [CIFilter filterWithName: @"CIColorMatrix"  keysAndValues:
+                                         @"inputImage", img,
+                                         @"inputRVector", [CIVector vectorWithX: 0  Y: 0  Z: 1  W: 0],
+                                         @"inputGVector", [CIVector vectorWithX: 0  Y: 1  Z: 0  W: 0],
+                                         @"inputBVector", [CIVector vectorWithX: 1  Y: 0  Z: 0  W: 0],
+                                         @"inputAVector", [CIVector vectorWithX: 0  Y: 0  Z: 0  W: 1],
+                                         @"inputBiasVector", [CIVector vectorWithX: 0  Y: 0  Z: 0  W: 0],
+                                         nil];
+            CIImage *img = [colorSwapFilter valueForKey: @"outputImage"];
+            NSBitmapImageRep *bitmap =[[NSBitmapImageRep alloc] initWithCIImage:img];
+            //requesting the bitmap data is slow,
+            //but it's better to do it here to avoid blocking the main thread for a long.
+            [bitmap bitmapData];
+            frame = QVideoFrame(new NSBitmapVideoBuffer(bitmap), QSize(w,h), QVideoFrame::Format_RGB32 );
+            [bitmap release];
         }
 
-        QVideoFrame frame( new NSBitmapVideoBuffer(bitmap), QSize(w,h), QVideoFrame::Format_RGB32 );
-
-        //static int i=0;
-        //i++;
-        //QImage img([bitmap bitmapData], w, h, QImage::Format_RGB32);
-        //img.save(QString("img%1.jpg").arg(i));
-
-        [bitmap release];
-
         if (m_renderer)
             m_renderer->renderFrame(frame);
     }
@@ -228,7 +236,8 @@
    :QT7VideoRendererControl(parent),
     m_movie(0),
     m_movieView(0),
-    m_surface(0)
+    m_surface(0),
+    m_pendingRenderEvent(false)
 {    
 }
 
@@ -265,11 +274,15 @@
         }
 
         [movieView setMovie:(QTMovie*)m_movie];
-        //[movieView setDrawRect:QRect(QPoint(0,0), m_nativeSize)];
+        [movieView setDrawRect:QRect(QPoint(0,0), m_nativeSize)];
     }
 
     if (m_surface && !m_nativeSize.isEmpty()) {
-        QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32);
+        bool coreImageFrameSupported = !m_surface->supportedPixelFormats(QAbstractVideoBuffer::CoreImageHandle).isEmpty() &&
+                                       !m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).isEmpty();
+
+        QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32,
+                                   coreImageFrameSupported ? QAbstractVideoBuffer::CoreImageHandle : QAbstractVideoBuffer::NoHandle);
 
         if (m_surface->isActive() && m_surface->surfaceFormat() != format) {
             qDebug() << "Surface format was changed, stop the surface.";
@@ -284,10 +297,6 @@
     }
 }
 
-void QT7MovieViewRenderer::setEnabled(bool)
-{
-}
-
 void QT7MovieViewRenderer::setMovie(void *movie)
 {
     if (movie == m_movie)
@@ -298,6 +307,14 @@
     setupVideoOutput();
 }
 
+void QT7MovieViewRenderer::updateNaturalSize(const QSize &newSize)
+{
+    if (m_nativeSize != newSize) {
+        m_nativeSize = newSize;
+        setupVideoOutput();
+    }
+}
+
 QAbstractVideoSurface *QT7MovieViewRenderer::surface() const
 {
     return m_surface;
@@ -319,18 +336,21 @@
 
 void QT7MovieViewRenderer::renderFrame(const QVideoFrame &frame)
 {
-    {
-        QMutexLocker locker(&m_mutex);
-        m_currentFrame = frame;
-    }
+
+    QMutexLocker locker(&m_mutex);
+    m_currentFrame = frame;
 
-    qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority);
+    if (!m_pendingRenderEvent)
+        qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority);
+
+    m_pendingRenderEvent = true;
 }
 
 bool QT7MovieViewRenderer::event(QEvent *event)
 {
     if (event->type() == QEvent::User) {
         QMutexLocker locker(&m_mutex);
+        m_pendingRenderEvent = false;
         if (m_surface->isActive())
             m_surface->present(m_currentFrame);
     }