summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorGareth Stockwell <ext-gareth.stockwell@nokia.com>2011-11-11 13:34:23 +0000
committerGareth Stockwell <ext-gareth.stockwell@nokia.com>2011-11-25 16:43:12 +0000
commitf7c1dda00aabb3931cebd6375741f96306ff65f3 (patch)
tree0b8d917c885a75e6fe071ea0dd76df7cb2bab265 /plugins
parenta9d8bf0d92a9ad171461fdcce0922e4de3bea08b (diff)
Add EGL video rendering path on Symbian
This change adds support for rendering video and camera viewfinder frames via EGL, as an alternative to the existing rendering path in which frames are sent directly to the compositing window manager. Rendering via EGL rather than directly to the compositor has a number of advantages, including: * Elimination of artefacts. The direct rendering path requires content on the video and UI surfaces to be synchronized; in the EGL rendering path, this synchronization is deferred to the OpenGLES/OpenVG implementation. * Full support for QGraphicsView and QML APIs. The direct rendering path does not support operations such as free rotation and shear transformations; these are supported by both OpenGLES and OpenVG. * Ability to transform video content using OpenGLES. Making video frames available to EGL means that they can be transformed using shader effects, or rendered into 3D scenes. It also has some disadvantages: * Greater memory consumption * Lower-quality scaling Due to these drawbacks, it is desirable to use the direct rendering path for 'standard' full-screen video playback / viewfinder display. The QGraphicsVideoItem implementation by defaut switches automatically between the two rendering paths; see comments in qgraphicsvideoitem_symbian.cpp for details. The EGL rendering path is implemented using the EGL_NOK_image_endpoint2 extension. If this is not available, QGraphicsVideoItem falls back to using the direct rendering path. If creation of the EGL endpoint fails, QGraphicsVideoItem falls back to using the direct rendering path. Task-number: QTMOBILITY-1818 Task-number: MOBILITY-3084 Reviewed-by: mread
Diffstat (limited to 'plugins')
-rw-r--r--plugins/multimedia/symbian/ecam/camera_s60.pri4
-rw-r--r--plugins/multimedia/symbian/ecam/s60bitmapviewfinderrenderercontrol.cpp (renamed from plugins/multimedia/symbian/ecam/s60videorenderercontrol.cpp)27
-rw-r--r--plugins/multimedia/symbian/ecam/s60bitmapviewfinderrenderercontrol.h (renamed from plugins/multimedia/symbian/ecam/s60videorenderercontrol.h)32
-rw-r--r--plugins/multimedia/symbian/ecam/s60cameraservice.cpp91
-rw-r--r--plugins/multimedia/symbian/ecam/s60cameraservice.h42
-rw-r--r--plugins/multimedia/symbian/ecam/s60cameraviewfinderengine.cpp155
-rw-r--r--plugins/multimedia/symbian/ecam/s60cameraviewfinderengine.h5
-rw-r--r--plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayercontrol.cpp5
-rw-r--r--plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayercontrol.h1
-rw-r--r--plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayerservice.cpp45
-rw-r--r--plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayerservice.h3
-rw-r--r--plugins/multimedia/symbian/mmf/mediaplayer/s60videoplayersession.cpp85
-rw-r--r--plugins/multimedia/symbian/mmf/mediaplayer/s60videoplayersession.h22
-rw-r--r--plugins/multimedia/symbian/videooutput/s60eglendpoint.cpp250
-rw-r--r--plugins/multimedia/symbian/videooutput/s60eglendpoint.h93
-rw-r--r--plugins/multimedia/symbian/videooutput/s60eglextensions.cpp188
-rw-r--r--plugins/multimedia/symbian/videooutput/s60eglextensions.h118
-rw-r--r--plugins/multimedia/symbian/videooutput/s60nativewindow.cpp115
-rw-r--r--plugins/multimedia/symbian/videooutput/s60nativewindow.h73
-rw-r--r--plugins/multimedia/symbian/videooutput/s60videobuffer.cpp251
-rw-r--r--plugins/multimedia/symbian/videooutput/s60videobuffer.h134
-rw-r--r--plugins/multimedia/symbian/videooutput/s60videoeglrenderercontrol.cpp219
-rw-r--r--plugins/multimedia/symbian/videooutput/s60videoeglrenderercontrol.h121
-rw-r--r--plugins/multimedia/symbian/videooutput/s60videoframerate.cpp101
-rw-r--r--plugins/multimedia/symbian/videooutput/s60videoframerate.h89
-rw-r--r--plugins/multimedia/symbian/videooutput/s60videooutputfactory.cpp116
-rw-r--r--plugins/multimedia/symbian/videooutput/s60videooutputfactory.h (renamed from plugins/multimedia/symbian/mmf/mediaplayer/s60videooutputinterface.h)41
-rw-r--r--plugins/multimedia/symbian/videooutput/videooutput.pri73
28 files changed, 2269 insertions, 230 deletions
diff --git a/plugins/multimedia/symbian/ecam/camera_s60.pri b/plugins/multimedia/symbian/ecam/camera_s60.pri
index c3d9164cca..2db67417fc 100644
--- a/plugins/multimedia/symbian/ecam/camera_s60.pri
+++ b/plugins/multimedia/symbian/ecam/camera_s60.pri
@@ -131,7 +131,7 @@ HEADERS += \
$$PWD/s60cameraengine.h \
$$PWD/s60cameraviewfinderengine.h \
$$PWD/s60cameraengineobserver.h \
- $$PWD/s60videorenderercontrol.h \
+ $$PWD/s60bitmapviewfinderrenderercontrol.h \
$$PWD/s60cameracapturedestinationcontrol.h \
$$PWD/s60cameracapturebufferformatcontrol.h \
$$PWD/s60filenamegenerator.h
@@ -158,7 +158,7 @@ SOURCES += \
$$PWD/s60cameraadvsettings.cpp \
$$PWD/s60cameraengine.cpp \
$$PWD/s60cameraviewfinderengine.cpp \
- $$PWD/s60videorenderercontrol.cpp \
+ $$PWD/s60bitmapviewfinderrenderercontrol.cpp \
$$PWD/s60cameracapturedestinationcontrol.cpp \
$$PWD/s60cameracapturebufferformatcontrol.cpp \
$$PWD/s60filenamegenerator.cpp
diff --git a/plugins/multimedia/symbian/ecam/s60videorenderercontrol.cpp b/plugins/multimedia/symbian/ecam/s60bitmapviewfinderrenderercontrol.cpp
index 3e488fe5d4..647158e199 100644
--- a/plugins/multimedia/symbian/ecam/s60videorenderercontrol.cpp
+++ b/plugins/multimedia/symbian/ecam/s60bitmapviewfinderrenderercontrol.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -41,36 +41,37 @@
#include <qabstractvideosurface.h>
-#include "s60videorenderercontrol.h"
+#include "s60bitmapviewfinderrenderercontrol.h"
-S60VideoRendererControl::S60VideoRendererControl(QObject *parent) :
+S60BitmapViewFinderRendererControl::S60BitmapViewFinderRendererControl(QObject *parent) :
QVideoRendererControl(parent),
m_surface(0)
{
}
-S60VideoRendererControl::~S60VideoRendererControl()
+S60BitmapViewFinderRendererControl::~S60BitmapViewFinderRendererControl()
{
// Stop surface if still active
if (m_surface && m_surface->isActive())
m_surface->stop();
}
-QAbstractVideoSurface *S60VideoRendererControl::surface() const
+QAbstractVideoSurface *S60BitmapViewFinderRendererControl::surface() const
{
return m_surface;
}
-void S60VideoRendererControl::setSurface(QAbstractVideoSurface *surface)
+void S60BitmapViewFinderRendererControl::setSurface(QAbstractVideoSurface *surface)
{
- if (surface == 0) {
- // Stop current surface if needed
- if (m_surface && m_surface->isActive())
- m_surface->stop();
+ if (m_surface != surface) {
+ if (surface == 0) {
+ // Stop current surface if needed
+ if (m_surface && m_surface->isActive())
+ m_surface->stop();
+ }
+ m_surface = surface;
+ emit surfaceChanged();
}
-
- m_surface = surface;
- emit viewFinderSurfaceSet();
}
// End of file
diff --git a/plugins/multimedia/symbian/ecam/s60videorenderercontrol.h b/plugins/multimedia/symbian/ecam/s60bitmapviewfinderrenderercontrol.h
index 9ef3332697..8cdd34ffba 100644
--- a/plugins/multimedia/symbian/ecam/s60videorenderercontrol.h
+++ b/plugins/multimedia/symbian/ecam/s60bitmapviewfinderrenderercontrol.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -39,38 +39,32 @@
**
****************************************************************************/
-#ifndef S60VIDEORENDERERCONTROL_H
-#define S60VIDEORENDERERCONTROL_H
+#ifndef S60BITMAPVIEWFINDERRENDERERCONTROL_H
+#define S60BITMAPVIEWFINDERRENDERERCONTROL_H
#include <qvideorenderercontrol.h>
/*
* Control for QGraphicsVideoItem. Viewfinder frames are streamed to a surface
- * which is drawn to the display by the Qt Graphics Vide Framework.
+ * which is drawn to the display by the Qt Graphics View Framework.
* VideoRendererControl uses only Bitmap Viewfinder.
*/
-class S60VideoRendererControl : public QVideoRendererControl
+class S60BitmapViewFinderRendererControl : public QVideoRendererControl
{
Q_OBJECT
+public:
+ S60BitmapViewFinderRendererControl(QObject *parent = 0);
+ virtual ~S60BitmapViewFinderRendererControl();
-public: // Constructor & Destructor
-
- S60VideoRendererControl(QObject *parent = 0);
- virtual ~S60VideoRendererControl();
-
-public: // S60VideoRendererControl
-
+ // S60VideoRendererControl
QAbstractVideoSurface *surface() const;
void setSurface(QAbstractVideoSurface *surface);
-signals: // Internal Signals
-
- void viewFinderSurfaceSet();
-
-private: // Data
+signals:
+ void surfaceChanged();
+private:
QAbstractVideoSurface *m_surface;
-
};
-#endif // S60VIDEORENDERERCONTROL_H
+#endif // S60VIEWFINDERRENDERERCONTROL_H
diff --git a/plugins/multimedia/symbian/ecam/s60cameraservice.cpp b/plugins/multimedia/symbian/ecam/s60cameraservice.cpp
index 48d977aefe..cc3c03e690 100644
--- a/plugins/multimedia/symbian/ecam/s60cameraservice.cpp
+++ b/plugins/multimedia/symbian/ecam/s60cameraservice.cpp
@@ -54,16 +54,20 @@
#include "s60mediarecordercontrol.h"
#include "s60videocapturesession.h"
#include "s60imagecapturesession.h"
-#include "s60videowidgetcontrol.h"
#include "s60mediacontainercontrol.h"
#include "s60videoencodercontrol.h"
#include "s60audioencodercontrol.h"
#include "s60imageencodercontrol.h"
#include "s60cameralockscontrol.h"
-#include "s60videorenderercontrol.h"
-#include "s60videowindowcontrol.h"
+#include "s60bitmapviewfinderrenderercontrol.h"
#include "s60cameracapturedestinationcontrol.h"
#include "s60cameracapturebufferformatcontrol.h"
+#include "s60videooutputfactory.h"
+#include "s60videowidgetcontrol.h"
+#include "s60videowindowcontrol.h"
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+#include "s60videoeglrenderercontrol.h"
+#endif
#include "s60cameraviewfinderengine.h" // ViewfinderOutputType
@@ -87,13 +91,12 @@ S60CameraService::S60CameraService(QObject *parent) :
m_mediaFormat = new S60MediaContainerControl(m_videosession, this);
m_videoEncoder = new S60VideoEncoderControl(m_videosession, this);
m_audioEncoder = new S60AudioEncoderControl(m_videosession, this);
- m_viewFinderWidget = new S60VideoWidgetControl(this);
m_imageEncoderControl = new S60ImageEncoderControl(m_imagesession, this);
m_locksControl = new S60CameraLocksControl(this, m_imagesession, this);
- m_rendererControl = new S60VideoRendererControl(this);
- m_windowControl = new S60VideoWindowControl(this);
+ m_bitmapRendererControl = new S60BitmapViewFinderRendererControl(this);
m_captureDestinationControl = new S60CameraCaptureDestinationControl(m_imagesession, this);
m_bufferFormatControl = new S60CameraCaptureBufferFormatControl(m_imagesession, this);
+ m_videoOutputFactory = new S60VideoOutputFactory(this);
}
}
@@ -135,15 +138,6 @@ S60CameraService::~S60CameraService()
if (m_control)
delete m_control;
- // Delete viewfinder controls after CameraControl to be sure that
- // ViewFinder gets stopped before widget (and window) is destroyed
- if (m_viewFinderWidget)
- delete m_viewFinderWidget;
- if (m_rendererControl)
- delete m_rendererControl;
- if (m_windowControl)
- delete m_windowControl;
-
// Delete sessions
if (m_videosession)
delete m_videosession;
@@ -174,36 +168,6 @@ QMediaControl *S60CameraService::requestControl(const char *name)
if (qstrcmp(name, QCameraFlashControl_iid) == 0)
return m_flashControl;
- if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
- if (m_viewFinderWidget) {
- m_control->setVideoOutput(m_viewFinderWidget,
- S60CameraViewfinderEngine::OutputTypeVideoWidget);
- return m_viewFinderWidget;
- } else {
- return 0;
- }
- }
-
- if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
- if (m_rendererControl) {
- m_control->setVideoOutput(m_rendererControl,
- S60CameraViewfinderEngine::OutputTypeRenderer);
- return m_rendererControl;
- } else {
- return 0;
- }
- }
-
- if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
- if (m_windowControl) {
- m_control->setVideoOutput(m_windowControl,
- S60CameraViewfinderEngine::OutputTypeVideoWindow);
- return m_windowControl;
- } else {
- return 0;
- }
- }
-
if (qstrcmp(name, QCameraFocusControl_iid) == 0)
return m_focusControl;
@@ -228,23 +192,38 @@ QMediaControl *S60CameraService::requestControl(const char *name)
if (qstrcmp(name, QCameraCaptureBufferFormatControl_iid) == 0)
return m_bufferFormatControl;
- return 0;
+ QMediaControl *videoOutputControl = m_videoOutputFactory->requestControl(name);
+ if (!videoOutputControl && qstrcmp(name, QVideoRendererControl_iid) == 0)
+ videoOutputControl = m_bitmapRendererControl;
+ if (qobject_cast<S60VideoWidgetControl *>(videoOutputControl))
+ m_control->setVideoOutput(videoOutputControl,
+ S60CameraViewfinderEngine::OutputTypeVideoWidget);
+ else if (qobject_cast<S60VideoWindowControl *>(videoOutputControl))
+ m_control->setVideoOutput(videoOutputControl,
+ S60CameraViewfinderEngine::OutputTypeVideoWindow);
+ else if (qobject_cast<S60BitmapViewFinderRendererControl *>(videoOutputControl)
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ || qobject_cast<S60VideoEglRendererControl *>(videoOutputControl)
+#endif
+ )
+ m_control->setVideoOutput(videoOutputControl,
+ S60CameraViewfinderEngine::OutputTypeRenderer);
+ return videoOutputControl;
}
void S60CameraService::releaseControl(QMediaControl *control)
{
- if (control == 0)
- return;
-
- // Release viewfinder output
- if (control == m_viewFinderWidget)
+ if (qobject_cast<S60VideoWidgetControl *>(control))
m_control->releaseVideoOutput(S60CameraViewfinderEngine::OutputTypeVideoWidget);
-
- if (control == m_rendererControl)
- m_control->releaseVideoOutput(S60CameraViewfinderEngine::OutputTypeRenderer);
-
- if (control == m_windowControl)
+ else if (qobject_cast<S60VideoWindowControl *>(control))
m_control->releaseVideoOutput(S60CameraViewfinderEngine::OutputTypeVideoWindow);
+ else if (qobject_cast<S60BitmapViewFinderRendererControl *>(control)
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ || qobject_cast<S60VideoEglRendererControl *>(control)
+#endif
+ )
+ m_control->releaseVideoOutput(S60CameraViewfinderEngine::OutputTypeRenderer);
+ m_videoOutputFactory->releaseControl(control);
}
int S60CameraService::deviceCount()
diff --git a/plugins/multimedia/symbian/ecam/s60cameraservice.h b/plugins/multimedia/symbian/ecam/s60cameraservice.h
index 9a4d9f7e1d..f275210e7c 100644
--- a/plugins/multimedia/symbian/ecam/s60cameraservice.h
+++ b/plugins/multimedia/symbian/ecam/s60cameraservice.h
@@ -60,13 +60,12 @@ QT_FORWARD_DECLARE_CLASS(S60CameraExposureControl)
QT_FORWARD_DECLARE_CLASS(S60CameraFlashControl)
QT_FORWARD_DECLARE_CLASS(S60CameraImageProcessingControl)
QT_FORWARD_DECLARE_CLASS(S60CameraImageCaptureControl)
-QT_FORWARD_DECLARE_CLASS(S60VideoWidgetControl)
QT_FORWARD_DECLARE_CLASS(S60ImageEncoderControl)
QT_FORWARD_DECLARE_CLASS(S60CameraLocksControl)
-QT_FORWARD_DECLARE_CLASS(S60VideoRendererControl)
-QT_FORWARD_DECLARE_CLASS(S60VideoWindowControl)
+QT_FORWARD_DECLARE_CLASS(S60BitmapViewFinderRendererControl)
QT_FORWARD_DECLARE_CLASS(S60CameraCaptureDestinationControl)
QT_FORWARD_DECLARE_CLASS(S60CameraCaptureBufferFormatControl)
+QT_FORWARD_DECLARE_CLASS(S60VideoOutputFactory)
class S60CameraService : public QMediaService
{
@@ -90,26 +89,25 @@ public: // Static Device Info
private: // Data
- S60ImageCaptureSession *m_imagesession;
- S60VideoCaptureSession *m_videosession;
- S60MediaContainerControl *m_mediaFormat;
- S60VideoEncoderControl *m_videoEncoder;
- S60AudioEncoderControl *m_audioEncoder;
- S60CameraControl *m_control;
- S60VideoDeviceControl *m_videoDeviceControl;
- S60CameraFocusControl *m_focusControl;
- S60CameraExposureControl *m_exposureControl;
- S60CameraFlashControl *m_flashControl;
- S60CameraImageProcessingControl *m_imageProcessingControl;
- S60CameraImageCaptureControl *m_imageCaptureControl;
- S60MediaRecorderControl *m_media;
- S60VideoWidgetControl *m_viewFinderWidget;
- S60ImageEncoderControl *m_imageEncoderControl;
- S60CameraLocksControl *m_locksControl;
- S60VideoRendererControl *m_rendererControl;
- S60VideoWindowControl *m_windowControl;
- S60CameraCaptureDestinationControl *m_captureDestinationControl;
+ S60ImageCaptureSession *m_imagesession;
+ S60VideoCaptureSession *m_videosession;
+ S60MediaContainerControl *m_mediaFormat;
+ S60VideoEncoderControl *m_videoEncoder;
+ S60AudioEncoderControl *m_audioEncoder;
+ S60CameraControl *m_control;
+ S60VideoDeviceControl *m_videoDeviceControl;
+ S60CameraFocusControl *m_focusControl;
+ S60CameraExposureControl *m_exposureControl;
+ S60CameraFlashControl *m_flashControl;
+ S60CameraImageProcessingControl *m_imageProcessingControl;
+ S60CameraImageCaptureControl *m_imageCaptureControl;
+ S60MediaRecorderControl *m_media;
+ S60ImageEncoderControl *m_imageEncoderControl;
+ S60CameraLocksControl *m_locksControl;
+ S60BitmapViewFinderRendererControl *m_bitmapRendererControl;
+ S60CameraCaptureDestinationControl *m_captureDestinationControl;
S60CameraCaptureBufferFormatControl *m_bufferFormatControl;
+ S60VideoOutputFactory *m_videoOutputFactory;
};
#endif // S60CAMERASERVICE_H
diff --git a/plugins/multimedia/symbian/ecam/s60cameraviewfinderengine.cpp b/plugins/multimedia/symbian/ecam/s60cameraviewfinderengine.cpp
index eedce8df88..b5b74edd7d 100644
--- a/plugins/multimedia/symbian/ecam/s60cameraviewfinderengine.cpp
+++ b/plugins/multimedia/symbian/ecam/s60cameraviewfinderengine.cpp
@@ -50,11 +50,17 @@
#include "s60cameracontrol.h"
#include "s60videowidgetcontrol.h"
#include "s60videowidgetdisplay.h"
-#include "s60videorenderercontrol.h"
+#include "s60bitmapviewfinderrenderercontrol.h"
#include "s60videowindowcontrol.h"
#include "s60videowindowdisplay.h"
#include "s60cameraconstants.h"
+#ifdef VIDEOOUTPUT_EGL_RENDERER
+#include <QTimer>
+#include "s60nativewindow.h"
+#include "s60videoeglrenderercontrol.h"
+#endif
+
#include <coemain.h> // CCoeEnv
#include <coecntrl.h> // CCoeControl
#include <w32std.h>
@@ -87,7 +93,8 @@ S60CameraViewfinderEngine::S60CameraViewfinderEngine(S60CameraControl *control,
m_viewfinderType(OutputTypeNotSet),
m_viewfinderNativeType(EBitmapViewFinder), // Default type
m_isViewFinderVisible(true),
- m_vfErrorsSignalled(0)
+ m_vfErrorsSignalled(0),
+ m_dummyWindow(0)
{
m_cameraControl = control;
@@ -105,6 +112,14 @@ S60CameraViewfinderEngine::S60CameraViewfinderEngine(S60CameraControl *control,
}
// From now on it is safe to assume engine exists
+#ifdef VIDEOOUTPUT_EGL_RENDERER
+ // CCamera provides no API for starting the viewfinder (and therefore
+ // creating a viewfinder surface) without passing a native window
+ // handle. We therefore create an invisible window, pass this to
+ // CCamera and then extract from it the background surface handle.
+ m_dummyWindow = new S60NativeWindow(this);
+#endif
+
// Detect UI Rotations
connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(handleDesktopResize(int)));
}
@@ -216,14 +231,18 @@ void S60CameraViewfinderEngine::setVideoRendererControl(QObject *viewfinderOutpu
if (m_viewfinderOutput)
releaseControl(m_viewfinderType);
- S60VideoRendererControl* viewFinderRenderControl =
- qobject_cast<S60VideoRendererControl*>(viewfinderOutput);
+ QVideoRendererControl *rendererControl =
+ qobject_cast<QVideoRendererControl *>(viewfinderOutput);
- if (viewFinderRenderControl) {
- m_viewfinderNativeType = EBitmapViewFinder; // Always Bitmap
+ if (rendererControl) {
+ m_viewfinderNativeType = EBitmapViewFinder;
+#ifdef VIDEOOUTPUT_EGL_RENDERER
+ if (qobject_cast<S60VideoEglRendererControl *>(rendererControl))
+ m_viewfinderNativeType = EDirectScreenViewFinder;
+#endif
- connect(viewFinderRenderControl, SIGNAL(viewFinderSurfaceSet()),
- this, SLOT(rendererSurfaceSet()));
+ connect(rendererControl, SIGNAL(surfaceChanged()),
+ this, SLOT(rendererSurfaceChanged()));
m_viewfinderOutput = viewfinderOutput;
m_viewfinderType = OutputTypeRenderer;
@@ -255,8 +274,8 @@ void S60CameraViewfinderEngine::setVideoRendererControl(QObject *viewfinderOutpu
if (m_vfState == EVFIsConnectedIsStartedIsVisible)
startViewfinder(true, false);
- if (viewFinderRenderControl->surface())
- rendererSurfaceSet();
+ if (rendererControl->surface())
+ rendererSurfaceChanged();
}
}
@@ -326,6 +345,9 @@ void S60CameraViewfinderEngine::setVideoWindowControl(QObject *viewfinderOutput)
void S60CameraViewfinderEngine::releaseControl(ViewfinderOutputType type)
{
+ if (m_viewfinderType != type)
+ return;
+
if (m_vfState == EVFIsConnectedIsStartedIsVisible)
stopViewfinder(true, false);
@@ -426,17 +448,32 @@ void S60CameraViewfinderEngine::startViewfinder(bool internalStart, bool suppres
return;
if (m_viewfinderNativeType == EDirectScreenViewFinder) {
+ m_window = 0;
+ QRect extentRect;
+ QRect clipRect;
- if (RWindow *window = m_viewfinderDisplay ? m_viewfinderDisplay->windowHandle() : 0) {
- m_window = window;
- } else {
+ if (m_viewfinderDisplay) {
+ m_window = m_viewfinderDisplay->windowHandle();
+ extentRect = m_viewfinderDisplay->extentRect();
+ clipRect = m_viewfinderDisplay->clipRect();
+ }
+#ifdef VIDEOOUTPUT_EGL_RENDERER
+ else if (qobject_cast<S60VideoEglRendererControl *>(m_viewfinderOutput)) {
+ m_window = m_dummyWindow->windowHandle();
+ QSize windowSize;
+ if (m_window)
+ windowSize = QSize(m_window->Size().iWidth, m_window->Size().iHeight);
+ extentRect = QRect(QPoint(0, 0), windowSize);
+ clipRect = extentRect;
+ }
+#endif
+
+ if (!m_window) {
emit error(QCamera::CameraError, tr("Requesting window for viewfinder failed."));
qWarning("Requesting window for viewfinder failed. Viewfinder may not be visible.");
return;
}
- const QRect extentRect = m_viewfinderDisplay ? m_viewfinderDisplay->extentRect() : QRect();
- const QRect clipRect = m_viewfinderDisplay ? m_viewfinderDisplay->clipRect() : QRect();
TRect extentRectSymbian = qRect2TRect(extentRect);
TRect clipRectSymbian = qRect2TRect(clipRect);
@@ -447,6 +484,15 @@ void S60CameraViewfinderEngine::startViewfinder(bool internalStart, bool suppres
else
emit error(QCamera::CameraError, tr("Starting viewfinder failed."));
return;
+ } else {
+#ifdef VIDEOOUTPUT_EGL_RENDERER
+ if (qobject_cast<S60VideoEglRendererControl *>(m_viewfinderOutput))
+ // Temporary workaround for a bug in the BCM2727 graphics driver
+ // Without this delay, images acquired from the EGL endpoint all
+ // contain the same data, which may be a valid viewfinder frame,
+ // or may be garbage.
+ QTimer::singleShot(500, this, SLOT(setRendererNativeSurface()));
+#endif
}
m_actualViewFinderSize = QSize(extentRectSymbian.Size().iWidth, extentRectSymbian.Size().iHeight);
@@ -515,6 +561,17 @@ void S60CameraViewfinderEngine::startViewfinder(bool internalStart, bool suppres
m_viewfinderDisplay->setHasContent(true);
}
+void S60CameraViewfinderEngine::setRendererNativeSurface()
+{
+#ifdef VIDEOOUTPUT_EGL_RENDERER
+ S60VideoEglRendererControl *rendererControl =
+ qobject_cast<S60VideoEglRendererControl *>(m_viewfinderOutput);
+ const QSize windowSize(m_window->Size().iWidth, m_window->Size().iHeight);
+ rendererControl->setNativeSize(windowSize);
+ rendererControl->setNativeSurface(m_dummyWindow->nativeSurface());
+#endif
+}
+
void S60CameraViewfinderEngine::stopViewfinder(const bool internalStop, bool suppressHasContentChanged)
{
// Stop if viewfinder is started
@@ -548,6 +605,8 @@ void S60CameraViewfinderEngine::stopViewfinder(const bool internalStop, bool sup
}
}
+ m_window = 0;
+
if (m_viewfinderDisplay && !suppressHasContentChanged)
m_viewfinderDisplay->setHasContent(false);
}
@@ -606,57 +665,55 @@ void S60CameraViewfinderEngine::resetViewfinderDisplay()
}
}
-void S60CameraViewfinderEngine::rendererSurfaceSet()
+void S60CameraViewfinderEngine::rendererSurfaceChanged()
{
- S60VideoRendererControl* viewFinderRenderControl =
- qobject_cast<S60VideoRendererControl*>(m_viewfinderOutput);
+ QVideoRendererControl *rendererControl =
+ qobject_cast<QVideoRendererControl*>(m_viewfinderOutput);
+ Q_ASSERT(rendererControl);
// Reset old surface if needed
if (m_viewfinderSurface) {
handleVisibilityChange(false);
disconnect(m_viewfinderSurface);
- if (viewFinderRenderControl->surface())
- stopViewfinder(true); // Temporary stop
- else
- stopViewfinder(); // Stop for good
+ stopViewfinder(true);
m_viewfinderSize = QApplication::desktop()->screenGeometry().size();
m_viewfinderSurface = 0;
}
- // Set new surface
- m_viewfinderSurface = viewFinderRenderControl->surface();
- if (!m_viewfinderSurface)
- return;
- if (!m_viewfinderSurface->nativeResolution().isEmpty()) {
- if (m_viewfinderSurface->nativeResolution() != m_viewfinderSize)
- resetViewfinderSize(m_viewfinderSurface->nativeResolution());
- }
-
- connect(m_viewfinderSurface, SIGNAL(nativeResolutionChanged(const QSize&)),
- this, SLOT(resetViewfinderSize(QSize)));
+ m_viewfinderSurface = rendererControl->surface();
+ if (m_viewfinderSurface) {
+ // Set new surface
+ if (!m_viewfinderSurface->nativeResolution().isEmpty())
+ if (m_viewfinderSurface->nativeResolution() != m_viewfinderSize)
+ resetViewfinderSize(m_viewfinderSurface->nativeResolution());
+
+ connect(m_viewfinderSurface, SIGNAL(nativeResolutionChanged(const QSize&)),
+ this, SLOT(resetViewfinderSize(QSize)));
+
+ // Set Surface Properties
+ if (m_viewfinderSurface->supportedPixelFormats().contains(QVideoFrame::Format_RGB32))
+ m_surfaceFormat = QVideoSurfaceFormat(m_actualViewFinderSize, QVideoFrame::Format_RGB32);
+ else if (m_viewfinderSurface->supportedPixelFormats().contains(QVideoFrame::Format_ARGB32))
+ m_surfaceFormat = QVideoSurfaceFormat(m_actualViewFinderSize, QVideoFrame::Format_ARGB32);
+ else {
+ return;
+ }
+ m_surfaceFormat.setFrameRate(KViewfinderFrameRate);
+ m_surfaceFormat.setYCbCrColorSpace(QVideoSurfaceFormat::YCbCr_Undefined); // EColor16MU (compatible with EColor16MA)
+ m_surfaceFormat.setPixelAspectRatio(1,1); // PAR 1:1
- // Set Surface Properties
- if (m_viewfinderSurface->supportedPixelFormats().contains(QVideoFrame::Format_RGB32))
- m_surfaceFormat = QVideoSurfaceFormat(m_actualViewFinderSize, QVideoFrame::Format_RGB32);
- else if (m_viewfinderSurface->supportedPixelFormats().contains(QVideoFrame::Format_ARGB32))
- m_surfaceFormat = QVideoSurfaceFormat(m_actualViewFinderSize, QVideoFrame::Format_ARGB32);
- else {
- return;
+ if (qobject_cast<S60BitmapViewFinderRendererControl *>(rendererControl))
+ connect(this, SIGNAL(viewFinderFrameReady(const CFbsBitmap &)),
+ this, SLOT(viewFinderBitmapReady(const CFbsBitmap &)));
}
- m_surfaceFormat.setFrameRate(KViewfinderFrameRate);
- m_surfaceFormat.setYCbCrColorSpace(QVideoSurfaceFormat::YCbCr_Undefined); // EColor16MU (compatible with EColor16MA)
- m_surfaceFormat.setPixelAspectRatio(1,1); // PAR 1:1
-
- connect(this, SIGNAL(viewFinderFrameReady(const CFbsBitmap &)),
- this, SLOT(viewFinderBitmapReady(const CFbsBitmap &)));
-
- // Surface set, viewfinder is "visible"
- handleVisibilityChange(true);
+ handleVisibilityChange(m_viewfinderSurface != 0);
}
void S60CameraViewfinderEngine::viewFinderBitmapReady(const CFbsBitmap &bitmap)
{
+ Q_ASSERT(qobject_cast<S60BitmapViewFinderRendererControl *>(m_viewfinderOutput));
+
CFbsBitmap *bitmapPtr = const_cast<CFbsBitmap*>(&bitmap);
QPixmap pixmap = QPixmap::fromSymbianCFbsBitmap(bitmapPtr);
diff --git a/plugins/multimedia/symbian/ecam/s60cameraviewfinderengine.h b/plugins/multimedia/symbian/ecam/s60cameraviewfinderengine.h
index 5eac701eb1..005ac26714 100644
--- a/plugins/multimedia/symbian/ecam/s60cameraviewfinderengine.h
+++ b/plugins/multimedia/symbian/ecam/s60cameraviewfinderengine.h
@@ -53,6 +53,7 @@ QT_FORWARD_DECLARE_CLASS(S60CameraControl)
QT_FORWARD_DECLARE_CLASS(QAbstractVideoSurface)
QT_FORWARD_DECLARE_CLASS(QDesktopWidget)
QT_FORWARD_DECLARE_CLASS(S60VideoDisplay)
+QT_FORWARD_DECLARE_CLASS(S60NativeWindow)
// For DirectScreen ViewFinder
QT_FORWARD_DECLARE_CLASS(RWsSession)
@@ -122,7 +123,8 @@ private slots:
void handleWindowChange(RWindow *handle);
void handleDesktopResize(int screen);
void handleContentAspectRatioChange(const QSize& newSize);
- void rendererSurfaceSet();
+ void rendererSurfaceChanged();
+ void setRendererNativeSurface();
private: // Enums
@@ -171,6 +173,7 @@ private: // Data
QVideoSurfaceFormat m_surfaceFormat; // Used only by QVideoRendererControl
bool m_isViewFinderVisible;
int m_vfErrorsSignalled;
+ S60NativeWindow *m_dummyWindow;
};
#endif // S60CAMERAVIEWFINDERENGINE_H
diff --git a/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayercontrol.cpp b/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayercontrol.cpp
index cb7b556867..8cab27e8cf 100644
--- a/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayercontrol.cpp
+++ b/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayercontrol.cpp
@@ -379,6 +379,11 @@ void S60MediaPlayerControl::setVideoOutput(QObject *output)
m_session->setVideoRenderer(output);
}
+QObject *S60MediaPlayerControl::videoOutput() const
+{
+ return m_mediaSettings.videoOutput();
+}
+
/*!
* \return TRUE if Audio available or else FALSE.
*/
diff --git a/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayercontrol.h b/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayercontrol.h
index e929a6ed09..7fde62867c 100644
--- a/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayercontrol.h
+++ b/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayercontrol.h
@@ -136,6 +136,7 @@ public:
// Own methods
S60MediaPlayerSession* session();
void setVideoOutput(QObject *output);
+ QObject *videoOutput() const;
const S60MediaSettings& mediaControlSettings() const;
void setAudioEndpoint(const QString& name);
void setMediaType(S60MediaSettings::TMediaType type);
diff --git a/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayerservice.cpp b/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayerservice.cpp
index 7b32d8de28..51d9f5b4f2 100644
--- a/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayerservice.cpp
+++ b/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayerservice.cpp
@@ -49,8 +49,7 @@
#include "s60audioplayersession.h"
#include "s60mediametadataprovider.h"
#include "s60mediarecognizer.h"
-#include "s60videowidgetcontrol.h"
-#include "s60videowindowcontrol.h"
+#include "s60videooutputfactory.h"
#include "s60mediaplayeraudioendpointselector.h"
#include "s60medianetworkaccesscontrol.h"
#include "s60mediastreamcontrol.h"
@@ -65,12 +64,12 @@
S60MediaPlayerService::S60MediaPlayerService(QObject *parent)
: QMediaService(parent)
- , m_control(NULL)
- , m_metaData(NULL)
- , m_audioEndpointSelector(NULL)
- , m_streamControl(NULL)
- , m_networkAccessControl(NULL)
- , m_videoOutput(NULL)
+ , m_control(0)
+ , m_metaData(0)
+ , m_audioEndpointSelector(0)
+ , m_streamControl(0)
+ , m_networkAccessControl(0)
+ , m_videoOutputFactory(0)
{
TRACE("S60MediaPlayerService::S60MediaPlayerService" << qtThisPtr());
@@ -79,6 +78,7 @@ S60MediaPlayerService::S60MediaPlayerService(QObject *parent)
m_audioEndpointSelector = new S60MediaPlayerAudioEndpointSelector(m_control, this);
m_streamControl = new S60MediaStreamControl(m_control, this);
m_networkAccessControl = new S60MediaNetworkAccessControl(this);
+ m_videoOutputFactory = new S60VideoOutputFactory(this);
}
/*!
@@ -119,24 +119,12 @@ QMediaControl *S60MediaPlayerService::requestControl(const char *name)
if (qstrcmp(name, QMediaStreamsControl_iid) == 0)
result = m_streamControl;
- if (!m_videoOutput) {
- if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
- m_videoOutput = new S60VideoWidgetControl(this);
- }
- else if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
- m_videoOutput = new S60VideoWindowControl(this);
- }
-
- if (m_videoOutput) {
- m_control->setVideoOutput(m_videoOutput);
- result = m_videoOutput;
- }
- }else {
- if (qstrcmp(name, QVideoWidgetControl_iid) == 0 ||
- qstrcmp(name, QVideoWindowControl_iid) == 0){
- result = m_videoOutput;
- }
+ if (!result) {
+ result = m_videoOutputFactory->requestControl(name);
+ if (result)
+ m_control->setVideoOutput(result);
}
+
TRACE("S60MediaPlayerService::requestControl" << qtThisPtr()
<< "name" << name << "result" << result);
return result;
@@ -151,10 +139,9 @@ void S60MediaPlayerService::releaseControl(QMediaControl *control)
TRACE("S60MediaPlayerService::releaseControl" << qtThisPtr()
<< "control" << control);
- if (control == m_videoOutput) {
- m_videoOutput = 0;
- m_control->setVideoOutput(m_videoOutput);
- }
+ if (m_control->videoOutput() == control)
+ m_control->setVideoOutput(0);
+ m_videoOutputFactory->releaseControl(control);
}
/*!
diff --git a/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayerservice.h b/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayerservice.h
index 4b2685a94b..ec39a8d2a8 100644
--- a/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayerservice.h
+++ b/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayerservice.h
@@ -61,6 +61,7 @@ class S60MediaPlayerControl;
class S60MediaMetaDataProvider;
class S60MediaStreamControl;
class S60MediaRecognizer;
+class S60VideoOutputFactory;
class QMediaContent;
class QMediaPlaylistNavigator;
@@ -90,7 +91,7 @@ private:
S60MediaPlayerAudioEndpointSelector *m_audioEndpointSelector;
S60MediaStreamControl *m_streamControl;
S60MediaNetworkAccessControl *m_networkAccessControl;
- QMediaControl *m_videoOutput;
+ S60VideoOutputFactory *m_videoOutputFactory;
};
#endif
diff --git a/plugins/multimedia/symbian/mmf/mediaplayer/s60videoplayersession.cpp b/plugins/multimedia/symbian/mmf/mediaplayer/s60videoplayersession.cpp
index 43d40553dd..0bac88660e 100644
--- a/plugins/multimedia/symbian/mmf/mediaplayer/s60videoplayersession.cpp
+++ b/plugins/multimedia/symbian/mmf/mediaplayer/s60videoplayersession.cpp
@@ -47,6 +47,11 @@
#include "s60videowindowdisplay.h"
#include "s60mmtrace.h"
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+#include "s60videoeglrenderercontrol.h"
+#include "s60nativewindow.h"
+#endif
+
#include <QtCore/QTimer>
#include <QtGui/QApplication>
#include <QtGui/QDesktopWidget>
@@ -160,7 +165,9 @@ S60VideoPlayerSession::S60VideoPlayerSession(QMediaService *service, S60MediaNet
, m_screenDevice(CCoeEnv::Static()->ScreenDevice())
, m_service(service)
, m_player(0)
-#ifndef VIDEOOUTPUT_GRAPHICS_SURFACES
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ , m_nativeSurface(TSurfaceId::CreateNullId())
+#else
, m_dsaActive(false)
, m_dsaStopped(false)
#endif
@@ -187,6 +194,9 @@ S60VideoPlayerSession::S60VideoPlayerSession(QMediaService *service, S60MediaNet
EMdaPriorityPreferenceNone
));
m_player->RegisterForVideoLoadingNotification(*this);
+ m_dummyWindow = new S60NativeWindow(this);
+ connect(this, SIGNAL(nativeSurfaceChanged(TSurfaceId)),
+ m_dummyWindow, SLOT(setNativeSurface(TSurfaceId)));
#else
RWindow *window = 0;
QRect extentRect;
@@ -351,6 +361,10 @@ void S60VideoPlayerSession::setVideoRenderer(QObject *videoOutput)
TRACE("S60VideoPlayerSession::setVideoRenderer" << qtThisPtr()
<< "output" << videoOutput);
if (videoOutput != m_videoOutputControl) {
+ if (m_videoOutputControl) {
+ disconnect(m_videoOutputControl);
+ m_videoOutputControl->disconnect(this);
+ }
if (m_videoOutputDisplay) {
m_videoOutputDisplay->setHasContent(false);
disconnect(m_videoOutputDisplay);
@@ -358,10 +372,21 @@ void S60VideoPlayerSession::setVideoRenderer(QObject *videoOutput)
m_videoOutputDisplay = 0;
}
if (videoOutput) {
+ TRACE("S60VideoPlayerSession::setVideoRenderer output" << videoOutput);
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ if (S60VideoEglRendererControl *control = qobject_cast<S60VideoEglRendererControl *>(videoOutput)) {
+ control->setNativeSurface(m_nativeSurface);
+ control->setNativeSize(m_nativeSize);
+ connect(this, SIGNAL(nativeSurfaceChanged(TSurfaceId)), control, SLOT(setNativeSurface(TSurfaceId)));
+ connect(this, SIGNAL(nativeSizeChanged(QSize)), control, SLOT(setNativeSize(QSize)));
+ }
+ else
+#endif
if (S60VideoWidgetControl *control = qobject_cast<S60VideoWidgetControl *>(videoOutput))
m_videoOutputDisplay = control->display();
else if (S60VideoWindowControl *control = qobject_cast<S60VideoWindowControl *>(videoOutput))
m_videoOutputDisplay = control->display();
+ TRACE("S60VideoPlayerSession::setVideoRenderer display" << m_videoOutputDisplay);
if (m_videoOutputDisplay) {
m_videoOutputDisplay->setHasContent(QMediaPlayer::PlayingState == state());
m_videoOutputDisplay->setNativeSize(m_nativeSize);
@@ -576,6 +601,10 @@ void S60VideoPlayerSession::doClose()
m_player->Close();
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ m_nativeSurface = TSurfaceId::CreateNullId();
+#endif
+
// close will remove the window handle in media clint video.
// So mark it in pending changes.
m_pendingChanges |= WindowHandle;
@@ -708,8 +737,25 @@ void S60VideoPlayerSession::MvpuoPrepareComplete(TInt aError)
} else {
m_isaudiostream = false;
}
- applyPendingChanges(true); // force apply even though state is not Loaded
- if (KErrNone == this->error()) // applyPendingChanges() can call setError()
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ // Register for callbacks via MMMFSurfaceEventHandler
+ TRAP(error, m_player->AddDisplayL(*m_wsSession,
+ m_screenDevice->GetScreenNumber(),
+ *this));
+ if (!error)
+ // When switching from the 'direct' video rendering path (which
+ // sets the video surface as the background of a native window)
+ // to the EGL rendering path (which uses EGL endpoint to extract
+ // video frames as EGL images), the native window is first removed,
+ // then the EGL endpoint is created. In order to prevent the MMF
+ // from destroying the video surface when the window is removed,
+ // we must also provide a dummy, non-displayed window handle.
+ TRAP(error, m_player->AddDisplayWindowL(*m_wsSession, *m_screenDevice,
+ *m_dummyWindow->windowHandle(),
+ TRect(), TRect()));
+#endif
+ applyPendingChanges(true); // force apply even though state is not Loaded
+ if (KErrNone == error && KErrNone == this->error()) // applyPendingChanges() can call setError()
loaded();
}
} else {
@@ -766,6 +812,39 @@ void S60VideoPlayerSession::MvpuoEvent(const TMMFEvent &aEvent)
}
}
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+void S60VideoPlayerSession::MmsehSurfaceCreated(TInt aDisplayId, const TSurfaceId& aId,
+ const TRect& aCropRect,
+ TVideoAspectRatio aAspectRatio)
+{
+ TRACE("S60VideoPlayerSession::MmsehSurfaceCreated" << qtThisPtr() << "id" << (void*)aId.iInternal[3]);
+ Q_UNUSED(aCropRect)
+ Q_UNUSED(aAspectRatio)
+ Q_ASSERT(m_nativeSurface.IsNull());
+ m_nativeSurface = aId;
+ emit nativeSurfaceChanged(m_nativeSurface);
+}
+
+void S60VideoPlayerSession::MmsehSurfaceParametersChanged(const TSurfaceId& aId,
+ const TRect& aCropRect,
+ TVideoAspectRatio aAspectRatio)
+{
+ TRACE("S60VideoPlayerSession::MmsehSurfaceParametersChanged" << qtThisPtr() << "id" << (void*)aId.iInternal[3]);
+ Q_UNUSED(aId)
+ Q_UNUSED(aCropRect)
+ Q_UNUSED(aAspectRatio)
+}
+
+void S60VideoPlayerSession::MmsehRemoveSurface(const TSurfaceId& aId)
+{
+ TRACE("S60VideoPlayerSession::MmsehRemoveSurface" << qtThisPtr() << "id" << (void*)aId.iInternal[3]);
+ if (aId == m_nativeSurface) {
+ m_nativeSurface = TSurfaceId::CreateNullId();
+ emit nativeSurfaceChanged(m_nativeSurface);
+ }
+}
+#endif // VIDEOOUTPUT_GRAPHICS_SURFACES
+
/*!
Updates meta data entries in the current video clip.
diff --git a/plugins/multimedia/symbian/mmf/mediaplayer/s60videoplayersession.h b/plugins/multimedia/symbian/mmf/mediaplayer/s60videoplayersession.h
index 79df6aabd1..163daf8721 100644
--- a/plugins/multimedia/symbian/mmf/mediaplayer/s60videoplayersession.h
+++ b/plugins/multimedia/symbian/mmf/mediaplayer/s60videoplayersession.h
@@ -49,6 +49,8 @@
#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
#include <videoplayer2.h>
+#include <graphics/surface.h>
+#include <surfaceeventhandler.h>
#else
#include <videoplayer.h>
#endif // VIDEOOUTPUT_GRAPHICS_SURFACES
@@ -64,6 +66,7 @@
class QTimer;
class S60MediaNetworkAccessControl;
+class S60NativeWindow;
class S60VideoDisplay;
// Helper classes to pass Symbian events from WServ to the S60VideoPlayerSession
@@ -95,6 +98,9 @@ private:
class S60VideoPlayerSession : public S60MediaPlayerSession
, public MVideoPlayerUtilityObserver
, public MVideoLoadingObserver
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ , public MMMFSurfaceEventHandler
+#endif
#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
, public MAudioOutputObserver
#endif // HAS_AUDIOROUTING_IN_VIDEOPLAYER
@@ -130,6 +136,9 @@ public:
signals:
void nativeSizeChanged(QSize);
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ void nativeSurfaceChanged(TSurfaceId surface);
+#endif
public Q_SLOTS:
void setActiveEndpoint(const QString& name);
@@ -181,6 +190,17 @@ private:
void MvpuoPlayComplete(TInt aError);
void MvpuoEvent(const TMMFEvent &aEvent);
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ // MMMFSurfaceEventHandler
+ void MmsehSurfaceCreated(TInt aDisplayId, const TSurfaceId& aId,
+ const TRect& aCropRect,
+ TVideoAspectRatio aAspectRatio);
+ void MmsehSurfaceParametersChanged(const TSurfaceId& aId,
+ const TRect& aCropRect,
+ TVideoAspectRatio aAspectRatio);
+ void MmsehRemoveSurface(const TSurfaceId& aId);
+#endif
+
private:
int m_accessPointId;
S60MediaNetworkAccessControl* m_networkAccessControl;
@@ -189,6 +209,8 @@ private:
QMediaService *const m_service;
#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
CVideoPlayerUtility2 *m_player;
+ TSurfaceId m_nativeSurface;
+ S60NativeWindow *m_dummyWindow;
#else
CVideoPlayerUtility *m_player;
bool m_dsaActive;
diff --git a/plugins/multimedia/symbian/videooutput/s60eglendpoint.cpp b/plugins/multimedia/symbian/videooutput/s60eglendpoint.cpp
new file mode 100644
index 0000000000..c2bb7f79f1
--- /dev/null
+++ b/plugins/multimedia/symbian/videooutput/s60eglendpoint.cpp
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** qtThisPtr() file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "s60eglendpoint.h"
+#include "s60eglextensions.h"
+#include "s60mmtrace.h"
+#include <e32base.h>
+#include <egl/egl.h>
+#include <graphics/surface.h>
+#include <QtCore/QDebug>
+#include <QtCore/QTime>
+
+//-----------------------------------------------------------------------------
+// S60EglEndpointEventHandler
+//-----------------------------------------------------------------------------
+
+class S60EglEndpointEventHandler : public CActive
+{
+public:
+ static S60EglEndpointEventHandler *NewL(S60EglEndpoint *parent);
+ ~S60EglEndpointEventHandler();
+ void request();
+
+private:
+ S60EglEndpointEventHandler(S60EglEndpoint *parent);
+ void RunL();
+ void DoCancel();
+
+private:
+ S60EglEndpoint *const m_parent;
+};
+
+S60EglEndpointEventHandler *S60EglEndpointEventHandler::NewL(S60EglEndpoint *parent)
+{
+ S60EglEndpointEventHandler *self = new (ELeave) S60EglEndpointEventHandler(parent);
+ CActiveScheduler::Add(self);
+ return self;
+}
+
+S60EglEndpointEventHandler::S60EglEndpointEventHandler(S60EglEndpoint *parent)
+ : CActive(EPriorityStandard)
+ , m_parent(parent)
+{
+
+}
+
+S60EglEndpointEventHandler::~S60EglEndpointEventHandler()
+{
+ Cancel();
+}
+
+void S60EglEndpointEventHandler::request()
+{
+ TRACE("S60EglEndpointEventHandler::request" << qtThisPtr());
+ Q_ASSERT(!IsActive());
+ iStatus = KRequestPending;
+ EGLTRequestStatusNOK eglStatus = reinterpret_cast<EGLTRequestStatusNOK>(&iStatus);
+ const EGLBoolean ret = m_parent->m_extensions->endpointRequestNotification(m_parent->m_display,
+ m_parent->m_endpoint,
+ eglStatus);
+ if (ret) {
+ VERBOSE_TRACE("S60EglEndpointEventHandler::request" << qtThisPtr() << "endpointRequestNotification OK");
+ SetActive();
+ } else {
+ qWarning() << "S60EglEndpointEventHandler::request" << qtThisPtr() << "endpointRequestNotification failed";
+ }
+}
+
+void S60EglEndpointEventHandler::RunL()
+{
+ VERBOSE_TRACE("S60EglEndpointEventHandler::RunL" << qtThisPtr());
+ m_parent->endpointEvent();
+}
+
+void S60EglEndpointEventHandler::DoCancel()
+{
+ TRACE("S60EglEndpointEventHandler::DoCancel" << qtThisPtr());
+ m_parent->m_extensions->endpointCancelNotification(m_parent->m_display,
+ m_parent->m_endpoint);
+}
+
+//-----------------------------------------------------------------------------
+// S60EglEndpoint
+//-----------------------------------------------------------------------------
+
+S60EglEndpoint::S60EglEndpoint(const TSurfaceId &surface,
+ S60EglExtensions *extensions,
+ QObject *parent)
+ : QObject(parent)
+ , m_extensions(extensions)
+ , m_context(eglGetCurrentContext())
+ , m_api(0)
+ , m_display(eglGetCurrentDisplay())
+ , m_endpoint(EGL_NO_ENDPOINT_NOK)
+ , m_state(Null)
+{
+ TRACE("S60EglEndpoint::S60EglEndpoint" << qtThisPtr()
+ << "surface" << (void*)surface.iInternal[3]
+ << "context" << m_context << "display" << m_display);
+ Q_ASSERT(m_extensions);
+ bool ok = false;
+ if (m_context) {
+ m_api = eglQueryAPI();
+ if (m_api) {
+ m_display = eglGetCurrentDisplay();
+ if (EGL_NO_DISPLAY != m_display) {
+ ok = true;
+ } else {
+ qWarning() << "S60EglEndpoint::S60EglEndpoint" << qtThisPtr() << "failed to get valid EGL display";
+ }
+ } else {
+ qWarning() << "S60EglEndpoint::S60EglEndpoint" << qtThisPtr() << "failed to get valid rendering API";
+ }
+ } else {
+ qWarning() << "S60EglEndpoint::S60EglEndpoint" << qtThisPtr() << "failed to get valid EGL context";
+ }
+ if (ok) {
+ static const EGLenum type = EGL_ENDPOINT_TYPE_CONSUMER_NOK;
+ static const EGLenum sourceType = EGL_TSURFACEID_NOK;
+ TSurfaceId localSurface = surface;
+ EGLEndpointSourceNOK source = reinterpret_cast<EGLEndpointSourceNOK>(&localSurface);
+ static const EGLint *attributes = 0;
+ m_endpoint = m_extensions->createEndpoint(m_display, type, sourceType, source, attributes);
+ const EGLint error = eglGetError();
+ if (EGL_SUCCESS == error) {
+ TRACE("S60EglEndpoint::S60EglEndpoint" << qtThisPtr()
+ << "endpoint" << m_endpoint);
+ if (EGL_NO_ENDPOINT_NOK == m_endpoint) {
+ qWarning() << "S60EglEndpoint::S60EglEndpoint" << qtThisPtr() << "failed to create EGL endpoint";
+ } else {
+ TRAPD(err, m_eventHandler.reset(S60EglEndpointEventHandler::NewL(this)));
+ if (err) {
+ qWarning() << "S60EglEndpoint::S60EglEndpoint" << qtThisPtr() << "failed to create EGL endpoint event handler: error" << err;
+ } else {
+ m_state = Created;
+ EGLBoolean ready = m_extensions->getEndpointAttrib(m_display, m_endpoint, EGL_ENDPOINT_READY_NOK);
+ TRACE("S60EglEndpoint::S60EglEndpoint" << qtThisPtr() << "ready" << ready);
+ if (ready) {
+ // Producer has already submitted content to the source surface
+ m_state = Active;
+ m_eventHandler->request();
+ } else {
+ // Request notification when producer has submitted content
+ m_eventHandler->request();
+ }
+ }
+ }
+ } else {
+ qWarning() << "S60EglEndpoint::S60EglEndpoint" << qtThisPtr() << "failed to create EGL endpoint: error" << error;
+ }
+ }
+}
+
+S60EglEndpoint::~S60EglEndpoint()
+{
+ TRACE("S60EglEndpoint::~S60EglEndpoint" << qtThisPtr());
+ if (EGL_NO_ENDPOINT_NOK != m_endpoint)
+ m_extensions->destroyEndpoint(m_display, m_endpoint);
+}
+
+void S60EglEndpoint::endpointEvent()
+{
+ const EGLBoolean ready = m_extensions->getEndpointAttrib(m_display, m_endpoint, EGL_ENDPOINT_READY_NOK);
+ VERBOSE_TRACE("S60EglEndpoint::endpointEvent" << qtThisPtr() << "state" << m_state << "ready" << ready);
+ switch (m_state) {
+ case Created:
+ m_state = Active;
+ case Active:
+ emit imageAvailable();
+ break;
+ case Null:
+ default:
+ Q_ASSERT(false);
+ break;
+ }
+}
+
+bool S60EglEndpoint::isValid() const
+{
+ return (m_state != Null);
+}
+
+void S60EglEndpoint::setDelay(qint64 delay)
+{
+ VERBOSE_TRACE("S60EglEndpoint::setDelay" << qtThisPtr() << "delay" << delay);
+ m_extensions->setEndpointAttrib(m_display, m_endpoint, EGL_DELAY_NOK, delay);
+}
+
+EGLImageKHR S60EglEndpoint::acquireImage()
+{
+ Q_ASSERT(EGL_NO_IMAGE_KHR == m_image);
+ m_image = m_extensions->acquireImage(m_display, m_endpoint);
+ VERBOSE_TRACE("S60EglEndpoint::acquireImage" << qtThisPtr() << "image" << m_image);
+ if (EGL_NO_IMAGE_KHR == m_image) {
+ qWarning() << "S60EglEndpoint::endpointEvent" << qtThisPtr() << "null image";
+ if (!m_eventHandler->IsActive())
+ m_eventHandler->request();
+ }
+ return m_image;
+}
+
+void S60EglEndpoint::releaseImage()
+{
+ if (EGL_NO_IMAGE_KHR != m_image) {
+ VERBOSE_TRACE("S60EglEndpoint::releaseImage" << qtThisPtr() << "image" << m_image);
+ m_extensions->releaseImage(m_display, m_endpoint, m_image, m_api);
+ m_image = EGL_NO_IMAGE_KHR;
+ if (!m_eventHandler->IsActive())
+ m_eventHandler->request();
+ }
+}
+
diff --git a/plugins/multimedia/symbian/videooutput/s60eglendpoint.h b/plugins/multimedia/symbian/videooutput/s60eglendpoint.h
new file mode 100644
index 0000000000..39faa8a84d
--- /dev/null
+++ b/plugins/multimedia/symbian/videooutput/s60eglendpoint.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60EGLENDPOINT_H
+#define S60EGLENDPOINT_H
+
+#include <QtCore/QObject>
+#include <egl/eglext.h>
+
+QT_USE_NAMESPACE
+
+class QTime;
+class S60EglEndpointEventHandler;
+class S60EglExtensions;
+class TSurfaceId;
+
+class S60EglEndpoint : public QObject
+{
+ Q_OBJECT
+
+public:
+ S60EglEndpoint(const TSurfaceId &surface, S60EglExtensions *extensions,
+ QObject *parent);
+ ~S60EglEndpoint();
+
+ bool isValid() const;
+ void setDelay(qint64 delay);
+ EGLImageKHR acquireImage();
+ void releaseImage();
+
+signals:
+ void imageAvailable();
+
+private:
+ void requestImage();
+ void endpointEvent();
+
+private:
+ friend class S60EglEndpointEventHandler;
+ S60EglExtensions *m_extensions;
+ EGLContext m_context;
+ EGLenum m_api;
+ EGLDisplay m_display;
+ EGLEndpointNOK m_endpoint;
+ QScopedPointer<S60EglEndpointEventHandler> m_eventHandler;
+ enum State {
+ Null,
+ Created,
+ Active
+ } m_state;
+ EGLImageKHR m_image;
+};
+
+#endif // S60EGLENDPOINT_H
+
diff --git a/plugins/multimedia/symbian/videooutput/s60eglextensions.cpp b/plugins/multimedia/symbian/videooutput/s60eglextensions.cpp
new file mode 100644
index 0000000000..bf60957d33
--- /dev/null
+++ b/plugins/multimedia/symbian/videooutput/s60eglextensions.cpp
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "s60eglextensions.h"
+#include "s60mmtrace.h"
+#include <e32base.h>
+#include <egl/egl.h>
+#include <graphics/surface.h>
+#include <QtCore/QDebug>
+#include <QtCore/QTime>
+
+S60EglExtensions *S60EglExtensions::create(QObject *parent)
+{
+ S60EglExtensions *self = new S60EglExtensions(parent);
+ if (!self->initialize()) {
+ delete self;
+ self = 0;
+ }
+ return self;
+}
+
+S60EglExtensions::S60EglExtensions(QObject *parent)
+ : QObject(parent)
+ , m_eglCreateEndpointNOK(0)
+ , m_eglDestroyEndpointNOK(0)
+ , m_eglGetEndpointAttribNOK(0)
+ , m_eglSetEndpointAttribNOK(0)
+ , m_eglAcquireImageNOK(0)
+ , m_eglReleaseImageNOK(0)
+ , m_eglGetEndpointDirtyAreaNOK(0)
+ , m_eglEndpointRequestNotificationNOK(0)
+ , m_eglEndpointCancelNotificationNOK(0)
+ , m_eglDestroyImageKHR(0)
+#ifndef QT_NO_OPENGL
+ , m_glEGLImageTargetTexture2DOES(0)
+#endif
+#ifndef QT_NO_OPENVG
+ , m_vgCreateEGLImageTargetKHR(0)
+#endif
+{
+
+}
+
+S60EglExtensions::~S60EglExtensions()
+{
+
+}
+
+bool S60EglExtensions::initialize()
+{
+ const bool endpoint =
+ getProcAddress("eglCreateEndpointNOK", m_eglCreateEndpointNOK)
+ && getProcAddress("eglDestroyEndpointNOK", m_eglDestroyEndpointNOK)
+ && getProcAddress("eglGetEndpointAttribNOK", m_eglGetEndpointAttribNOK)
+ && getProcAddress("eglSetEndpointAttribNOK", m_eglSetEndpointAttribNOK)
+ && getProcAddress("eglAcquireImageNOK", m_eglAcquireImageNOK)
+ && getProcAddress("eglReleaseImageNOK", m_eglReleaseImageNOK)
+ && getProcAddress("eglGetEndpointDirtyAreaNOK", m_eglGetEndpointDirtyAreaNOK)
+ && getProcAddress("eglEndpointRequestNotificationNOK", m_eglEndpointRequestNotificationNOK)
+ && getProcAddress("eglEndpointCancelNotificationNOK", m_eglEndpointCancelNotificationNOK)
+ && getProcAddress("eglDestroyImageKHR", m_eglDestroyImageKHR);
+
+ bool gl = true;
+#ifndef QT_NO_OPENGL
+ gl = getProcAddress("glEGLImageTargetTexture2DOES", m_glEGLImageTargetTexture2DOES);
+#endif
+
+ bool vg = true;
+#ifndef QT_NO_OPENVG
+ vg = getProcAddress("vgCreateEGLImageTargetKHR", m_vgCreateEGLImageTargetKHR);
+#endif
+
+ return (endpoint && gl && vg);
+}
+
+template <typename FuncPtr>
+bool S60EglExtensions::getProcAddress(const char *procName, FuncPtr &funcPtr)
+{
+ funcPtr = reinterpret_cast<FuncPtr>(eglGetProcAddress(procName));
+ if (!funcPtr)
+ qWarning() << "S60EglEndpointFunctions::getProcAddress" << procName << "not found";
+ return (funcPtr != 0);
+}
+
+EGLEndpointNOK S60EglExtensions::createEndpoint(EGLDisplay dpy, EGLenum type, EGLenum source_type,
+ EGLEndpointSourceNOK source, const EGLint *attrib_list) const
+{
+ return m_eglCreateEndpointNOK(dpy, type, source_type, source, attrib_list);
+}
+
+EGLBoolean S60EglExtensions::destroyEndpoint(EGLDisplay dpy, EGLEndpointNOK endpoint) const
+{
+ return m_eglDestroyEndpointNOK(dpy, endpoint);
+}
+
+EGLint S60EglExtensions::getEndpointAttrib(EGLDisplay dpy, EGLEndpointNOK endpoint, EGLint attrib) const
+{
+ return m_eglGetEndpointAttribNOK(dpy, endpoint, attrib);
+}
+
+EGLBoolean S60EglExtensions::setEndpointAttrib(EGLDisplay dpy, EGLEndpointNOK endpoint, EGLint attrib, EGLint value) const
+{
+ return m_eglSetEndpointAttribNOK(dpy, endpoint, attrib, value);
+}
+
+EGLImageKHR S60EglExtensions::acquireImage(EGLDisplay dpy, EGLEndpointNOK endpoint) const
+{
+ return m_eglAcquireImageNOK(dpy, endpoint);
+}
+
+EGLBoolean S60EglExtensions::releaseImage(EGLDisplay dpy, EGLEndpointNOK endpoint, EGLImageKHR image, EGLenum api) const
+{
+ return m_eglReleaseImageNOK(dpy, endpoint, image, api);
+}
+
+EGLint S60EglExtensions::getEndpointDirtyArea(EGLDisplay dpy, EGLEndpointNOK endpoint, EGLint* rects,
+ EGLint start_rect, EGLint max_rects, EGLBoolean collapse) const
+{
+ return m_eglGetEndpointDirtyAreaNOK(dpy, endpoint, rects, start_rect, max_rects, collapse);
+}
+
+EGLBoolean S60EglExtensions::endpointRequestNotification(EGLDisplay dpy, EGLEndpointNOK endpoint, EGLTRequestStatusNOK sync) const
+{
+ return m_eglEndpointRequestNotificationNOK(dpy, endpoint, sync);
+}
+
+EGLBoolean S60EglExtensions::endpointCancelNotification(EGLDisplay dpy, EGLEndpointNOK endpoint) const
+{
+ return m_eglEndpointCancelNotificationNOK(dpy, endpoint);
+}
+
+EGLBoolean S60EglExtensions::destroyImage(EGLDisplay dpy, EGLImageKHR image) const
+{
+ return m_eglDestroyImageKHR(dpy, image);
+}
+
+#ifndef QT_NO_OPENGL
+void S60EglExtensions::glEglImageTargetTexture(GLenum target, GLeglImageOES image)
+{
+ return m_glEGLImageTargetTexture2DOES(target, image);
+}
+#endif
+
+#ifndef QT_NO_OPENVG
+VGImage S60EglExtensions::vgCreateEglImageTarget(EGLImageKHR image)
+{
+ return m_vgCreateEGLImageTargetKHR(image);
+}
+#endif // !QT_NO_OPENVG
+
diff --git a/plugins/multimedia/symbian/videooutput/s60eglextensions.h b/plugins/multimedia/symbian/videooutput/s60eglextensions.h
new file mode 100644
index 0000000000..85dd8db92b
--- /dev/null
+++ b/plugins/multimedia/symbian/videooutput/s60eglextensions.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60EGLEXTENSIONS_H
+#define S60EGLEXTENSIONS_H
+
+#include <QtCore/QObject>
+#include <egl/eglext.h>
+
+#ifndef QT_NO_OPENGL
+#include <QtOpenGL/qgl.h>
+#include <GLES/glext.h>
+#endif
+
+#ifndef QT_NO_OPENVG
+#include <QtOpenVG/qvg.h>
+#endif
+
+QT_USE_NAMESPACE
+
+class S60EglExtensions : public QObject
+ {
+public:
+ static S60EglExtensions *create(QObject *parent = 0);
+ ~S60EglExtensions();
+
+ // EGL_NOK_image_endpoint
+ EGLEndpointNOK createEndpoint(EGLDisplay dpy, EGLenum type, EGLenum source_type, EGLEndpointSourceNOK source, const EGLint *attrib_list) const;
+ EGLBoolean destroyEndpoint(EGLDisplay dpy, EGLEndpointNOK endpoint) const;
+ EGLint getEndpointAttrib(EGLDisplay dpy, EGLEndpointNOK endpoint, EGLint attrib) const;
+ EGLBoolean setEndpointAttrib(EGLDisplay dpy, EGLEndpointNOK endpoint, EGLint attrib, EGLint value) const;
+ EGLImageKHR acquireImage(EGLDisplay dpy, EGLEndpointNOK endpoint) const;
+ EGLBoolean releaseImage(EGLDisplay dpy, EGLEndpointNOK endpoint, EGLImageKHR image, EGLenum api) const;
+ EGLint getEndpointDirtyArea(EGLDisplay dpy, EGLEndpointNOK endpoint, EGLint *rects, EGLint start_rect, EGLint max_rects, EGLBoolean collapse) const;
+ EGLBoolean endpointRequestNotification(EGLDisplay dpy, EGLEndpointNOK endpoint, EGLTRequestStatusNOK sync) const;
+ EGLBoolean endpointCancelNotification(EGLDisplay dpy, EGLEndpointNOK endpoint) const;
+ EGLBoolean destroyImage(EGLDisplay dpy, EGLImageKHR image) const;
+
+#ifndef QT_NO_OPENGL
+ // EGL_KHR_gl_texture_2D_image
+ void glEglImageTargetTexture(GLenum target, GLeglImageOES image);
+#endif // !QT_NO_OPENGL
+
+#ifndef QT_NO_OPENVG
+ // EGL_KHR_vg_parent_image
+ VGImage vgCreateEglImageTarget(EGLImageKHR image);
+#endif // !QT_NO_OPENVG
+
+private:
+ S60EglExtensions(QObject *parent = 0);
+ bool initialize();
+ template <typename FuncPtr> static bool getProcAddress(const char *procName, FuncPtr &funcPtr);
+
+private:
+ // EGL_NOK_image_endpoint
+ PFNEGLCREATEENDPOINTNOKPROC m_eglCreateEndpointNOK;
+ PFNEGLDESTROYENDPOINTNOKPROC m_eglDestroyEndpointNOK;
+ PFNEGLGETENDPOINTATTRIBNOKPROC m_eglGetEndpointAttribNOK;
+ PFNEGLSETENDPOINTATTRIBNOKPROC m_eglSetEndpointAttribNOK;
+ PFNEGLACQUIREIMAGENOKPROC m_eglAcquireImageNOK;
+ PFNEGLRELEASEIMAGENOKPROC m_eglReleaseImageNOK;
+ PFNEGLGETENDPOINTDIRTYAREANOKPROC m_eglGetEndpointDirtyAreaNOK;
+ PFNEGLENDPOINTREQUESTNOTIFICATIONNOKPROC m_eglEndpointRequestNotificationNOK;
+ PFNEGLENDPOINTCANCELNOTIFICATIONNOKPROC m_eglEndpointCancelNotificationNOK;
+ PFNEGLDESTROYIMAGEKHRPROC m_eglDestroyImageKHR;
+
+#ifndef QT_NO_OPENGL
+ // EGL_KHR_gl_texture_2D_image
+ PFNGLEGLIMAGETARGETTEXTURE2DOESPROC m_glEGLImageTargetTexture2DOES;
+#endif // !QT_NO_OPENGL
+
+#ifndef QT_NO_OPENVG
+ // EGL_KHR_vg_parent_image
+ typedef VGImage (*PFNCREATEEGLIMAGETARGETKHRPROC)(EGLImageKHR);
+ PFNCREATEEGLIMAGETARGETKHRPROC m_vgCreateEGLImageTargetKHR;
+#endif // !QT_NO_OPENVG
+ };
+
+#endif // S60EGLEXTENSIONS_H
+
diff --git a/plugins/multimedia/symbian/videooutput/s60nativewindow.cpp b/plugins/multimedia/symbian/videooutput/s60nativewindow.cpp
new file mode 100644
index 0000000000..d1aeb22ffa
--- /dev/null
+++ b/plugins/multimedia/symbian/videooutput/s60nativewindow.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "s60mmtrace.h"
+#include "s60nativewindow.h"
+#include <coemain.h>
+#include <w32std.h>
+#include <graphics/surfaceconfiguration.h>
+
+static const int WindowWidth = 320;
+static const int WindowHeight = 240;
+
+S60NativeWindow::S60NativeWindow(QObject *parent)
+ : QObject(parent)
+ , m_window(0)
+ , m_surface(TSurfaceId::CreateNullId())
+{
+ TRACE("S60NativeWindow::S60NativeWindow" << qtThisPtr());
+ RWsSession &session = CCoeEnv::Static()->WsSession();
+ RWindowGroup &windowGroup = CCoeEnv::Static()->RootWin();
+ m_window = q_check_ptr(new RWindow(session));
+ const int err = m_window->Construct(windowGroup, reinterpret_cast<quint32>(this));
+ if (err) {
+ delete m_window;
+ m_window = 0;
+ } else {
+ m_window->SetExtent(TPoint(0, 0), TSize(WindowWidth, WindowHeight));
+ }
+}
+
+S60NativeWindow::~S60NativeWindow()
+{
+ TRACE("S60NativeWindow::~S60NativeWindow" << qtThisPtr());
+ if (m_window)
+ m_window->Close();
+ delete m_window;
+}
+
+RWindow *S60NativeWindow::windowHandle() const
+{
+ return m_window;
+}
+
+void S60NativeWindow::setNativeSurface(const TSurfaceId &surface)
+{
+ getSurface();
+ if (surface != m_surface) {
+ TRACE("S60NativeWindow::setNativeSurface" << (void*)surface.iInternal[3]);
+ if (RWindow *const window = windowHandle())
+ window->SetBackgroundSurface(surface);
+ }
+}
+
+TSurfaceId S60NativeWindow::nativeSurface()
+{
+ getSurface();
+ return m_surface;
+}
+
+void S60NativeWindow::getSurface()
+{
+ TSurfaceId surface = TSurfaceId::CreateNullId();
+ int err = 0;
+ RWindow *const window = windowHandle();
+ if (window) {
+ TSurfaceConfiguration config;
+ err = window->GetBackgroundSurface(config);
+ if (!err)
+ config.GetSurfaceId(surface);
+ }
+ if (!err) {
+ m_surface = surface;
+ if (!m_surface.IsNull())
+ window->RemoveBackgroundSurface(ETrue);
+ }
+}
+
diff --git a/plugins/multimedia/symbian/videooutput/s60nativewindow.h b/plugins/multimedia/symbian/videooutput/s60nativewindow.h
new file mode 100644
index 0000000000..7a359ad5e6
--- /dev/null
+++ b/plugins/multimedia/symbian/videooutput/s60nativewindow.h
@@ -0,0 +1,73 @@
+/**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60NATIVEWINDOW_H
+#define S60NATIVEWINDOW_H
+
+#include <QtCore/QObject>
+#include <graphics/surface.h>
+
+class RWindow;
+class RWindowGroup;
+
+QT_USE_NAMESPACE
+
+class S60NativeWindow : public QObject
+{
+ Q_OBJECT
+public:
+ S60NativeWindow(QObject *parent);
+ ~S60NativeWindow();
+
+ RWindow *windowHandle() const;
+ TSurfaceId nativeSurface();
+
+public slots:
+ void setNativeSurface(const TSurfaceId &surface);
+
+private:
+ void getSurface();
+
+private:
+ RWindow *m_window;
+ TSurfaceId m_surface;
+};
+
+#endif // S60NATIVEWINDOW_H
diff --git a/plugins/multimedia/symbian/videooutput/s60videobuffer.cpp b/plugins/multimedia/symbian/videooutput/s60videobuffer.cpp
new file mode 100644
index 0000000000..3a4fbd253d
--- /dev/null
+++ b/plugins/multimedia/symbian/videooutput/s60videobuffer.cpp
@@ -0,0 +1,251 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "s60eglextensions.h"
+#include "s60mmtrace.h"
+#include "s60videoeglrenderercontrol.h"
+#include "s60videobuffer.h"
+#include <QtCore/QElapsedTimer>
+#include <QtCore/QVariant>
+
+#ifndef QT_NO_OPENGL
+#include <GLES/glext.h>
+#endif
+
+// TODO: get rid of these magic numbers
+const QAbstractVideoBuffer::HandleType EGLImageTextureHandle =
+ QAbstractVideoBuffer::HandleType(QAbstractVideoBuffer::UserHandle + 128);
+const QAbstractVideoBuffer::HandleType VGImageTextureHandle =
+ QAbstractVideoBuffer::HandleType(QAbstractVideoBuffer::UserHandle + 129);
+
+// Dummy pointer returned by map() - see comments below
+static uchar* const DummyMapReturnValue = reinterpret_cast<uchar *>(1);
+
+//-----------------------------------------------------------------------------
+// S60EglImageVideoBuffer
+//-----------------------------------------------------------------------------
+
+S60EglImageVideoBuffer::S60EglImageVideoBuffer(S60VideoEglRendererControl *control,
+ S60EglEndpoint *endpoint)
+ : QAbstractVideoBuffer(EGLImageTextureHandle)
+ , m_timer(new QElapsedTimer)
+ , m_control(control)
+ , m_endpoint(endpoint)
+ , m_delay(0)
+{
+ VERBOSE_TRACE("S60EglImageVideoBuffer::S60EglImageVideoBuffer" << qtThisPtr());
+}
+
+S60EglImageVideoBuffer::S60EglImageVideoBuffer(S60VideoEglRendererControl *control,
+ S60EglEndpoint *endpoint,
+ QAbstractVideoBuffer::HandleType type)
+ : QAbstractVideoBuffer(type)
+ , m_timer(new QElapsedTimer)
+ , m_control(control)
+ , m_endpoint(endpoint)
+ , m_delay(0)
+{
+
+}
+
+S60EglImageVideoBuffer::~S60EglImageVideoBuffer()
+{
+ VERBOSE_TRACE("S60EglImageVideoBuffer::~S60EglImageVideoBuffer" << qtThisPtr());
+ unmap();
+}
+
+QAbstractVideoBuffer::MapMode S60EglImageVideoBuffer::mapMode() const
+{
+ return NotMapped;
+}
+
+// Note: the use of map/unmap to indicate when the frame has been displayed
+// by QGraphicsVideoItem is something of a hack, but in QtMobility 1.2,
+// there is no suitable QVideoFrame API, so we must do it this way.
+
+uchar *S60EglImageVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
+{
+ Q_UNUSED(mode);
+ Q_UNUSED(numBytes);
+ Q_UNUSED(bytesPerLine);
+ VERBOSE_TRACE("S60EglImageVideoBuffer::map" << qtThisPtr());
+ acquireEglImage();
+ return DummyMapReturnValue;
+}
+
+void S60EglImageVideoBuffer::unmap()
+{
+ VERBOSE_TRACE("S60EglImageVideoBuffer::unmap" << qtThisPtr());
+ releaseEglImage();
+}
+
+QVariant S60EglImageVideoBuffer::handle() const
+{
+ return m_eglImage;
+}
+
+void S60EglImageVideoBuffer::acquireEglImage()
+{
+ Q_ASSERT(EGL_NO_IMAGE_KHR == m_eglImage);
+ m_timer->start();
+ m_eglImage = m_control->acquireEglImage(m_endpoint);
+}
+
+void S60EglImageVideoBuffer::releaseEglImage()
+{
+ if (EGL_NO_IMAGE_KHR != m_eglImage) {
+ VERBOSE_TRACE("S60EglImageVideoBuffer::releaseEglImage" << qtThisPtr());
+ // Here we need to calculate the time interval between acquiring an image
+ // from the endpoint, and that image being rendered. This is passed back
+ // to the producer, which may use it to correct AV sync.
+ // We assume that unmap() was called by the client shortly after rendering
+ // the image.
+ m_delay = 1000 * m_timer->elapsed();
+ m_control->releaseEglImage(m_endpoint, m_delay);
+ m_eglImage = EGL_NO_IMAGE_KHR;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// S60GlTextureVideoBuffer
+//-----------------------------------------------------------------------------
+
+#ifndef QT_NO_OPENGL
+
+S60GlTextureVideoBuffer::S60GlTextureVideoBuffer(S60VideoEglRendererControl *control,
+ S60EglEndpoint *endpoint,
+ S60EglExtensions *extensions)
+ : S60EglImageVideoBuffer(control, endpoint, QAbstractVideoBuffer::GLTextureHandle)
+ , m_extensions(extensions)
+ , m_texture(0)
+{
+
+}
+
+S60GlTextureVideoBuffer::~S60GlTextureVideoBuffer()
+{
+ VERBOSE_TRACE("S60GlTextureVideoBuffer::~S60GlTextureVideoBuffer" << qtThisPtr());
+ unmap();
+}
+
+uchar *S60GlTextureVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
+{
+ Q_UNUSED(mode);
+ Q_UNUSED(numBytes);
+ Q_UNUSED(bytesPerLine);
+ VERBOSE_TRACE("S60GlTextureVideoBuffer::map" << qtThisPtr());
+ acquireEglImage();
+ glGenTextures(1, &m_texture);
+ glBindTexture(GL_TEXTURE_2D, m_texture);
+ const GLeglImageOES glImage = reinterpret_cast<GLeglImageOES>(m_eglImage);
+ m_extensions->glEglImageTargetTexture(GL_TEXTURE_2D, glImage);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ return DummyMapReturnValue;
+}
+
+void S60GlTextureVideoBuffer::unmap()
+{
+ VERBOSE_TRACE("S60GlTextureVideoBuffer::unmap" << qtThisPtr());
+ if (m_texture)
+ glDeleteTextures(1, &m_texture);
+ releaseEglImage();
+}
+
+QVariant S60GlTextureVideoBuffer::handle() const
+{
+ return m_texture;
+}
+
+#endif // !QT_NO_OPENGL
+
+
+//-----------------------------------------------------------------------------
+// S60VGImageVideoBuffer
+//-----------------------------------------------------------------------------
+
+#ifndef QT_NO_OPENGL
+
+S60VgImageVideoBuffer::S60VgImageVideoBuffer(S60VideoEglRendererControl *control,
+ S60EglEndpoint *endpoint,
+ S60EglExtensions *extensions)
+ : S60EglImageVideoBuffer(control, endpoint, VGImageTextureHandle)
+ , m_extensions(extensions)
+{
+ VERBOSE_TRACE("S60VgImageVideoBuffer::S60VgImageVideoBuffer" << qtThisPtr());
+}
+
+S60VgImageVideoBuffer::~S60VgImageVideoBuffer()
+{
+ VERBOSE_TRACE("S60VgImageVideoBuffer::~S60VgImageVideoBuffer" << qtThisPtr());
+ unmap();
+}
+
+uchar *S60VgImageVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
+{
+ Q_UNUSED(mode);
+ Q_UNUSED(numBytes);
+ Q_UNUSED(bytesPerLine);
+ VERBOSE_TRACE("S60GlTextureVideoBuffer::map" << qtThisPtr());
+ acquireEglImage();
+ m_vgImage = m_extensions->vgCreateEglImageTarget(m_eglImage);
+ return DummyMapReturnValue;
+}
+
+void S60VgImageVideoBuffer::unmap()
+{
+ VERBOSE_TRACE("S60VgImageVideoBuffer::unmap" << qtThisPtr());
+ if (VG_INVALID_HANDLE != m_vgImage)
+ vgDestroyImage(m_vgImage);
+ releaseEglImage();
+}
+
+QVariant S60VgImageVideoBuffer::handle() const
+{
+ return static_cast<quint32>(m_vgImage);
+}
+
+#endif // !QT_NO_OPENGL
+
diff --git a/plugins/multimedia/symbian/videooutput/s60videobuffer.h b/plugins/multimedia/symbian/videooutput/s60videobuffer.h
new file mode 100644
index 0000000000..032809b419
--- /dev/null
+++ b/plugins/multimedia/symbian/videooutput/s60videobuffer.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60VIDEOBUFFER_H
+#define S60VIDEOBUFFER_H
+
+#include <QtMultimediaKit/QAbstractVideoBuffer>
+#include <egl/eglext.h>
+
+#ifndef QT_NO_OPENGL
+#include <QtOpenGL/qgl.h>
+#endif
+
+#ifndef QT_NO_OPENVG
+#include <QtOpenVG/qvg.h>
+#endif
+
+QT_USE_NAMESPACE
+
+class QElapsedTimer;
+class S60EglEndpoint;
+class S60EglExtensions;
+class S60VideoEglRendererControl;
+
+class S60EglImageVideoBuffer : public QAbstractVideoBuffer
+{
+public:
+ S60EglImageVideoBuffer(S60VideoEglRendererControl *control,
+ S60EglEndpoint *endpoint);
+ ~S60EglImageVideoBuffer();
+
+ // QAbstractVideoBuffer
+ MapMode mapMode() const;
+ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine);
+ void unmap();
+ QVariant handle() const;
+
+protected:
+ S60EglImageVideoBuffer(S60VideoEglRendererControl *control,
+ S60EglEndpoint *endpoint,
+ QAbstractVideoBuffer::HandleType type);
+ void acquireEglImage();
+ void releaseEglImage();
+
+protected:
+ EGLImageKHR m_eglImage;
+
+private:
+ QScopedPointer<QElapsedTimer> m_timer;
+ S60VideoEglRendererControl *m_control;
+ S60EglEndpoint *m_endpoint;
+ qint64 m_delay;
+};
+
+#ifndef QT_NO_OPENGL
+class S60GlTextureVideoBuffer : public S60EglImageVideoBuffer
+{
+public:
+ S60GlTextureVideoBuffer(S60VideoEglRendererControl *control,
+ S60EglEndpoint *endpoint,
+ S60EglExtensions *extensions);
+ ~S60GlTextureVideoBuffer();
+
+ // QAbstractVideoBuffer
+ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine);
+ void unmap();
+ QVariant handle() const;
+
+private:
+ S60EglExtensions *m_extensions;
+ GLuint m_texture;
+};
+#endif // !QT_NO_OPENGL
+
+#ifndef QT_NO_OPENVG
+class S60VgImageVideoBuffer : public S60EglImageVideoBuffer
+{
+public:
+ S60VgImageVideoBuffer(S60VideoEglRendererControl *control,
+ S60EglEndpoint *endpoint,
+ S60EglExtensions *extensions);
+ ~S60VgImageVideoBuffer();
+
+ // QAbstractVideoBuffer
+ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine);
+ void unmap();
+ QVariant handle() const;
+
+private:
+ S60EglExtensions *m_extensions;
+ VGImage m_vgImage;
+};
+#endif // !QT_NO_OPENVG
+
+#endif // S60VIDEOBUFFER_H
+
diff --git a/plugins/multimedia/symbian/videooutput/s60videoeglrenderercontrol.cpp b/plugins/multimedia/symbian/videooutput/s60videoeglrenderercontrol.cpp
new file mode 100644
index 0000000000..a7cea15cde
--- /dev/null
+++ b/plugins/multimedia/symbian/videooutput/s60videoeglrenderercontrol.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "s60eglendpoint.h"
+#include "s60mmtrace.h"
+#include "s60videobuffer.h"
+#include "s60videoeglrenderercontrol.h"
+#include <EGL/egl.h>
+#include <QtMultimediaKit/QAbstractVideoSurface>
+#include <QtMultimediaKit/QVideoFrame>
+#include <QtMultimediaKit/QVideoSurfaceFormat>
+
+#ifdef VIDEOOUTPUT_MEASURE_FRAMERATE
+#include "s60videoframerate.h"
+#endif
+
+S60VideoEglRendererControl::S60VideoEglRendererControl(S60EglExtensions *extensions, QObject *parent)
+ : QVideoRendererControl(parent)
+ , m_nativeSurface(TSurfaceId::CreateNullId())
+ , m_doesProduceEglImages(false)
+ , m_surface(0)
+ , m_eglExtensions(extensions)
+ , m_eglEndpoint(0)
+ , m_buffer(0)
+ , m_frameRate(0)
+{
+ TRACE("S60VideoEglRendererControl::S60VideoEglRendererControl" << qtThisPtr());
+ Q_ASSERT(m_eglExtensions);
+#ifdef VIDEOOUTPUT_MEASURE_FRAMERATE
+ m_frameRate = new S60VideoFrameRate(this);
+#endif
+}
+
+S60VideoEglRendererControl::~S60VideoEglRendererControl()
+{
+ TRACE("S60VideoEglRendererControl::~S60VideoEglRendererControl" << qtThisPtr());
+}
+
+QAbstractVideoSurface *S60VideoEglRendererControl::surface() const
+{
+ return m_surface;
+}
+
+void S60VideoEglRendererControl::setSurface(QAbstractVideoSurface *surface)
+{
+ if (surface != m_surface) {
+ TRACE("S60VideoEglRendererControl::setSurface" << qtThisPtr()
+ << "surface" << surface);
+ m_surface = surface;
+ if (!m_surface)
+ destroyEndpoint();
+ else if (!m_nativeSurface.IsNull())
+ createEndpoint();
+ emit surfaceChanged();
+ }
+}
+
+void S60VideoEglRendererControl::setNativeSurface(TSurfaceId surface)
+{
+ if (surface != m_nativeSurface) {
+ TRACE("S60VideoEglRendererControl::setNativeSurface" << qtThisPtr()
+ << "surface" << (void*)surface.iInternal[3]);
+ m_nativeSurface = surface;
+ if (m_nativeSurface.IsNull())
+ destroyEndpoint();
+ else if (m_surface)
+ createEndpoint();
+ }
+}
+
+const QSize &S60VideoEglRendererControl::nativeSize() const
+{
+ return m_nativeSize;
+}
+
+bool S60VideoEglRendererControl::doesProduceEglImages() const
+{
+ return m_doesProduceEglImages;
+}
+
+void S60VideoEglRendererControl::setNativeSize(QSize size)
+{
+ if (size != m_nativeSize) {
+ TRACE("S60VideoEglRendererControl::setNativeSize" << qtThisPtr()
+ << "size" << size);
+ m_nativeSize = size;
+ emit nativeSizeChanged();
+ }
+}
+
+void S60VideoEglRendererControl::setDoesProduceEglImages(bool enabled)
+{
+ if (enabled != m_doesProduceEglImages) {
+ TRACE("S60VideoEglRendererControl::setDoesProduceEglImages" << qtThisPtr()
+ << "enabled" << enabled);
+ m_doesProduceEglImages = enabled;
+ }
+}
+
+// Helper function
+EGLenum currentEglApi()
+{
+ EGLenum api = 0;
+ if (EGL_NO_CONTEXT != eglGetCurrentContext())
+ api = eglQueryAPI();
+ return api;
+}
+
+void S60VideoEglRendererControl::imageAvailable()
+{
+ const EGLenum api = currentEglApi();
+ VERBOSE_TRACE("S60VideoEglRendererControl::imageAvailable" << qtThisPtr()
+ << "api" << api);
+ Q_ASSERT(!m_buffer);
+ if (m_doesProduceEglImages) {
+ m_buffer = new S60EglImageVideoBuffer(this, m_eglEndpoint);
+ } else {
+ switch (api) {
+ case EGL_OPENGL_ES_API:
+ m_buffer = new S60GlTextureVideoBuffer(this, m_eglEndpoint, m_eglExtensions);
+ break;
+ case EGL_OPENVG_API:
+ m_buffer = new S60VgImageVideoBuffer(this, m_eglEndpoint, m_eglExtensions);
+ break;
+ }
+ }
+ Q_ASSERT(m_buffer);
+ QVideoSurfaceFormat format(m_nativeSize,
+ QVideoFrame::Format_RGB32,
+ m_buffer->handleType());
+ format.setScanLineDirection(QVideoSurfaceFormat::BottomToTop);
+ if (!m_surface->isActive())
+ m_surface->start(format);
+ const QVideoFrame frame(m_buffer, format.frameSize(), format.pixelFormat());
+ m_surface->present(frame);
+#ifdef VIDEOOUTPUT_MEASURE_FRAMERATE
+ m_frameRate->notify();
+#endif
+}
+
+EGLImageKHR S60VideoEglRendererControl::acquireEglImage(S60EglEndpoint *endpoint) const
+{
+ VERBOSE_TRACE("S60VideoEglRendererControl::acquireEglImage" << qtThisPtr());
+ EGLImageKHR image = EGL_NO_IMAGE_KHR;
+ if (m_eglEndpoint == endpoint)
+ image = m_eglEndpoint->acquireImage();
+ return image;
+}
+
+void S60VideoEglRendererControl::releaseEglImage(S60EglEndpoint *endpoint, qint64 delay)
+{
+ VERBOSE_TRACE("S60VideoEglRendererControl::releaseEglImage" << qtThisPtr()
+ << "delay" << delay);
+ if (m_eglEndpoint == endpoint) {
+ if (delay)
+ m_eglEndpoint->setDelay(delay);
+ m_eglEndpoint->releaseImage();
+ }
+ m_buffer = 0;
+}
+
+void S60VideoEglRendererControl::destroyEndpoint()
+{
+ if (m_eglEndpoint) {
+ delete m_eglEndpoint;
+ m_eglEndpoint = 0;
+ }
+}
+
+void S60VideoEglRendererControl::createEndpoint()
+{
+ Q_ASSERT(m_surface);
+ Q_ASSERT(!m_nativeSurface.IsNull());
+ Q_ASSERT(!m_eglEndpoint);
+ m_eglEndpoint = new S60EglEndpoint(m_nativeSurface, m_eglExtensions, this);
+ if (m_eglEndpoint->isValid())
+ connect(m_eglEndpoint, SIGNAL(imageAvailable()),
+ this, SLOT(imageAvailable()));
+ else
+ emit error();
+}
diff --git a/plugins/multimedia/symbian/videooutput/s60videoeglrenderercontrol.h b/plugins/multimedia/symbian/videooutput/s60videoeglrenderercontrol.h
new file mode 100644
index 0000000000..3cfc20414a
--- /dev/null
+++ b/plugins/multimedia/symbian/videooutput/s60videoeglrenderercontrol.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60VIDEOEGLRENDERERCONTROL_H
+#define S60VIDEOEGLRENDERERCONTROL_H
+
+#include <QtCore/QSize>
+#include <QtMultimediaKit/QVideoRendererControl>
+#include <egl/eglext.h>
+#include <graphics/surface.h>
+
+QT_USE_NAMESPACE
+
+class QTime;
+class QVideoFrame;
+class S60EglEndpoint;
+class S60EglExtensions;
+class S60EglImageVideoBuffer;
+class S60VideoFrameRate;
+
+class S60VideoEglRendererControl : public QVideoRendererControl
+{
+ Q_OBJECT
+ Q_PROPERTY(QSize nativeSize READ nativeSize WRITE setNativeSize NOTIFY nativeSizeChanged)
+
+ /**
+ * If set, the returned QVideoFrame handle type is EGLImageKHR.
+ * If not set, the returned handle type depends on the current EGL rendering
+ * API:
+ * for OpenGLES, GL texture handles
+ * for OpenVG, VG image handles
+ * The default value is false.
+ */
+ Q_PROPERTY(bool doesProduceEglImages READ doesProduceEglImages WRITE setDoesProduceEglImages)
+
+public:
+ S60VideoEglRendererControl(S60EglExtensions *extensions, QObject *parent);
+ ~S60VideoEglRendererControl();
+
+public:
+ // QVideoRendererControl
+ QAbstractVideoSurface *surface() const;
+ void setSurface(QAbstractVideoSurface *surface);
+
+ const QSize &nativeSize() const;
+ bool doesProduceEglImages() const;
+
+public slots:
+ void setNativeSurface(TSurfaceId surface);
+ void setNativeSize(QSize size);
+ void setDoesProduceEglImages(bool enabled);
+
+signals:
+ void surfaceChanged();
+ void nativeSizeChanged();
+ void error();
+
+private slots:
+ void imageAvailable();
+
+private:
+ void destroyEndpoint();
+ void createEndpoint();
+
+private:
+ // Called by S60EglImageVideoBuffer
+ EGLImageKHR acquireEglImage(S60EglEndpoint *endpoint) const;
+ void releaseEglImage(S60EglEndpoint *endpoint, qint64 delay);
+
+private:
+ friend class S60EglImageVideoBuffer;
+ TSurfaceId m_nativeSurface;
+ QSize m_nativeSize;
+ bool m_doesProduceEglImages;
+ QAbstractVideoSurface *m_surface;
+ S60EglExtensions *m_eglExtensions;
+ S60EglEndpoint *m_eglEndpoint;
+ S60EglImageVideoBuffer *m_buffer;
+ S60VideoFrameRate *m_frameRate;
+};
+
+#endif // S60VIDEOEGLRENDERERCONTROL_H
+
diff --git a/plugins/multimedia/symbian/videooutput/s60videoframerate.cpp b/plugins/multimedia/symbian/videooutput/s60videoframerate.cpp
new file mode 100644
index 0000000000..936052bf0f
--- /dev/null
+++ b/plugins/multimedia/symbian/videooutput/s60videoframerate.cpp
@@ -0,0 +1,101 @@
+/**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "s60videoframerate.h"
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+
+static const int HistoryLength = 5;
+static const int SamplingInterval = 100;
+static const int TraceInterval = 2000;
+
+S60VideoFrameRate::S60VideoFrameRate(QObject *parent)
+ : QObject(parent)
+ , m_sampleTimer(new QTimer(this))
+ , m_traceTimer(new QTimer(this))
+ , m_elapsedTimer(new QElapsedTimer)
+ , m_count(0)
+ , m_history(HistoryLength, 0.0)
+ , m_historyIndex(0)
+ , m_historyCount(0)
+ , m_frequency(0.0)
+ , m_frequencySum(0.0)
+{
+ connect(m_sampleTimer, SIGNAL(timeout()), this, SLOT(sample()));
+ m_sampleTimer->start(SamplingInterval);
+ connect(m_traceTimer, SIGNAL(timeout()), this, SLOT(trace()));
+ m_traceTimer->start(TraceInterval);
+ m_elapsedTimer->start();
+}
+
+S60VideoFrameRate::~S60VideoFrameRate()
+{
+
+}
+
+qreal S60VideoFrameRate::frequency() const
+{
+ return m_frequency;
+}
+
+void S60VideoFrameRate::notify()
+{
+ ++m_count;
+}
+
+void S60VideoFrameRate::sample()
+{
+ const int ms = m_elapsedTimer->restart();
+ const qreal freq = qreal(m_count * 1000) / ms;
+ m_frequencySum -= m_history[m_historyIndex];
+ m_frequencySum += freq;
+ m_history[m_historyIndex] = freq;
+ m_historyIndex = (m_historyIndex + 1) % m_history.count();
+ if (m_historyCount < m_history.count())
+ ++m_historyCount;
+ m_frequency = m_frequencySum / m_historyCount;
+ emit frequencyChanged(m_frequency);
+ m_count = 0;
+}
+
+void S60VideoFrameRate::trace()
+{
+ qDebug() << "S60VideoFrameRate" << m_frequency << "fps";
+}
diff --git a/plugins/multimedia/symbian/videooutput/s60videoframerate.h b/plugins/multimedia/symbian/videooutput/s60videoframerate.h
new file mode 100644
index 0000000000..e501483ce5
--- /dev/null
+++ b/plugins/multimedia/symbian/videooutput/s60videoframerate.h
@@ -0,0 +1,89 @@
+/**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef S60VIDEOFRAMERATE_H
+#define S60VIDEOFRAMERATE_H
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QVector>
+
+class QElapsedTimer;
+class QTimer;
+
+/**
+ * Class for measuring video frame rate
+ *
+ * Delivery of a new video frame is notified by the client via the notify() slot.
+ * This class performs regular sampling of the event frequency and calculates a
+ * rolling average which is published via the frequency property.
+ */
+class S60VideoFrameRate : public QObject
+{
+ Q_OBJECT
+
+public:
+ S60VideoFrameRate(QObject *parent = 0);
+ ~S60VideoFrameRate();
+ qreal frequency() const;
+
+signals:
+ void frequencyChanged(qreal freq) const;
+
+public slots:
+ void notify();
+
+private slots:
+ void sample();
+ void trace();
+
+private:
+ QTimer *m_sampleTimer;
+ QTimer *m_traceTimer;
+ QScopedPointer<QElapsedTimer> m_elapsedTimer;
+ int m_count;
+ QVector<qreal> m_history;
+ int m_historyIndex;
+ int m_historyCount;
+ qreal m_frequencySum;
+ qreal m_frequency;
+};
+
+#endif // S60VIDEOFRAMERATE_H
diff --git a/plugins/multimedia/symbian/videooutput/s60videooutputfactory.cpp b/plugins/multimedia/symbian/videooutput/s60videooutputfactory.cpp
new file mode 100644
index 0000000000..cf77ade0cf
--- /dev/null
+++ b/plugins/multimedia/symbian/videooutput/s60videooutputfactory.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "s60mmtrace.h"
+#include "s60videooutputfactory.h"
+#include "s60videowidgetcontrol.h"
+#include "s60videowindowcontrol.h"
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+#include "s60eglextensions.h"
+#include "s60videoeglrenderercontrol.h"
+#endif
+#include <QtCore/QVariant>
+
+S60VideoOutputFactory::S60VideoOutputFactory(QObject *parent)
+ : QObject(parent)
+ , m_eglExtensions(0)
+{
+ TRACE("S60VideoOutputFactory::S60VideoOutputFactory" << qtThisPtr());
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ m_eglExtensions = S60EglExtensions::create(this);
+#endif
+}
+
+S60VideoOutputFactory::~S60VideoOutputFactory()
+{
+ TRACE("S60VideoOutputFactory::~S60VideoOutputFactory" << qtThisPtr());
+ foreach (ControlData d, m_data)
+ delete d.control;
+}
+
+QMediaControl *S60VideoOutputFactory::requestControl(const char *name)
+{
+ TRACE("S60VideoOutputFactory::requestControl" << qtThisPtr() << "name" << name);
+ QMediaControl *control = 0;
+ for (int i=0; i<m_data.count(); ++i) {
+ ControlData &d = m_data[i];
+ if (d.name == name) {
+ control = d.control;
+ // TODO: protect against multithreaded usage, if QMediaService is
+ // required to be thread-safe
+ ++d.refCount;
+ }
+ }
+ if (!control) {
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
+ if (m_eglExtensions)
+ control = new S60VideoEglRendererControl(m_eglExtensions, this);
+ } else
+#endif
+ if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
+ control = new S60VideoWidgetControl(this);
+ } else if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
+ control = new S60VideoWindowControl(this);
+ }
+ if (control) {
+ ControlData d;
+ d.control = control;
+ d.name = name;
+ d.refCount = 1;
+ m_data += d;
+ }
+ }
+ return control;
+}
+
+void S60VideoOutputFactory::releaseControl(QMediaControl *control)
+{
+ TRACE("S60VideoOutputFactory::requestControl" << qtThisPtr() << "control" << control);
+ int index = -1;
+ for (int i=0; index == -1 && i<m_data.count(); ++i)
+ if (m_data.at(i).control == control)
+ index = i;
+ if (index != -1 && --m_data[index].refCount == 0) {
+ delete control;
+ m_data.remove(index);
+ }
+}
diff --git a/plugins/multimedia/symbian/mmf/mediaplayer/s60videooutputinterface.h b/plugins/multimedia/symbian/videooutput/s60videooutputfactory.h
index f0e993339d..2d0a5681ea 100644
--- a/plugins/multimedia/symbian/mmf/mediaplayer/s60videooutputinterface.h
+++ b/plugins/multimedia/symbian/videooutput/s60videooutputfactory.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -39,24 +39,35 @@
**
****************************************************************************/
-#ifndef S60VIDEOOUTPUTINTERFACE_H
-#define S60VIDEOOUTPUTINTERFACE_H
+#ifndef S60VIDEOOUTPUTFACTORY_H
+#define S60VIDEOOUTPUTFACTORY_H
-#include <QtCore/qglobal.h>
-#include <QtGui/qwindowdefs.h>
-#include <coecntrl.h>
+#include <qmediacontrol.h>
+#include <QtCore/QVector>
-class S60VideoOutputInterface
+QT_USE_NAMESPACE
+
+class S60EglExtensions;
+
+class S60VideoOutputFactory : public QObject
{
public:
- RWindow *videoWindowHandle() const { return videoWinId() ? static_cast<RWindow *>(videoWinId()->DrawableWindow()) : 0 ; }
- virtual WId videoWinId() const = 0;
- // If VIDEOOUTPUT_GRAPHICS_SURFACES is defined, the return value is the video
- // rectangle relative to the video window. If not, the return value is the
- // absolute screen rectangle.
- virtual QRect videoDisplayRect() const = 0;
- virtual Qt::AspectRatioMode videoAspectRatio() const = 0;
+ S60VideoOutputFactory(QObject *parent = 0);
+ ~S60VideoOutputFactory();
+
+ QMediaControl *requestControl(const char *name);
+ void releaseControl(QMediaControl *control);
+
+private:
+ struct ControlData
+ {
+ QString name;
+ QMediaControl *control;
+ int refCount;
+ };
+ QVector<ControlData> m_data;
+ S60EglExtensions *m_eglExtensions;
};
-#endif // S60VIDEOOUTPUTINTERFACE_H
+#endif // S60VIDEOOUTPUTFACTORY_H
diff --git a/plugins/multimedia/symbian/videooutput/videooutput.pri b/plugins/multimedia/symbian/videooutput/videooutput.pri
index 13aa7a0fc7..130c33ed55 100644
--- a/plugins/multimedia/symbian/videooutput/videooutput.pri
+++ b/plugins/multimedia/symbian/videooutput/videooutput.pri
@@ -2,9 +2,62 @@ INCLUDEPATH += $$PWD
message("VideoOutput: using common implementation")
+include(../trace/trace.pri)
+
+HEADERS += $$PWD/s60videodisplay.h \
+ $$PWD/s60videooutpututils.h \
+ $$PWD/s60videooutputfactory.h \
+ $$PWD/s60videowidget.h \
+ $$PWD/s60videowidgetcontrol.h \
+ $$PWD/s60videowidgetdisplay.h \
+ $$PWD/s60videowindowcontrol.h \
+ $$PWD/s60videowindowdisplay.h
+
+SOURCES += $$PWD/s60videodisplay.cpp \
+ $$PWD/s60videooutpututils.cpp \
+ $$PWD/s60videooutputfactory.cpp \
+ $$PWD/s60videowidget.cpp \
+ $$PWD/s60videowidgetcontrol.cpp \
+ $$PWD/s60videowidgetdisplay.cpp \
+ $$PWD/s60videowindowcontrol.cpp \
+ $$PWD/s60videowindowdisplay.cpp
+
+LIBS *= -lcone
+LIBS *= -lws32
+
+# Uncomment this to enable frame rate measurement
+#videooutput_measure_framerate = yes
+
contains(surfaces_s60_enabled, yes) {
message("VideoOutput: graphics surface rendering supported")
DEFINES += VIDEOOUTPUT_GRAPHICS_SURFACES
+ HEADERS += $$PWD/s60eglendpoint.h \
+ $$PWD/s60eglextensions.h \
+ $$PWD/s60nativewindow.h \
+ $$PWD/s60videobuffer.h \
+ $$PWD/s60videoeglrenderercontrol.h
+ SOURCES += $$PWD/s60eglendpoint.cpp \
+ $$PWD/s60eglextensions.cpp \
+ $$PWD/s60nativewindow.cpp \
+ $$PWD/s60videobuffer.cpp \
+ $$PWD/s60videoeglrenderercontrol.cpp
+ DEFINES += VIDEOOUTPUT_EGL_RENDERER
+ LIBS += -llibegl
+ contains(QT_CONFIG, opengl) | contains(QT_CONFIG, opengles2) {
+ QT += opengl
+ } else {
+ DEFINES += QT_NO_OPENGL
+ }
+ contains(QT_CONFIG, openvg) {
+ LIBS += -llibopenvg
+ } else {
+ DEFINES += QT_NO_OPENVG
+ }
+ contains(videooutput_measure_framerate, yes) {
+ HEADERS += $$PWD/s60videoframerate.h
+ SOURCES += $$PWD/s60videoframerate.cpp
+ DEFINES += VIDEOOUTPUT_MEASURE_FRAMERATE
+ }
} else {
message("VideoOutput: no graphics surface rendering support - DSA only")
}
@@ -15,23 +68,3 @@ exists($$[QT_INSTALL_HEADERS]/QtGui/private/qwidget_p.h) {
} else {
message("VideoOutput: private QtGui headers not available - video and viewfinder may not be rendered correctly")
}
-
-HEADERS += $$PWD/s60videodisplay.h \
- $$PWD/s60videooutpututils.h \
- $$PWD/s60videowidget.h \
- $$PWD/s60videowidgetcontrol.h \
- $$PWD/s60videowidgetdisplay.h \
- $$PWD/s60videowindowcontrol.h \
- $$PWD/s60videowindowdisplay.h
-
-SOURCES += $$PWD/s60videodisplay.cpp \
- $$PWD/s60videooutpututils.cpp \
- $$PWD/s60videowidget.cpp \
- $$PWD/s60videowidgetcontrol.cpp \
- $$PWD/s60videowidgetdisplay.cpp \
- $$PWD/s60videowindowcontrol.cpp \
- $$PWD/s60videowindowdisplay.cpp
-
-LIBS *= -lcone
-LIBS *= -lws32
-