Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

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

    r2 r561  
    4747    setAudioNode(m_mediaObjectAudioNode);
    4848
    49     m_metaData = new QuickTimeMetaData();
    5049    m_audioGraph = new AudioGraph(this);
    5150
     
    5655    m_percentageLoaded = 0;
    5756    m_waitNextSwap = false;
     57    m_autoplayTitles = true;
    5858    m_audioEffectCount = 0;
    5959    m_audioOutputCount = 0;
     
    6464
    6565    m_tickTimer = 0;
    66     m_bufferTimer = 0;
     66    m_videoTimer = 0;
     67    m_audioTimer = 0;
    6768    m_rapidTimer = 0;
    6869
     70#if QT_ALLOW_QUICKTIME
     71    m_displayLink = 0;
     72    m_pendingDisplayLinkEvent = false;
     73#endif
     74
    6975    checkForError();
    7076}
    7177
    7278MediaObject::~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
    7584    m_audioPlayer->unsetVideoPlayer();
    7685    m_nextAudioPlayer->unsetVideoPlayer();
    7786    delete m_videoPlayer;
    7887    delete m_nextVideoPlayer;
    79     delete m_metaData;
    8088    checkForError();
    8189}
     
    8997        if (m_state != state){
    9098            // End-application did something
    91             // upon  receiving the signal. 
     99            // upon  receiving the signal.
    92100            return false;
    93101        }
     
    123131    // effects or outputs connected. This will have
    124132    // influence on the audio system and video system that ends up beeing used:
    125     int prevVideoOutputCount = m_videoOutputCount;     
     133    int prevVideoOutputCount = m_videoOutputCount;
    126134    m_audioEffectCount = 0;
    127135    m_audioOutputCount = 0;
     
    135143            MediaNodeEvent e1(MediaNodeEvent::VideoOutputCountChanged, &m_videoOutputCount);
    136144            notify(&e1);
    137         }       
     145    }
    138146}
    139147
     
    168176    if (newAudioSystem == m_audioSystem)
    169177        return;
    170  
     178
    171179    // Enable selected audio system:
    172     m_audioSystem = newAudioSystem; 
     180    m_audioSystem = newAudioSystem;
    173181    switch (newAudioSystem){
    174182        case AS_Silent:
    175183            m_audioGraph->stop();
    176184            m_videoPlayer->enableAudio(false);
    177             m_nextVideoPlayer->enableAudio(false);   
     185            m_nextVideoPlayer->enableAudio(false);
    178186            m_audioPlayer->enableAudio(false);
    179187            m_nextAudioPlayer->enableAudio(false);
     
    215223        PhononAutoReleasePool pool;
    216224    setState(Phonon::LoadingState);
    217    
     225
    218226    // Save current state for event/signal handling below:
    219227    bool prevHasVideo = m_videoPlayer->hasVideo();
    220228    qint64 prevTotalTime = totalTime();
     229    int prevTrackCount = m_videoPlayer->trackCount();
    221230    m_waitNextSwap = false;
    222        
     231
    223232    // Cancel cross-fade if any:
    224233    m_nextVideoPlayer->pause();
    225234    m_nextAudioPlayer->pause();
    226235    m_mediaObjectAudioNode->cancelCrossFade();
    227    
     236
    228237    // Set new source:
    229238    m_audioPlayer->unsetVideoPlayer();
    230239    m_videoPlayer->setMediaSource(source);
    231240    m_audioPlayer->setVideoPlayer(m_videoPlayer);
    232     m_metaData->setVideo(m_videoPlayer);       
    233 
    234     m_audioGraph->updateStreamSpecifications();       
     241
     242    m_audioGraph->updateStreamSpecifications();
    235243    m_nextAudioPlayer->unsetVideoPlayer();
    236     m_nextVideoPlayer->unsetVideo();
     244    m_nextVideoPlayer->unsetCurrentMediaSource();
    237245    m_currentTime = 0;
    238        
     246
    239247    // Emit/notify information about the new source:
    240248    QRect videoRect = m_videoPlayer->videoRect();
     
    247255
    248256    emit currentSourceChanged(source);
    249     emit metaDataChanged(m_metaData->metaData());
     257    emit metaDataChanged(m_videoPlayer->metaData());
    250258
    251259    if (prevHasVideo != m_videoPlayer->hasVideo())
    252         emit hasVideoChanged(m_videoPlayer->hasVideo());       
     260        emit hasVideoChanged(m_videoPlayer->hasVideo());
    253261    if (prevTotalTime != totalTime())
    254         emit totalTimeChanged(totalTime());       
     262        emit totalTimeChanged(totalTime());
     263    if (prevTrackCount != m_videoPlayer->trackCount())
     264        emit availableTitlesChanged(m_videoPlayer->trackCount());
    255265    if (checkForError())
    256266        return;
     
    261271    if (!m_videoPlayer->canPlayMedia())
    262272        SET_ERROR("Cannot play media.", FATAL_ERROR)
    263        
     273
    264274    // The state might have changed from LoadingState
    265275    // as a response to an error state change. So we
     
    288298    bool prevHasVideo = m_videoPlayer->hasVideo();
    289299    qint64 prevTotalTime = totalTime();
     300    int prevTrackCount = m_videoPlayer->trackCount();
    290301
    291302    qSwap(m_audioPlayer, m_nextAudioPlayer);
     
    293304    m_mediaObjectAudioNode->startCrossFade(transitionTime);
    294305    m_audioGraph->updateStreamSpecifications();
    295     m_metaData->setVideo(m_videoPlayer);
    296306
    297307    m_waitNextSwap = false;
    298308    m_currentTime = 0;
    299        
     309
    300310    // Emit/notify information about the new source:
    301311    QRect videoRect = m_videoPlayer->videoRect();
     
    304314
    305315    emit currentSourceChanged(m_videoPlayer->mediaSource());
    306     emit metaDataChanged(m_metaData->metaData());
     316    emit metaDataChanged(m_videoPlayer->metaData());
    307317
    308318    if (prevHasVideo != m_videoPlayer->hasVideo())
    309         emit hasVideoChanged(m_videoPlayer->hasVideo());       
     319        emit hasVideoChanged(m_videoPlayer->hasVideo());
    310320    if (prevTotalTime != totalTime())
    311321        emit totalTimeChanged(totalTime());
     322    if (prevTrackCount != m_videoPlayer->trackCount())
     323        emit availableTitlesChanged(m_videoPlayer->trackCount());
    312324    if (checkForError())
    313325        return;
     
    328340}
    329341
    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
     343static 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
     355void 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
     370void 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;
     387fail:
     388    stopDisplayLink();
     389}
     390
     391void 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
     401void 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();
    337427}
    338428
     
    341431    // Play main audio/video:
    342432    m_videoPlayer->play();
    343     m_audioPlayer->play();     
     433    m_audioPlayer->play();
    344434    updateLipSynch(0);
    345435    // Play old audio/video to finish cross-fade:
     
    348438        m_nextAudioPlayer->play();
    349439    }
    350     bufferAudioVideo();
    351     updateTimer(m_rapidTimer, 100);
     440    restartAudioVideoTimers();
     441    if (!m_rapidTimer)
     442        m_rapidTimer = startTimer(100);
    352443}
    353444
     
    359450    m_videoPlayer->pause();
    360451    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
    364461    if (m_waitNextSwap)
    365462        m_swapTimeLeft = m_swapTime.msecsTo(QTime::currentTime());
     
    383480        return;
    384481    if (!setState(Phonon::PlayingState))
    385         return;       
     482        return;
    386483    if (m_audioSystem == AS_Graph){
    387484        m_audioGraph->start();
     
    424521        return;
    425522    m_waitNextSwap = false;
    426     m_nextVideoPlayer->unsetVideo();
     523    m_nextVideoPlayer->unsetCurrentMediaSource();
    427524    m_nextAudioPlayer->unsetVideoPlayer();
    428525    pause_internal();
     
    436533    if (m_state == Phonon::ErrorState)
    437534        return;
    438        
     535
    439536    // Stop cross-fade if any:
    440     m_nextVideoPlayer->unsetVideo();
     537    m_nextVideoPlayer->unsetCurrentMediaSource();
    441538    m_nextAudioPlayer->unsetVideoPlayer();
    442539    m_mediaObjectAudioNode->cancelCrossFade();
     
    447544    m_audioPlayer->seek(m_videoPlayer->currentTime());
    448545    m_mediaObjectAudioNode->setMute(false);
    449    
     546
    450547    // Update time and cancel pending swap:
    451548    if (m_currentTime < m_videoPlayer->duration())
     
    558655{
    559656    IMPLEMENTED_SILENT;
    560     const_cast<MediaObject *>(this)->updateCurrentTime(); 
     657    const_cast<MediaObject *>(this)->updateCurrentTime();
    561658    return m_currentTime;
    562659}
     
    568665    quint64 total = m_videoPlayer->duration();
    569666
    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
    583685        if (lastUpdateTime < m_currentTime && m_currentTime == total){
    584686            emit finished();
     
    590692        // We have a next source.
    591693        // 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);
    593695        if (m_waitNextSwap && m_state == Phonon::PlayingState &&
    594696            m_transitionTime < m_swapTime.msecsTo(QTime::currentTime())){
     
    693795void MediaObject::updateCrossFade()
    694796{
    695     m_mediaObjectAudioNode->updateCrossFade(m_currentTime);   
     797    m_mediaObjectAudioNode->updateCrossFade(m_currentTime);
    696798    // Clean-up previous movie if done fading:
    697799    if (m_mediaObjectAudioNode->m_fadeDuration == 0){
    698800        if (m_nextVideoPlayer->isPlaying() || m_nextAudioPlayer->isPlaying()){
    699             m_nextVideoPlayer->unsetVideo();
     801            m_nextVideoPlayer->unsetCurrentMediaSource();
    700802            m_nextAudioPlayer->unsetVideoPlayer();
    701803        }
    702     }       
     804    }
    703805}
    704806
     
    729831    if (m_videoPlayer->videoFrameChanged()){
    730832        updateLipSynch(50);
    731         VideoFrame frame(m_videoPlayer);           
     833        VideoFrame frame(m_videoPlayer);
    732834        if (m_nextVideoPlayer->isPlaying()
    733835            && m_nextVideoPlayer->hasVideo()
     
    737839            frame.setBaseOpacity(m_mediaObjectAudioNode->m_volume1);
    738840        }
    739        
     841
    740842        // Send the frame through the graph:
    741         updateVideo(frame);   
     843        updateVideo(frame);
    742844        checkForError();
    743845    }
     
    750852    if (m_videoSinkList.isEmpty() || m_audioSinkList.isEmpty())
    751853        return;
    752        
     854
    753855    if (m_videoPlayer->hasVideo()){
    754856        qint64 diff = m_audioPlayer->currentTime() - m_videoPlayer->currentTime();
     
    762864            m_nextAudioPlayer->seek(m_nextVideoPlayer->currentTime());
    763865    }
    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));
    774866}
    775867
     
    798890            checkForError();
    799891            m_mediaObjectAudioNode->setMute(false);
    800              if (m_state == Phonon::PlayingState)
    801                 bufferAudioVideo();
     892            if (m_state == Phonon::PlayingState)
     893                restartAudioVideoTimers();
    802894            break;
    803895        case MediaNodeEvent::AudioGraphCannotPlay:
     
    810902                m_mediaObjectAudioNode->setMute(false);
    811903            }
    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             }
    830904            break;
    831905        default:
    832906            break;
    833907    }
     908}
     909
     910bool 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    }
    834935    return QObject::event(event);
    835936}
    836937
    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 {
     938void 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
     948bool MediaObject::hasInterface(Interface iface) const
     949{
     950    return iface == AddonInterface::TitleInterface;
     951}
     952
     953QVariant 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    }
    844974    return QVariant();
    845975}
Note: See TracChangeset for help on using the changeset viewer.