1
/* This file is part of the KDE project.
3
Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
5
This library is free software: you can redistribute it and/or modify
6
it under the terms of the GNU Lesser General Public License as published by
7
the Free Software Foundation, either version 2.1 or 3 of the License.
9
This library is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU Lesser General Public License for more details.
14
You should have received a copy of the GNU Lesser General Public License
15
along with this library. If not, see <http://www.gnu.org/licenses/>.
18
#include "qbasefilter.h"
21
#include <QtCore/QMutex>
30
class QEnumPins : public IEnumPins
33
QEnumPins(QBaseFilter *filter) : m_refCount(1),
34
m_filter(filter), m_pins(filter->pins()), m_index(0)
44
STDMETHODIMP QueryInterface(const IID &iid,void **out)
51
if (iid == IID_IEnumPins) {
52
*out = static_cast<IEnumPins*>(this);
53
} else if (iid == IID_IUnknown) {
54
*out = static_cast<IUnknown*>(this);
65
STDMETHODIMP_(ULONG) AddRef()
67
return InterlockedIncrement(&m_refCount);
70
STDMETHODIMP_(ULONG) Release()
72
ULONG refCount = InterlockedDecrement(&m_refCount);
80
STDMETHODIMP Next(ULONG count,IPin **ret,ULONG *fetched)
82
QMutexLocker locker(&m_mutex);
83
if (m_filter->pins() != m_pins) {
84
return VFW_E_ENUM_OUT_OF_SYNC;
87
if (fetched == 0 && count > 1) {
96
while (nbfetched < count && m_index < m_pins.count()) {
97
IPin *current = m_pins[m_index];
99
ret[nbfetched] = current;
105
*fetched = nbfetched;
108
return nbfetched == count ? S_OK : S_FALSE;
111
STDMETHODIMP Skip(ULONG count)
113
QMutexLocker locker(&m_mutex);
114
if (m_filter->pins() != m_pins) {
115
return VFW_E_ENUM_OUT_OF_SYNC;
118
m_index = qMin(m_index + int(count), m_pins.count());
119
return m_index == m_pins.count() ? S_FALSE : S_OK;
124
QMutexLocker locker(&m_mutex);
129
STDMETHODIMP Clone(IEnumPins **out)
131
QMutexLocker locker(&m_mutex);
132
if (m_filter->pins() != m_pins) {
133
return VFW_E_ENUM_OUT_OF_SYNC;
140
*out = new QEnumPins(m_filter);
141
(*out)->Skip(m_index);
148
QBaseFilter *m_filter;
155
QBaseFilter::QBaseFilter(const CLSID &clsid):
156
m_refCount(1), m_clsid(clsid), m_clock(0), m_graph(0), m_state(State_Stopped)
160
QBaseFilter::~QBaseFilter()
162
while (!m_pins.isEmpty()) {
163
delete m_pins.first();
167
const QList<QPin *> QBaseFilter::pins() const
169
QMutexLocker locker(&m_mutex);
173
void QBaseFilter::addPin(QPin *pin)
175
QMutexLocker locker(&m_mutex);
179
void QBaseFilter::removePin(QPin *pin)
181
QMutexLocker locker(&m_mutex);
182
m_pins.removeAll(pin);
185
FILTER_STATE QBaseFilter::state() const
190
IFilterGraph *QBaseFilter::graph() const
195
STDMETHODIMP QBaseFilter::QueryInterface(REFIID iid, void **out)
203
if (iid == IID_IBaseFilter) {
204
*out = static_cast<IBaseFilter*>(this);
205
} else if (iid == IID_IMediaFilter) {
206
*out = static_cast<IMediaFilter*>(this);
207
} else if (iid == IID_IPersist) {
208
*out = static_cast<IPersist*>(this);
209
} else if (iid == IID_IUnknown) {
210
*out = static_cast<IUnknown*>(static_cast<IBaseFilter*>(this));
212
else if (iid == IID_IMediaPosition || iid == IID_IMediaSeeking) {
213
if (inputPins().isEmpty()) {
214
*out = getUpStreamInterface(iid);
216
return S_OK; //we return here to avoid adding a reference
220
} else if (iid == IID_IMediaSeeking) {
221
*out = static_cast<IMediaSeeking*>(this);
222
} else if (iid == IID_IMediaPosition ||iid == IID_IDispatch) {
223
*out = static_cast<IMediaPosition*>(this);
237
STDMETHODIMP_(ULONG) QBaseFilter::AddRef()
239
return InterlockedIncrement(&m_refCount);
242
STDMETHODIMP_(ULONG) QBaseFilter::Release()
244
ULONG refCount = InterlockedDecrement(&m_refCount);
252
STDMETHODIMP QBaseFilter::GetClassID(CLSID *clsid)
254
QMutexLocker locker(&m_mutex);
259
STDMETHODIMP QBaseFilter::Stop()
261
QMutexLocker locker(&m_mutex);
262
m_state = State_Stopped;
266
STDMETHODIMP QBaseFilter::Pause()
268
QMutexLocker locker(&m_mutex);
269
m_state = State_Paused;
273
STDMETHODIMP QBaseFilter::Run(REFERENCE_TIME)
275
QMutexLocker locker(&m_mutex);
276
m_state = State_Running;
280
STDMETHODIMP QBaseFilter::GetState(DWORD, FILTER_STATE *state)
282
QMutexLocker locker(&m_mutex);
291
STDMETHODIMP QBaseFilter::SetSyncSource(IReferenceClock *clock)
293
QMutexLocker locker(&m_mutex);
304
STDMETHODIMP QBaseFilter::GetSyncSource(IReferenceClock **clock)
306
QMutexLocker locker(&m_mutex);
319
STDMETHODIMP QBaseFilter::FindPin(LPCWSTR name, IPin**pin)
325
for (int i = 0; i < m_pins.count(); ++i) {
326
IPin * current = m_pins.at(i);
328
current->QueryPinInfo(&info);
330
info.pFilter->Release();
332
if ( wcscmp(info.achName, name) == 0) {
340
return VFW_E_NOT_FOUND;
343
STDMETHODIMP QBaseFilter::QueryFilterInfo(FILTER_INFO *info )
345
QMutexLocker locker(&m_mutex);
349
info->pGraph = m_graph;
353
memcpy(info->achName, m_name.utf16(), qMin(MAX_FILTER_NAME, m_name.length()+1) *2);
357
STDMETHODIMP QBaseFilter::JoinFilterGraph(IFilterGraph *graph, LPCWSTR name)
359
QMutexLocker locker(&m_mutex);
361
m_name = QString::fromUtf16((unsigned short*) name);
365
STDMETHODIMP QBaseFilter::EnumPins( IEnumPins **ep)
371
*ep = new QEnumPins(this);
376
STDMETHODIMP QBaseFilter::QueryVendorInfo(LPWSTR *)
378
//we give no information on that
382
//implementation from IMediaSeeking
383
STDMETHODIMP QBaseFilter::GetCapabilities(DWORD *pCapabilities)
385
IMediaSeeking *ms = getUpstreamMediaSeeking();
390
HRESULT hr = ms->GetCapabilities(pCapabilities);
395
STDMETHODIMP QBaseFilter::CheckCapabilities(DWORD *pCapabilities)
397
IMediaSeeking *ms = getUpstreamMediaSeeking();
402
HRESULT hr = ms->CheckCapabilities(pCapabilities);
407
STDMETHODIMP QBaseFilter::IsFormatSupported(const GUID *pFormat)
409
IMediaSeeking *ms = getUpstreamMediaSeeking();
414
HRESULT hr = ms->IsFormatSupported(pFormat);
419
STDMETHODIMP QBaseFilter::QueryPreferredFormat(GUID *pFormat)
421
IMediaSeeking *ms = getUpstreamMediaSeeking();
426
HRESULT hr = ms->QueryPreferredFormat(pFormat);
431
STDMETHODIMP QBaseFilter::GetTimeFormat(GUID *pFormat)
433
IMediaSeeking *ms = getUpstreamMediaSeeking();
438
HRESULT hr = ms->GetTimeFormat(pFormat);
443
STDMETHODIMP QBaseFilter::IsUsingTimeFormat(const GUID *pFormat)
445
IMediaSeeking *ms = getUpstreamMediaSeeking();
450
HRESULT hr = ms->IsUsingTimeFormat(pFormat);
455
STDMETHODIMP QBaseFilter::SetTimeFormat(const GUID *pFormat)
457
IMediaSeeking *ms = getUpstreamMediaSeeking();
462
HRESULT hr = ms->SetTimeFormat(pFormat);
467
STDMETHODIMP QBaseFilter::GetDuration(LONGLONG *pDuration)
469
IMediaSeeking *ms = getUpstreamMediaSeeking();
474
HRESULT hr = ms->GetDuration(pDuration);
479
STDMETHODIMP QBaseFilter::GetStopPosition(LONGLONG *pStop)
481
IMediaSeeking *ms = getUpstreamMediaSeeking();
486
HRESULT hr = ms->GetStopPosition(pStop);
491
STDMETHODIMP QBaseFilter::GetCurrentPosition(LONGLONG *pCurrent)
493
IMediaSeeking *ms = getUpstreamMediaSeeking();
498
HRESULT hr = ms->GetCurrentPosition(pCurrent);
503
STDMETHODIMP QBaseFilter::ConvertTimeFormat(LONGLONG *pTarget,
504
const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat)
506
IMediaSeeking *ms = getUpstreamMediaSeeking();
511
HRESULT hr = ms->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat);
516
STDMETHODIMP QBaseFilter::SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags)
518
IMediaSeeking *ms = getUpstreamMediaSeeking();
523
HRESULT hr = ms->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags);
528
STDMETHODIMP QBaseFilter::GetPositions(LONGLONG *pCurrent, LONGLONG *pStop)
530
IMediaSeeking *ms = getUpstreamMediaSeeking();
535
HRESULT hr = ms->GetPositions(pCurrent, pStop);
540
STDMETHODIMP QBaseFilter::GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest)
542
IMediaSeeking *ms = getUpstreamMediaSeeking();
547
HRESULT hr = ms->GetAvailable(pEarliest, pLatest);
552
STDMETHODIMP QBaseFilter::SetRate(double dRate)
554
IMediaSeeking *ms = getUpstreamMediaSeeking();
559
HRESULT hr = ms->SetRate(dRate);
564
STDMETHODIMP QBaseFilter::GetRate(double *dRate)
566
IMediaSeeking *ms = getUpstreamMediaSeeking();
571
HRESULT hr = ms->GetRate(dRate);
576
STDMETHODIMP QBaseFilter::GetPreroll(LONGLONG *pllPreroll)
578
IMediaSeeking *ms = getUpstreamMediaSeeking();
583
HRESULT hr = ms->GetPreroll(pllPreroll);
588
//implementation from IMediaPosition
589
STDMETHODIMP QBaseFilter::get_Duration(REFTIME *plength)
591
IMediaPosition *mp = getUpstreamMediaPosition();
596
HRESULT hr = mp->get_Duration(plength);
601
STDMETHODIMP QBaseFilter::put_CurrentPosition(REFTIME llTime)
603
IMediaPosition *mp = getUpstreamMediaPosition();
608
HRESULT hr = mp->put_CurrentPosition(llTime);
613
STDMETHODIMP QBaseFilter::get_CurrentPosition(REFTIME *pllTime)
615
IMediaPosition *mp = getUpstreamMediaPosition();
620
HRESULT hr = mp->get_CurrentPosition(pllTime);
625
STDMETHODIMP QBaseFilter::get_StopTime(REFTIME *pllTime)
627
IMediaPosition *mp = getUpstreamMediaPosition();
632
HRESULT hr = mp->get_StopTime(pllTime);
637
STDMETHODIMP QBaseFilter::put_StopTime(REFTIME llTime)
639
IMediaPosition *mp = getUpstreamMediaPosition();
644
HRESULT hr = mp->put_StopTime(llTime);
649
STDMETHODIMP QBaseFilter::get_PrerollTime(REFTIME *pllTime)
651
IMediaPosition *mp = getUpstreamMediaPosition();
656
HRESULT hr = mp->get_PrerollTime(pllTime);
661
STDMETHODIMP QBaseFilter::put_PrerollTime(REFTIME llTime)
663
IMediaPosition *mp = getUpstreamMediaPosition();
668
HRESULT hr = mp->put_PrerollTime(llTime);
673
STDMETHODIMP QBaseFilter::put_Rate(double dRate)
675
IMediaPosition *mp = getUpstreamMediaPosition();
680
HRESULT hr = mp->put_Rate(dRate);
685
STDMETHODIMP QBaseFilter::get_Rate(double *pdRate)
687
IMediaPosition *mp = getUpstreamMediaPosition();
692
HRESULT hr = mp->get_Rate(pdRate);
697
STDMETHODIMP QBaseFilter::CanSeekForward(LONG *pCanSeekForward)
699
IMediaPosition *mp = getUpstreamMediaPosition();
704
HRESULT hr = mp->CanSeekForward(pCanSeekForward);
709
STDMETHODIMP QBaseFilter::CanSeekBackward(LONG *pCanSeekBackward)
711
IMediaPosition *mp = getUpstreamMediaPosition();
716
HRESULT hr = mp->CanSeekBackward(pCanSeekBackward);
721
STDMETHODIMP QBaseFilter::GetTypeInfoCount(UINT *pctinfo)
723
IMediaPosition *mp = getUpstreamMediaPosition();
728
HRESULT hr = mp->GetTypeInfoCount(pctinfo);
733
STDMETHODIMP QBaseFilter::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
735
IMediaPosition *mp = getUpstreamMediaPosition();
740
HRESULT hr = mp->GetTypeInfo(iTInfo, lcid, ppTInfo);
745
STDMETHODIMP QBaseFilter::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
747
IMediaPosition *mp = getUpstreamMediaPosition();
752
HRESULT hr = mp->GetIDsOfNames(riid, rgszNames, cNames, lcid, rgDispId);
757
STDMETHODIMP QBaseFilter::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
758
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
760
IMediaPosition *mp = getUpstreamMediaPosition();
765
HRESULT hr = mp->Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
771
IMediaSeeking *QBaseFilter::getUpstreamMediaSeeking()
773
return static_cast<IMediaSeeking*>(getUpStreamInterface(IID_IMediaSeeking));
776
IMediaPosition *QBaseFilter::getUpstreamMediaPosition()
778
return static_cast<IMediaPosition*>(getUpStreamInterface(IID_IMediaPosition));
781
QList<QPin*> QBaseFilter::inputPins() const
784
for(int i = 0; i < m_pins.count(); ++i) {
785
QPin * pin = m_pins.at(i);
786
if (pin->direction() == PINDIR_INPUT) {
793
QList<QPin*> QBaseFilter::outputPins() const
796
for(int i = 0; i < m_pins.count(); ++i) {
797
QPin * pin = m_pins.at(i);
798
if (pin->direction() == PINDIR_OUTPUT) {
805
void *QBaseFilter::getUpStreamInterface(const IID &iid) const
807
const QList<QPin*> inputs = inputPins();
808
for (int i = 0; i < inputs.count(); ++i) {
809
IPin *out = inputs.at(i)->connected();
812
out->QueryInterface(iid, &ms);
824
HRESULT QBaseFilter::processSample(IMediaSample *)