예제 #1
0
 QList<InputPin> BackendNode::pins(const Filter &filter, PIN_DIRECTION wantedDirection)
 {
     QList<InputPin> ret;
     if (filter) {
         ComPointer<IEnumPins> enumPin;
         HRESULT hr = filter->EnumPins(enumPin.pparam());
         Q_UNUSED(hr);
         Q_ASSERT( SUCCEEDED(hr));
         InputPin pin;
         while (enumPin->Next(1, pin.pparam(), 0) == S_OK) {
             PIN_DIRECTION dir;
             hr = pin->QueryDirection(&dir);
             Q_ASSERT( SUCCEEDED(hr));
             if (dir == wantedDirection) {
                 ret.append(pin);
             }
         }
     }
     return ret;
 }
예제 #2
0
void WorkerThread::handleTask()
{
    const Work w = dequeueWork();

    if (m_finished) {
        return;
    }

    HRESULT hr = S_OK;

    m_currentRender = w.graph;
    m_currentRenderId = w.id;
    if (w.task == ReplaceGraph) {
        QMutexLocker locker(&m_mutex);
        HANDLE h;

        int index = -1;
        for(int i = 0; i < FILTER_COUNT; ++i) {
            if (m_graphHandle[i].graph == w.oldGraph) {
                m_graphHandle[i].graph = Graph();
                index = i;
                break;
            } else if (index == -1 && m_graphHandle[i].graph == 0) {
                //this is the first available slot
                index = i;
            }
        }

        Q_ASSERT(index != -1);

        //add the new graph
        if (SUCCEEDED(ComPointer<IMediaEvent>(w.graph, IID_IMediaEvent)
                      ->GetEventHandle(reinterpret_cast<OAEVENT*>(&h)))) {
            m_graphHandle[index].graph = w.graph;
            m_graphHandle[index].handle = h;
        }
    } else if (w.task == Render) {
        if (w.filter) {
            //let's render pins
            w.graph->AddFilter(w.filter, 0);
            const QList<OutputPin> outputs = BackendNode::pins(w.filter, PINDIR_OUTPUT);
            for (int i = 0; i < outputs.count(); ++i) {
                //blocking call
                hr = w.graph->Render(outputs.at(i));
                if (FAILED(hr)) {
                    break;
                }
            }
        } else if (!w.url.isEmpty()) {
            //let's render a url (blocking call)
            hr = w.graph->RenderFile(reinterpret_cast<const wchar_t *>(w.url.utf16()), 0);
        }
        if (hr != E_ABORT) {
            emit asyncRenderFinished(w.id, hr, w.graph);
        }
    } else if (w.task == Seek) {
        //that's a seekrequest
        ComPointer<IMediaSeeking> mediaSeeking(w.graph, IID_IMediaSeeking);
        qint64 newtime = w.time * 10000;
        hr = mediaSeeking->SetPositions(&newtime, AM_SEEKING_AbsolutePositioning,
                                        0, AM_SEEKING_NoPositioning);
        qint64 currentTime = -1;
        if (SUCCEEDED(hr)) {
            hr = mediaSeeking->GetCurrentPosition(&currentTime);
            if (SUCCEEDED(hr)) {
                currentTime /= 10000; //convert to ms
            }
        }
        emit asyncSeekingFinished(w.id, currentTime);
        hr = E_ABORT; //to avoid emitting asyncRenderFinished
    } else if (w.task == ChangeState) {

        //remove useless decoders
        QList<Filter> unused;
        for (int i = 0; i < w.decoders.count(); ++i) {
            const Filter &filter = w.decoders.at(i);
            bool used = false;
            const QList<OutputPin> pins = BackendNode::pins(filter, PINDIR_OUTPUT);
            for( int i = 0; i < pins.count(); ++i) {
                InputPin input;
                if (pins.at(i)->ConnectedTo(input.pparam()) == S_OK) {
                    used = true;
                }
            }
            if (!used) {
                unused += filter;
            }
        }

        //we can get the state
        for (int i = 0; i < unused.count(); ++i) {
            //we should remove this filter from the graph
            w.graph->RemoveFilter(unused.at(i));
        }


        //we can get the state
        ComPointer<IMediaControl> mc(w.graph, IID_IMediaControl);

        //we change the state here
        switch(w.state)
        {
        case State_Stopped:
            mc->Stop();
            break;
        case State_Paused:
            mc->Pause();
            break;
        case State_Running:
            mc->Run();
            break;
        }
        OAFilterState s;
        //blocking call
        HRESULT hr = mc->GetState(INFINITE, &s);

        if (SUCCEEDED(hr)) {
            if (s == State_Stopped) {
                emit stateReady(w.graph, Phonon::StoppedState);
            } else if (s == State_Paused) {
                emit stateReady(w.graph, Phonon::PausedState);
            } else { /*if (s == State_Running)*/
                emit stateReady(w.graph, Phonon::PlayingState);
            }
        }
    }

    m_currentRender = Graph();
    m_currentRenderId = 0;

}