Changeset 846 for trunk/src/3rdparty/phonon/qt7/mediaobject.mm
- Timestamp:
- May 5, 2011, 5:36:53 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.7.2 (added) merged: 845 /branches/vendor/nokia/qt/current merged: 844 /branches/vendor/nokia/qt/4.6.3 removed
- Property svn:mergeinfo changed
-
trunk/src/3rdparty/phonon/qt7/mediaobject.mm
r561 r846 47 47 setAudioNode(m_mediaObjectAudioNode); 48 48 49 m_metaData = new QuickTimeMetaData(); 49 50 m_audioGraph = new AudioGraph(this); 50 51 … … 55 56 m_percentageLoaded = 0; 56 57 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_videoTimer = 0; 67 m_audioTimer = 0; 66 m_bufferTimer = 0; 68 67 m_rapidTimer = 0; 69 68 70 #if QT_ALLOW_QUICKTIME71 m_displayLink = 0;72 m_pendingDisplayLinkEvent = false;73 #endif74 75 69 checkForError(); 76 70 } 77 71 78 72 MediaObject::~MediaObject() 79 { 80 // m_mediaObjectAudioNode is owned by super class. 81 #if QT_ALLOW_QUICKTIME 82 stopDisplayLink(); 83 #endif 73 { 74 // m_mediaObjectAudioNode is owned by super class. 84 75 m_audioPlayer->unsetVideoPlayer(); 85 76 m_nextAudioPlayer->unsetVideoPlayer(); 86 77 delete m_videoPlayer; 87 78 delete m_nextVideoPlayer; 79 delete m_metaData; 88 80 checkForError(); 89 81 } … … 97 89 if (m_state != state){ 98 90 // End-application did something 99 // upon receiving the signal. 91 // upon receiving the signal. 100 92 return false; 101 93 } … … 131 123 // effects or outputs connected. This will have 132 124 // influence on the audio system and video system that ends up beeing used: 133 int prevVideoOutputCount = m_videoOutputCount; 125 int prevVideoOutputCount = m_videoOutputCount; 134 126 m_audioEffectCount = 0; 135 127 m_audioOutputCount = 0; … … 143 135 MediaNodeEvent e1(MediaNodeEvent::VideoOutputCountChanged, &m_videoOutputCount); 144 136 notify(&e1); 145 } 137 } 146 138 } 147 139 … … 176 168 if (newAudioSystem == m_audioSystem) 177 169 return; 178 170 179 171 // Enable selected audio system: 180 m_audioSystem = newAudioSystem; 172 m_audioSystem = newAudioSystem; 181 173 switch (newAudioSystem){ 182 174 case AS_Silent: 183 175 m_audioGraph->stop(); 184 176 m_videoPlayer->enableAudio(false); 185 m_nextVideoPlayer->enableAudio(false); 177 m_nextVideoPlayer->enableAudio(false); 186 178 m_audioPlayer->enableAudio(false); 187 179 m_nextAudioPlayer->enableAudio(false); … … 223 215 PhononAutoReleasePool pool; 224 216 setState(Phonon::LoadingState); 225 217 226 218 // Save current state for event/signal handling below: 227 219 bool prevHasVideo = m_videoPlayer->hasVideo(); 228 220 qint64 prevTotalTime = totalTime(); 229 int prevTrackCount = m_videoPlayer->trackCount();230 221 m_waitNextSwap = false; 231 222 232 223 // Cancel cross-fade if any: 233 224 m_nextVideoPlayer->pause(); 234 225 m_nextAudioPlayer->pause(); 235 226 m_mediaObjectAudioNode->cancelCrossFade(); 236 227 237 228 // Set new source: 238 229 m_audioPlayer->unsetVideoPlayer(); 239 230 m_videoPlayer->setMediaSource(source); 240 231 m_audioPlayer->setVideoPlayer(m_videoPlayer); 241 242 m_audioGraph->updateStreamSpecifications(); 232 m_metaData->setVideo(m_videoPlayer); 233 234 m_audioGraph->updateStreamSpecifications(); 243 235 m_nextAudioPlayer->unsetVideoPlayer(); 244 m_nextVideoPlayer->unset CurrentMediaSource();236 m_nextVideoPlayer->unsetVideo(); 245 237 m_currentTime = 0; 246 238 247 239 // Emit/notify information about the new source: 248 240 QRect videoRect = m_videoPlayer->videoRect(); … … 255 247 256 248 emit currentSourceChanged(source); 257 emit metaDataChanged(m_ videoPlayer->metaData());249 emit metaDataChanged(m_metaData->metaData()); 258 250 259 251 if (prevHasVideo != m_videoPlayer->hasVideo()) 260 emit hasVideoChanged(m_videoPlayer->hasVideo()); 252 emit hasVideoChanged(m_videoPlayer->hasVideo()); 261 253 if (prevTotalTime != totalTime()) 262 emit totalTimeChanged(totalTime()); 263 if (prevTrackCount != m_videoPlayer->trackCount()) 264 emit availableTitlesChanged(m_videoPlayer->trackCount()); 254 emit totalTimeChanged(totalTime()); 265 255 if (checkForError()) 266 256 return; … … 271 261 if (!m_videoPlayer->canPlayMedia()) 272 262 SET_ERROR("Cannot play media.", FATAL_ERROR) 273 263 274 264 // The state might have changed from LoadingState 275 265 // as a response to an error state change. So we … … 298 288 bool prevHasVideo = m_videoPlayer->hasVideo(); 299 289 qint64 prevTotalTime = totalTime(); 300 int prevTrackCount = m_videoPlayer->trackCount();301 290 302 291 qSwap(m_audioPlayer, m_nextAudioPlayer); … … 304 293 m_mediaObjectAudioNode->startCrossFade(transitionTime); 305 294 m_audioGraph->updateStreamSpecifications(); 295 m_metaData->setVideo(m_videoPlayer); 306 296 307 297 m_waitNextSwap = false; 308 298 m_currentTime = 0; 309 299 310 300 // Emit/notify information about the new source: 311 301 QRect videoRect = m_videoPlayer->videoRect(); … … 314 304 315 305 emit currentSourceChanged(m_videoPlayer->mediaSource()); 316 emit metaDataChanged(m_ videoPlayer->metaData());306 emit metaDataChanged(m_metaData->metaData()); 317 307 318 308 if (prevHasVideo != m_videoPlayer->hasVideo()) 319 emit hasVideoChanged(m_videoPlayer->hasVideo()); 309 emit hasVideoChanged(m_videoPlayer->hasVideo()); 320 310 if (prevTotalTime != totalTime()) 321 311 emit totalTimeChanged(totalTime()); 322 if (prevTrackCount != m_videoPlayer->trackCount())323 emit availableTitlesChanged(m_videoPlayer->trackCount());324 312 if (checkForError()) 325 313 return; … … 340 328 } 341 329 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(); 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); 427 337 } 428 338 … … 431 341 // Play main audio/video: 432 342 m_videoPlayer->play(); 433 m_audioPlayer->play(); 343 m_audioPlayer->play(); 434 344 updateLipSynch(0); 435 345 // Play old audio/video to finish cross-fade: … … 438 348 m_nextAudioPlayer->play(); 439 349 } 440 restartAudioVideoTimers(); 441 if (!m_rapidTimer) 442 m_rapidTimer = startTimer(100); 350 bufferAudioVideo(); 351 updateTimer(m_rapidTimer, 100); 443 352 } 444 353 … … 450 359 m_videoPlayer->pause(); 451 360 m_nextVideoPlayer->pause(); 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 361 updateTimer(m_rapidTimer, -1); 362 updateTimer(m_bufferTimer, -1); 363 461 364 if (m_waitNextSwap) 462 365 m_swapTimeLeft = m_swapTime.msecsTo(QTime::currentTime()); … … 480 383 return; 481 384 if (!setState(Phonon::PlayingState)) 482 return; 385 return; 483 386 if (m_audioSystem == AS_Graph){ 484 387 m_audioGraph->start(); … … 521 424 return; 522 425 m_waitNextSwap = false; 523 m_nextVideoPlayer->unset CurrentMediaSource();426 m_nextVideoPlayer->unsetVideo(); 524 427 m_nextAudioPlayer->unsetVideoPlayer(); 525 428 pause_internal(); … … 533 436 if (m_state == Phonon::ErrorState) 534 437 return; 535 438 536 439 // Stop cross-fade if any: 537 m_nextVideoPlayer->unset CurrentMediaSource();440 m_nextVideoPlayer->unsetVideo(); 538 441 m_nextAudioPlayer->unsetVideoPlayer(); 539 442 m_mediaObjectAudioNode->cancelCrossFade(); … … 544 447 m_audioPlayer->seek(m_videoPlayer->currentTime()); 545 448 m_mediaObjectAudioNode->setMute(false); 546 449 547 450 // Update time and cancel pending swap: 548 451 if (m_currentTime < m_videoPlayer->duration()) … … 655 558 { 656 559 IMPLEMENTED_SILENT; 657 const_cast<MediaObject *>(this)->updateCurrentTime(); 560 const_cast<MediaObject *>(this)->updateCurrentTime(); 658 561 return m_currentTime; 659 562 } … … 665 568 quint64 total = m_videoPlayer->duration(); 666 569 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 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: 685 583 if (lastUpdateTime < m_currentTime && m_currentTime == total){ 686 584 emit finished(); … … 692 590 // We have a next source. 693 591 // Check if it's time to swap to next source: 694 quint32mark = qMax(quint64(0), total + m_transitionTime);592 mark = qMax(quint64(0), total + m_transitionTime); 695 593 if (m_waitNextSwap && m_state == Phonon::PlayingState && 696 594 m_transitionTime < m_swapTime.msecsTo(QTime::currentTime())){ … … 795 693 void MediaObject::updateCrossFade() 796 694 { 797 m_mediaObjectAudioNode->updateCrossFade(m_currentTime); 695 m_mediaObjectAudioNode->updateCrossFade(m_currentTime); 798 696 // Clean-up previous movie if done fading: 799 697 if (m_mediaObjectAudioNode->m_fadeDuration == 0){ 800 698 if (m_nextVideoPlayer->isPlaying() || m_nextAudioPlayer->isPlaying()){ 801 m_nextVideoPlayer->unset CurrentMediaSource();699 m_nextVideoPlayer->unsetVideo(); 802 700 m_nextAudioPlayer->unsetVideoPlayer(); 803 701 } 804 } 702 } 805 703 } 806 704 … … 831 729 if (m_videoPlayer->videoFrameChanged()){ 832 730 updateLipSynch(50); 833 VideoFrame frame(m_videoPlayer); 731 VideoFrame frame(m_videoPlayer); 834 732 if (m_nextVideoPlayer->isPlaying() 835 733 && m_nextVideoPlayer->hasVideo() … … 839 737 frame.setBaseOpacity(m_mediaObjectAudioNode->m_volume1); 840 738 } 841 739 842 740 // Send the frame through the graph: 843 updateVideo(frame); 741 updateVideo(frame); 844 742 checkForError(); 845 743 } … … 852 750 if (m_videoSinkList.isEmpty() || m_audioSinkList.isEmpty()) 853 751 return; 854 752 855 753 if (m_videoPlayer->hasVideo()){ 856 754 qint64 diff = m_audioPlayer->currentTime() - m_videoPlayer->currentTime(); … … 864 762 m_nextAudioPlayer->seek(m_nextVideoPlayer->currentTime()); 865 763 } 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)); 866 774 } 867 775 … … 890 798 checkForError(); 891 799 m_mediaObjectAudioNode->setMute(false); 892 if (m_state == Phonon::PlayingState)893 restartAudioVideoTimers();800 if (m_state == Phonon::PlayingState) 801 bufferAudioVideo(); 894 802 break; 895 803 case MediaNodeEvent::AudioGraphCannotPlay: … … 902 810 m_mediaObjectAudioNode->setMute(false); 903 811 } 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 } 904 830 break; 905 831 default: 906 832 break; 907 833 } 908 }909 910 bool MediaObject::event(QEvent *event)911 {912 switch (event->type()){913 #if QT_ALLOW_QUICKTIME914 case QEvent::User:{915 m_displayLinkMutex.lock();916 m_pendingDisplayLinkEvent = false;917 m_displayLinkMutex.unlock();918 updateVideoFrames();919 break; }920 #endif921 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 }935 834 return QObject::event(event); 936 835 } 937 836 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 } 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 { 974 844 return QVariant(); 975 845 }
Note:
See TracChangeset
for help on using the changeset viewer.