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/ds9/mediaobject.cpp

    r2 r561  
    2424#ifndef Q_CC_MSVC
    2525#include <dshow.h>
    26 #endif //Q_CC_MSVC
     26#endif
    2727#include <objbase.h>
    2828#include <initguid.h>
     
    3737#include <QtCore/QDebug>
    3838
    39 #define TIMER_INTERVAL 16 //... ms for the timer that polls the current state (we use the multimedia timer
     39#define TIMER_INTERVAL 16 //... ms for the timer that polls the current state (we use the multimedia timer)
    4040#define PRELOAD_TIME 2000 // 2 seconds to load a source
    4141
     
    5050        //first the definition of the WorkerThread class
    5151        WorkerThread::WorkerThread()
    52           : QThread(), m_currentRenderId(0), m_finished(false), m_currentWorkId(1)
     52          : QThread(), m_finished(false), m_currentWorkId(1)
    5353        {
    5454        }
     
    5656        WorkerThread::~WorkerThread()
    5757        {
    58         }
    59 
    60         WorkerThread::Work WorkerThread::dequeueWork()
    61         {
    62             QMutexLocker locker(&m_mutex);
    63             if (m_finished) {
    64                 return Work();
    65             }
    66             Work ret = m_queue.dequeue();
    67 
    68             //we ensure to have the wait condition in the right state
    69             if (m_queue.isEmpty()) {
    70                 m_waitCondition.reset();
    71             } else {
    72                 m_waitCondition.set();
    73             }
    74 
    75             return ret;
    7658        }
    7759
     
    8971                DWORD result = ::WaitForMultipleObjects(count, handles, FALSE, INFINITE);
    9072                if (result == WAIT_OBJECT_0) {
    91                     if (m_finished) {
    92                         //that's the end if the thread execution
    93                         return;
    94                     }
    95 
    9673                    handleTask();
    9774                } else {
     
    181158            w.graph = Graph(CLSID_FilterGraph, IID_IGraphBuilder);
    182159            w.filter = filter;
     160            w.graph->AddFilter(filter, 0);
    183161            w.id = m_currentWorkId++;
    184162            m_queue.enqueue(w);
     
    200178        void WorkerThread::handleTask()
    201179        {
    202             const Work w = dequeueWork();
    203 
    204             if (m_finished) {
    205                 return;
     180            QMutexLocker locker(Backend::directShowMutex);
     181            {
     182                QMutexLocker locker(&m_mutex);
     183                if (m_finished || m_queue.isEmpty()) {
     184                    return;
     185                }
     186
     187                m_currentWork = m_queue.dequeue();
     188
     189                //we ensure to have the wait condition in the right state
     190                if (m_queue.isEmpty()) {
     191                    m_waitCondition.reset();
     192                } else {
     193                    m_waitCondition.set();
     194                }
    206195            }
    207196
    208197            HRESULT hr = S_OK;
    209198
    210             m_currentRender = w.graph;
    211                         m_currentRenderId = w.id;
    212             if (w.task == ReplaceGraph) {
    213                 QMutexLocker locker(&m_mutex);
    214                 HANDLE h;
    215 
     199            if (m_currentWork.task == ReplaceGraph) {
    216200                int index = -1;
    217201                for(int i = 0; i < FILTER_COUNT; ++i) {
    218                     if (m_graphHandle[i].graph == w.oldGraph) {
     202                    if (m_graphHandle[i].graph == m_currentWork.oldGraph) {
    219203                        m_graphHandle[i].graph = Graph();
    220204                        index = i;
     
    229213
    230214                //add the new graph
    231                 if (SUCCEEDED(ComPointer<IMediaEvent>(w.graph, IID_IMediaEvent)
     215                HANDLE h;
     216                if (SUCCEEDED(ComPointer<IMediaEvent>(m_currentWork.graph, IID_IMediaEvent)
    232217                    ->GetEventHandle(reinterpret_cast<OAEVENT*>(&h)))) {
    233                     m_graphHandle[index].graph = w.graph;
     218                    m_graphHandle[index].graph = m_currentWork.graph;
    234219                    m_graphHandle[index].handle = h;
    235220                }
    236             } else if (w.task == Render) {
    237                 if (w.filter) {
     221            } else if (m_currentWork.task == Render) {
     222                if (m_currentWork.filter) {
    238223                    //let's render pins
    239                     w.graph->AddFilter(w.filter, 0);
    240                     const QList<OutputPin> outputs = BackendNode::pins(w.filter, PINDIR_OUTPUT);
    241                     for (int i = 0; i < outputs.count(); ++i) {
    242                         //blocking call
    243                         hr = w.graph->Render(outputs.at(i));
    244                         if (FAILED(hr)) {
    245                             break;
    246                         }
    247                     }
    248                 } else if (!w.url.isEmpty()) {
     224                    const QList<OutputPin> outputs = BackendNode::pins(m_currentWork.filter, PINDIR_OUTPUT);
     225                    for (int i = 0; SUCCEEDED(hr) && i < outputs.count(); ++i) {
     226                        hr = m_currentWork.graph->Render(outputs.at(i));
     227                    }
     228                } else if (!m_currentWork.url.isEmpty()) {
    249229                    //let's render a url (blocking call)
    250                     hr = w.graph->RenderFile(reinterpret_cast<const wchar_t *>(w.url.utf16()), 0);
     230                    hr = m_currentWork.graph->RenderFile(reinterpret_cast<const wchar_t *>(m_currentWork.url.utf16()), 0);
    251231                }
    252232                if (hr != E_ABORT) {
    253                                         emit asyncRenderFinished(w.id, hr, w.graph);
    254                 }
    255             } else if (w.task == Seek) {
     233                    emit asyncRenderFinished(m_currentWork.id, hr, m_currentWork.graph);
     234                }
     235            } else if (m_currentWork.task == Seek) {
    256236                //that's a seekrequest
    257                 ComPointer<IMediaSeeking> mediaSeeking(w.graph, IID_IMediaSeeking);
    258                 qint64 newtime = w.time * 10000;
     237                ComPointer<IMediaSeeking> mediaSeeking(m_currentWork.graph, IID_IMediaSeeking);
     238                qint64 newtime = m_currentWork.time * 10000;
    259239                hr = mediaSeeking->SetPositions(&newtime, AM_SEEKING_AbsolutePositioning,
    260240                    0, AM_SEEKING_NoPositioning);
    261                 qint64 currentTime = -1;
    262                 if (SUCCEEDED(hr)) {
    263                     hr = mediaSeeking->GetCurrentPosition(&currentTime);
    264                     if (SUCCEEDED(hr)) {
    265                         currentTime /= 10000; //convert to ms
    266                     }
    267                 }
    268                 emit asyncSeekingFinished(w.id, currentTime);
    269                 hr = E_ABORT; //to avoid emitting asyncRenderFinished
    270             } else if (w.task == ChangeState) {
     241                emit asyncSeekingFinished(m_currentWork.id, newtime / 10000);
     242                hr = E_ABORT; //to avoid emitting asyncRenderFinished
     243            } else if (m_currentWork.task == ChangeState) {
    271244
    272245                //remove useless decoders
    273246                QList<Filter> unused;
    274                 for (int i = 0; i < w.decoders.count(); ++i) {
    275                     const Filter &filter = w.decoders.at(i);
     247                for (int i = 0; i < m_currentWork.decoders.count(); ++i) {
     248                    const Filter &filter = m_currentWork.decoders.at(i);
    276249                    bool used = false;
    277250                    const QList<OutputPin> pins = BackendNode::pins(filter, PINDIR_OUTPUT);
     
    290263                for (int i = 0; i < unused.count(); ++i) {
    291264                    //we should remove this filter from the graph
    292                     w.graph->RemoveFilter(unused.at(i));
     265                    m_currentWork.graph->RemoveFilter(unused.at(i));
    293266                }
    294267
    295268
    296269                //we can get the state
    297                 ComPointer<IMediaControl> mc(w.graph, IID_IMediaControl);
     270                ComPointer<IMediaControl> mc(m_currentWork.graph, IID_IMediaControl);
    298271
    299272                //we change the state here
    300                 switch(w.state)
     273                switch(m_currentWork.state)
    301274                {
    302275                case State_Stopped:
     
    316289                if (SUCCEEDED(hr)) {
    317290                    if (s == State_Stopped) {
    318                         emit stateReady(w.graph, Phonon::StoppedState);
     291                        emit stateReady(m_currentWork.graph, Phonon::StoppedState);
    319292                    } else if (s == State_Paused) {
    320                         emit stateReady(w.graph, Phonon::PausedState);
     293                        emit stateReady(m_currentWork.graph, Phonon::PausedState);
    321294                    } else /*if (s == State_Running)*/ {
    322                         emit stateReady(w.graph, Phonon::PlayingState);
    323                     }
    324                 }
    325             }
    326 
    327             m_currentRender = Graph();
    328                         m_currentRenderId = 0;
    329 
    330         }
    331 
    332                 void WorkerThread::abortCurrentRender(qint16 renderId)
    333                 {
     295                        emit stateReady(m_currentWork.graph, Phonon::PlayingState);
     296                    }
     297                }
     298            }
     299
     300            {
     301                QMutexLocker locker(&m_mutex);
     302                m_currentWork = Work(); //reinitialize
     303            }
     304        }
     305
     306        void WorkerThread::abortCurrentRender(qint16 renderId)
     307        {
    334308            QMutexLocker locker(&m_mutex);
     309            if (m_currentWork.id == renderId) {
     310                m_currentWork.graph->Abort();
     311            }
    335312            bool found = false;
    336             //we try to see if there is already an attempt to seek and we remove it
    337313            for(int i = 0; !found && i < m_queue.size(); ++i) {
    338314                const Work &w = m_queue.at(i);
     
    340316                    found = true;
    341317                    m_queue.removeAt(i);
    342                 }
    343             }
    344 
    345                         if (m_currentRender && m_currentRenderId == renderId) {
    346                                 m_currentRender->Abort();
    347                         }
    348                 }
     318                    if (m_queue.isEmpty()) {
     319                        m_waitCondition.reset();
     320                    }
     321                }
     322            }
     323        }
    349324
    350325        //tells the thread to stop processing
     
    353328            QMutexLocker locker(&m_mutex);
    354329            m_queue.clear();
    355             if (m_currentRender) {
     330            if (m_currentWork.graph) {
    356331                //in case we're currently rendering something
    357                 m_currentRender->Abort();
     332                m_currentWork.graph->Abort();
    358333
    359334            }
     
    384359
    385360            for(int i = 0; i < FILTER_COUNT; ++i) {
    386                 m_graphs[i] = new MediaGraph(this, i);               
    387             }
    388 
    389             connect(&m_thread, SIGNAL(stateReady(Graph, Phonon::State)),
    390                                SLOT(slotStateReady(Graph, Phonon::State)));
    391 
    392             connect(&m_thread, SIGNAL(eventReady(Graph, long, long)),
    393                                SLOT(handleEvents(Graph, long, long)));
    394 
    395             connect(&m_thread, SIGNAL(asyncRenderFinished(quint16, HRESULT, Graph)),
    396                 SLOT(finishLoading(quint16, HRESULT, Graph)));
    397 
    398             connect(&m_thread, SIGNAL(asyncSeekingFinished(quint16, qint64)),
    399                 SLOT(finishSeeking(quint16, qint64)));
     361                m_graphs[i] = new MediaGraph(this, i);
     362            }
     363
     364            connect(&m_thread, SIGNAL(stateReady(Graph,Phonon::State)),
     365                               SLOT(slotStateReady(Graph,Phonon::State)));
     366
     367            connect(&m_thread, SIGNAL(eventReady(Graph,long,long)),
     368                               SLOT(handleEvents(Graph,long,long)));
     369
     370            connect(&m_thread, SIGNAL(asyncRenderFinished(quint16,HRESULT,Graph)),
     371                SLOT(finishLoading(quint16,HRESULT,Graph)));
     372
     373            connect(&m_thread, SIGNAL(asyncSeekingFinished(quint16,qint64)),
     374                SLOT(finishSeeking(quint16,qint64)));
    400375            //really special case
    401376            m_mediaObject = this;
     
    485460
    486461                    if (!m_aboutToFinishSent && remaining < PRELOAD_TIME - m_transitionTime  + TIMER_INTERVAL/2) {
    487                         //let's take a 2 seconds time time to actually load the next file
     462                        //let's take a 2 seconds time to actually load the next file
    488463#ifdef GRAPH_DEBUG
    489464                        qDebug() << "DS9: emit aboutToFinish" << remaining << QTime::currentTime().toString();
     
    520495            qSwap(m_graphs[0], m_graphs[1]); //swap the graphs
    521496
     497            if (m_transitionTime >= 0)
     498                m_graphs[1]->stop(); //make sure we stop the previous graph
     499
     500            if (currentGraph()->mediaSource().type() != Phonon::MediaSource::Invalid &&
     501                catchComError(currentGraph()->renderResult())) {
     502                    setState(Phonon::ErrorState);
     503                    return;
     504            }
     505
     506            //we need to play the next media
     507            play();
     508
    522509            //we tell the video widgets to switch now to the new source
    523510#ifndef QT_NO_PHONON_VIDEO
     
    528515
    529516            emit currentSourceChanged(currentGraph()->mediaSource());
    530 
    531             if (currentGraph()->isLoading()) {
    532                 //will simply tell that when loading is finished
    533                 //it should start the playback
    534                 play();
    535             }
    536 
    537 
    538 
    539517            emit metaDataChanged(currentGraph()->metadata());
    540518
     
    549527            setTitles(currentGraph()->titles());
    550528#endif //QT_NO_PHONON_MEDIACONTROLLER
    551 
    552             //this manages only gapless transitions
    553             if (currentGraph()->mediaSource().type() != Phonon::MediaSource::Invalid) {
    554                 if (catchComError(currentGraph()->renderResult())) {
    555                     setState(Phonon::ErrorState);
    556                 } else {
    557                     play();
    558                 }
    559             }
    560529        }
    561530
     
    583552#ifndef QT_NO_PHONON_MEDIACONTROLLER
    584553            //1st, check if there is more titles after
    585             const qint64 ret = (m_currentTitle < _iface_availableTitles() - 1) ? 
     554            const qint64 ret = (m_currentTitle < _iface_availableTitles() - 1) ?
    586555                titleAbsolutePosition(m_currentTitle+1) : currentGraph()->absoluteTotalTime();
    587556
     
    596565        {
    597566            //this handles inaccuracy when stopping on a title
    598             return currentGraph()->absoluteCurrentTime() 
     567            return currentGraph()->absoluteCurrentTime()
    599568#ifndef QT_NO_PHONON_MEDIACONTROLLER
    600569                - titleAbsolutePosition(m_currentTitle)
     
    746715            setState(Phonon::LoadingState);
    747716            //After loading we go into stopped state
    748             m_nextState = Phonon::StoppedState; 
     717            m_nextState = Phonon::StoppedState;
    749718            catchComError(currentGraph()->loadSource(source));
    750719            emit currentSourceChanged(source);
     
    760729        void MediaObject::loadingFinished(MediaGraph *mg)
    761730        {
    762             if (mg == currentGraph()) { 
     731            if (mg == currentGraph()) {
    763732#ifndef QT_NO_PHONON_MEDIACONTROLLER
    764733                //Title interface
     
    791760                case Phonon::PausedState:
    792761                    pause();
    793                     break;
    794                 case Phonon::StoppedState:
    795                     stop();
    796762                    break;
    797763                case Phonon::PlayingState:
     
    801767                    setState(Phonon::ErrorState);
    802768                    break;
     769                case Phonon::StoppedState:
     770                default:
     771                    stop();
     772                    break;
    803773                }
    804774            }
     
    817787        void MediaObject::seekingFinished(MediaGraph *mg)
    818788        {
    819             if (mg == currentGraph()) { 
     789            if (mg == currentGraph()) {
    820790
    821791                updateTargetTick();
     
    848818                LPAMGETERRORTEXT getErrorText = (LPAMGETERRORTEXT)QLibrary::resolve(QLatin1String("quartz"), "AMGetErrorTextW");
    849819
    850                 ushort buffer[MAX_ERROR_TEXT_LEN];
    851                 if (getErrorText && getErrorText(hr, (WCHAR*)buffer, MAX_ERROR_TEXT_LEN)) {
    852                     m_errorString = QString::fromUtf16(buffer);
     820                WCHAR buffer[MAX_ERROR_TEXT_LEN];
     821                if (getErrorText && getErrorText(hr, buffer, MAX_ERROR_TEXT_LEN)) {
     822                    m_errorString = QString::fromWCharArray(buffer);
    853823                } else {
    854824                    m_errorString = QString::fromLatin1("Unknown error");
     
    892862                if (VideoWidget *video = qobject_cast<VideoWidget*>(sink)) {
    893863                    m_videoWidgets += video;
    894                 } else 
     864                } else
    895865#endif //QT_NO_PHONON_VIDEO
    896866                    if (AudioOutput *audio = qobject_cast<AudioOutput*>(sink)) {
     
    911881                if (VideoWidget *video = qobject_cast<VideoWidget*>(sink)) {
    912882                    m_videoWidgets.removeOne(video);
    913                 } else 
     883                } else
    914884#endif //QT_NO_PHONON_VIDEO
    915885                    if (AudioOutput *audio = qobject_cast<AudioOutput*>(sink)) {
     
    993963                }
    994964                break;
    995             case EC_LENGTH_CHANGED: 
     965            case EC_LENGTH_CHANGED:
    996966                if (graph == currentGraph()->graph()) {
    997967                    emit totalTimeChanged( totalTime() );
Note: See TracChangeset for help on using the changeset viewer.