summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/phonon/mmf/abstractvideoplayer.cpp')
-rw-r--r--src/3rdparty/phonon/mmf/abstractvideoplayer.cpp490
1 files changed, 490 insertions, 0 deletions
diff --git a/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp b/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp
new file mode 100644
index 0000000..8cb9db5
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp
@@ -0,0 +1,490 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 2.1 or 3 of the License.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <QUrl>
+#include <QTimer>
+#include <QWidget>
+
+#include <coemain.h> // for CCoeEnv
+
+#include "abstractvideoplayer.h"
+#include "utils.h"
+
+#ifndef QT_NO_DEBUG
+#include "objectdump.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::AbstractVideoPlayer
+ \internal
+*/
+
+//-----------------------------------------------------------------------------
+// Constructor / destructor
+//-----------------------------------------------------------------------------
+
+MMF::AbstractVideoPlayer::AbstractVideoPlayer(MediaObject *parent, const AbstractPlayer *player)
+ : AbstractMediaPlayer(parent, player)
+ , m_wsSession(CCoeEnv::Static()->WsSession())
+ , m_screenDevice(*CCoeEnv::Static()->ScreenDevice())
+ , m_window(0)
+ , m_scaleWidth(1.0)
+ , m_scaleHeight(1.0)
+ , m_totalTime(0)
+{
+
+}
+
+void MMF::AbstractVideoPlayer::construct()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::AbstractVideoPlayer, EVideoApi);
+ TRACE_ENTRY_0();
+
+ if (m_videoOutput) {
+ initVideoOutput();
+ m_window = m_videoOutput->videoWindow();
+ }
+
+ createPlayer();
+
+ TRACE_EXIT_0();
+}
+
+MMF::AbstractVideoPlayer::~AbstractVideoPlayer()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::~AbstractVideoPlayer, EVideoApi);
+ TRACE_ENTRY_0();
+
+ // QObject destructor removes all signal-slot connections involving this
+ // object, so we do not need to disconnect from m_videoOutput here.
+
+ TRACE_EXIT_0();
+}
+
+CVideoPlayerUtility* MMF::AbstractVideoPlayer::nativePlayer() const
+{
+ return m_player.data();
+}
+
+//-----------------------------------------------------------------------------
+// Public API
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractVideoPlayer::doPlay()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::doPlay, EVideoApi);
+
+ handlePendingParametersChanged();
+
+ m_player->Play();
+}
+
+void MMF::AbstractVideoPlayer::doPause()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::doPause, EVideoApi);
+
+ TRAPD(err, m_player->PauseL());
+ if (KErrNone != err && state() != ErrorState) {
+ TRACE("PauseL error %d", err);
+ setError(tr("Pause failed"), err);
+ }
+}
+
+void MMF::AbstractVideoPlayer::doStop()
+{
+ m_player->Stop();
+}
+
+void MMF::AbstractVideoPlayer::doSeek(qint64 ms)
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::doSeek, EVideoApi);
+
+ TRAPD(err, m_player->SetPositionL(TTimeIntervalMicroSeconds(ms * 1000)));
+
+ if (KErrNone != err)
+ setError(tr("Seek failed"), err);
+}
+
+int MMF::AbstractVideoPlayer::setDeviceVolume(int mmfVolume)
+{
+ TRAPD(err, m_player->SetVolumeL(mmfVolume));
+ return err;
+}
+
+int MMF::AbstractVideoPlayer::openFile(RFile &file)
+{
+ TRAPD(err, m_player->OpenFileL(file));
+ return err;
+}
+
+int MMF::AbstractVideoPlayer::openUrl(const QString &url)
+{
+ TRAPD(err, m_player->OpenUrlL(qt_QString2TPtrC(url)));
+ return err;
+}
+
+int MMF::AbstractVideoPlayer::bufferStatus() const
+{
+ int result = 0;
+ TRAP_IGNORE(m_player->GetVideoLoadingProgressL(result));
+ return result;
+}
+
+void MMF::AbstractVideoPlayer::close()
+{
+ m_player->Close();
+}
+
+bool MMF::AbstractVideoPlayer::hasVideo() const
+{
+ return true;
+}
+
+qint64 MMF::AbstractVideoPlayer::currentTime() const
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::currentTime, EVideoApi);
+
+ TTimeIntervalMicroSeconds us;
+ TRAPD(err, us = m_player->PositionL())
+
+ qint64 result = 0;
+
+ if (KErrNone == err) {
+ result = toMilliSeconds(us);
+ } else {
+ TRACE("PositionL error %d", err);
+
+ // If we don't cast away constness here, we simply have to ignore
+ // the error.
+ const_cast<AbstractVideoPlayer*>(this)->setError(tr("Getting position failed"), err);
+ }
+
+ return result;
+}
+
+qint64 MMF::AbstractVideoPlayer::totalTime() const
+{
+ return m_totalTime;
+}
+
+
+//-----------------------------------------------------------------------------
+// Public slots
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractVideoPlayer::videoWindowChanged()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::videoOutputRegionChanged, EVideoInternal);
+ TRACE_ENTRY("state %d", state());
+
+ m_window = m_videoOutput ? m_videoOutput->videoWindow() : 0;
+
+ handleVideoWindowChanged();
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractVideoPlayer::aspectRatioChanged()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::aspectRatioChanged, EVideoInternal);
+ TRACE_ENTRY("state %d aspectRatio %d", state());
+
+ updateScaleFactors(m_videoOutput->videoWindowSize());
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractVideoPlayer::scaleModeChanged()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::scaleModeChanged, EVideoInternal);
+ TRACE_ENTRY("state %d", state());
+
+ updateScaleFactors(m_videoOutput->videoWindowSize());
+
+ TRACE_EXIT_0();
+}
+
+
+//-----------------------------------------------------------------------------
+// MVideoPlayerUtilityObserver callbacks
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractVideoPlayer::MvpuoOpenComplete(TInt aError)
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::MvpuoOpenComplete, EVideoApi);
+ TRACE_ENTRY("state %d error %d", state(), aError);
+
+ __ASSERT_ALWAYS(LoadingState == state(), Utils::panic(InvalidStatePanic));
+
+ if (KErrNone == aError)
+ m_player->Prepare();
+ else
+ setError(tr("Opening clip failed"), aError);
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractVideoPlayer::MvpuoPrepareComplete(TInt aError)
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::MvpuoPrepareComplete, EVideoApi);
+ TRACE_ENTRY("state %d error %d", state(), aError);
+
+ __ASSERT_ALWAYS(LoadingState == state(), Utils::panic(InvalidStatePanic));
+
+ TRAPD(err, getVideoClipParametersL(aError));
+
+ if (KErrNone == err) {
+ maxVolumeChanged(m_player->MaxVolume());
+
+ if (m_videoOutput)
+ m_videoOutput->setVideoSize(m_videoFrameSize);
+
+ prepareCompleted();
+ handlePendingParametersChanged();
+
+ emit totalTimeChanged(totalTime());
+ changeState(StoppedState);
+ } else {
+ setError(tr("Buffering clip failed"), err);
+ }
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractVideoPlayer::getVideoClipParametersL(TInt aError)
+{
+ User::LeaveIfError(aError);
+
+ // Get frame size
+ TSize size;
+ m_player->VideoFrameSizeL(size);
+ m_videoFrameSize = QSize(size.iWidth, size.iHeight);
+
+ // Get duration
+ m_totalTime = toMilliSeconds(m_player->DurationL());
+}
+
+
+void MMF::AbstractVideoPlayer::MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError)
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::MvpuoFrameReady, EVideoApi);
+ TRACE_ENTRY("state %d error %d", state(), aError);
+
+ Q_UNUSED(aFrame);
+ Q_UNUSED(aError); // suppress warnings in release builds
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractVideoPlayer::MvpuoPlayComplete(TInt aError)
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::MvpuoPlayComplete, EVideoApi)
+ TRACE_ENTRY("state %d error %d", state(), aError);
+
+ // Call base class function which handles end of playback for both
+ // audio and video clips.
+ playbackComplete(aError);
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractVideoPlayer::MvpuoEvent(const TMMFEvent &aEvent)
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::MvpuoEvent, EVideoApi);
+ TRACE_ENTRY("state %d", state());
+
+ Q_UNUSED(aEvent);
+
+ TRACE_EXIT_0();
+}
+
+
+//-----------------------------------------------------------------------------
+// MVideoLoadingObserver callbacks
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractVideoPlayer::MvloLoadingStarted()
+{
+ bufferingStarted();
+}
+
+void MMF::AbstractVideoPlayer::MvloLoadingComplete()
+{
+ bufferingComplete();
+}
+
+
+//-----------------------------------------------------------------------------
+// Video window updates
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractVideoPlayer::videoOutputChanged()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::videoOutputChanged, EVideoInternal);
+ TRACE_ENTRY_0();
+
+ if (m_videoOutput)
+ initVideoOutput();
+
+ videoWindowChanged();
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractVideoPlayer::initVideoOutput()
+{
+ bool connected = connect(
+ m_videoOutput, SIGNAL(videoWindowChanged()),
+ this, SLOT(videoWindowChanged())
+ );
+ Q_ASSERT(connected);
+
+ connected = connect(
+ m_videoOutput, SIGNAL(aspectRatioChanged()),
+ this, SLOT(aspectRatioChanged())
+ );
+ Q_ASSERT(connected);
+
+ connected = connect(
+ m_videoOutput, SIGNAL(scaleModeChanged()),
+ this, SLOT(scaleModeChanged())
+ );
+ Q_ASSERT(connected);
+
+ // Suppress warnings in release builds
+ Q_UNUSED(connected);
+
+ // Do these after all connections are complete, to ensure
+ // that any signals generated get to their destinations.
+ m_videoOutput->winId();
+ m_videoOutput->setVideoSize(m_videoFrameSize);
+}
+
+// Helper function for aspect ratio / scale mode handling
+QSize scaleToAspect(const QSize &srcRect, int aspectWidth, int aspectHeight)
+{
+ const qreal aspectRatio = qreal(aspectWidth) / aspectHeight;
+
+ int width = srcRect.width();
+ int height = srcRect.width() / aspectRatio;
+ if (height > srcRect.height()){
+ height = srcRect.height();
+ width = srcRect.height() * aspectRatio;
+ }
+ return QSize(width, height);
+}
+
+void MMF::AbstractVideoPlayer::updateScaleFactors(const QSize &windowSize, bool apply)
+{
+ if (m_videoFrameSize.isValid()) {
+ QRect videoRect;
+
+ // Calculate size of smallest rect which contains video frame size
+ // and conforms to aspect ratio
+ switch (m_videoOutput->aspectRatio()) {
+ case Phonon::VideoWidget::AspectRatioAuto:
+ videoRect.setSize(m_videoFrameSize);
+ break;
+
+ case Phonon::VideoWidget::AspectRatioWidget:
+ videoRect.setSize(windowSize);
+ break;
+
+ case Phonon::VideoWidget::AspectRatio4_3:
+ videoRect.setSize(scaleToAspect(m_videoFrameSize, 4, 3));
+ break;
+
+ case Phonon::VideoWidget::AspectRatio16_9:
+ videoRect.setSize(scaleToAspect(m_videoFrameSize, 16, 9));
+ break;
+ }
+
+ // Scale to fill the window width
+ const int windowWidth = windowSize.width();
+ const int windowHeight = windowSize.height();
+ const qreal windowScaleFactor = qreal(windowWidth) / videoRect.width();
+ int videoWidth = windowWidth;
+ int videoHeight = videoRect.height() * windowScaleFactor;
+
+ const qreal windowToVideoHeightRatio = qreal(windowHeight) / videoHeight;
+
+ switch (m_videoOutput->scaleMode()) {
+ case Phonon::VideoWidget::ScaleAndCrop:
+ if (videoHeight < windowHeight) {
+ videoWidth *= windowToVideoHeightRatio;
+ videoHeight = windowHeight;
+ }
+ break;
+ case Phonon::VideoWidget::FitInView:
+ default:
+ if (videoHeight > windowHeight) {
+ videoWidth *= windowToVideoHeightRatio;
+ videoHeight = windowHeight;
+ }
+ break;
+ }
+
+ // Calculate scale factors
+ m_scaleWidth = 100.0f * videoWidth / m_videoFrameSize.width();
+ m_scaleHeight = 100.0f * videoHeight / m_videoFrameSize.height();
+
+ if (apply)
+ parametersChanged(ScaleFactors);
+ }
+}
+
+void MMF::AbstractVideoPlayer::parametersChanged(VideoParameters parameters)
+{
+ if (state() == LoadingState)
+ m_pendingChanges |= parameters;
+ else
+ handleParametersChanged(parameters);
+}
+
+void MMF::AbstractVideoPlayer::handlePendingParametersChanged()
+{
+ if (m_pendingChanges)
+ handleParametersChanged(m_pendingChanges);
+ m_pendingChanges = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Metadata
+//-----------------------------------------------------------------------------
+
+int MMF::AbstractVideoPlayer::numberOfMetaDataEntries() const
+{
+ int numberOfEntries = 0;
+ TRAP_IGNORE(numberOfEntries = m_player->NumberOfMetaDataEntriesL());
+ return numberOfEntries;
+}
+
+QPair<QString, QString> MMF::AbstractVideoPlayer::metaDataEntry(int index) const
+{
+ CMMFMetaDataEntry *entry = 0;
+ QT_TRAP_THROWING(entry = m_player->MetaDataEntryL(index));
+ return QPair<QString, QString>(qt_TDesC2QString(entry->Name()), qt_TDesC2QString(entry->Value()));
+}
+
+QT_END_NAMESPACE
+