summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/phonon/qt7/mediaobject.mm
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@trolltech.com>2010-03-30 13:49:21 (GMT)
committerOlivier Goffart <ogoffart@trolltech.com>2010-03-30 13:49:21 (GMT)
commit00f7426f3906361fb5addb36e428648eee5e2983 (patch)
treec299b0f6f323ea2f37161cfdf5b2fb33bbe35673 /src/3rdparty/phonon/qt7/mediaobject.mm
parent429b747d492ef038c2ed58a9a72060d951721252 (diff)
parentae305abfdb795b472b2b9d200bf3b11af00d7d1f (diff)
downloadQt-00f7426f3906361fb5addb36e428648eee5e2983.zip
Qt-00f7426f3906361fb5addb36e428648eee5e2983.tar.gz
Qt-00f7426f3906361fb5addb36e428648eee5e2983.tar.bz2
Merge remote branch 'origin/4.7' into 4.7
Conflicts: src/3rdparty/phonon/ds9/iodevicereader.cpp
Diffstat (limited to 'src/3rdparty/phonon/qt7/mediaobject.mm')
-rw-r--r--src/3rdparty/phonon/qt7/mediaobject.mm306
1 files changed, 88 insertions, 218 deletions
diff --git a/src/3rdparty/phonon/qt7/mediaobject.mm b/src/3rdparty/phonon/qt7/mediaobject.mm
index 677640c..002c337 100644
--- a/src/3rdparty/phonon/qt7/mediaobject.mm
+++ b/src/3rdparty/phonon/qt7/mediaobject.mm
@@ -46,6 +46,7 @@ MediaObject::MediaObject(QObject *parent) : MediaNode(AudioSource | VideoSource,
m_mediaObjectAudioNode = new MediaObjectAudioNode(m_audioPlayer, m_nextAudioPlayer);
setAudioNode(m_mediaObjectAudioNode);
+ m_metaData = new QuickTimeMetaData();
m_audioGraph = new AudioGraph(this);
m_tickInterval = 0;
@@ -54,7 +55,6 @@ MediaObject::MediaObject(QObject *parent) : MediaNode(AudioSource | VideoSource,
m_transitionTime = 0;
m_percentageLoaded = 0;
m_waitNextSwap = false;
- m_autoplayTitles = true;
m_audioEffectCount = 0;
m_audioOutputCount = 0;
m_videoEffectCount = 0;
@@ -63,28 +63,20 @@ MediaObject::MediaObject(QObject *parent) : MediaNode(AudioSource | VideoSource,
m_errorType = Phonon::NoError;
m_tickTimer = 0;
- m_videoTimer = 0;
- m_audioTimer = 0;
+ m_bufferTimer = 0;
m_rapidTimer = 0;
-#if QT_ALLOW_QUICKTIME
- m_displayLink = 0;
- m_pendingDisplayLinkEvent = false;
-#endif
-
checkForError();
}
MediaObject::~MediaObject()
-{
- // m_mediaObjectAudioNode is owned by super class.
-#if QT_ALLOW_QUICKTIME
- stopDisplayLink();
-#endif
+{
+ // m_mediaObjectAudioNode is owned by super class.
m_audioPlayer->unsetVideoPlayer();
m_nextAudioPlayer->unsetVideoPlayer();
delete m_videoPlayer;
delete m_nextVideoPlayer;
+ delete m_metaData;
checkForError();
}
@@ -96,7 +88,7 @@ bool MediaObject::setState(Phonon::State state)
emit stateChanged(m_state, prevState);
if (m_state != state){
// End-application did something
- // upon receiving the signal.
+ // upon receiving the signal.
return false;
}
}
@@ -130,7 +122,7 @@ void MediaObject::inspectGraph()
// Inspect the graph to check wether there are any
// effects or outputs connected. This will have
// influence on the audio system and video system that ends up beeing used:
- int prevVideoOutputCount = m_videoOutputCount;
+ int prevVideoOutputCount = m_videoOutputCount;
m_audioEffectCount = 0;
m_audioOutputCount = 0;
m_videoEffectCount = 0;
@@ -142,7 +134,7 @@ void MediaObject::inspectGraph()
if (m_videoOutputCount != prevVideoOutputCount){
MediaNodeEvent e1(MediaNodeEvent::VideoOutputCountChanged, &m_videoOutputCount);
notify(&e1);
- }
+ }
}
void MediaObject::setupAudioSystem()
@@ -175,14 +167,14 @@ void MediaObject::setupAudioSystem()
if (newAudioSystem == m_audioSystem)
return;
-
+
// Enable selected audio system:
- m_audioSystem = newAudioSystem;
+ m_audioSystem = newAudioSystem;
switch (newAudioSystem){
case AS_Silent:
m_audioGraph->stop();
m_videoPlayer->enableAudio(false);
- m_nextVideoPlayer->enableAudio(false);
+ m_nextVideoPlayer->enableAudio(false);
m_audioPlayer->enableAudio(false);
m_nextAudioPlayer->enableAudio(false);
break;
@@ -222,28 +214,28 @@ void MediaObject::setSource(const MediaSource &source)
IMPLEMENTED;
PhononAutoReleasePool pool;
setState(Phonon::LoadingState);
-
+
// Save current state for event/signal handling below:
bool prevHasVideo = m_videoPlayer->hasVideo();
qint64 prevTotalTime = totalTime();
- int prevTrackCount = m_videoPlayer->trackCount();
m_waitNextSwap = false;
-
+
// Cancel cross-fade if any:
m_nextVideoPlayer->pause();
m_nextAudioPlayer->pause();
m_mediaObjectAudioNode->cancelCrossFade();
-
+
// Set new source:
m_audioPlayer->unsetVideoPlayer();
m_videoPlayer->setMediaSource(source);
m_audioPlayer->setVideoPlayer(m_videoPlayer);
+ m_metaData->setVideo(m_videoPlayer);
- m_audioGraph->updateStreamSpecifications();
+ m_audioGraph->updateStreamSpecifications();
m_nextAudioPlayer->unsetVideoPlayer();
- m_nextVideoPlayer->unsetCurrentMediaSource();
+ m_nextVideoPlayer->unsetVideo();
m_currentTime = 0;
-
+
// Emit/notify information about the new source:
QRect videoRect = m_videoPlayer->videoRect();
MediaNodeEvent e1(MediaNodeEvent::VideoFrameSizeChanged, &videoRect);
@@ -254,14 +246,12 @@ void MediaObject::setSource(const MediaSource &source)
updateVideo(emptyFrame);
emit currentSourceChanged(source);
- emit metaDataChanged(m_videoPlayer->metaData());
+ emit metaDataChanged(m_metaData->metaData());
if (prevHasVideo != m_videoPlayer->hasVideo())
- emit hasVideoChanged(m_videoPlayer->hasVideo());
+ emit hasVideoChanged(m_videoPlayer->hasVideo());
if (prevTotalTime != totalTime())
- emit totalTimeChanged(totalTime());
- if (prevTrackCount != m_videoPlayer->trackCount())
- emit availableTitlesChanged(m_videoPlayer->trackCount());
+ emit totalTimeChanged(totalTime());
if (checkForError())
return;
if (!m_videoPlayer->isDrmAuthorized())
@@ -270,7 +260,7 @@ void MediaObject::setSource(const MediaSource &source)
return;
if (!m_videoPlayer->canPlayMedia())
SET_ERROR("Cannot play media.", FATAL_ERROR)
-
+
// The state might have changed from LoadingState
// as a response to an error state change. So we
// need to check it before stopping:
@@ -297,30 +287,28 @@ void MediaObject::swapCurrentWithNext(qint32 transitionTime)
// Save current state for event/signal handling below:
bool prevHasVideo = m_videoPlayer->hasVideo();
qint64 prevTotalTime = totalTime();
- int prevTrackCount = m_videoPlayer->trackCount();
qSwap(m_audioPlayer, m_nextAudioPlayer);
qSwap(m_videoPlayer, m_nextVideoPlayer);
m_mediaObjectAudioNode->startCrossFade(transitionTime);
m_audioGraph->updateStreamSpecifications();
+ m_metaData->setVideo(m_videoPlayer);
m_waitNextSwap = false;
m_currentTime = 0;
-
+
// Emit/notify information about the new source:
QRect videoRect = m_videoPlayer->videoRect();
MediaNodeEvent e1(MediaNodeEvent::VideoFrameSizeChanged, &videoRect);
notify(&e1);
emit currentSourceChanged(m_videoPlayer->mediaSource());
- emit metaDataChanged(m_videoPlayer->metaData());
+ emit metaDataChanged(m_metaData->metaData());
if (prevHasVideo != m_videoPlayer->hasVideo())
- emit hasVideoChanged(m_videoPlayer->hasVideo());
+ emit hasVideoChanged(m_videoPlayer->hasVideo());
if (prevTotalTime != totalTime())
emit totalTimeChanged(totalTime());
- if (prevTrackCount != m_videoPlayer->trackCount())
- emit availableTitlesChanged(m_videoPlayer->trackCount());
if (checkForError())
return;
if (!m_videoPlayer->isDrmAuthorized())
@@ -339,107 +327,28 @@ void MediaObject::swapCurrentWithNext(qint32 transitionTime)
}
}
-#if QT_ALLOW_QUICKTIME
-static CVReturn displayLinkCallback(CVDisplayLinkRef /*displayLink*/,
- const CVTimeStamp */*inNow*/,
- const CVTimeStamp */*inOutputTime*/,
- CVOptionFlags /*flagsIn*/,
- CVOptionFlags */*flagsOut*/,
- void *userData)
-{
- MediaObject *mediaObject = static_cast<MediaObject *>(userData);
- mediaObject->displayLinkEvent();
- return kCVReturnSuccess;
-}
-
-void MediaObject::displayLinkEvent()
-{
- // This function is called from a
- // thread != gui thread. So we post the event.
- // But we need to make sure that we don't post faster
- // than the event loop can eat:
- m_displayLinkMutex.lock();
- bool pending = m_pendingDisplayLinkEvent;
- m_pendingDisplayLinkEvent = true;
- m_displayLinkMutex.unlock();
-
- if (!pending)
- qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority);
-}
-
-void MediaObject::startDisplayLink()
+void MediaObject::updateTimer(int &timer, int interval)
{
- if (m_displayLink)
- return;
- OSStatus err = CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &m_displayLink);
- if (err != noErr)
- goto fail;
- err = CVDisplayLinkSetCurrentCGDisplay(m_displayLink, kCGDirectMainDisplay);
- if (err != noErr)
- goto fail;
- err = CVDisplayLinkSetOutputCallback(m_displayLink, displayLinkCallback, this);
- if (err != noErr)
- goto fail;
- err = CVDisplayLinkStart(m_displayLink);
- if (err != noErr)
- goto fail;
- return;
-fail:
- stopDisplayLink();
-}
-
-void MediaObject::stopDisplayLink()
-{
- if (!m_displayLink)
- return;
- CVDisplayLinkStop(m_displayLink);
- CFRelease(m_displayLink);
- m_displayLink = 0;
-}
-#endif
-
-void MediaObject::restartAudioVideoTimers()
-{
- if (m_videoTimer)
- killTimer(m_videoTimer);
- if (m_audioTimer)
- killTimer(m_audioTimer);
-
-#if QT_ALLOW_QUICKTIME
- // We prefer to use a display link as timer if available, since
- // it is more steady, and results in better and smoother frame drawing:
- startDisplayLink();
- if (!m_displayLink){
- float fps = m_videoPlayer->staticFps();
- long videoUpdateFrequency = fps ? long(1000.0f / fps) : 0.001;
- m_videoTimer = startTimer(videoUpdateFrequency);
- }
-#else
- float fps = m_videoPlayer->staticFps();
- long videoUpdateFrequency = fps ? long(1000.0f / fps) : 0.001;
- m_videoTimer = startTimer(videoUpdateFrequency);
-#endif
-
- long audioUpdateFrequency = m_audioPlayer->regularTaskFrequency();
- m_audioTimer = startTimer(audioUpdateFrequency);
- updateVideoFrames();
- updateAudioBuffers();
+ if (timer)
+ killTimer(timer);
+ timer = 0;
+ if (interval >= 0)
+ timer = startTimer(interval);
}
void MediaObject::play_internal()
{
// Play main audio/video:
m_videoPlayer->play();
- m_audioPlayer->play();
+ m_audioPlayer->play();
updateLipSynch(0);
// Play old audio/video to finish cross-fade:
if (m_nextVideoPlayer->currentTime() > 0){
m_nextVideoPlayer->play();
m_nextAudioPlayer->play();
}
- restartAudioVideoTimers();
- if (!m_rapidTimer)
- m_rapidTimer = startTimer(100);
+ bufferAudioVideo();
+ updateTimer(m_rapidTimer, 100);
}
void MediaObject::pause_internal()
@@ -449,15 +358,9 @@ void MediaObject::pause_internal()
m_nextAudioPlayer->pause();
m_videoPlayer->pause();
m_nextVideoPlayer->pause();
- killTimer(m_rapidTimer);
- killTimer(m_videoTimer);
- killTimer(m_audioTimer);
- m_rapidTimer = 0;
- m_videoTimer = 0;
- m_audioTimer = 0;
-#if QT_ALLOW_QUICKTIME
- stopDisplayLink();
-#endif
+ updateTimer(m_rapidTimer, -1);
+ updateTimer(m_bufferTimer, -1);
+
if (m_waitNextSwap)
m_swapTimeLeft = m_swapTime.msecsTo(QTime::currentTime());
}
@@ -479,7 +382,7 @@ void MediaObject::play()
if (!m_videoPlayer->canPlayMedia())
return;
if (!setState(Phonon::PlayingState))
- return;
+ return;
if (m_audioSystem == AS_Graph){
m_audioGraph->start();
m_mediaObjectAudioNode->setMute(true);
@@ -520,7 +423,7 @@ void MediaObject::stop()
if (!setState(Phonon::StoppedState))
return;
m_waitNextSwap = false;
- m_nextVideoPlayer->unsetCurrentMediaSource();
+ m_nextVideoPlayer->unsetVideo();
m_nextAudioPlayer->unsetVideoPlayer();
pause_internal();
seek(0);
@@ -532,9 +435,9 @@ void MediaObject::seek(qint64 milliseconds)
IMPLEMENTED;
if (m_state == Phonon::ErrorState)
return;
-
+
// Stop cross-fade if any:
- m_nextVideoPlayer->unsetCurrentMediaSource();
+ m_nextVideoPlayer->unsetVideo();
m_nextAudioPlayer->unsetVideoPlayer();
m_mediaObjectAudioNode->cancelCrossFade();
@@ -543,7 +446,7 @@ void MediaObject::seek(qint64 milliseconds)
m_videoPlayer->seek(milliseconds);
m_audioPlayer->seek(m_videoPlayer->currentTime());
m_mediaObjectAudioNode->setMute(false);
-
+
// Update time and cancel pending swap:
if (m_currentTime < m_videoPlayer->duration())
m_waitNextSwap = false;
@@ -654,7 +557,7 @@ bool MediaObject::isSeekable() const
qint64 MediaObject::currentTime() const
{
IMPLEMENTED_SILENT;
- const_cast<MediaObject *>(this)->updateCurrentTime();
+ const_cast<MediaObject *>(this)->updateCurrentTime();
return m_currentTime;
}
@@ -664,24 +567,19 @@ void MediaObject::updateCurrentTime()
m_currentTime = (m_audioSystem == AS_Graph) ? m_audioPlayer->currentTime() : m_videoPlayer->currentTime();
quint64 total = m_videoPlayer->duration();
- if (m_videoPlayer->currentTrack() < m_videoPlayer->trackCount() - 1){
- // There are still more tracks to play after the current track.
- if (m_autoplayTitles) {
- if (lastUpdateTime < m_currentTime && m_currentTime == total)
- setCurrentTrack(m_videoPlayer->currentTrack() + 1);
- }
- } else if (m_nextVideoPlayer->state() == QuickTimeVideoPlayer::NoMedia){
- // There is no more sources or tracks to play after the current source.
- // Check if it's time to emit aboutToFinish:
- quint32 mark = qMax(quint64(0), qMin(total, total + m_transitionTime - 2000));
- if (lastUpdateTime < mark && mark <= m_currentTime)
- emit aboutToFinish();
-
- // Check if it's time to emit prefinishMarkReached:
- mark = qMax(quint64(0), total - m_prefinishMark);
- if (lastUpdateTime < mark && mark <= m_currentTime)
- emit prefinishMarkReached(total - m_currentTime);
+ // Check if it's time to emit aboutToFinish:
+ quint32 mark = qMax(quint64(0), qMin(total, total + m_transitionTime - 2000));
+ if (lastUpdateTime < mark && mark <= m_currentTime)
+ emit aboutToFinish();
+ // Check if it's time to emit prefinishMarkReached:
+ mark = qMax(quint64(0), total - m_prefinishMark);
+ if (lastUpdateTime < mark && mark <= m_currentTime)
+ emit prefinishMarkReached(total - m_currentTime);
+
+ if (m_nextVideoPlayer->state() == QuickTimeVideoPlayer::NoMedia){
+ // There is no next source in que.
+ // Check if it's time to emit finished:
if (lastUpdateTime < m_currentTime && m_currentTime == total){
emit finished();
m_currentTime = (m_audioSystem == AS_Graph) ? m_audioPlayer->currentTime() : m_videoPlayer->currentTime();
@@ -691,7 +589,7 @@ void MediaObject::updateCurrentTime()
} else {
// We have a next source.
// Check if it's time to swap to next source:
- quint32 mark = qMax(quint64(0), total + m_transitionTime);
+ mark = qMax(quint64(0), total + m_transitionTime);
if (m_waitNextSwap && m_state == Phonon::PlayingState &&
m_transitionTime < m_swapTime.msecsTo(QTime::currentTime())){
swapCurrentWithNext(0);
@@ -794,14 +692,14 @@ bool MediaObject::setAudioDeviceOnMovie(int id)
void MediaObject::updateCrossFade()
{
- m_mediaObjectAudioNode->updateCrossFade(m_currentTime);
+ m_mediaObjectAudioNode->updateCrossFade(m_currentTime);
// Clean-up previous movie if done fading:
if (m_mediaObjectAudioNode->m_fadeDuration == 0){
if (m_nextVideoPlayer->isPlaying() || m_nextAudioPlayer->isPlaying()){
- m_nextVideoPlayer->unsetCurrentMediaSource();
+ m_nextVideoPlayer->unsetVideo();
m_nextAudioPlayer->unsetVideoPlayer();
}
- }
+ }
}
void MediaObject::updateBufferStatus()
@@ -830,7 +728,7 @@ void MediaObject::updateVideoFrames()
// Draw next frame if awailable:
if (m_videoPlayer->videoFrameChanged()){
updateLipSynch(50);
- VideoFrame frame(m_videoPlayer);
+ VideoFrame frame(m_videoPlayer);
if (m_nextVideoPlayer->isPlaying()
&& m_nextVideoPlayer->hasVideo()
&& isCrossFading()){
@@ -838,9 +736,9 @@ void MediaObject::updateVideoFrames()
frame.setBackgroundFrame(bgFrame);
frame.setBaseOpacity(m_mediaObjectAudioNode->m_volume1);
}
-
+
// Send the frame through the graph:
- updateVideo(frame);
+ updateVideo(frame);
checkForError();
}
}
@@ -851,7 +749,7 @@ void MediaObject::updateLipSynch(int allowedOffset)
return;
if (m_videoSinkList.isEmpty() || m_audioSinkList.isEmpty())
return;
-
+
if (m_videoPlayer->hasVideo()){
qint64 diff = m_audioPlayer->currentTime() - m_videoPlayer->currentTime();
if (-allowedOffset > diff || diff > allowedOffset)
@@ -865,6 +763,16 @@ void MediaObject::updateLipSynch(int allowedOffset)
}
}
+void MediaObject::bufferAudioVideo()
+{
+ long nextVideoUpdate = m_videoPlayer->hasVideo() ? 30 : INT_MAX;
+ long nextAudioUpdate = m_audioPlayer->regularTaskFrequency();
+ updateAudioBuffers();
+ updateVideoFrames();
+ if (m_state == Phonon::PlayingState)
+ updateTimer(m_bufferTimer, qMin(nextVideoUpdate, nextAudioUpdate));
+}
+
void MediaObject::updateRapidly()
{
updateCurrentTime();
@@ -889,8 +797,8 @@ void MediaObject::mediaNodeEvent(const MediaNodeEvent *event)
synchAudioVideo();
checkForError();
m_mediaObjectAudioNode->setMute(false);
- if (m_state == Phonon::PlayingState)
- restartAudioVideoTimers();
+ if (m_state == Phonon::PlayingState)
+ bufferAudioVideo();
break;
case MediaNodeEvent::AudioGraphCannotPlay:
case MediaNodeEvent::AudioGraphInitialized:
@@ -901,7 +809,7 @@ void MediaObject::mediaNodeEvent(const MediaNodeEvent *event)
checkForError();
m_mediaObjectAudioNode->setMute(false);
}
- break;
+ break;
default:
break;
}
@@ -910,67 +818,29 @@ void MediaObject::mediaNodeEvent(const MediaNodeEvent *event)
bool MediaObject::event(QEvent *event)
{
switch (event->type()){
-#if QT_ALLOW_QUICKTIME
- case QEvent::User:{
- m_displayLinkMutex.lock();
- m_pendingDisplayLinkEvent = false;
- m_displayLinkMutex.unlock();
- updateVideoFrames();
- break; }
-#endif
- case QEvent::Timer:{
- int timerId = static_cast<QTimerEvent *>(event)->timerId();
- if (timerId == m_rapidTimer)
+ case QEvent::Timer: {
+ QTimerEvent *timerEvent = static_cast<QTimerEvent *>(event);
+ if (timerEvent->timerId() == m_rapidTimer)
updateRapidly();
- else if (timerId == m_tickTimer)
+ else if (timerEvent->timerId() == m_tickTimer)
emit tick(currentTime());
- else if (timerId == m_videoTimer)
- updateVideoFrames();
- else if (timerId == m_audioTimer)
- updateAudioBuffers();
- break; }
+ else if (timerEvent->timerId() == m_bufferTimer)
+ bufferAudioVideo();
+ }
+ break;
default:
break;
}
return QObject::event(event);
}
-void MediaObject::setCurrentTrack(int track)
+bool MediaObject::hasInterface(Interface /*interface*/) const
{
- if (track == m_videoPlayer->currentTrack() || track < 0 || track >= m_videoPlayer->trackCount())
- return;
-
- m_videoPlayer->setCurrentTrack(track);
- emit titleChanged(track);
- emit metaDataChanged(m_videoPlayer->metaData());
+ return false;
}
-bool MediaObject::hasInterface(Interface iface) const
+QVariant MediaObject::interfaceCall(Interface /*interface*/, int /*command*/, const QList<QVariant> &/*arguments*/)
{
- return iface == AddonInterface::TitleInterface;
-}
-
-QVariant MediaObject::interfaceCall(Interface iface, int command, const QList<QVariant> &params)
-{
- switch (iface) {
- case TitleInterface:
- switch (command) {
- case availableTitles:
- return m_videoPlayer->trackCount();
- case title:
- return m_videoPlayer->currentTrack();
- case setTitle:
- setCurrentTrack(params.first().toInt());
- break;
- case autoplayTitles:
- return m_autoplayTitles;
- case setAutoplayTitles:
- m_autoplayTitles = params.first().toBool();
- break;
- }
- default:
- break;
- }
return QVariant();
}