qtmobility/src/multimedia/qgraphicsvideoitem_maemo5.cpp
changeset 1 2b40d63a9c3d
child 4 90517678cc4f
equal deleted inserted replaced
0:cfcbf08528c4 1:2b40d63a9c3d
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <QtCore/qpointer.h>
       
    43 #include <QtGui/qgraphicsscene.h>
       
    44 #include <QtGui/qgraphicsview.h>
       
    45 #include <QtGui/qscrollbar.h>
       
    46 #include <QtGui/qx11info_x11.h>
       
    47 
       
    48 #include <qgraphicsvideoitem.h>
       
    49 
       
    50 #include <qmediaobject.h>
       
    51 #include <qmediaservice.h>
       
    52 #include <qpaintervideosurface_p.h>
       
    53 #include <qvideooutputcontrol.h>
       
    54 #include <qvideorenderercontrol.h>
       
    55 
       
    56 #include <QtMultimedia/qvideosurfaceformat.h>
       
    57 
       
    58 #include <qxvideosurface_maemo5_p.h>
       
    59 
       
    60 QTM_BEGIN_NAMESPACE
       
    61 
       
    62 class QGraphicsVideoItemPrivate
       
    63 {
       
    64 public:
       
    65     QGraphicsVideoItemPrivate()
       
    66         : q_ptr(0)
       
    67         , surface(0)
       
    68         , mediaObject(0)
       
    69         , service(0)
       
    70         , outputControl(0)
       
    71         , rendererControl(0)
       
    72         , savedViewportUpdateMode(QGraphicsView::FullViewportUpdate)
       
    73         , aspectRatioMode(Qt::KeepAspectRatio)
       
    74         , rect(0.0, 0.0, 320, 240)
       
    75     {
       
    76     }
       
    77 
       
    78     QGraphicsVideoItem *q_ptr;
       
    79 
       
    80     QXVideoSurface *surface;
       
    81     QMediaObject *mediaObject;
       
    82     QMediaService *service;
       
    83     QVideoOutputControl *outputControl;
       
    84     QVideoRendererControl *rendererControl;
       
    85     QPointer<QGraphicsView> currentView;
       
    86     QGraphicsView::ViewportUpdateMode savedViewportUpdateMode;
       
    87 
       
    88     Qt::AspectRatioMode aspectRatioMode;
       
    89     QRectF rect;
       
    90     QRectF boundingRect;
       
    91     QRectF sourceRect;
       
    92     QSizeF nativeSize;
       
    93 
       
    94     void clearService();
       
    95     void updateRects();
       
    96 
       
    97     void _q_present();
       
    98     void _q_formatChanged(const QVideoSurfaceFormat &format);
       
    99     void _q_serviceDestroyed();
       
   100     void _q_mediaObjectDestroyed();
       
   101 };
       
   102 
       
   103 void QGraphicsVideoItemPrivate::clearService()
       
   104 {
       
   105     if (outputControl) {
       
   106         outputControl->setOutput(QVideoOutputControl::NoOutput);
       
   107         outputControl = 0;
       
   108     }
       
   109     if (rendererControl) {
       
   110         surface->stop();
       
   111         rendererControl->setSurface(0);
       
   112         rendererControl = 0;
       
   113     }
       
   114     if (service) {
       
   115         QObject::disconnect(service, SIGNAL(destroyed()), q_ptr, SLOT(_q_serviceDestroyed()));
       
   116         service = 0;
       
   117     }
       
   118 }
       
   119 
       
   120 void QGraphicsVideoItemPrivate::updateRects()
       
   121 {
       
   122     q_ptr->prepareGeometryChange();
       
   123 
       
   124     if (nativeSize.isEmpty()) {
       
   125         boundingRect = QRectF();
       
   126     } else if (aspectRatioMode == Qt::IgnoreAspectRatio) {
       
   127         boundingRect = rect;
       
   128         sourceRect = QRectF(0, 0, 1, 1);
       
   129     } else if (aspectRatioMode == Qt::KeepAspectRatio) {
       
   130         QSizeF size = nativeSize;
       
   131         size.scale(rect.size(), Qt::KeepAspectRatio);
       
   132 
       
   133         boundingRect = QRectF(0, 0, size.width(), size.height());
       
   134         boundingRect.moveCenter(rect.center());
       
   135 
       
   136         sourceRect = QRectF(0, 0, 1, 1);
       
   137     } else if (aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
       
   138         boundingRect = rect;
       
   139 
       
   140         QSizeF size = rect.size();
       
   141         size.scale(nativeSize, Qt::KeepAspectRatio);
       
   142 
       
   143         sourceRect = QRectF(
       
   144                 0, 0, size.width() / nativeSize.width(), size.height() / nativeSize.height());
       
   145         sourceRect.moveCenter(QPointF(0.5, 0.5));
       
   146     }
       
   147 }
       
   148 
       
   149 void QGraphicsVideoItemPrivate::_q_present()
       
   150 {
       
   151     q_ptr->update(boundingRect);
       
   152 }
       
   153 
       
   154 void QGraphicsVideoItemPrivate::_q_formatChanged(const QVideoSurfaceFormat &format)
       
   155 {
       
   156     nativeSize = format.sizeHint();
       
   157 
       
   158     updateRects();
       
   159 
       
   160     emit q_ptr->nativeSizeChanged(nativeSize);
       
   161 }
       
   162 
       
   163 void QGraphicsVideoItemPrivate::_q_serviceDestroyed()
       
   164 {
       
   165     rendererControl = 0;
       
   166     outputControl = 0;
       
   167     service = 0;
       
   168 
       
   169     surface->stop();
       
   170 }
       
   171 
       
   172 void QGraphicsVideoItemPrivate::_q_mediaObjectDestroyed()
       
   173 {
       
   174     mediaObject = 0;
       
   175 
       
   176     clearService();
       
   177 }
       
   178 
       
   179 /*!
       
   180     \class QGraphicsVideoItem
       
   181 
       
   182     \brief The QGraphicsVideoItem class provides a graphics item which display video produced by a QMediaObject.
       
   183 
       
   184     \ingroup multimedia
       
   185 
       
   186     Attaching a QGraphicsVideoItem to a QMediaObject allows it to display
       
   187     the video or image output of that media object.  A QGraphicsVideoItem
       
   188     is attached to a media object by passing a pointer to the QMediaObject
       
   189     to the setMediaObject() function.
       
   190 
       
   191     \code
       
   192     player = new QMediaPlayer(this);
       
   193 
       
   194     QGraphicsVideoItem *item = new QGraphicsVideoItem;
       
   195     item->setMediaObject(player);
       
   196     graphicsView->scence()->addItem(item);
       
   197     graphicsView->show();
       
   198 
       
   199     player->setMedia(video);
       
   200     player->play();
       
   201     \endcode
       
   202 
       
   203     \bold {Note}: Only a single display output can be attached to a media object at one time.
       
   204 
       
   205     \sa QMediaObject, QMediaPlayer, QVideoWidget
       
   206 */
       
   207 
       
   208 /*!
       
   209     \enum QGraphicsVideoItem::FillMode
       
   210 
       
   211     Enumerates the methods of scaling a video to fit a graphics item.
       
   212 
       
   213     \value Stretch The video is stretched to fit the item's size.
       
   214     \value PreserveAspectFit The video is uniformly scaled to fix the item's
       
   215     size without cropping.
       
   216     \value PreserveAspectCrop The video is uniformly scaled to fill the item's
       
   217     size, cropping if necessary.
       
   218 */
       
   219 
       
   220 /*!
       
   221     Constructs a graphics item that displays video.
       
   222 
       
   223     The \a parent is passed to QGraphicsItem.
       
   224 */
       
   225 QGraphicsVideoItem::QGraphicsVideoItem(QGraphicsItem *parent)
       
   226     : QGraphicsObject(parent)
       
   227     , d_ptr(new QGraphicsVideoItemPrivate)
       
   228 {
       
   229     d_ptr->q_ptr = this;
       
   230     d_ptr->surface = new QXVideoSurface;
       
   231 
       
   232     setCacheMode(NoCache);
       
   233     setFlag(QGraphicsItem::ItemIgnoresParentOpacity);
       
   234     setFlag(QGraphicsItem::ItemSendsGeometryChanges);
       
   235     setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
       
   236 
       
   237     connect(d_ptr->surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
       
   238             this, SLOT(_q_formatChanged(QVideoSurfaceFormat)));
       
   239 
       
   240     connect(d_ptr->surface, SIGNAL(activeChanged(bool)), this, SLOT(_q_present()));
       
   241 }
       
   242 
       
   243 /*!
       
   244     Destroys a video graphics item.
       
   245 */
       
   246 QGraphicsVideoItem::~QGraphicsVideoItem()
       
   247 {
       
   248 
       
   249     if (d_ptr->outputControl)
       
   250         d_ptr->outputControl->setOutput(QVideoOutputControl::NoOutput);
       
   251 
       
   252     if (d_ptr->rendererControl)
       
   253         d_ptr->rendererControl->setSurface(0);
       
   254 
       
   255     if (d_ptr->currentView)
       
   256         d_ptr->currentView->setViewportUpdateMode(d_ptr->savedViewportUpdateMode);
       
   257 
       
   258     delete d_ptr->surface;
       
   259     delete d_ptr;
       
   260 }
       
   261 
       
   262 /*!
       
   263     \property QGraphicsVideoItem::mediaObject
       
   264     \brief the media object which provides the video displayed by a graphics item.
       
   265 */
       
   266 
       
   267 QMediaObject *QGraphicsVideoItem::mediaObject() const
       
   268 {
       
   269     return d_func()->mediaObject;
       
   270 }
       
   271 
       
   272 void QGraphicsVideoItem::setMediaObject(QMediaObject *object)
       
   273 {
       
   274     Q_D(QGraphicsVideoItem);
       
   275 
       
   276     if (object == d->mediaObject)
       
   277         return;
       
   278 
       
   279     d->clearService();
       
   280 
       
   281     if (d->mediaObject) {
       
   282         disconnect(d->mediaObject, SIGNAL(destroyed()), this, SLOT(_q_mediaObjectDestroyed()));
       
   283         d->mediaObject->unbind(this);
       
   284     }
       
   285 
       
   286     d->mediaObject = object;
       
   287 
       
   288     if (d->mediaObject) {
       
   289         d->mediaObject->bind(this);
       
   290 
       
   291         connect(d->mediaObject, SIGNAL(destroyed()), this, SLOT(_q_mediaObjectDestroyed()));
       
   292 
       
   293         d->service = d->mediaObject->service();
       
   294 
       
   295         if (d->service) {
       
   296             connect(d->service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed()));
       
   297 
       
   298             d->outputControl = qobject_cast<QVideoOutputControl *>(
       
   299                     d->service->control(QVideoOutputControl_iid));
       
   300             d->rendererControl = qobject_cast<QVideoRendererControl *>(
       
   301                     d->service->control(QVideoRendererControl_iid));
       
   302 
       
   303             if (d->outputControl != 0 && d->rendererControl != 0) {
       
   304                 d->rendererControl->setSurface(d->surface);
       
   305 
       
   306                 if (isVisible())
       
   307                     d->outputControl->setOutput(QVideoOutputControl::RendererOutput);
       
   308             }
       
   309         }
       
   310     }
       
   311 }
       
   312 
       
   313 /*!
       
   314     \property QGraphicsVideoItem::aspectRatioMode
       
   315     \brief how a video is scaled to fit the graphics item's size.
       
   316 */
       
   317 
       
   318 Qt::AspectRatioMode QGraphicsVideoItem::aspectRatioMode() const
       
   319 {
       
   320     return d_func()->aspectRatioMode;
       
   321 }
       
   322 
       
   323 void QGraphicsVideoItem::setAspectRatioMode(Qt::AspectRatioMode mode)
       
   324 {
       
   325     Q_D(QGraphicsVideoItem);
       
   326 
       
   327     d->aspectRatioMode = mode;
       
   328     d->updateRects();
       
   329 }
       
   330 
       
   331 /*!
       
   332     \property QGraphicsVideoItem::offset
       
   333     \brief the video item's offset.
       
   334 
       
   335     QGraphicsVideoItem will draw video using the offset for its top left
       
   336     corner.
       
   337 */
       
   338 
       
   339 QPointF QGraphicsVideoItem::offset() const
       
   340 {
       
   341     return d_func()->rect.topLeft();
       
   342 }
       
   343 
       
   344 void QGraphicsVideoItem::setOffset(const QPointF &offset)
       
   345 {
       
   346     Q_D(QGraphicsVideoItem);
       
   347 
       
   348     d->rect.moveTo(offset);
       
   349     d->updateRects();
       
   350 }
       
   351 
       
   352 /*!
       
   353     \property QGraphicsVideoItem::size
       
   354     \brief the video item's size.
       
   355 
       
   356     QGraphicsVideoItem will draw video scaled to fit size according to its
       
   357     fillMode.
       
   358 */
       
   359 
       
   360 QSizeF QGraphicsVideoItem::size() const
       
   361 {
       
   362     return d_func()->rect.size();
       
   363 }
       
   364 
       
   365 void QGraphicsVideoItem::setSize(const QSizeF &size)
       
   366 {
       
   367     Q_D(QGraphicsVideoItem);
       
   368 
       
   369     d->rect.setSize(size.isValid() ? size : QSizeF(0, 0));
       
   370     d->updateRects();
       
   371 }
       
   372 
       
   373 /*!
       
   374     \property QGraphicsVideoItem::nativeSize
       
   375     \brief the native size of the video.
       
   376 */
       
   377 
       
   378 QSizeF QGraphicsVideoItem::nativeSize() const
       
   379 {
       
   380     return d_func()->nativeSize;
       
   381 }
       
   382 
       
   383 /*!
       
   384     \fn QGraphicsVideoItem::nativeSizeChanged(const QSizeF &size)
       
   385 
       
   386     Signals that the native \a size of the video has changed.
       
   387 */
       
   388 
       
   389 
       
   390 /*!
       
   391     \reimp
       
   392 */
       
   393 QRectF QGraphicsVideoItem::boundingRect() const
       
   394 {
       
   395     return d_func()->boundingRect;
       
   396 }
       
   397 
       
   398 
       
   399 /*!
       
   400     \reimp
       
   401 */
       
   402 void QGraphicsVideoItem::paint(
       
   403         QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
       
   404 {
       
   405     Q_UNUSED(option);
       
   406     Q_D(QGraphicsVideoItem);
       
   407 
       
   408     //qDebug() << "paint video item on widget" << widget;
       
   409 
       
   410     QGraphicsView *view = 0;
       
   411     if (scene() && !scene()->views().isEmpty())
       
   412         view = scene()->views().first();
       
   413 
       
   414     //it's necessary to switch vieport update mode to FullViewportUpdate
       
   415     //otherwise the video item area can be just scrolled without notifying overlay
       
   416     //about geometry changes
       
   417     if (view != d->currentView) {
       
   418         if (d->currentView) {
       
   419             d->currentView->setViewportUpdateMode(d->savedViewportUpdateMode);
       
   420             /*disconnect(d->currentView->verticalScrollBar(), SIGNAL(valueChanged(int)),
       
   421                        this, SLOT(_q_present()));
       
   422             disconnect(d->currentView->horizontalScrollBar(), SIGNAL(valueChanged(int)),
       
   423                        this, SLOT(_q_present()));*/
       
   424         }
       
   425 
       
   426         d->currentView = view;
       
   427         if (view) {
       
   428             d->savedViewportUpdateMode = view->viewportUpdateMode();
       
   429             view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
       
   430             /*connect(d->currentView->verticalScrollBar(), SIGNAL(valueChanged(int)),
       
   431                     this, SLOT(_q_present()));
       
   432             connect(d->currentView->horizontalScrollBar(), SIGNAL(valueChanged(int)),
       
   433                     this, SLOT(_q_present()));*/
       
   434         }
       
   435     }
       
   436 
       
   437     QColor colorKey = Qt::black;
       
   438 
       
   439     if (d->surface) {
       
   440         if (widget)
       
   441             d->surface->setWinId(widget->winId());
       
   442 
       
   443         QTransform transform = painter->combinedTransform();
       
   444         QRect deviceRect = transform.mapRect(boundingRect()).toRect();
       
   445 
       
   446         if (widget) {
       
   447             //workaround for xvideo issue with U/V planes swapped
       
   448             QPoint topLeft = widget->mapToGlobal(deviceRect.topLeft());
       
   449             if ((topLeft.x() & 1) == 0)
       
   450                 deviceRect.moveLeft(deviceRect.left()-1);
       
   451         }
       
   452 
       
   453         if (d->surface->displayRect() != deviceRect) {
       
   454             //qDebug() << "set video display rect:" << deviceRect;
       
   455             d->surface->setDisplayRect( deviceRect );
       
   456             // repaint last frame after the color key area is filled
       
   457             QMetaObject::invokeMethod(d->surface, "repaintLastFrame", Qt::QueuedConnection);
       
   458         }
       
   459 
       
   460         colorKey = d->surface->colorKey();
       
   461     }
       
   462 
       
   463     painter->fillRect(d->boundingRect, colorKey);
       
   464 }
       
   465 
       
   466 /*!
       
   467     \reimp
       
   468 
       
   469     \internal
       
   470 */
       
   471 QVariant QGraphicsVideoItem::itemChange(GraphicsItemChange change, const QVariant &value)
       
   472 {
       
   473     Q_D(QGraphicsVideoItem);
       
   474 
       
   475     if (change == ItemVisibleChange && d->outputControl != 0 && d->rendererControl != 0) {
       
   476         if (value.toBool()) {
       
   477             d->outputControl->setOutput(QVideoOutputControl::RendererOutput);
       
   478 
       
   479             return d->outputControl->output() == QVideoOutputControl::RendererOutput;
       
   480         } else {
       
   481             d->outputControl->setOutput(QVideoOutputControl::NoOutput);
       
   482 
       
   483             return value;
       
   484         }
       
   485     } else if (change == ItemScenePositionHasChanged) {
       
   486         update(boundingRect());
       
   487     } else {
       
   488         return QGraphicsItem::itemChange(change, value);
       
   489     }
       
   490 
       
   491     return value;
       
   492 }
       
   493 
       
   494 #include "moc_qgraphicsvideoitem.cpp"
       
   495 QTM_END_NAMESPACE