--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qtmobility/src/multimedia/qgraphicsvideoitem_maemo5.cpp Fri Apr 16 15:51:22 2010 +0300
@@ -0,0 +1,495 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qpointer.h>
+#include <QtGui/qgraphicsscene.h>
+#include <QtGui/qgraphicsview.h>
+#include <QtGui/qscrollbar.h>
+#include <QtGui/qx11info_x11.h>
+
+#include <qgraphicsvideoitem.h>
+
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+#include <qpaintervideosurface_p.h>
+#include <qvideooutputcontrol.h>
+#include <qvideorenderercontrol.h>
+
+#include <QtMultimedia/qvideosurfaceformat.h>
+
+#include <qxvideosurface_maemo5_p.h>
+
+QTM_BEGIN_NAMESPACE
+
+class QGraphicsVideoItemPrivate
+{
+public:
+ QGraphicsVideoItemPrivate()
+ : q_ptr(0)
+ , surface(0)
+ , mediaObject(0)
+ , service(0)
+ , outputControl(0)
+ , rendererControl(0)
+ , savedViewportUpdateMode(QGraphicsView::FullViewportUpdate)
+ , aspectRatioMode(Qt::KeepAspectRatio)
+ , rect(0.0, 0.0, 320, 240)
+ {
+ }
+
+ QGraphicsVideoItem *q_ptr;
+
+ QXVideoSurface *surface;
+ QMediaObject *mediaObject;
+ QMediaService *service;
+ QVideoOutputControl *outputControl;
+ QVideoRendererControl *rendererControl;
+ QPointer<QGraphicsView> currentView;
+ QGraphicsView::ViewportUpdateMode savedViewportUpdateMode;
+
+ Qt::AspectRatioMode aspectRatioMode;
+ QRectF rect;
+ QRectF boundingRect;
+ QRectF sourceRect;
+ QSizeF nativeSize;
+
+ void clearService();
+ void updateRects();
+
+ void _q_present();
+ void _q_formatChanged(const QVideoSurfaceFormat &format);
+ void _q_serviceDestroyed();
+ void _q_mediaObjectDestroyed();
+};
+
+void QGraphicsVideoItemPrivate::clearService()
+{
+ if (outputControl) {
+ outputControl->setOutput(QVideoOutputControl::NoOutput);
+ outputControl = 0;
+ }
+ if (rendererControl) {
+ surface->stop();
+ rendererControl->setSurface(0);
+ rendererControl = 0;
+ }
+ if (service) {
+ QObject::disconnect(service, SIGNAL(destroyed()), q_ptr, SLOT(_q_serviceDestroyed()));
+ service = 0;
+ }
+}
+
+void QGraphicsVideoItemPrivate::updateRects()
+{
+ q_ptr->prepareGeometryChange();
+
+ if (nativeSize.isEmpty()) {
+ boundingRect = QRectF();
+ } else if (aspectRatioMode == Qt::IgnoreAspectRatio) {
+ boundingRect = rect;
+ sourceRect = QRectF(0, 0, 1, 1);
+ } else if (aspectRatioMode == Qt::KeepAspectRatio) {
+ QSizeF size = nativeSize;
+ size.scale(rect.size(), Qt::KeepAspectRatio);
+
+ boundingRect = QRectF(0, 0, size.width(), size.height());
+ boundingRect.moveCenter(rect.center());
+
+ sourceRect = QRectF(0, 0, 1, 1);
+ } else if (aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
+ boundingRect = rect;
+
+ QSizeF size = rect.size();
+ size.scale(nativeSize, Qt::KeepAspectRatio);
+
+ sourceRect = QRectF(
+ 0, 0, size.width() / nativeSize.width(), size.height() / nativeSize.height());
+ sourceRect.moveCenter(QPointF(0.5, 0.5));
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_present()
+{
+ q_ptr->update(boundingRect);
+}
+
+void QGraphicsVideoItemPrivate::_q_formatChanged(const QVideoSurfaceFormat &format)
+{
+ nativeSize = format.sizeHint();
+
+ updateRects();
+
+ emit q_ptr->nativeSizeChanged(nativeSize);
+}
+
+void QGraphicsVideoItemPrivate::_q_serviceDestroyed()
+{
+ rendererControl = 0;
+ outputControl = 0;
+ service = 0;
+
+ surface->stop();
+}
+
+void QGraphicsVideoItemPrivate::_q_mediaObjectDestroyed()
+{
+ mediaObject = 0;
+
+ clearService();
+}
+
+/*!
+ \class QGraphicsVideoItem
+
+ \brief The QGraphicsVideoItem class provides a graphics item which display video produced by a QMediaObject.
+
+ \ingroup multimedia
+
+ Attaching a QGraphicsVideoItem to a QMediaObject allows it to display
+ the video or image output of that media object. A QGraphicsVideoItem
+ is attached to a media object by passing a pointer to the QMediaObject
+ to the setMediaObject() function.
+
+ \code
+ player = new QMediaPlayer(this);
+
+ QGraphicsVideoItem *item = new QGraphicsVideoItem;
+ item->setMediaObject(player);
+ graphicsView->scence()->addItem(item);
+ graphicsView->show();
+
+ player->setMedia(video);
+ player->play();
+ \endcode
+
+ \bold {Note}: Only a single display output can be attached to a media object at one time.
+
+ \sa QMediaObject, QMediaPlayer, QVideoWidget
+*/
+
+/*!
+ \enum QGraphicsVideoItem::FillMode
+
+ Enumerates the methods of scaling a video to fit a graphics item.
+
+ \value Stretch The video is stretched to fit the item's size.
+ \value PreserveAspectFit The video is uniformly scaled to fix the item's
+ size without cropping.
+ \value PreserveAspectCrop The video is uniformly scaled to fill the item's
+ size, cropping if necessary.
+*/
+
+/*!
+ Constructs a graphics item that displays video.
+
+ The \a parent is passed to QGraphicsItem.
+*/
+QGraphicsVideoItem::QGraphicsVideoItem(QGraphicsItem *parent)
+ : QGraphicsObject(parent)
+ , d_ptr(new QGraphicsVideoItemPrivate)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->surface = new QXVideoSurface;
+
+ setCacheMode(NoCache);
+ setFlag(QGraphicsItem::ItemIgnoresParentOpacity);
+ setFlag(QGraphicsItem::ItemSendsGeometryChanges);
+ setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
+
+ connect(d_ptr->surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ this, SLOT(_q_formatChanged(QVideoSurfaceFormat)));
+
+ connect(d_ptr->surface, SIGNAL(activeChanged(bool)), this, SLOT(_q_present()));
+}
+
+/*!
+ Destroys a video graphics item.
+*/
+QGraphicsVideoItem::~QGraphicsVideoItem()
+{
+
+ if (d_ptr->outputControl)
+ d_ptr->outputControl->setOutput(QVideoOutputControl::NoOutput);
+
+ if (d_ptr->rendererControl)
+ d_ptr->rendererControl->setSurface(0);
+
+ if (d_ptr->currentView)
+ d_ptr->currentView->setViewportUpdateMode(d_ptr->savedViewportUpdateMode);
+
+ delete d_ptr->surface;
+ delete d_ptr;
+}
+
+/*!
+ \property QGraphicsVideoItem::mediaObject
+ \brief the media object which provides the video displayed by a graphics item.
+*/
+
+QMediaObject *QGraphicsVideoItem::mediaObject() const
+{
+ return d_func()->mediaObject;
+}
+
+void QGraphicsVideoItem::setMediaObject(QMediaObject *object)
+{
+ Q_D(QGraphicsVideoItem);
+
+ if (object == d->mediaObject)
+ return;
+
+ d->clearService();
+
+ if (d->mediaObject) {
+ disconnect(d->mediaObject, SIGNAL(destroyed()), this, SLOT(_q_mediaObjectDestroyed()));
+ d->mediaObject->unbind(this);
+ }
+
+ d->mediaObject = object;
+
+ if (d->mediaObject) {
+ d->mediaObject->bind(this);
+
+ connect(d->mediaObject, SIGNAL(destroyed()), this, SLOT(_q_mediaObjectDestroyed()));
+
+ d->service = d->mediaObject->service();
+
+ if (d->service) {
+ connect(d->service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed()));
+
+ d->outputControl = qobject_cast<QVideoOutputControl *>(
+ d->service->control(QVideoOutputControl_iid));
+ d->rendererControl = qobject_cast<QVideoRendererControl *>(
+ d->service->control(QVideoRendererControl_iid));
+
+ if (d->outputControl != 0 && d->rendererControl != 0) {
+ d->rendererControl->setSurface(d->surface);
+
+ if (isVisible())
+ d->outputControl->setOutput(QVideoOutputControl::RendererOutput);
+ }
+ }
+ }
+}
+
+/*!
+ \property QGraphicsVideoItem::aspectRatioMode
+ \brief how a video is scaled to fit the graphics item's size.
+*/
+
+Qt::AspectRatioMode QGraphicsVideoItem::aspectRatioMode() const
+{
+ return d_func()->aspectRatioMode;
+}
+
+void QGraphicsVideoItem::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->aspectRatioMode = mode;
+ d->updateRects();
+}
+
+/*!
+ \property QGraphicsVideoItem::offset
+ \brief the video item's offset.
+
+ QGraphicsVideoItem will draw video using the offset for its top left
+ corner.
+*/
+
+QPointF QGraphicsVideoItem::offset() const
+{
+ return d_func()->rect.topLeft();
+}
+
+void QGraphicsVideoItem::setOffset(const QPointF &offset)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->rect.moveTo(offset);
+ d->updateRects();
+}
+
+/*!
+ \property QGraphicsVideoItem::size
+ \brief the video item's size.
+
+ QGraphicsVideoItem will draw video scaled to fit size according to its
+ fillMode.
+*/
+
+QSizeF QGraphicsVideoItem::size() const
+{
+ return d_func()->rect.size();
+}
+
+void QGraphicsVideoItem::setSize(const QSizeF &size)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->rect.setSize(size.isValid() ? size : QSizeF(0, 0));
+ d->updateRects();
+}
+
+/*!
+ \property QGraphicsVideoItem::nativeSize
+ \brief the native size of the video.
+*/
+
+QSizeF QGraphicsVideoItem::nativeSize() const
+{
+ return d_func()->nativeSize;
+}
+
+/*!
+ \fn QGraphicsVideoItem::nativeSizeChanged(const QSizeF &size)
+
+ Signals that the native \a size of the video has changed.
+*/
+
+
+/*!
+ \reimp
+*/
+QRectF QGraphicsVideoItem::boundingRect() const
+{
+ return d_func()->boundingRect;
+}
+
+
+/*!
+ \reimp
+*/
+void QGraphicsVideoItem::paint(
+ QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_D(QGraphicsVideoItem);
+
+ //qDebug() << "paint video item on widget" << widget;
+
+ QGraphicsView *view = 0;
+ if (scene() && !scene()->views().isEmpty())
+ view = scene()->views().first();
+
+ //it's necessary to switch vieport update mode to FullViewportUpdate
+ //otherwise the video item area can be just scrolled without notifying overlay
+ //about geometry changes
+ if (view != d->currentView) {
+ if (d->currentView) {
+ d->currentView->setViewportUpdateMode(d->savedViewportUpdateMode);
+ /*disconnect(d->currentView->verticalScrollBar(), SIGNAL(valueChanged(int)),
+ this, SLOT(_q_present()));
+ disconnect(d->currentView->horizontalScrollBar(), SIGNAL(valueChanged(int)),
+ this, SLOT(_q_present()));*/
+ }
+
+ d->currentView = view;
+ if (view) {
+ d->savedViewportUpdateMode = view->viewportUpdateMode();
+ view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
+ /*connect(d->currentView->verticalScrollBar(), SIGNAL(valueChanged(int)),
+ this, SLOT(_q_present()));
+ connect(d->currentView->horizontalScrollBar(), SIGNAL(valueChanged(int)),
+ this, SLOT(_q_present()));*/
+ }
+ }
+
+ QColor colorKey = Qt::black;
+
+ if (d->surface) {
+ if (widget)
+ d->surface->setWinId(widget->winId());
+
+ QTransform transform = painter->combinedTransform();
+ QRect deviceRect = transform.mapRect(boundingRect()).toRect();
+
+ if (widget) {
+ //workaround for xvideo issue with U/V planes swapped
+ QPoint topLeft = widget->mapToGlobal(deviceRect.topLeft());
+ if ((topLeft.x() & 1) == 0)
+ deviceRect.moveLeft(deviceRect.left()-1);
+ }
+
+ if (d->surface->displayRect() != deviceRect) {
+ //qDebug() << "set video display rect:" << deviceRect;
+ d->surface->setDisplayRect( deviceRect );
+ // repaint last frame after the color key area is filled
+ QMetaObject::invokeMethod(d->surface, "repaintLastFrame", Qt::QueuedConnection);
+ }
+
+ colorKey = d->surface->colorKey();
+ }
+
+ painter->fillRect(d->boundingRect, colorKey);
+}
+
+/*!
+ \reimp
+
+ \internal
+*/
+QVariant QGraphicsVideoItem::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ Q_D(QGraphicsVideoItem);
+
+ if (change == ItemVisibleChange && d->outputControl != 0 && d->rendererControl != 0) {
+ if (value.toBool()) {
+ d->outputControl->setOutput(QVideoOutputControl::RendererOutput);
+
+ return d->outputControl->output() == QVideoOutputControl::RendererOutput;
+ } else {
+ d->outputControl->setOutput(QVideoOutputControl::NoOutput);
+
+ return value;
+ }
+ } else if (change == ItemScenePositionHasChanged) {
+ update(boundingRect());
+ } else {
+ return QGraphicsItem::itemChange(change, value);
+ }
+
+ return value;
+}
+
+#include "moc_qgraphicsvideoitem.cpp"
+QTM_END_NAMESPACE