Changeset 561 for trunk/src/3rdparty/phonon/qt7/mediaobject.mm
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/3rdparty/phonon/qt7/mediaobject.mm
r2 r561 47 47 setAudioNode(m_mediaObjectAudioNode); 48 48 49 m_metaData = new QuickTimeMetaData();50 49 m_audioGraph = new AudioGraph(this); 51 50 … … 56 55 m_percentageLoaded = 0; 57 56 m_waitNextSwap = false; 57 m_autoplayTitles = true; 58 58 m_audioEffectCount = 0; 59 59 m_audioOutputCount = 0; … … 64 64 65 65 m_tickTimer = 0; 66 m_bufferTimer = 0; 66 m_videoTimer = 0; 67 m_audioTimer = 0; 67 68 m_rapidTimer = 0; 68 69 70 #if QT_ALLOW_QUICKTIME 71 m_displayLink = 0; 72 m_pendingDisplayLinkEvent = false; 73 #endif 74 69 75 checkForError(); 70 76 } 71 77 72 78 MediaObject::~MediaObject() 73 { 74 // m_mediaObjectAudioNode is owned by super class. 79 { 80 // m_mediaObjectAudioNode is owned by super class. 81 #if QT_ALLOW_QUICKTIME 82 stopDisplayLink(); 83 #endif 75 84 m_audioPlayer->unsetVideoPlayer(); 76 85 m_nextAudioPlayer->unsetVideoPlayer(); 77 86 delete m_videoPlayer; 78 87 delete m_nextVideoPlayer; 79 delete m_metaData;80 88 checkForError(); 81 89 } … … 89 97 if (m_state != state){ 90 98 // End-application did something 91 // upon receiving the signal. 99 // upon receiving the signal. 92 100 return false; 93 101 } … … 123 131 // effects or outputs connected. This will have 124 132 // influence on the audio system and video system that ends up beeing used: 125 int prevVideoOutputCount = m_videoOutputCount; 133 int prevVideoOutputCount = m_videoOutputCount; 126 134 m_audioEffectCount = 0; 127 135 m_audioOutputCount = 0; … … 135 143 MediaNodeEvent e1(MediaNodeEvent::VideoOutputCountChanged, &m_videoOutputCount); 136 144 notify(&e1); 137 } 145 } 138 146 } 139 147 … … 168 176 if (newAudioSystem == m_audioSystem) 169 177 return; 170 178 171 179 // Enable selected audio system: 172 m_audioSystem = newAudioSystem; 180 m_audioSystem = newAudioSystem; 173 181 switch (newAudioSystem){ 174 182 case AS_Silent: 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); 217 225 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; 222 231 223 232 // Cancel cross-fade if any: 224 233 m_nextVideoPlayer->pause(); 225 234 m_nextAudioPlayer->pause(); 226 235 m_mediaObjectAudioNode->cancelCrossFade(); 227 236 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); 233 234 m_audioGraph->updateStreamSpecifications(); 241 242 m_audioGraph->updateStreamSpecifications(); 235 243 m_nextAudioPlayer->unsetVideoPlayer(); 236 m_nextVideoPlayer->unset Video();244 m_nextVideoPlayer->unsetCurrentMediaSource(); 237 245 m_currentTime = 0; 238 246 239 247 // Emit/notify information about the new source: 240 248 QRect videoRect = m_videoPlayer->videoRect(); … … 247 255 248 256 emit currentSourceChanged(source); 249 emit metaDataChanged(m_ metaData->metaData());257 emit metaDataChanged(m_videoPlayer->metaData()); 250 258 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()) 256 266 return; … … 261 271 if (!m_videoPlayer->canPlayMedia()) 262 272 SET_ERROR("Cannot play media.", FATAL_ERROR) 263 273 264 274 // The state might have changed from LoadingState 265 275 // as a response to an error state change. So we … … 288 298 bool prevHasVideo = m_videoPlayer->hasVideo(); 289 299 qint64 prevTotalTime = totalTime(); 300 int prevTrackCount = m_videoPlayer->trackCount(); 290 301 291 302 qSwap(m_audioPlayer, m_nextAudioPlayer); … … 293 304 m_mediaObjectAudioNode->startCrossFade(transitionTime); 294 305 m_audioGraph->updateStreamSpecifications(); 295 m_metaData->setVideo(m_videoPlayer);296 306 297 307 m_waitNextSwap = false; 298 308 m_currentTime = 0; 299 309 300 310 // Emit/notify information about the new source: 301 311 QRect videoRect = m_videoPlayer->videoRect(); … … 304 314 305 315 emit currentSourceChanged(m_videoPlayer->mediaSource()); 306 emit metaDataChanged(m_ metaData->metaData());316 emit metaDataChanged(m_videoPlayer->metaData()); 307 317 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()) 313 325 return; … … 328 340 } 329 341 330 void MediaObject::updateTimer(int &timer, int interval) 331 { 332 if (timer) 333 killTimer(timer); 334 timer = 0; 335 if (interval >= 0) 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*/, 348 void *userData) 349 { 350 MediaObject *mediaObject = static_cast<MediaObject *>(userData); 351 mediaObject->displayLinkEvent(); 352 return kCVReturnSuccess; 353 } 354 355 void MediaObject::displayLinkEvent() 356 { 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(); 365 366 if (!pending) 367 qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority); 368 } 369 370 void MediaObject::startDisplayLink() 371 { 372 if (m_displayLink) 373 return; 374 OSStatus err = CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &m_displayLink); 375 if (err != noErr) 376 goto fail; 377 err = CVDisplayLinkSetCurrentCGDisplay(m_displayLink, kCGDirectMainDisplay); 378 if (err != noErr) 379 goto fail; 380 err = CVDisplayLinkSetOutputCallback(m_displayLink, displayLinkCallback, this); 381 if (err != noErr) 382 goto fail; 383 err = CVDisplayLinkStart(m_displayLink); 384 if (err != noErr) 385 goto fail; 386 return; 387 fail: 388 stopDisplayLink(); 389 } 390 391 void MediaObject::stopDisplayLink() 392 { 393 if (!m_displayLink) 394 return; 395 CVDisplayLinkStop(m_displayLink); 396 CFRelease(m_displayLink); 397 m_displayLink = 0; 398 } 399 #endif 400 401 void MediaObject::restartAudioVideoTimers() 402 { 403 if (m_videoTimer) 404 killTimer(m_videoTimer); 405 if (m_audioTimer) 406 killTimer(m_audioTimer); 407 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: 411 startDisplayLink(); 412 if (!m_displayLink){ 413 float fps = m_videoPlayer->staticFps(); 414 long videoUpdateFrequency = fps ? long(1000.0f / fps) : 0.001; 415 m_videoTimer = startTimer(videoUpdateFrequency); 416 } 417 #else 418 float fps = m_videoPlayer->staticFps(); 419 long videoUpdateFrequency = fps ? long(1000.0f / fps) : 0.001; 420 m_videoTimer = startTimer(videoUpdateFrequency); 421 #endif 422 423 long audioUpdateFrequency = m_audioPlayer->regularTaskFrequency(); 424 m_audioTimer = startTimer(audioUpdateFrequency); 425 updateVideoFrames(); 426 updateAudioBuffers(); 337 427 } 338 428 … … 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: … … 348 438 m_nextAudioPlayer->play(); 349 439 } 350 bufferAudioVideo(); 351 updateTimer(m_rapidTimer, 100); 440 restartAudioVideoTimers(); 441 if (!m_rapidTimer) 442 m_rapidTimer = startTimer(100); 352 443 } 353 444 … … 359 450 m_videoPlayer->pause(); 360 451 m_nextVideoPlayer->pause(); 361 updateTimer(m_rapidTimer, -1); 362 updateTimer(m_bufferTimer, -1); 363 452 killTimer(m_rapidTimer); 453 killTimer(m_videoTimer); 454 killTimer(m_audioTimer); 455 m_rapidTimer = 0; 456 m_videoTimer = 0; 457 m_audioTimer = 0; 458 #if QT_ALLOW_QUICKTIME 459 stopDisplayLink(); 460 #endif 364 461 if (m_waitNextSwap) 365 462 m_swapTimeLeft = m_swapTime.msecsTo(QTime::currentTime()); … … 383 480 return; 384 481 if (!setState(Phonon::PlayingState)) 385 return; 482 return; 386 483 if (m_audioSystem == AS_Graph){ 387 484 m_audioGraph->start(); … … 424 521 return; 425 522 m_waitNextSwap = false; 426 m_nextVideoPlayer->unset Video();523 m_nextVideoPlayer->unsetCurrentMediaSource(); 427 524 m_nextAudioPlayer->unsetVideoPlayer(); 428 525 pause_internal(); … … 436 533 if (m_state == Phonon::ErrorState) 437 534 return; 438 535 439 536 // Stop cross-fade if any: 440 m_nextVideoPlayer->unset Video();537 m_nextVideoPlayer->unsetCurrentMediaSource(); 441 538 m_nextAudioPlayer->unsetVideoPlayer(); 442 539 m_mediaObjectAudioNode->cancelCrossFade(); … … 447 544 m_audioPlayer->seek(m_videoPlayer->currentTime()); 448 545 m_mediaObjectAudioNode->setMute(false); 449 546 450 547 // Update time and cancel pending swap: 451 548 if (m_currentTime < m_videoPlayer->duration()) … … 558 655 { 559 656 IMPLEMENTED_SILENT; 560 const_cast<MediaObject *>(this)->updateCurrentTime(); 657 const_cast<MediaObject *>(this)->updateCurrentTime(); 561 658 return m_currentTime; 562 659 } … … 568 665 quint64 total = m_videoPlayer->duration(); 569 666 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(); 574 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); 579 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); 672 } 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(); 679 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); 684 583 685 if (lastUpdateTime < m_currentTime && m_currentTime == total){ 584 686 emit finished(); … … 590 692 // We have a next source. 591 693 // Check if it's time to swap to next source: 592 mark = qMax(quint64(0), total + m_transitionTime);694 quint32 mark = qMax(quint64(0), total + m_transitionTime); 593 695 if (m_waitNextSwap && m_state == Phonon::PlayingState && 594 696 m_transitionTime < m_swapTime.msecsTo(QTime::currentTime())){ … … 693 795 void MediaObject::updateCrossFade() 694 796 { 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->unset Video();801 m_nextVideoPlayer->unsetCurrentMediaSource(); 700 802 m_nextAudioPlayer->unsetVideoPlayer(); 701 803 } 702 } 804 } 703 805 } 704 806 … … 729 831 if (m_videoPlayer->videoFrameChanged()){ 730 832 updateLipSynch(50); 731 VideoFrame frame(m_videoPlayer); 833 VideoFrame frame(m_videoPlayer); 732 834 if (m_nextVideoPlayer->isPlaying() 733 835 && m_nextVideoPlayer->hasVideo() … … 737 839 frame.setBaseOpacity(m_mediaObjectAudioNode->m_volume1); 738 840 } 739 841 740 842 // Send the frame through the graph: 741 updateVideo(frame); 843 updateVideo(frame); 742 844 checkForError(); 743 845 } … … 750 852 if (m_videoSinkList.isEmpty() || m_audioSinkList.isEmpty()) 751 853 return; 752 854 753 855 if (m_videoPlayer->hasVideo()){ 754 856 qint64 diff = m_audioPlayer->currentTime() - m_videoPlayer->currentTime(); … … 762 864 m_nextAudioPlayer->seek(m_nextVideoPlayer->currentTime()); 763 865 } 764 }765 766 void MediaObject::bufferAudioVideo()767 {768 long nextVideoUpdate = m_videoPlayer->hasVideo() ? 30 : INT_MAX;769 long nextAudioUpdate = m_audioPlayer->regularTaskFrequency();770 updateAudioBuffers();771 updateVideoFrames();772 if (m_state == Phonon::PlayingState)773 updateTimer(m_bufferTimer, qMin(nextVideoUpdate, nextAudioUpdate));774 866 } 775 867 … … 798 890 checkForError(); 799 891 m_mediaObjectAudioNode->setMute(false); 800 801 bufferAudioVideo();892 if (m_state == Phonon::PlayingState) 893 restartAudioVideoTimers(); 802 894 break; 803 895 case MediaNodeEvent::AudioGraphCannotPlay: … … 810 902 m_mediaObjectAudioNode->setMute(false); 811 903 } 812 break;813 default:814 break;815 }816 }817 818 bool MediaObject::event(QEvent *event)819 {820 switch (event->type()){821 case QEvent::Timer: {822 QTimerEvent *timerEvent = static_cast<QTimerEvent *>(event);823 if (timerEvent->timerId() == m_rapidTimer)824 updateRapidly();825 else if (timerEvent->timerId() == m_tickTimer)826 emit tick(currentTime());827 else if (timerEvent->timerId() == m_bufferTimer)828 bufferAudioVideo();829 }830 904 break; 831 905 default: 832 906 break; 833 907 } 908 } 909 910 bool MediaObject::event(QEvent *event) 911 { 912 switch (event->type()){ 913 #if QT_ALLOW_QUICKTIME 914 case QEvent::User:{ 915 m_displayLinkMutex.lock(); 916 m_pendingDisplayLinkEvent = false; 917 m_displayLinkMutex.unlock(); 918 updateVideoFrames(); 919 break; } 920 #endif 921 case QEvent::Timer:{ 922 int timerId = static_cast<QTimerEvent *>(event)->timerId(); 923 if (timerId == m_rapidTimer) 924 updateRapidly(); 925 else if (timerId == m_tickTimer) 926 emit tick(currentTime()); 927 else if (timerId == m_videoTimer) 928 updateVideoFrames(); 929 else if (timerId == m_audioTimer) 930 updateAudioBuffers(); 931 break; } 932 default: 933 break; 934 } 834 935 return QObject::event(event); 835 936 } 836 937 837 bool MediaObject::hasInterface(Interface /*interface*/) const 838 { 839 return false; 840 } 841 842 QVariant MediaObject::interfaceCall(Interface /*interface*/, int /*command*/, const QList<QVariant> &/*arguments*/) 843 { 938 void MediaObject::setCurrentTrack(int track) 939 { 940 if (track == m_videoPlayer->currentTrack() || track < 0 || track >= m_videoPlayer->trackCount()) 941 return; 942 943 m_videoPlayer->setCurrentTrack(track); 944 emit titleChanged(track); 945 emit metaDataChanged(m_videoPlayer->metaData()); 946 } 947 948 bool MediaObject::hasInterface(Interface iface) const 949 { 950 return iface == AddonInterface::TitleInterface; 951 } 952 953 QVariant MediaObject::interfaceCall(Interface iface, int command, const QList<QVariant> ¶ms) 954 { 955 switch (iface) { 956 case TitleInterface: 957 switch (command) { 958 case availableTitles: 959 return m_videoPlayer->trackCount(); 960 case title: 961 return m_videoPlayer->currentTrack(); 962 case setTitle: 963 setCurrentTrack(params.first().toInt()); 964 break; 965 case autoplayTitles: 966 return m_autoplayTitles; 967 case setAutoplayTitles: 968 m_autoplayTitles = params.first().toBool(); 969 break; 970 } 971 default: 972 break; 973 } 844 974 return QVariant(); 845 975 }
Note:
See TracChangeset
for help on using the changeset viewer.