From 109e04933e4e6b51a3e546f9dc3f0a062eb8470e Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Tue, 18 Aug 2009 18:30:53 +0100 Subject: Started work on VideoPlayer implementation --- src/3rdparty/phonon/mmf/abstractmediaplayer.cpp | 16 +++-- src/3rdparty/phonon/mmf/abstractmediaplayer.h | 8 ++- src/3rdparty/phonon/mmf/audioplayer.cpp | 32 ++++----- src/3rdparty/phonon/mmf/audioplayer.h | 9 +-- src/3rdparty/phonon/mmf/mediaobject.cpp | 80 ++++++++++++++-------- src/3rdparty/phonon/mmf/mediaobject.h | 61 ++++------------- src/3rdparty/phonon/mmf/utils.h | 12 +++- src/3rdparty/phonon/mmf/videoplayer.cpp | 91 +++++++++++++++++++++++-- src/3rdparty/phonon/mmf/videoplayer.h | 24 ++++--- src/plugins/phonon/mmf/mmf.pro | 4 ++ 10 files changed, 214 insertions(+), 123 deletions(-) diff --git a/src/3rdparty/phonon/mmf/abstractmediaplayer.cpp b/src/3rdparty/phonon/mmf/abstractmediaplayer.cpp index a3affef..703590b 100644 --- a/src/3rdparty/phonon/mmf/abstractmediaplayer.cpp +++ b/src/3rdparty/phonon/mmf/abstractmediaplayer.cpp @@ -178,13 +178,8 @@ void MMF::AbstractMediaPlayer::setTickInterval(qint32 interval) Phonon::ErrorType MMF::AbstractMediaPlayer::errorType() const { - TRACE_CONTEXT(AbstractMediaPlayer::errorType, EAudioApi); - TRACE_ENTRY("state %d", m_state); - const Phonon::ErrorType result = (ErrorState == m_state) ? m_error : NoError; - - TRACE_RETURN("%d", result); } QString MMF::AbstractMediaPlayer::errorString() const @@ -466,6 +461,17 @@ void MMF::AbstractMediaPlayer::changeState(PrivateState newState) TRACE_EXIT_0(); } +void MMF::AbstractMediaPlayer::setError(Phonon::ErrorType error) +{ + TRACE_CONTEXT(AbstractMediaPlayer::setError, EAudioInternal); + TRACE_ENTRY("state %d error %d", m_state, error); + + m_error = error; + changeState(ErrorState); + + TRACE_EXIT_0(); +} + qint64 MMF::AbstractMediaPlayer::toMilliSeconds(const TTimeIntervalMicroSeconds &in) { return in.Int64() / 1000; diff --git a/src/3rdparty/phonon/mmf/abstractmediaplayer.h b/src/3rdparty/phonon/mmf/abstractmediaplayer.h index 6f7ae1d..9f86ee6 100644 --- a/src/3rdparty/phonon/mmf/abstractmediaplayer.h +++ b/src/3rdparty/phonon/mmf/abstractmediaplayer.h @@ -111,6 +111,11 @@ namespace Phonon */ void changeState(PrivateState newState); + /** + * Records error and changes state to ErrorState + */ + void setError(Phonon::ErrorType error); + static qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &); Q_SIGNALS: @@ -124,11 +129,10 @@ namespace Phonon */ void tick(); - protected: // Temporary + private: PrivateState m_state; Phonon::ErrorType m_error; - private: qint32 m_tickInterval; QScopedPointer m_tickTimer; qreal m_volume; diff --git a/src/3rdparty/phonon/mmf/audioplayer.cpp b/src/3rdparty/phonon/mmf/audioplayer.cpp index 45105ee..ec29ac1 100644 --- a/src/3rdparty/phonon/mmf/audioplayer.cpp +++ b/src/3rdparty/phonon/mmf/audioplayer.cpp @@ -33,11 +33,13 @@ MMF::AudioPlayer::AudioPlayer() : m_player(NULL) TRACE_CONTEXT(AudioPlayer::AudioPlayer, EAudioApi); TRACE_ENTRY_0(); - Q_UNUSED(parent); - - // TODO: should leaves be trapped in the constructor? - m_player = CPlayerType::NewL(*this, 0, EMdaPriorityPreferenceNone); - + // TODO: is this the correct way to handle errors in constructing Symbian objects? + TRAPD(err, m_player = CPlayerType::NewL(*this, 0, EMdaPriorityPreferenceNone)); + if(KErrNone != err) + { + changeState(ErrorState); + } + TRACE_EXIT_0(); } @@ -101,7 +103,7 @@ void MMF::AudioPlayer::close() void MMF::AudioPlayer::seek(qint64 ms) { TRACE_CONTEXT(AudioPlayer::seek, EAudioApi); - TRACE_ENTRY("state %d pos %Ld", m_state, ms); + TRACE_ENTRY("state %d pos %Ld", state(), ms); m_player->SetPosition(TTimeIntervalMicroSeconds(ms)); @@ -111,14 +113,14 @@ void MMF::AudioPlayer::seek(qint64 ms) bool MMF::AudioPlayer::hasVideo() const { TRACE_CONTEXT(AudioPlayer::hasVideo, EAudioApi); - TRACE_ENTRY("state %d", m_state); + TRACE_ENTRY("state %d", state()); TRACE_RETURN("%d", false); } qint64 MMF::AudioPlayer::currentTime() const { TRACE_CONTEXT(AudioPlayer::currentTime, EAudioApi); - TRACE_ENTRY("state %d", m_state); + TRACE_ENTRY("state %d", state()); TTimeIntervalMicroSeconds us; const TInt err = m_player->GetPosition(us); @@ -135,7 +137,7 @@ qint64 MMF::AudioPlayer::currentTime() const qint64 MMF::AudioPlayer::totalTime() const { TRACE_CONTEXT(AudioPlayer::totalTime, EAudioApi); - TRACE_ENTRY("state %d", m_state); + TRACE_ENTRY("state %d", state()); const qint64 result = toMilliSeconds(m_player->Duration()); @@ -156,9 +158,9 @@ void MMF::AudioPlayer::MapcInitComplete(TInt aError, #endif { TRACE_CONTEXT(AudioPlayer::MapcInitComplete, EAudioInternal); - TRACE_ENTRY("state %d error %d", m_state, aError); + TRACE_ENTRY("state %d error %d", state(), aError); - __ASSERT_ALWAYS(LoadingState == m_state, Utils::panic(InvalidStatePanic)); + __ASSERT_ALWAYS(LoadingState == state(), Utils::panic(InvalidStatePanic)); if(KErrNone == aError) { @@ -175,8 +177,7 @@ void MMF::AudioPlayer::MapcInitComplete(TInt aError, else { // TODO: set different error states according to value of aError? - m_error = NormalError; - changeState(ErrorState); + setError(NormalError); } TRACE_EXIT_0(); @@ -189,7 +190,7 @@ void MMF::AudioPlayer::MapcPlayComplete(TInt aError) #endif { TRACE_CONTEXT(AudioPlayer::MapcPlayComplete, EAudioInternal); - TRACE_ENTRY("state %d error %d", m_state, aError); + TRACE_ENTRY("state %d error %d", state(), aError); stopTickTimer(); @@ -201,8 +202,7 @@ void MMF::AudioPlayer::MapcPlayComplete(TInt aError) else { // TODO: do something with aError? - m_error = NormalError; - changeState(ErrorState); + setError(NormalError); } /* diff --git a/src/3rdparty/phonon/mmf/audioplayer.h b/src/3rdparty/phonon/mmf/audioplayer.h index f58ee0d..39e55d9 100644 --- a/src/3rdparty/phonon/mmf/audioplayer.h +++ b/src/3rdparty/phonon/mmf/audioplayer.h @@ -23,7 +23,6 @@ along with this library. If not, see . class CDrmPlayerUtility; class TTimeIntervalMicroSeconds; -class QTimer; #ifdef QT_PHONON_MMF_AUDIO_DRM #include @@ -39,18 +38,16 @@ namespace Phonon { namespace MMF { - class AudioOutput; - /** * * See * How to * play a video file using CVideoPlayerUtility */ - class AudioPlayer : public AbstractMediaPlayer - , public MPlayerObserverType // typedef + class AudioPlayer : public AbstractMediaPlayer + , public MPlayerObserverType // typedef #ifdef QT_PHONON_MMF_AUDIO_DRM - , public MAudioLoadingObserver + , public MAudioLoadingObserver #endif { Q_OBJECT diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp index 62dc903..5b0ac36 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.cpp +++ b/src/3rdparty/phonon/mmf/mediaobject.cpp @@ -29,25 +29,14 @@ using namespace Phonon::MMF; // Constructor / destructor //----------------------------------------------------------------------------- -MMF::MediaObject::MediaObject(QObject *parent) : QObject::QObject(parent) +MMF::MediaObject::MediaObject(QObject *parent) : QObject::QObject(parent) + , m_recognizerOpened(false) { TRACE_CONTEXT(MediaObject::MediaObject, EAudioApi); TRACE_ENTRY_0(); Q_UNUSED(parent); - TInt err = m_recognizer.Connect(); - err = m_fileServer.Connect(); - // TODO: handle this error - - // This must be called in order to be able to share file handles with - // the recognizer server (see fileMediaType function). - err = m_fileServer.ShareProtected(); - // TODO: handle this error - - m_tickTimer = new QTimer(this); - connect(m_tickTimer, SIGNAL(timeout()), this, SLOT(tick())); - TRACE_EXIT_0(); } @@ -56,8 +45,6 @@ MMF::MediaObject::~MediaObject() TRACE_CONTEXT(MediaObject::~MediaObject, EAudioApi); TRACE_ENTRY_0(); - delete m_tickTimer; - m_file.Close(); m_fileServer.Close(); m_recognizer.Close(); @@ -70,6 +57,36 @@ MMF::MediaObject::~MediaObject() // Recognizer //----------------------------------------------------------------------------- +bool MMF::MediaObject::openRecognizer() +{ + if(!m_recognizerOpened) + { + TInt err = m_recognizer.Connect(); + if(KErrNone != err) + { + return false; + } + + err = m_fileServer.Connect(); + if(KErrNone != err) + { + return false; + } + + // This must be called in order to be able to share file handles with + // the recognizer server (see fileMediaType function). + err = m_fileServer.ShareProtected(); + if(KErrNone != err) + { + return false; + } + + m_recognizerOpened = true; + } + + return true; +} + const TInt KMimePrefixLength = 6; // either "audio/" or "video/" _LIT(KMimePrefixAudio, "audio/"); _LIT(KMimePrefixVideo, "video/"); @@ -96,21 +113,25 @@ MMF::MediaObject::MediaType MMF::MediaObject::fileMediaType { MediaType result = MediaTypeUnknown; - QHBufC fileNameSymbian = Utils::symbianFilename(fileName); + if(openRecognizer()) + { + QHBufC fileNameSymbian = Utils::symbianFilename(fileName); + + m_file.Close(); + TInt err = m_file.Open(m_fileServer, *fileNameSymbian, EFileRead|EFileShareReadersOnly); - m_file.Close(); - TInt err = m_file.Open(m_fileServer, *fileNameSymbian, EFileRead|EFileShareReadersOnly); - - if(KErrNone == err) - { - TDataRecognitionResult recognizerResult; - err = m_recognizer.RecognizeData(m_file, recognizerResult); if(KErrNone == err) { - const TPtrC mimeType = recognizerResult.iDataType.Des(); - result = mimeTypeToMediaType(mimeType); + TDataRecognitionResult recognizerResult; + err = m_recognizer.RecognizeData(m_file, recognizerResult); + if(KErrNone == err) + { + const TPtrC mimeType = recognizerResult.iDataType.Des(); + result = mimeTypeToMediaType(mimeType); + } } } + return result; } @@ -251,7 +272,7 @@ MediaSource MMF::MediaObject::source() const void MMF::MediaObject::setSource(const MediaSource &source) { - loadPlayer(source); + createPlayer(source); if(!m_player.isNull()) { //m_player->setSource(source); @@ -262,11 +283,10 @@ void MMF::MediaObject::setSource(const MediaSource &source) } } -void MMF::MediaObject::loadPlayer(const MediaSource &source) +void MMF::MediaObject::createPlayer(const MediaSource &source) { - TRACE_CONTEXT(AudioPlayer::loadPlayer, EAudioApi); - //TRACE_ENTRY("state %d source.type %d", m_state, source.type()); - // TODO: log state + TRACE_CONTEXT(AudioPlayer::createPlayer, EAudioApi); + TRACE_ENTRY("state %d source.type %d", state(), source.type()); TRACE_ENTRY("source.type %d", source.type()); // Destroy old player object diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h index 2eb70c3..9c39884 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.h +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -79,63 +79,28 @@ namespace Phonon Phonon::State newState); void finished(); void tick(qint64 time); - - private: - static qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &); - -// The following has been moved into the AbstractPlayer-derived classes -// This needs to be cleaned up - at present, there is no way for this class -// to enter an error state, unless it has already constructed m_player -#if 0 - /** - * Defined private state enumeration in order to add GroundState - */ - enum PrivateState - { - LoadingState = Phonon::LoadingState, - StoppedState = Phonon::StoppedState, - PlayingState = Phonon::PlayingState, - BufferingState = Phonon::BufferingState, - PausedState = Phonon::PausedState, - ErrorState = Phonon::ErrorState, - GroundState - }; - - /** - * Converts PrivateState into the corresponding Phonon::State - */ - static Phonon::State phononState(PrivateState state); - - /** - * Changes state and emits stateChanged() - */ - void changeState(PrivateState newState); - ErrorType m_error; - PrivateState m_state; -#endif + private: + void createPlayer(const MediaSource &source); + bool openRecognizer(); - RApaLsSession m_recognizer; - RFs m_fileServer; - enum MediaType { MediaTypeUnknown, MediaTypeAudio, MediaTypeVideo }; + // Audio / video media type recognition + enum MediaType { MediaTypeUnknown, MediaTypeAudio, MediaTypeVideo }; MediaType mimeTypeToMediaType(const TDesC& mimeType); MediaType fileMediaType(const QString& fileName); // TODO: urlMediaType function + + static qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &); + + private: + // Audio / video media type recognition + bool m_recognizerOpened; + RApaLsSession m_recognizer; + RFs m_fileServer; // Storing the file handle here to work around KErrInUse error // from MMF player utility OpenFileL functions RFile m_file; - - AudioOutput* m_audioOutput; - - qint32 m_tickInterval; - - QTimer* m_tickTimer; - - qreal m_volume; - int m_maxVolume; - - void loadPlayer(const MediaSource &source); QScopedPointer m_player; }; diff --git a/src/3rdparty/phonon/mmf/utils.h b/src/3rdparty/phonon/mmf/utils.h index 51470cd..e3e7317 100644 --- a/src/3rdparty/phonon/mmf/utils.h +++ b/src/3rdparty/phonon/mmf/utils.h @@ -65,7 +65,17 @@ namespace Phonon /** * Internal functions in the audio implementation */ - EAudioInternal = 0x00000002 + EAudioInternal = 0x00000002, + + /** + * Functions which map directly to the public Phonon video API + */ + EVideoApi = 0x00010000, + + /** + * Internal functions in the video implementation + */ + EVideoInternal = 0x00020000 }; /** diff --git a/src/3rdparty/phonon/mmf/videoplayer.cpp b/src/3rdparty/phonon/mmf/videoplayer.cpp index 3ffa3e7..3cf468a 100644 --- a/src/3rdparty/phonon/mmf/videoplayer.cpp +++ b/src/3rdparty/phonon/mmf/videoplayer.cpp @@ -19,6 +19,8 @@ along with this library. If not, see . #include #include +#include // For CCoeEnv + #include "videoplayer.h" #include "utils.h" @@ -33,15 +35,44 @@ MMF::VideoPlayer::VideoPlayer() { TRACE_CONTEXT(VideoPlayer::VideoPlayer, EAudioApi); TRACE_ENTRY_0(); - - // TODO + + const TInt priority = 0; + const TMdaPriorityPreference preference = EMdaPriorityPreferenceNone; + CCoeEnv* coeEnv = CCoeEnv::Static(); + RWsSession& wsSession = coeEnv->WsSession(); + CWsScreenDevice& screenDevice = *(coeEnv->ScreenDevice()); + /* DUMMY */ RWindow window; + /* DUMMY */ TRect screenRect; + /* DUMMY */ TRect clipRect; + + // TODO: is this the correct way to handle errors in constructing Symbian objects? + TRAPD(err, + m_player = CVideoPlayerUtility::NewL + ( + *this, + priority, preference, + wsSession, screenDevice, + window, + screenRect, clipRect + ) + ); + + if(KErrNone != err) + { + changeState(ErrorState); + } TRACE_EXIT_0(); } MMF::VideoPlayer::~VideoPlayer() { - // TODO + TRACE_CONTEXT(VideoPlayer::~VideoPlayer, EVideoApi); + TRACE_ENTRY_0(); + + delete m_player; + + TRACE_EXIT_0(); } //----------------------------------------------------------------------------- @@ -107,10 +138,60 @@ qint64 MMF::VideoPlayer::totalTime() const //----------------------------------------------------------------------------- -// Symbian multimedia client observer callbacks +// MVideoPlayerUtilityObserver callbacks //----------------------------------------------------------------------------- -// TODO +void MMF::VideoPlayer::MvpuoOpenComplete(TInt aError) +{ + TRACE_CONTEXT(VideoPlayer::MvpuoOpenComplete, EVideoApi); + TRACE_ENTRY("state %d error %d", state(), aError); + + // TODO + + TRACE_EXIT_0(); +} + +void MMF::VideoPlayer::MvpuoPrepareComplete(TInt aError) +{ + TRACE_CONTEXT(VideoPlayer::MvpuoPrepareComplete, EVideoApi); + TRACE_ENTRY("state %d error %d", state(), aError); + + // TODO + + TRACE_EXIT_0(); +} + +void MMF::VideoPlayer::MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError) +{ + TRACE_CONTEXT(VideoPlayer::MvpuoFrameReady, EVideoApi); + TRACE_ENTRY("state %d error %d", state(), aError); + + // TODO + Q_UNUSED(aFrame); + + TRACE_EXIT_0(); +} + +void MMF::VideoPlayer::MvpuoPlayComplete(TInt aError) +{ + TRACE_CONTEXT(VideoPlayer::MvpuoPlayComplete, EVideoApi) + TRACE_ENTRY("state %d error %d", state(), aError); + + // TODO + + TRACE_EXIT_0(); +} + +void MMF::VideoPlayer::MvpuoEvent(const TMMFEvent &aEvent) +{ + TRACE_CONTEXT(VideoPlayer::MvpuoEvent, EVideoApi); + TRACE_ENTRY("state %d", state()); + + // TODO + Q_UNUSED(aEvent); + + TRACE_EXIT_0(); +} diff --git a/src/3rdparty/phonon/mmf/videoplayer.h b/src/3rdparty/phonon/mmf/videoplayer.h index 65133c2..a10bee3 100644 --- a/src/3rdparty/phonon/mmf/videoplayer.h +++ b/src/3rdparty/phonon/mmf/videoplayer.h @@ -19,30 +19,24 @@ along with this library. If not, see . #ifndef PHONON_MMF_VIDEOPLAYER_H #define PHONON_MMF_VIDEOPLAYER_H -/* We use the extra qualification include/ to avoid picking up the include - * Phonon has. */ #include -#include "abstractmediaplayer.h" -#include +#include "abstractmediaplayer.h" -class CDrmPlayerUtility; -class TTimeIntervalMicroSeconds; -class QTimer; +class CVideoPlayerUtility; namespace Phonon { namespace MMF { - class AudioOutput; - /** * * See * How to * play a video file using CVideoPlayerUtility */ - class VideoPlayer : public AbstractMediaPlayer + class VideoPlayer : public AbstractMediaPlayer + , public MVideoPlayerUtilityObserver { Q_OBJECT public: @@ -62,11 +56,21 @@ namespace Phonon virtual qint64 currentTime() const; virtual qint64 totalTime() const; + // MVideoPlayerUtilityObserver + virtual void MvpuoOpenComplete(TInt aError); + virtual void MvpuoPrepareComplete(TInt aError); + virtual void MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError); + virtual void MvpuoPlayComplete(TInt aError); + virtual void MvpuoEvent(const TMMFEvent &aEvent); + Q_SIGNALS: void totalTimeChanged(); void stateChanged(Phonon::State oldState, Phonon::State newState); void finished(); + + private: + CVideoPlayerUtility* m_player; }; } diff --git a/src/plugins/phonon/mmf/mmf.pro b/src/plugins/phonon/mmf/mmf.pro index 040a6a7..4a4d856 100644 --- a/src/plugins/phonon/mmf/mmf.pro +++ b/src/plugins/phonon/mmf/mmf.pro @@ -21,6 +21,10 @@ phonon_mmf_audio_drm { LIBS += -lmediaclientaudio.lib } +LIBS += -lmediaclientvideo.lib # For CVideoPlayerUtility +LIBS += -lcone.lib # For CCoeEnv +LIBS += -lws32.lib # For RWindow + HEADERS += \ $$PHONON_MMF_DIR/abstractplayer.h \ $$PHONON_MMF_DIR/abstractmediaplayer.h \ -- cgit v0.12