Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/3rdparty/phonon/qt7/mediaobject.mm

    r561 r846  
    4747    setAudioNode(m_mediaObjectAudioNode);
    4848
     49    m_metaData = new QuickTimeMetaData();
    4950    m_audioGraph = new AudioGraph(this);
    5051
     
    5556    m_percentageLoaded = 0;
    5657    m_waitNextSwap = false;
    57     m_autoplayTitles = true;
    5858    m_audioEffectCount = 0;
    5959    m_audioOutputCount = 0;
     
    6464
    6565    m_tickTimer = 0;
    66     m_videoTimer = 0;
    67     m_audioTimer = 0;
     66    m_bufferTimer = 0;
    6867    m_rapidTimer = 0;
    6968
    70 #if QT_ALLOW_QUICKTIME
    71     m_displayLink = 0;
    72     m_pendingDisplayLinkEvent = false;
    73 #endif
    74 
    7569    checkForError();
    7670}
    7771
    7872MediaObject::~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.   
    8475    m_audioPlayer->unsetVideoPlayer();
    8576    m_nextAudioPlayer->unsetVideoPlayer();
    8677    delete m_videoPlayer;
    8778    delete m_nextVideoPlayer;
     79    delete m_metaData;
    8880    checkForError();
    8981}
     
    9789        if (m_state != state){
    9890            // End-application did something
    99             // upon  receiving the signal.
     91            // upon  receiving the signal. 
    10092            return false;
    10193        }
     
    131123    // effects or outputs connected. This will have
    132124    // influence on the audio system and video system that ends up beeing used:
    133     int prevVideoOutputCount = m_videoOutputCount;
     125    int prevVideoOutputCount = m_videoOutputCount;     
    134126    m_audioEffectCount = 0;
    135127    m_audioOutputCount = 0;
     
    143135            MediaNodeEvent e1(MediaNodeEvent::VideoOutputCountChanged, &m_videoOutputCount);
    144136            notify(&e1);
    145     }
     137        }       
    146138}
    147139
     
    176168    if (newAudioSystem == m_audioSystem)
    177169        return;
    178 
     170 
    179171    // Enable selected audio system:
    180     m_audioSystem = newAudioSystem;
     172    m_audioSystem = newAudioSystem; 
    181173    switch (newAudioSystem){
    182174        case AS_Silent:
    183175            m_audioGraph->stop();
    184176            m_videoPlayer->enableAudio(false);
    185             m_nextVideoPlayer->enableAudio(false);
     177            m_nextVideoPlayer->enableAudio(false);   
    186178            m_audioPlayer->enableAudio(false);
    187179            m_nextAudioPlayer->enableAudio(false);
     
    223215        PhononAutoReleasePool pool;
    224216    setState(Phonon::LoadingState);
    225 
     217   
    226218    // Save current state for event/signal handling below:
    227219    bool prevHasVideo = m_videoPlayer->hasVideo();
    228220    qint64 prevTotalTime = totalTime();
    229     int prevTrackCount = m_videoPlayer->trackCount();
    230221    m_waitNextSwap = false;
    231 
     222       
    232223    // Cancel cross-fade if any:
    233224    m_nextVideoPlayer->pause();
    234225    m_nextAudioPlayer->pause();
    235226    m_mediaObjectAudioNode->cancelCrossFade();
    236 
     227   
    237228    // Set new source:
    238229    m_audioPlayer->unsetVideoPlayer();
    239230    m_videoPlayer->setMediaSource(source);
    240231    m_audioPlayer->setVideoPlayer(m_videoPlayer);
    241 
    242     m_audioGraph->updateStreamSpecifications();
     232    m_metaData->setVideo(m_videoPlayer);       
     233
     234    m_audioGraph->updateStreamSpecifications();       
    243235    m_nextAudioPlayer->unsetVideoPlayer();
    244     m_nextVideoPlayer->unsetCurrentMediaSource();
     236    m_nextVideoPlayer->unsetVideo();
    245237    m_currentTime = 0;
    246 
     238       
    247239    // Emit/notify information about the new source:
    248240    QRect videoRect = m_videoPlayer->videoRect();
     
    255247
    256248    emit currentSourceChanged(source);
    257     emit metaDataChanged(m_videoPlayer->metaData());
     249    emit metaDataChanged(m_metaData->metaData());
    258250
    259251    if (prevHasVideo != m_videoPlayer->hasVideo())
    260         emit hasVideoChanged(m_videoPlayer->hasVideo());
     252        emit hasVideoChanged(m_videoPlayer->hasVideo());       
    261253    if (prevTotalTime != totalTime())
    262         emit totalTimeChanged(totalTime());
    263     if (prevTrackCount != m_videoPlayer->trackCount())
    264         emit availableTitlesChanged(m_videoPlayer->trackCount());
     254        emit totalTimeChanged(totalTime());       
    265255    if (checkForError())
    266256        return;
     
    271261    if (!m_videoPlayer->canPlayMedia())
    272262        SET_ERROR("Cannot play media.", FATAL_ERROR)
    273 
     263       
    274264    // The state might have changed from LoadingState
    275265    // as a response to an error state change. So we
     
    298288    bool prevHasVideo = m_videoPlayer->hasVideo();
    299289    qint64 prevTotalTime = totalTime();
    300     int prevTrackCount = m_videoPlayer->trackCount();
    301290
    302291    qSwap(m_audioPlayer, m_nextAudioPlayer);
     
    304293    m_mediaObjectAudioNode->startCrossFade(transitionTime);
    305294    m_audioGraph->updateStreamSpecifications();
     295    m_metaData->setVideo(m_videoPlayer);
    306296
    307297    m_waitNextSwap = false;
    308298    m_currentTime = 0;
    309 
     299       
    310300    // Emit/notify information about the new source:
    311301    QRect videoRect = m_videoPlayer->videoRect();
     
    314304
    315305    emit currentSourceChanged(m_videoPlayer->mediaSource());
    316     emit metaDataChanged(m_videoPlayer->metaData());
     306    emit metaDataChanged(m_metaData->metaData());
    317307
    318308    if (prevHasVideo != m_videoPlayer->hasVideo())
    319         emit hasVideoChanged(m_videoPlayer->hasVideo());
     309        emit hasVideoChanged(m_videoPlayer->hasVideo());       
    320310    if (prevTotalTime != totalTime())
    321311        emit totalTimeChanged(totalTime());
    322     if (prevTrackCount != m_videoPlayer->trackCount())
    323         emit availableTitlesChanged(m_videoPlayer->trackCount());
    324312    if (checkForError())
    325313        return;
     
    340328}
    341329
    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();
     330void MediaObject::updateTimer(int &timer, int interval)
     331{
     332    if (timer)
     333        killTimer(timer);
     334    timer = 0;
     335    if (interval >= 0)   
     336        timer = startTimer(interval);
    427337}
    428338
     
    431341    // Play main audio/video:
    432342    m_videoPlayer->play();
    433     m_audioPlayer->play();
     343    m_audioPlayer->play();     
    434344    updateLipSynch(0);
    435345    // Play old audio/video to finish cross-fade:
     
    438348        m_nextAudioPlayer->play();
    439349    }
    440     restartAudioVideoTimers();
    441     if (!m_rapidTimer)
    442         m_rapidTimer = startTimer(100);
     350    bufferAudioVideo();
     351    updateTimer(m_rapidTimer, 100);
    443352}
    444353
     
    450359    m_videoPlayer->pause();
    451360    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
    461364    if (m_waitNextSwap)
    462365        m_swapTimeLeft = m_swapTime.msecsTo(QTime::currentTime());
     
    480383        return;
    481384    if (!setState(Phonon::PlayingState))
    482         return;
     385        return;       
    483386    if (m_audioSystem == AS_Graph){
    484387        m_audioGraph->start();
     
    521424        return;
    522425    m_waitNextSwap = false;
    523     m_nextVideoPlayer->unsetCurrentMediaSource();
     426    m_nextVideoPlayer->unsetVideo();
    524427    m_nextAudioPlayer->unsetVideoPlayer();
    525428    pause_internal();
     
    533436    if (m_state == Phonon::ErrorState)
    534437        return;
    535 
     438       
    536439    // Stop cross-fade if any:
    537     m_nextVideoPlayer->unsetCurrentMediaSource();
     440    m_nextVideoPlayer->unsetVideo();
    538441    m_nextAudioPlayer->unsetVideoPlayer();
    539442    m_mediaObjectAudioNode->cancelCrossFade();
     
    544447    m_audioPlayer->seek(m_videoPlayer->currentTime());
    545448    m_mediaObjectAudioNode->setMute(false);
    546 
     449   
    547450    // Update time and cancel pending swap:
    548451    if (m_currentTime < m_videoPlayer->duration())
     
    655558{
    656559    IMPLEMENTED_SILENT;
    657     const_cast<MediaObject *>(this)->updateCurrentTime();
     560    const_cast<MediaObject *>(this)->updateCurrentTime(); 
    658561    return m_currentTime;
    659562}
     
    665568    quint64 total = m_videoPlayer->duration();
    666569
    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:
    685583        if (lastUpdateTime < m_currentTime && m_currentTime == total){
    686584            emit finished();
     
    692590        // We have a next source.
    693591        // Check if it's time to swap to next source:
    694         quint32 mark = qMax(quint64(0), total + m_transitionTime);
     592        mark = qMax(quint64(0), total + m_transitionTime);
    695593        if (m_waitNextSwap && m_state == Phonon::PlayingState &&
    696594            m_transitionTime < m_swapTime.msecsTo(QTime::currentTime())){
     
    795693void MediaObject::updateCrossFade()
    796694{
    797     m_mediaObjectAudioNode->updateCrossFade(m_currentTime);
     695    m_mediaObjectAudioNode->updateCrossFade(m_currentTime);   
    798696    // Clean-up previous movie if done fading:
    799697    if (m_mediaObjectAudioNode->m_fadeDuration == 0){
    800698        if (m_nextVideoPlayer->isPlaying() || m_nextAudioPlayer->isPlaying()){
    801             m_nextVideoPlayer->unsetCurrentMediaSource();
     699            m_nextVideoPlayer->unsetVideo();
    802700            m_nextAudioPlayer->unsetVideoPlayer();
    803701        }
    804     }
     702    }       
    805703}
    806704
     
    831729    if (m_videoPlayer->videoFrameChanged()){
    832730        updateLipSynch(50);
    833         VideoFrame frame(m_videoPlayer);
     731        VideoFrame frame(m_videoPlayer);           
    834732        if (m_nextVideoPlayer->isPlaying()
    835733            && m_nextVideoPlayer->hasVideo()
     
    839737            frame.setBaseOpacity(m_mediaObjectAudioNode->m_volume1);
    840738        }
    841 
     739       
    842740        // Send the frame through the graph:
    843         updateVideo(frame);
     741        updateVideo(frame);   
    844742        checkForError();
    845743    }
     
    852750    if (m_videoSinkList.isEmpty() || m_audioSinkList.isEmpty())
    853751        return;
    854 
     752       
    855753    if (m_videoPlayer->hasVideo()){
    856754        qint64 diff = m_audioPlayer->currentTime() - m_videoPlayer->currentTime();
     
    864762            m_nextAudioPlayer->seek(m_nextVideoPlayer->currentTime());
    865763    }
     764}
     765
     766void 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));
    866774}
    867775
     
    890798            checkForError();
    891799            m_mediaObjectAudioNode->setMute(false);
    892             if (m_state == Phonon::PlayingState)
    893                 restartAudioVideoTimers();
     800             if (m_state == Phonon::PlayingState)
     801                bufferAudioVideo();
    894802            break;
    895803        case MediaNodeEvent::AudioGraphCannotPlay:
     
    902810                m_mediaObjectAudioNode->setMute(false);
    903811            }
     812            break;
     813        default:
     814            break;
     815    }
     816}
     817
     818bool 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            }
    904830            break;
    905831        default:
    906832            break;
    907833    }
    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     }
    935834    return QObject::event(event);
    936835}
    937836
    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> &params)
    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     }
     837bool MediaObject::hasInterface(Interface /*interface*/) const
     838{
     839    return false;
     840}
     841
     842QVariant MediaObject::interfaceCall(Interface /*interface*/, int /*command*/, const QList<QVariant> &/*arguments*/)
     843{
    974844    return QVariant();
    975845}
Note: See TracChangeset for help on using the changeset viewer.