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 } |
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); |
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 |
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 |