qtmobility/plugins/multimedia/qt7/qt7movierenderer.mm
changeset 14 6fbed849b4f4
parent 11 06b8e2af4411
equal deleted inserted replaced
11:06b8e2af4411 14:6fbed849b4f4
    44 #include "qt7backend.h"
    44 #include "qt7backend.h"
    45 
    45 
    46 #include "qt7playercontrol.h"
    46 #include "qt7playercontrol.h"
    47 #include "qt7movierenderer.h"
    47 #include "qt7movierenderer.h"
    48 #include "qt7playersession.h"
    48 #include "qt7playersession.h"
       
    49 #include "qt7ciimagevideobuffer.h"
    49 #include "qcvdisplaylink.h"
    50 #include "qcvdisplaylink.h"
    50 #include <QtCore/qdebug.h>
    51 #include <QtCore/qdebug.h>
    51 #include <QtCore/qcoreapplication.h>
    52 #include <QtCore/qcoreapplication.h>
    52 
    53 
    53 #include <QGLWidget>
    54 #include <QGLWidget>
    54 
    55 
    55 #include <QtMultimedia/qabstractvideobuffer.h>
    56 #include <qabstractvideobuffer.h>
    56 #include <QtMultimedia/qabstractvideosurface.h>
    57 #include <qabstractvideosurface.h>
    57 #include <QtMultimedia/qvideosurfaceformat.h>
    58 #include <qvideosurfaceformat.h>
    58 
    59 
    59 QT_USE_NAMESPACE
    60 QT_USE_NAMESPACE
       
    61 
       
    62 //#define USE_MAIN_MONITOR_COLOR_SPACE 1
    60 
    63 
    61 class CVGLTextureVideoBuffer : public QAbstractVideoBuffer
    64 class CVGLTextureVideoBuffer : public QAbstractVideoBuffer
    62 {
    65 {
    63 public:
    66 public:
    64     CVGLTextureVideoBuffer(CVOpenGLTextureRef buffer)
    67     CVGLTextureVideoBuffer(CVOpenGLTextureRef buffer)
    65         : QAbstractVideoBuffer(NoHandle)
    68         : QAbstractVideoBuffer(GLTextureHandle)
    66         , m_buffer(buffer)
    69         , m_buffer(buffer)
    67         , m_mode(NotMapped)
    70         , m_mode(NotMapped)
    68     {
    71     {
    69         CVOpenGLTextureRetain(m_buffer);
    72         CVOpenGLTextureRetain(m_buffer);
    70     }
    73     }
    76 
    79 
    77     QVariant handle() const
    80     QVariant handle() const
    78     {
    81     {
    79         GLuint id = CVOpenGLTextureGetName(m_buffer);
    82         GLuint id = CVOpenGLTextureGetName(m_buffer);
    80         return QVariant(int(id));
    83         return QVariant(int(id));
    81     }
       
    82 
       
    83     HandleType handleType() const
       
    84     {
       
    85         return GLTextureHandle;
       
    86     }
    84     }
    87 
    85 
    88     MapMode mapMode() const { return m_mode; }
    86     MapMode mapMode() const { return m_mode; }
    89 
    87 
    90     uchar *map(MapMode mode, int *numBytes, int *bytesPerLine)
    88     uchar *map(MapMode mode, int *numBytes, int *bytesPerLine)
   232     CFMutableDictionaryRef  visualContextOptions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
   230     CFMutableDictionaryRef  visualContextOptions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
   233                                                                              &kCFTypeDictionaryKeyCallBacks,
   231                                                                              &kCFTypeDictionaryKeyCallBacks,
   234                                                                              &kCFTypeDictionaryValueCallBacks);
   232                                                                              &kCFTypeDictionaryValueCallBacks);
   235     CFDictionarySetValue(visualContextOptions, kQTVisualContextPixelBufferAttributesKey, pixelBufferOptions);
   233     CFDictionarySetValue(visualContextOptions, kQTVisualContextPixelBufferAttributesKey, pixelBufferOptions);
   236 
   234 
   237     CFDictionarySetValue(visualContextOptions, kQTVisualContextWorkingColorSpaceKey, CGColorSpaceCreateDeviceRGB());
   235     CGColorSpaceRef colorSpace = NULL;
   238     CFDictionarySetValue(visualContextOptions, kQTVisualContextOutputColorSpaceKey, CGColorSpaceCreateDeviceRGB());
   236 
       
   237 #if USE_MAIN_MONITOR_COLOR_SPACE
       
   238     CMProfileRef sysprof = NULL;
       
   239 
       
   240     // Get the Systems Profile for the main display
       
   241     if (CMGetSystemProfile(&sysprof) == noErr) {
       
   242         // Create a colorspace with the systems profile
       
   243         colorSpace = CGColorSpaceCreateWithPlatformColorSpace(sysprof);
       
   244         CMCloseProfile(sysprof);
       
   245     }
       
   246 #endif
       
   247 
       
   248     if (!colorSpace)
       
   249         colorSpace = CGColorSpaceCreateDeviceRGB();
       
   250 
       
   251     CFDictionarySetValue(visualContextOptions, kQTVisualContextOutputColorSpaceKey, colorSpace);
   239 
   252 
   240     OSStatus err = QTPixelBufferContextCreate(kCFAllocatorDefault,
   253     OSStatus err = QTPixelBufferContextCreate(kCFAllocatorDefault,
   241                                                visualContextOptions,
   254                                                visualContextOptions,
   242                                                &m_visualContext);
   255                                                &m_visualContext);
   243     CFRelease(pixelBufferOptions);
   256     CFRelease(pixelBufferOptions);
   269     if (m_movie == 0 || m_surface == 0) {
   282     if (m_movie == 0 || m_surface == 0) {
   270         m_displayLink->stop();
   283         m_displayLink->stop();
   271         return;
   284         return;
   272     }
   285     }
   273 
   286 
   274     NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieCurrentSizeAttribute"] sizeValue];
   287     NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue];
   275     m_nativeSize = QSize(size.width, size.height);
   288     m_nativeSize = QSize(size.width, size.height);
   276 
   289 
   277 #ifdef QUICKTIME_C_API_AVAILABLE
   290 #ifdef QUICKTIME_C_API_AVAILABLE
   278     bool usedGLContext = m_usingGLContext;
   291     bool usedGLContext = m_usingGLContext;
   279 
   292 
   286             QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32, QAbstractVideoBuffer::GLTextureHandle);
   299             QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32, QAbstractVideoBuffer::GLTextureHandle);
   287 
   300 
   288             if (m_surface->isActive())
   301             if (m_surface->isActive())
   289                 m_surface->stop();
   302                 m_surface->stop();
   290 
   303 
   291             qDebug() << "Starting the surface with format" << format;
       
   292             if (!m_surface->start(format)) {
   304             if (!m_surface->start(format)) {
   293                 qDebug() << "failed to start video surface" << m_surface->error();
   305                 qWarning() << "failed to start video surface" << m_surface->error();
       
   306                 qWarning() << "Surface format:" << format;
   294                 glSupported = false;
   307                 glSupported = false;
   295             } else {
   308             } else {
   296                 m_usingGLContext = true;
   309                 m_usingGLContext = true;
   297             }
   310             }
   298 
   311 
   307                 m_surface->stop();
   320                 m_surface->stop();
   308             }
   321             }
   309 
   322 
   310             if (!m_surface->isActive()) {
   323             if (!m_surface->isActive()) {
   311                 qDebug() << "Starting the surface with format" << format;
   324                 qDebug() << "Starting the surface with format" << format;
   312                 if (!m_surface->start(format))
   325                 if (!m_surface->start(format)) {
   313                     qDebug() << "failed to start video surface" << m_surface->error();
   326                     qWarning() << "failed to start video surface" << m_surface->error();
       
   327                     qWarning() << "Surface format:" << format;
       
   328                 }
   314             }
   329             }
   315         }
   330         }
   316     }
   331     }
   317 
   332 
   318 
   333 
   320         //check if the visual context still can be reused
   335         //check if the visual context still can be reused
   321         if (usedGLContext != m_usingGLContext ||
   336         if (usedGLContext != m_usingGLContext ||
   322             (m_usingGLContext && (m_currentGLContext != QGLContext::currentContext())) ||
   337             (m_usingGLContext && (m_currentGLContext != QGLContext::currentContext())) ||
   323             (!m_usingGLContext && (m_pixelBufferContextGeometry != m_nativeSize))) {
   338             (!m_usingGLContext && (m_pixelBufferContextGeometry != m_nativeSize))) {
   324             QTVisualContextRelease(m_visualContext);
   339             QTVisualContextRelease(m_visualContext);
       
   340             m_pixelBufferContextGeometry = QSize();
   325             m_visualContext = 0;
   341             m_visualContext = 0;
   326         }
   342         }
   327     }
   343     }
   328 
   344 
   329     if (!m_visualContext) {
   345     if (!m_nativeSize.isEmpty()) {
   330         if (m_usingGLContext) {
   346         if (!m_visualContext) {
   331             qDebug() << "Building OpenGL visual context";
   347             if (m_usingGLContext) {
   332             m_currentGLContext = QGLContext::currentContext();
   348                 qDebug() << "Building OpenGL visual context" << m_nativeSize;
   333             if (!createGLVisualContext()) {
   349                 m_currentGLContext = QGLContext::currentContext();
   334                 qWarning() << "QT7MovieRenderer: failed to create visual context";
   350                 if (!createGLVisualContext()) {
   335                 return;
   351                     qWarning() << "QT7MovieRenderer: failed to create visual context";
       
   352                     return;
       
   353                 }
       
   354             } else {
       
   355                 qDebug() << "Building Pixel Buffer visual context" << m_nativeSize;
       
   356                 if (!createPixelBufferVisualContext()) {
       
   357                     qWarning() << "QT7MovieRenderer: failed to create visual context";
       
   358                     return;
       
   359                 }
   336             }
   360             }
   337         } else {
   361         }
   338             qDebug() << "Building Pixel Buffer visual context";
   362 
   339             if (!createPixelBufferVisualContext()) {
   363         // targets a Movie to render into a visual context
   340                 qWarning() << "QT7MovieRenderer: failed to create visual context";
   364         SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], m_visualContext);
   341                 return;
   365 
   342             }
   366         m_displayLink->start();
   343         }
   367     }
   344     }
       
   345 
       
   346     // targets a Movie to render into a visual context
       
   347     SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], m_visualContext);
       
   348 
       
   349 
       
   350 #endif
   368 #endif
   351 
   369 
   352     m_displayLink->start();
       
   353 }
       
   354 
       
   355 void QT7MovieRenderer::setEnabled(bool)
       
   356 {
       
   357 }
   370 }
   358 
   371 
   359 void QT7MovieRenderer::setMovie(void *movie)
   372 void QT7MovieRenderer::setMovie(void *movie)
   360 {
   373 {
   361     qDebug() << "QT7MovieRenderer::setMovie" << movie;
   374     //qDebug() << "QT7MovieRenderer::setMovie" << movie;
   362 
   375 
   363     if (m_movie == movie)
   376 #ifdef QUICKTIME_C_API_AVAILABLE
   364         return;
       
   365 
       
   366     QMutexLocker locker(&m_mutex);
   377     QMutexLocker locker(&m_mutex);
   367 
   378 
   368 #ifdef QUICKTIME_C_API_AVAILABLE
   379     if (m_movie != movie) {
   369     //ensure the old movie doesn't hold the visual context, otherwise it can't be reused
   380         if (m_movie) {
   370     if (m_movie && m_visualContext)
   381             //ensure the old movie doesn't hold the visual context, otherwise it can't be reused
   371         SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], 0);
   382             SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], nil);
       
   383             [(QTMovie*)m_movie release];
       
   384         }
       
   385 
       
   386         m_movie = movie;
       
   387         [(QTMovie*)m_movie retain];
       
   388 
       
   389         setupVideoOutput();
       
   390     }
   372 #endif
   391 #endif
   373 
   392 }
   374     m_movie = movie;
   393 
   375     setupVideoOutput();
   394 void QT7MovieRenderer::updateNaturalSize(const QSize &newSize)
       
   395 {
       
   396     if (m_nativeSize != newSize) {
       
   397         m_nativeSize = newSize;
       
   398         setupVideoOutput();
       
   399     }
   376 }
   400 }
   377 
   401 
   378 QAbstractVideoSurface *QT7MovieRenderer::surface() const
   402 QAbstractVideoSurface *QT7MovieRenderer::surface() const
   379 {
   403 {
   380     return m_surface;
   404     return m_surface;
   381 }
   405 }
   382 
   406 
   383 void QT7MovieRenderer::setSurface(QAbstractVideoSurface *surface)
   407 void QT7MovieRenderer::setSurface(QAbstractVideoSurface *surface)
   384 {
   408 {
   385     qDebug() << "Set video surface" << surface;
   409     //qDebug() << "Set video surface" << surface;
   386 
   410 
   387     if (surface == m_surface)
   411     if (surface == m_surface)
   388         return;
   412         return;
   389 
   413 
   390     QMutexLocker locker(&m_mutex);
   414     QMutexLocker locker(&m_mutex);
   414         CVImageBufferRef imageBuffer = NULL;
   438         CVImageBufferRef imageBuffer = NULL;
   415 
   439 
   416         OSStatus status = QTVisualContextCopyImageForTime(m_visualContext, NULL, &ts, &imageBuffer);
   440         OSStatus status = QTVisualContextCopyImageForTime(m_visualContext, NULL, &ts, &imageBuffer);
   417 
   441 
   418         if (status == noErr && imageBuffer) {
   442         if (status == noErr && imageBuffer) {
   419             //qDebug() << "render video frame";
       
   420             QAbstractVideoBuffer *buffer = 0;
   443             QAbstractVideoBuffer *buffer = 0;
   421 
   444 
   422             if (m_usingGLContext) {
   445             if (m_usingGLContext) {
   423                 buffer = new CVGLTextureVideoBuffer((CVOpenGLTextureRef)imageBuffer);
   446                 buffer = new QT7CIImageVideoBuffer([CIImage imageWithCVImageBuffer:imageBuffer]);
   424                 CVOpenGLTextureRelease((CVOpenGLTextureRef)imageBuffer);
   447                 CVOpenGLTextureRelease((CVOpenGLTextureRef)imageBuffer);
   425                 //qDebug() << "render GL video frame" << buffer->handle();
       
   426             } else {
   448             } else {
   427                 buffer = new CVPixelBufferVideoBuffer((CVPixelBufferRef)imageBuffer);
   449                 buffer = new CVPixelBufferVideoBuffer((CVPixelBufferRef)imageBuffer);
       
   450                 //buffer = new QT7CIImageVideoBuffer( [CIImage imageWithCVImageBuffer:imageBuffer] );
   428                 CVPixelBufferRelease((CVPixelBufferRef)imageBuffer);
   451                 CVPixelBufferRelease((CVPixelBufferRef)imageBuffer);
   429             }
   452             }
   430 
   453 
   431             QVideoFrame frame(buffer, m_nativeSize, QVideoFrame::Format_RGB32);            
   454             QVideoFrame frame(buffer, m_nativeSize, QVideoFrame::Format_RGB32);
   432             m_surface->present(frame);
   455             m_surface->present(frame);
   433             QTVisualContextTask(m_visualContext);
   456             QTVisualContextTask(m_visualContext);
   434         }
   457         }
   435     }
   458     }
   436 #else
   459 #else