src/3rdparty/phonon/mmf/abstractvideoplayer.cpp
changeset 19 fcece45ef507
child 14 c0432d11811c
equal deleted inserted replaced
18:2f34d5167611 19:fcece45ef507
       
     1 /*  This file is part of the KDE project.
       
     2 
       
     3 Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 
       
     5 This library is free software: you can redistribute it and/or modify
       
     6 it under the terms of the GNU Lesser General Public License as published by
       
     7 the Free Software Foundation, either version 2.1 or 3 of the License.
       
     8 
       
     9 This library is distributed in the hope that it will be useful,
       
    10 but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12 GNU Lesser General Public License for more details.
       
    13 
       
    14 You should have received a copy of the GNU Lesser General Public License
       
    15 along with this library.  If not, see <http://www.gnu.org/licenses/>.
       
    16 
       
    17 */
       
    18 
       
    19 #include <QUrl>
       
    20 #include <QTimer>
       
    21 #include <QWidget>
       
    22 
       
    23 #include <coemain.h>    // for CCoeEnv
       
    24 
       
    25 #include "abstractvideoplayer.h"
       
    26 #include "utils.h"
       
    27 
       
    28 #ifndef QT_NO_DEBUG
       
    29 #include "objectdump.h"
       
    30 #endif
       
    31 
       
    32 QT_BEGIN_NAMESPACE
       
    33 
       
    34 using namespace Phonon;
       
    35 using namespace Phonon::MMF;
       
    36 
       
    37 /*! \class MMF::AbstractVideoPlayer
       
    38   \internal
       
    39 */
       
    40 
       
    41 //-----------------------------------------------------------------------------
       
    42 // Constructor / destructor
       
    43 //-----------------------------------------------------------------------------
       
    44 
       
    45 MMF::AbstractVideoPlayer::AbstractVideoPlayer(MediaObject *parent, const AbstractPlayer *player)
       
    46     :   AbstractMediaPlayer(parent, player)
       
    47     ,   m_wsSession(CCoeEnv::Static()->WsSession())
       
    48     ,   m_screenDevice(*CCoeEnv::Static()->ScreenDevice())
       
    49     ,   m_window(0)
       
    50     ,   m_scaleWidth(1.0)
       
    51     ,   m_scaleHeight(1.0)
       
    52     ,   m_totalTime(0)
       
    53 {
       
    54 
       
    55 }
       
    56 
       
    57 void MMF::AbstractVideoPlayer::construct()
       
    58 {
       
    59     TRACE_CONTEXT(AbstractVideoPlayer::AbstractVideoPlayer, EVideoApi);
       
    60     TRACE_ENTRY_0();
       
    61 
       
    62     if (m_videoOutput) {
       
    63         initVideoOutput();
       
    64         m_window = m_videoOutput->videoWindow();
       
    65     }
       
    66 
       
    67     createPlayer();
       
    68 
       
    69     TRACE_EXIT_0();
       
    70 }
       
    71 
       
    72 MMF::AbstractVideoPlayer::~AbstractVideoPlayer()
       
    73 {
       
    74     TRACE_CONTEXT(AbstractVideoPlayer::~AbstractVideoPlayer, EVideoApi);
       
    75     TRACE_ENTRY_0();
       
    76 
       
    77     // QObject destructor removes all signal-slot connections involving this
       
    78     // object, so we do not need to disconnect from m_videoOutput here.
       
    79 
       
    80     TRACE_EXIT_0();
       
    81 }
       
    82 
       
    83 CVideoPlayerUtility* MMF::AbstractVideoPlayer::nativePlayer() const
       
    84 {
       
    85     return m_player.data();
       
    86 }
       
    87 
       
    88 //-----------------------------------------------------------------------------
       
    89 // Public API
       
    90 //-----------------------------------------------------------------------------
       
    91 
       
    92 void MMF::AbstractVideoPlayer::doPlay()
       
    93 {
       
    94     TRACE_CONTEXT(AbstractVideoPlayer::doPlay, EVideoApi);
       
    95 
       
    96     handlePendingParametersChanged();
       
    97 
       
    98     m_player->Play();
       
    99 }
       
   100 
       
   101 void MMF::AbstractVideoPlayer::doPause()
       
   102 {
       
   103     TRACE_CONTEXT(AbstractVideoPlayer::doPause, EVideoApi);
       
   104 
       
   105     TRAPD(err, m_player->PauseL());
       
   106     if (KErrNone != err && state() != ErrorState) {
       
   107         TRACE("PauseL error %d", err);
       
   108         setError(tr("Pause failed"), err);
       
   109     }
       
   110 }
       
   111 
       
   112 void MMF::AbstractVideoPlayer::doStop()
       
   113 {
       
   114     m_player->Stop();
       
   115 }
       
   116 
       
   117 void MMF::AbstractVideoPlayer::doSeek(qint64 ms)
       
   118 {
       
   119     TRACE_CONTEXT(AbstractVideoPlayer::doSeek, EVideoApi);
       
   120 
       
   121     TRAPD(err, m_player->SetPositionL(TTimeIntervalMicroSeconds(ms * 1000)));
       
   122 
       
   123     if (KErrNone != err)
       
   124         setError(tr("Seek failed"), err);
       
   125 }
       
   126 
       
   127 int MMF::AbstractVideoPlayer::setDeviceVolume(int mmfVolume)
       
   128 {
       
   129     TRAPD(err, m_player->SetVolumeL(mmfVolume));
       
   130     return err;
       
   131 }
       
   132 
       
   133 int MMF::AbstractVideoPlayer::openFile(RFile &file)
       
   134 {
       
   135     TRAPD(err, m_player->OpenFileL(file));
       
   136     return err;
       
   137 }
       
   138 
       
   139 int MMF::AbstractVideoPlayer::openUrl(const QString &url)
       
   140 {
       
   141     TRAPD(err, m_player->OpenUrlL(qt_QString2TPtrC(url)));
       
   142     return err;
       
   143 }
       
   144 
       
   145 int MMF::AbstractVideoPlayer::bufferStatus() const
       
   146 {
       
   147     int result = 0;
       
   148     TRAP_IGNORE(m_player->GetVideoLoadingProgressL(result));
       
   149     return result;
       
   150 }
       
   151 
       
   152 void MMF::AbstractVideoPlayer::close()
       
   153 {
       
   154     m_player->Close();
       
   155 }
       
   156 
       
   157 bool MMF::AbstractVideoPlayer::hasVideo() const
       
   158 {
       
   159     return true;
       
   160 }
       
   161 
       
   162 qint64 MMF::AbstractVideoPlayer::currentTime() const
       
   163 {
       
   164     TRACE_CONTEXT(AbstractVideoPlayer::currentTime, EVideoApi);
       
   165 
       
   166     TTimeIntervalMicroSeconds us;
       
   167     TRAPD(err, us = m_player->PositionL())
       
   168 
       
   169     qint64 result = 0;
       
   170 
       
   171     if (KErrNone == err) {
       
   172         result = toMilliSeconds(us);
       
   173     } else {
       
   174         TRACE("PositionL error %d", err);
       
   175 
       
   176         // If we don't cast away constness here, we simply have to ignore
       
   177         // the error.
       
   178         const_cast<AbstractVideoPlayer*>(this)->setError(tr("Getting position failed"), err);
       
   179     }
       
   180 
       
   181     return result;
       
   182 }
       
   183 
       
   184 qint64 MMF::AbstractVideoPlayer::totalTime() const
       
   185 {
       
   186     return m_totalTime;
       
   187 }
       
   188 
       
   189 
       
   190 //-----------------------------------------------------------------------------
       
   191 // Public slots
       
   192 //-----------------------------------------------------------------------------
       
   193 
       
   194 void MMF::AbstractVideoPlayer::videoWindowChanged()
       
   195 {
       
   196     TRACE_CONTEXT(AbstractVideoPlayer::videoOutputRegionChanged, EVideoInternal);
       
   197     TRACE_ENTRY("state %d", state());
       
   198 
       
   199     m_window = m_videoOutput ? m_videoOutput->videoWindow() : 0;
       
   200 
       
   201     handleVideoWindowChanged();
       
   202 
       
   203     TRACE_EXIT_0();
       
   204 }
       
   205 
       
   206 void MMF::AbstractVideoPlayer::aspectRatioChanged()
       
   207 {
       
   208     TRACE_CONTEXT(AbstractVideoPlayer::aspectRatioChanged, EVideoInternal);
       
   209     TRACE_ENTRY("state %d aspectRatio %d", state());
       
   210 
       
   211     updateScaleFactors(m_videoOutput->videoWindowSize());
       
   212 
       
   213     TRACE_EXIT_0();
       
   214 }
       
   215 
       
   216 void MMF::AbstractVideoPlayer::scaleModeChanged()
       
   217 {
       
   218     TRACE_CONTEXT(AbstractVideoPlayer::scaleModeChanged, EVideoInternal);
       
   219     TRACE_ENTRY("state %d", state());
       
   220 
       
   221     updateScaleFactors(m_videoOutput->videoWindowSize());
       
   222 
       
   223     TRACE_EXIT_0();
       
   224 }
       
   225 
       
   226 
       
   227 //-----------------------------------------------------------------------------
       
   228 // MVideoPlayerUtilityObserver callbacks
       
   229 //-----------------------------------------------------------------------------
       
   230 
       
   231 void MMF::AbstractVideoPlayer::MvpuoOpenComplete(TInt aError)
       
   232 {
       
   233     TRACE_CONTEXT(AbstractVideoPlayer::MvpuoOpenComplete, EVideoApi);
       
   234     TRACE_ENTRY("state %d error %d", state(), aError);
       
   235 
       
   236     __ASSERT_ALWAYS(LoadingState == state(), Utils::panic(InvalidStatePanic));
       
   237 
       
   238     if (KErrNone == aError)
       
   239         m_player->Prepare();
       
   240     else
       
   241         setError(tr("Opening clip failed"), aError);
       
   242 
       
   243     TRACE_EXIT_0();
       
   244 }
       
   245 
       
   246 void MMF::AbstractVideoPlayer::MvpuoPrepareComplete(TInt aError)
       
   247 {
       
   248     TRACE_CONTEXT(AbstractVideoPlayer::MvpuoPrepareComplete, EVideoApi);
       
   249     TRACE_ENTRY("state %d error %d", state(), aError);
       
   250 
       
   251     __ASSERT_ALWAYS(LoadingState == state(), Utils::panic(InvalidStatePanic));
       
   252 
       
   253     TRAPD(err, getVideoClipParametersL(aError));
       
   254 
       
   255     if (KErrNone == err) {
       
   256         maxVolumeChanged(m_player->MaxVolume());
       
   257 
       
   258         if (m_videoOutput)
       
   259             m_videoOutput->setVideoSize(m_videoFrameSize);
       
   260 
       
   261         prepareCompleted();
       
   262         handlePendingParametersChanged();
       
   263 
       
   264         emit totalTimeChanged(totalTime());
       
   265         changeState(StoppedState);
       
   266     } else {
       
   267         setError(tr("Buffering clip failed"), err);
       
   268     }
       
   269 
       
   270     TRACE_EXIT_0();
       
   271 }
       
   272 
       
   273 void MMF::AbstractVideoPlayer::getVideoClipParametersL(TInt aError)
       
   274 {
       
   275     User::LeaveIfError(aError);
       
   276 
       
   277     // Get frame size
       
   278     TSize size;
       
   279     m_player->VideoFrameSizeL(size);
       
   280     m_videoFrameSize = QSize(size.iWidth, size.iHeight);
       
   281 
       
   282     // Get duration
       
   283     m_totalTime = toMilliSeconds(m_player->DurationL());
       
   284 }
       
   285 
       
   286 
       
   287 void MMF::AbstractVideoPlayer::MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError)
       
   288 {
       
   289     TRACE_CONTEXT(AbstractVideoPlayer::MvpuoFrameReady, EVideoApi);
       
   290     TRACE_ENTRY("state %d error %d", state(), aError);
       
   291 
       
   292     Q_UNUSED(aFrame);
       
   293     Q_UNUSED(aError);   // suppress warnings in release builds
       
   294 
       
   295     TRACE_EXIT_0();
       
   296 }
       
   297 
       
   298 void MMF::AbstractVideoPlayer::MvpuoPlayComplete(TInt aError)
       
   299 {
       
   300     TRACE_CONTEXT(AbstractVideoPlayer::MvpuoPlayComplete, EVideoApi)
       
   301     TRACE_ENTRY("state %d error %d", state(), aError);
       
   302 
       
   303     // Call base class function which handles end of playback for both
       
   304     // audio and video clips.
       
   305     playbackComplete(aError);
       
   306 
       
   307     TRACE_EXIT_0();
       
   308 }
       
   309 
       
   310 void MMF::AbstractVideoPlayer::MvpuoEvent(const TMMFEvent &aEvent)
       
   311 {
       
   312     TRACE_CONTEXT(AbstractVideoPlayer::MvpuoEvent, EVideoApi);
       
   313     TRACE_ENTRY("state %d", state());
       
   314 
       
   315     Q_UNUSED(aEvent);
       
   316 
       
   317     TRACE_EXIT_0();
       
   318 }
       
   319 
       
   320 
       
   321 //-----------------------------------------------------------------------------
       
   322 // MVideoLoadingObserver callbacks
       
   323 //-----------------------------------------------------------------------------
       
   324 
       
   325 void MMF::AbstractVideoPlayer::MvloLoadingStarted()
       
   326 {
       
   327     bufferingStarted();
       
   328 }
       
   329 
       
   330 void MMF::AbstractVideoPlayer::MvloLoadingComplete()
       
   331 {
       
   332     bufferingComplete();
       
   333 }
       
   334 
       
   335 
       
   336 //-----------------------------------------------------------------------------
       
   337 // Video window updates
       
   338 //-----------------------------------------------------------------------------
       
   339 
       
   340 void MMF::AbstractVideoPlayer::videoOutputChanged()
       
   341 {
       
   342     TRACE_CONTEXT(AbstractVideoPlayer::videoOutputChanged, EVideoInternal);
       
   343     TRACE_ENTRY_0();
       
   344 
       
   345     if (m_videoOutput)
       
   346         initVideoOutput();
       
   347 
       
   348     videoWindowChanged();
       
   349 
       
   350     TRACE_EXIT_0();
       
   351 }
       
   352 
       
   353 void MMF::AbstractVideoPlayer::initVideoOutput()
       
   354 {
       
   355     bool connected = connect(
       
   356         m_videoOutput, SIGNAL(videoWindowChanged()),
       
   357         this, SLOT(videoWindowChanged())
       
   358     );
       
   359     Q_ASSERT(connected);
       
   360 
       
   361     connected = connect(
       
   362         m_videoOutput, SIGNAL(aspectRatioChanged()),
       
   363         this, SLOT(aspectRatioChanged())
       
   364     );
       
   365     Q_ASSERT(connected);
       
   366 
       
   367     connected = connect(
       
   368         m_videoOutput, SIGNAL(scaleModeChanged()),
       
   369         this, SLOT(scaleModeChanged())
       
   370     );
       
   371     Q_ASSERT(connected);
       
   372 
       
   373     // Suppress warnings in release builds
       
   374     Q_UNUSED(connected);
       
   375 
       
   376     // Do these after all connections are complete, to ensure
       
   377     // that any signals generated get to their destinations.
       
   378     m_videoOutput->winId();
       
   379     m_videoOutput->setVideoSize(m_videoFrameSize);
       
   380 }
       
   381 
       
   382 // Helper function for aspect ratio / scale mode handling
       
   383 QSize scaleToAspect(const QSize &srcRect, int aspectWidth, int aspectHeight)
       
   384 {
       
   385     const qreal aspectRatio = qreal(aspectWidth) / aspectHeight;
       
   386 
       
   387     int width = srcRect.width();
       
   388     int height = srcRect.width() / aspectRatio;
       
   389     if (height > srcRect.height()){
       
   390         height = srcRect.height();
       
   391         width = srcRect.height() * aspectRatio;
       
   392     }
       
   393     return QSize(width, height);
       
   394 }
       
   395 
       
   396 void MMF::AbstractVideoPlayer::updateScaleFactors(const QSize &windowSize, bool apply)
       
   397 {
       
   398     if (m_videoFrameSize.isValid()) {
       
   399         QRect videoRect;
       
   400 
       
   401         // Calculate size of smallest rect which contains video frame size
       
   402         // and conforms to aspect ratio
       
   403         switch (m_videoOutput->aspectRatio()) {
       
   404         case Phonon::VideoWidget::AspectRatioAuto:
       
   405             videoRect.setSize(m_videoFrameSize);
       
   406             break;
       
   407 
       
   408         case Phonon::VideoWidget::AspectRatioWidget:
       
   409             videoRect.setSize(windowSize);
       
   410             break;
       
   411 
       
   412         case Phonon::VideoWidget::AspectRatio4_3:
       
   413             videoRect.setSize(scaleToAspect(m_videoFrameSize, 4, 3));
       
   414             break;
       
   415 
       
   416         case Phonon::VideoWidget::AspectRatio16_9:
       
   417             videoRect.setSize(scaleToAspect(m_videoFrameSize, 16, 9));
       
   418             break;
       
   419         }
       
   420 
       
   421         // Scale to fill the window width
       
   422         const int windowWidth = windowSize.width();
       
   423         const int windowHeight = windowSize.height();
       
   424         const qreal windowScaleFactor = qreal(windowWidth) / videoRect.width();
       
   425         int videoWidth = windowWidth;
       
   426         int videoHeight = videoRect.height() * windowScaleFactor;
       
   427 
       
   428         const qreal windowToVideoHeightRatio = qreal(windowHeight) / videoHeight;
       
   429 
       
   430         switch (m_videoOutput->scaleMode()) {
       
   431         case Phonon::VideoWidget::ScaleAndCrop:
       
   432             if (videoHeight < windowHeight) {
       
   433                 videoWidth *= windowToVideoHeightRatio;
       
   434                 videoHeight = windowHeight;
       
   435             }
       
   436             break;
       
   437         case Phonon::VideoWidget::FitInView:
       
   438         default:
       
   439             if (videoHeight > windowHeight) {
       
   440                 videoWidth *= windowToVideoHeightRatio;
       
   441                 videoHeight = windowHeight;
       
   442             }
       
   443             break;
       
   444         }
       
   445 
       
   446         // Calculate scale factors
       
   447         m_scaleWidth = 100.0f * videoWidth / m_videoFrameSize.width();
       
   448         m_scaleHeight = 100.0f * videoHeight / m_videoFrameSize.height();
       
   449 
       
   450         if (apply)
       
   451             parametersChanged(ScaleFactors);
       
   452     }
       
   453 }
       
   454 
       
   455 void MMF::AbstractVideoPlayer::parametersChanged(VideoParameters parameters)
       
   456 {
       
   457     if (state() == LoadingState)
       
   458         m_pendingChanges |= parameters;
       
   459     else
       
   460         handleParametersChanged(parameters);
       
   461 }
       
   462 
       
   463 void MMF::AbstractVideoPlayer::handlePendingParametersChanged()
       
   464 {
       
   465     if (m_pendingChanges)
       
   466         handleParametersChanged(m_pendingChanges);
       
   467     m_pendingChanges = 0;
       
   468 }
       
   469 
       
   470 
       
   471 //-----------------------------------------------------------------------------
       
   472 // Metadata
       
   473 //-----------------------------------------------------------------------------
       
   474 
       
   475 int MMF::AbstractVideoPlayer::numberOfMetaDataEntries() const
       
   476 {
       
   477     int numberOfEntries = 0;
       
   478     TRAP_IGNORE(numberOfEntries = m_player->NumberOfMetaDataEntriesL());
       
   479     return numberOfEntries;
       
   480 }
       
   481 
       
   482 QPair<QString, QString> MMF::AbstractVideoPlayer::metaDataEntry(int index) const
       
   483 {
       
   484     CMMFMetaDataEntry *entry = 0;
       
   485     QT_TRAP_THROWING(entry = m_player->MetaDataEntryL(index));
       
   486     return QPair<QString, QString>(qt_TDesC2QString(entry->Name()), qt_TDesC2QString(entry->Value()));
       
   487 }
       
   488 
       
   489 QT_END_NAMESPACE
       
   490