63
63
m_errorType = Phonon::NoError;
70
#if QT_ALLOW_QUICKTIME
72
m_pendingDisplayLinkEvent = false;
72
78
MediaObject::~MediaObject()
74
// m_mediaObjectAudioNode is owned by super class.
80
// m_mediaObjectAudioNode is owned by super class.
81
#if QT_ALLOW_QUICKTIME
75
84
m_audioPlayer->unsetVideoPlayer();
76
85
m_nextAudioPlayer->unsetVideoPlayer();
77
86
delete m_videoPlayer;
78
87
delete m_nextVideoPlayer;
168
176
if (newAudioSystem == m_audioSystem)
171
179
// Enable selected audio system:
172
m_audioSystem = newAudioSystem;
180
m_audioSystem = newAudioSystem;
173
181
switch (newAudioSystem){
175
183
m_audioGraph->stop();
176
184
m_videoPlayer->enableAudio(false);
177
m_nextVideoPlayer->enableAudio(false);
185
m_nextVideoPlayer->enableAudio(false);
178
186
m_audioPlayer->enableAudio(false);
179
187
m_nextAudioPlayer->enableAudio(false);
215
223
PhononAutoReleasePool pool;
216
224
setState(Phonon::LoadingState);
218
226
// Save current state for event/signal handling below:
219
227
bool prevHasVideo = m_videoPlayer->hasVideo();
220
228
qint64 prevTotalTime = totalTime();
229
int prevTrackCount = m_videoPlayer->trackCount();
221
230
m_waitNextSwap = false;
223
232
// Cancel cross-fade if any:
224
233
m_nextVideoPlayer->pause();
225
234
m_nextAudioPlayer->pause();
226
235
m_mediaObjectAudioNode->cancelCrossFade();
228
237
// Set new source:
229
238
m_audioPlayer->unsetVideoPlayer();
230
239
m_videoPlayer->setMediaSource(source);
231
240
m_audioPlayer->setVideoPlayer(m_videoPlayer);
232
m_metaData->setVideo(m_videoPlayer);
234
m_audioGraph->updateStreamSpecifications();
242
m_audioGraph->updateStreamSpecifications();
235
243
m_nextAudioPlayer->unsetVideoPlayer();
236
m_nextVideoPlayer->unsetVideo();
244
m_nextVideoPlayer->unsetCurrentMediaSource();
237
245
m_currentTime = 0;
239
247
// Emit/notify information about the new source:
240
248
QRect videoRect = m_videoPlayer->videoRect();
241
249
MediaNodeEvent e1(MediaNodeEvent::VideoFrameSizeChanged, &videoRect);
246
254
updateVideo(emptyFrame);
248
256
emit currentSourceChanged(source);
249
emit metaDataChanged(m_metaData->metaData());
257
emit metaDataChanged(m_videoPlayer->metaData());
251
259
if (prevHasVideo != m_videoPlayer->hasVideo())
252
emit hasVideoChanged(m_videoPlayer->hasVideo());
260
emit hasVideoChanged(m_videoPlayer->hasVideo());
253
261
if (prevTotalTime != totalTime())
254
emit totalTimeChanged(totalTime());
262
emit totalTimeChanged(totalTime());
263
if (prevTrackCount != m_videoPlayer->trackCount())
264
emit availableTitlesChanged(m_videoPlayer->trackCount());
255
265
if (checkForError())
257
267
if (!m_videoPlayer->isDrmAuthorized())
287
297
// Save current state for event/signal handling below:
288
298
bool prevHasVideo = m_videoPlayer->hasVideo();
289
299
qint64 prevTotalTime = totalTime();
300
int prevTrackCount = m_videoPlayer->trackCount();
291
302
qSwap(m_audioPlayer, m_nextAudioPlayer);
292
303
qSwap(m_videoPlayer, m_nextVideoPlayer);
293
304
m_mediaObjectAudioNode->startCrossFade(transitionTime);
294
305
m_audioGraph->updateStreamSpecifications();
295
m_metaData->setVideo(m_videoPlayer);
297
307
m_waitNextSwap = false;
298
308
m_currentTime = 0;
300
310
// Emit/notify information about the new source:
301
311
QRect videoRect = m_videoPlayer->videoRect();
302
312
MediaNodeEvent e1(MediaNodeEvent::VideoFrameSizeChanged, &videoRect);
305
315
emit currentSourceChanged(m_videoPlayer->mediaSource());
306
emit metaDataChanged(m_metaData->metaData());
316
emit metaDataChanged(m_videoPlayer->metaData());
308
318
if (prevHasVideo != m_videoPlayer->hasVideo())
309
emit hasVideoChanged(m_videoPlayer->hasVideo());
319
emit hasVideoChanged(m_videoPlayer->hasVideo());
310
320
if (prevTotalTime != totalTime())
311
321
emit totalTimeChanged(totalTime());
322
if (prevTrackCount != m_videoPlayer->trackCount())
323
emit availableTitlesChanged(m_videoPlayer->trackCount());
312
324
if (checkForError())
314
326
if (!m_videoPlayer->isDrmAuthorized())
330
void MediaObject::updateTimer(int &timer, int interval)
336
timer = startTimer(interval);
342
#if QT_ALLOW_QUICKTIME
343
static CVReturn displayLinkCallback(CVDisplayLinkRef /*displayLink*/,
344
const CVTimeStamp */*inNow*/,
345
const CVTimeStamp */*inOutputTime*/,
346
CVOptionFlags /*flagsIn*/,
347
CVOptionFlags */*flagsOut*/,
350
MediaObject *mediaObject = static_cast<MediaObject *>(userData);
351
mediaObject->displayLinkEvent();
352
return kCVReturnSuccess;
355
void MediaObject::displayLinkEvent()
357
// This function is called from a
358
// thread != gui thread. So we post the event.
359
// But we need to make sure that we don't post faster
360
// than the event loop can eat:
361
m_displayLinkMutex.lock();
362
bool pending = m_pendingDisplayLinkEvent;
363
m_pendingDisplayLinkEvent = true;
364
m_displayLinkMutex.unlock();
367
qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority);
370
void MediaObject::startDisplayLink()
374
OSStatus err = CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &m_displayLink);
377
err = CVDisplayLinkSetCurrentCGDisplay(m_displayLink, kCGDirectMainDisplay);
380
err = CVDisplayLinkSetOutputCallback(m_displayLink, displayLinkCallback, this);
383
err = CVDisplayLinkStart(m_displayLink);
391
void MediaObject::stopDisplayLink()
395
CVDisplayLinkStop(m_displayLink);
396
CFRelease(m_displayLink);
401
void MediaObject::restartAudioVideoTimers()
404
killTimer(m_videoTimer);
406
killTimer(m_audioTimer);
408
#if QT_ALLOW_QUICKTIME
409
// We prefer to use a display link as timer if available, since
410
// it is more steady, and results in better and smoother frame drawing:
413
float fps = m_videoPlayer->staticFps();
414
long videoUpdateFrequency = fps ? long(1000.0f / fps) : 0.001;
415
m_videoTimer = startTimer(videoUpdateFrequency);
418
float fps = m_videoPlayer->staticFps();
419
long videoUpdateFrequency = fps ? long(1000.0f / fps) : 0.001;
420
m_videoTimer = startTimer(videoUpdateFrequency);
423
long audioUpdateFrequency = m_audioPlayer->regularTaskFrequency();
424
m_audioTimer = startTimer(audioUpdateFrequency);
426
updateAudioBuffers();
339
429
void MediaObject::play_internal()
341
431
// Play main audio/video:
342
432
m_videoPlayer->play();
343
m_audioPlayer->play();
433
m_audioPlayer->play();
344
434
updateLipSynch(0);
345
435
// Play old audio/video to finish cross-fade:
346
436
if (m_nextVideoPlayer->currentTime() > 0){
347
437
m_nextVideoPlayer->play();
348
438
m_nextAudioPlayer->play();
351
updateTimer(m_rapidTimer, 100);
440
restartAudioVideoTimers();
442
m_rapidTimer = startTimer(100);
354
445
void MediaObject::pause_internal()
567
664
m_currentTime = (m_audioSystem == AS_Graph) ? m_audioPlayer->currentTime() : m_videoPlayer->currentTime();
568
665
quint64 total = m_videoPlayer->duration();
570
// Check if it's time to emit aboutToFinish:
571
quint32 mark = qMax(quint64(0), qMin(total, total + m_transitionTime - 2000));
572
if (lastUpdateTime < mark && mark <= m_currentTime)
573
emit aboutToFinish();
575
// Check if it's time to emit prefinishMarkReached:
576
mark = qMax(quint64(0), total - m_prefinishMark);
577
if (lastUpdateTime < mark && mark <= m_currentTime)
578
emit prefinishMarkReached(total - m_currentTime);
580
if (m_nextVideoPlayer->state() == QuickTimeVideoPlayer::NoMedia){
581
// There is no next source in que.
582
// Check if it's time to emit finished:
667
if (m_videoPlayer->currentTrack() < m_videoPlayer->trackCount() - 1){
668
// There are still more tracks to play after the current track.
669
if (m_autoplayTitles) {
670
if (lastUpdateTime < m_currentTime && m_currentTime == total)
671
setCurrentTrack(m_videoPlayer->currentTrack() + 1);
673
} else if (m_nextVideoPlayer->state() == QuickTimeVideoPlayer::NoMedia){
674
// There is no more sources or tracks to play after the current source.
675
// Check if it's time to emit aboutToFinish:
676
quint32 mark = qMax(quint64(0), qMin(total, total + m_transitionTime - 2000));
677
if (lastUpdateTime < mark && mark <= m_currentTime)
678
emit aboutToFinish();
680
// Check if it's time to emit prefinishMarkReached:
681
mark = qMax(quint64(0), total - m_prefinishMark);
682
if (lastUpdateTime < mark && mark <= m_currentTime)
683
emit prefinishMarkReached(total - m_currentTime);
583
685
if (lastUpdateTime < m_currentTime && m_currentTime == total){
585
687
m_currentTime = (m_audioSystem == AS_Graph) ? m_audioPlayer->currentTime() : m_videoPlayer->currentTime();
693
795
void MediaObject::updateCrossFade()
695
m_mediaObjectAudioNode->updateCrossFade(m_currentTime);
797
m_mediaObjectAudioNode->updateCrossFade(m_currentTime);
696
798
// Clean-up previous movie if done fading:
697
799
if (m_mediaObjectAudioNode->m_fadeDuration == 0){
698
800
if (m_nextVideoPlayer->isPlaying() || m_nextAudioPlayer->isPlaying()){
699
m_nextVideoPlayer->unsetVideo();
801
m_nextVideoPlayer->unsetCurrentMediaSource();
700
802
m_nextAudioPlayer->unsetVideoPlayer();
705
807
void MediaObject::updateBufferStatus()
818
910
bool MediaObject::event(QEvent *event)
820
912
switch (event->type()){
821
case QEvent::Timer: {
822
QTimerEvent *timerEvent = static_cast<QTimerEvent *>(event);
823
if (timerEvent->timerId() == m_rapidTimer)
913
#if QT_ALLOW_QUICKTIME
915
m_displayLinkMutex.lock();
916
m_pendingDisplayLinkEvent = false;
917
m_displayLinkMutex.unlock();
922
int timerId = static_cast<QTimerEvent *>(event)->timerId();
923
if (timerId == m_rapidTimer)
825
else if (timerEvent->timerId() == m_tickTimer)
925
else if (timerId == m_tickTimer)
826
926
emit tick(currentTime());
827
else if (timerEvent->timerId() == m_bufferTimer)
927
else if (timerId == m_videoTimer)
929
else if (timerId == m_audioTimer)
930
updateAudioBuffers();
834
935
return QObject::event(event);
837
bool MediaObject::hasInterface(Interface /*interface*/) const
842
QVariant MediaObject::interfaceCall(Interface /*interface*/, int /*command*/, const QList<QVariant> &/*arguments*/)
938
void MediaObject::setCurrentTrack(int track)
940
if (track == m_videoPlayer->currentTrack() || track < 0 || track >= m_videoPlayer->trackCount())
943
m_videoPlayer->setCurrentTrack(track);
944
emit titleChanged(track);
945
emit metaDataChanged(m_videoPlayer->metaData());
948
bool MediaObject::hasInterface(Interface iface) const
950
return iface == AddonInterface::TitleInterface;
953
QVariant MediaObject::interfaceCall(Interface iface, int command, const QList<QVariant> ¶ms)
958
case availableTitles:
959
return m_videoPlayer->trackCount();
961
return m_videoPlayer->currentTrack();
963
setCurrentTrack(params.first().toInt());
966
return m_autoplayTitles;
967
case setAutoplayTitles:
968
m_autoplayTitles = params.first().toBool();
844
974
return QVariant();