/* This file is part of the KDE project.+ −
+ −
Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).+ −
+ −
This library is free software: you can redistribute it and/or modify+ −
it under the terms of the GNU Lesser General Public License as published by+ −
the Free Software Foundation, either version 2.1 or 3 of the License.+ −
+ −
This library is distributed in the hope that it will be useful,+ −
but WITHOUT ANY WARRANTY; without even the implied warranty of+ −
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ −
GNU Lesser General Public License for more details.+ −
+ −
You should have received a copy of the GNU Lesser General Public License+ −
along with this library. If not, see <http://www.gnu.org/licenses/>.+ −
*/+ −
+ −
#include "qasyncreader.h"+ −
#include "qbasefilter.h"+ −
+ −
QT_BEGIN_NAMESPACE+ −
+ −
namespace Phonon+ −
{+ −
namespace DS9+ −
{+ −
QAsyncReader::QAsyncReader(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mediaTypes) : QPin(parent, PINDIR_OUTPUT, mediaTypes)+ −
{+ −
}+ −
+ −
QAsyncReader::~QAsyncReader()+ −
{+ −
}+ −
+ −
STDMETHODIMP QAsyncReader::QueryInterface(REFIID iid, void **out)+ −
{+ −
if (!out) {+ −
return E_POINTER;+ −
}+ −
+ −
if (iid == IID_IAsyncReader) {+ −
AddRef();+ −
*out = static_cast<IAsyncReader*>(this);+ −
return S_OK;+ −
}+ −
+ −
return QPin::QueryInterface(iid, out);+ −
}+ −
+ −
STDMETHODIMP_(ULONG) QAsyncReader::AddRef()+ −
{+ −
return QPin::AddRef();+ −
}+ −
+ −
STDMETHODIMP_(ULONG) QAsyncReader::Release()+ −
{+ −
return QPin::Release();+ −
}+ −
+ −
+ −
STDMETHODIMP QAsyncReader::RequestAllocator(IMemAllocator *preferred, ALLOCATOR_PROPERTIES *prop,IMemAllocator **actual)+ −
{+ −
ALLOCATOR_PROPERTIES prop2;+ −
+ −
if (prop->cbAlign == 0) {+ −
prop->cbAlign = 1; //align on 1 char+ −
}+ −
+ −
if (preferred && preferred->SetProperties(prop, &prop2) == S_OK) {+ −
preferred->AddRef();+ −
*actual = preferred;+ −
return S_OK;+ −
}+ −
+ −
//we should try to create one memory allocator ourselves here+ −
return E_FAIL;+ −
}+ −
+ −
STDMETHODIMP QAsyncReader::Request(IMediaSample *sample,DWORD_PTR user)+ −
{+ −
QMutexLocker locker(&m_mutex);+ −
if (m_flushing) {+ −
return VFW_E_WRONG_STATE;+ −
}+ −
+ −
m_requestQueue.enqueue(AsyncRequest(sample, user));+ −
m_requestWait.wakeOne();+ −
return S_OK;+ −
}+ −
+ −
STDMETHODIMP QAsyncReader::WaitForNext(DWORD timeout, IMediaSample **sample, DWORD_PTR *user)+ −
{+ −
QMutexLocker locker(&m_mutex);+ −
if (!sample ||!user) {+ −
return E_POINTER;+ −
}+ −
+ −
//msdn says to return immediately if we're flushing but that doesn't seem to be true+ −
//since it triggers a dead-lock somewhere inside directshow (see task 258830)+ −
+ −
*sample = 0;+ −
*user = 0;+ −
+ −
if (m_requestQueue.isEmpty()) {+ −
if (m_requestWait.wait(&m_mutex, timeout) == false) {+ −
return VFW_E_TIMEOUT;+ −
}+ −
if (m_requestQueue.isEmpty()) {+ −
return VFW_E_WRONG_STATE;+ −
}+ −
}+ −
+ −
AsyncRequest r = m_requestQueue.dequeue();+ −
+ −
//at this point we're sure to have a request to proceed+ −
if (r.sample == 0) {+ −
return E_FAIL;+ −
}+ −
+ −
*sample = r.sample;+ −
*user = r.user;+ −
return syncReadAlignedUnlocked(r.sample);+ −
}+ −
+ −
STDMETHODIMP QAsyncReader::BeginFlush()+ −
{+ −
QMutexLocker locker(&m_mutex);+ −
m_flushing = true;+ −
m_requestWait.wakeOne();+ −
return S_OK;+ −
}+ −
+ −
STDMETHODIMP QAsyncReader::EndFlush()+ −
{+ −
QMutexLocker locker(&m_mutex);+ −
m_flushing = false;+ −
return S_OK;+ −
}+ −
+ −
STDMETHODIMP QAsyncReader::SyncReadAligned(IMediaSample *sample)+ −
{+ −
QMutexLocker locker(&m_mutex);+ −
return syncReadAlignedUnlocked(sample);+ −
}+ −
+ −
STDMETHODIMP QAsyncReader::SyncRead(LONGLONG pos, LONG length, BYTE *buffer)+ −
{+ −
QMutexLocker locker(&m_mutex);+ −
return read(pos, length, buffer, 0);+ −
}+ −
+ −
+ −
STDMETHODIMP QAsyncReader::syncReadAlignedUnlocked(IMediaSample *sample)+ −
{+ −
Q_ASSERT(!m_mutex.tryLock());+ −
+ −
if (!sample) {+ −
return E_POINTER;+ −
}+ −
+ −
REFERENCE_TIME start = 0,+ −
stop = 0;+ −
HRESULT hr = sample->GetTime(&start, &stop);+ −
if(FAILED(hr)) {+ −
return hr;+ −
}+ −
+ −
LONGLONG startPos = start / 10000000;+ −
LONG length = static_cast<LONG>((stop - start) / 10000000);+ −
+ −
BYTE *buffer;+ −
hr = sample->GetPointer(&buffer);+ −
if(FAILED(hr)) {+ −
return hr;+ −
}+ −
+ −
LONG actual = 0;+ −
read(startPos, length, buffer, &actual);+ −
+ −
return sample->SetActualDataLength(actual);+ −
}+ −
+ −
}+ −
}+ −
+ −
QT_END_NAMESPACE+ −