diff options
author | Justin McPherson <justin.mcpherson@nokia.com> | 2010-03-25 04:00:31 (GMT) |
---|---|---|
committer | Justin McPherson <justin.mcpherson@nokia.com> | 2010-03-25 04:00:31 (GMT) |
commit | 19a3fc3bd817628070e5637caf158b0be79eee82 (patch) | |
tree | 4f8b778fe7306970399ef2c237c867680682160f /src/3rdparty | |
parent | edb67f204302fff4f1e46676112931ea054deb88 (diff) | |
download | Qt-19a3fc3bd817628070e5637caf158b0be79eee82.zip Qt-19a3fc3bd817628070e5637caf158b0be79eee82.tar.gz Qt-19a3fc3bd817628070e5637caf158b0be79eee82.tar.bz2 |
Update Phonon ds9 backend to 4.4.0.
Diffstat (limited to 'src/3rdparty')
33 files changed, 621 insertions, 996 deletions
diff --git a/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp b/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp index a9d0694..e932e70 100644 --- a/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp +++ b/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp @@ -99,8 +99,8 @@ namespace Phonon m_dstX = m_dstY = 0; if (ratio > 0) { - if ((realWidth / realHeight > ratio && scaleMode == Phonon::VideoWidget::FitInView) - || (realWidth / realHeight < ratio && scaleMode == Phonon::VideoWidget::ScaleAndCrop)) { + if (realWidth / realHeight > ratio && scaleMode == Phonon::VideoWidget::FitInView + || realWidth / realHeight < ratio && scaleMode == Phonon::VideoWidget::ScaleAndCrop) { //the height is correct, let's change the width m_dstWidth = qRound(realHeight * ratio); m_dstX = qRound((realWidth - realHeight * ratio) / 2.); diff --git a/src/3rdparty/phonon/ds9/backend.cpp b/src/3rdparty/phonon/ds9/backend.cpp index fbc4bdc..2c56af7 100644 --- a/src/3rdparty/phonon/ds9/backend.cpp +++ b/src/3rdparty/phonon/ds9/backend.cpp @@ -41,8 +41,6 @@ namespace Phonon { namespace DS9 { - QMutex *Backend::directShowMutex = 0; - bool Backend::AudioMoniker::operator==(const AudioMoniker &other) { return other->IsEqual(*this) == S_OK; @@ -52,8 +50,6 @@ namespace Phonon Backend::Backend(QObject *parent, const QVariantList &) : QObject(parent) { - directShowMutex = &m_directShowMutex; - ::CoInitialize(0); //registering meta types @@ -66,8 +62,6 @@ namespace Phonon m_audioOutputs.clear(); m_audioEffects.clear(); ::CoUninitialize(); - - directShowMutex = 0; } QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args) @@ -137,7 +131,6 @@ namespace Phonon QList<int> Backend::objectDescriptionIndexes(Phonon::ObjectDescriptionType type) const { - QMutexLocker locker(&m_directShowMutex); QList<int> ret; switch(type) @@ -164,7 +157,7 @@ namespace Phonon while (S_OK == enumMon->Next(1, mon.pparam(), 0)) { LPOLESTR str = 0; mon->GetDisplayName(0,0,&str); - const QString name = QString::fromWCharArray(str); + const QString name = QString::fromUtf16((unsigned short*)str); ComPointer<IMalloc> alloc; ::CoGetMalloc(1, alloc.pparam()); alloc->Free(str); @@ -211,7 +204,6 @@ namespace Phonon QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(Phonon::ObjectDescriptionType type, int index) const { - QMutexLocker locker(&m_directShowMutex); QHash<QByteArray, QVariant> ret; switch (type) { @@ -224,7 +216,7 @@ namespace Phonon LPOLESTR str = 0; HRESULT hr = mon->GetDisplayName(0,0, &str); if (SUCCEEDED(hr)) { - QString name = QString::fromWCharArray(str); + QString name = QString::fromUtf16((unsigned short*)str); ComPointer<IMalloc> alloc; ::CoGetMalloc(1, alloc.pparam()); alloc->Free(str); @@ -239,7 +231,7 @@ namespace Phonon WCHAR name[80]; // 80 is clearly stated in the MSDN doc HRESULT hr = ::DMOGetName(m_audioEffects[index], name); if (SUCCEEDED(hr)) { - ret["name"] = QString::fromWCharArray(name); + ret["name"] = QString::fromUtf16((unsigned short*)name); } } break; diff --git a/src/3rdparty/phonon/ds9/backend.h b/src/3rdparty/phonon/ds9/backend.h index 7c3c109..ad638f2 100644 --- a/src/3rdparty/phonon/ds9/backend.h +++ b/src/3rdparty/phonon/ds9/backend.h @@ -23,7 +23,6 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include <phonon/phononnamespace.h> #include <QtCore/QList> -#include <QtCore/QMutex> #include "compointer.h" #include "backendnode.h" @@ -64,8 +63,6 @@ namespace Phonon Filter getAudioOutputFilter(int index) const; - static QMutex *directShowMutex; - Q_SIGNALS: void objectDescriptionChanged(ObjectDescriptionType); @@ -77,7 +74,6 @@ namespace Phonon }; mutable QVector<AudioMoniker> m_audioOutputs; mutable QVector<CLSID> m_audioEffects; - mutable QMutex m_directShowMutex; }; } } diff --git a/src/3rdparty/phonon/ds9/backendnode.cpp b/src/3rdparty/phonon/ds9/backendnode.cpp index 737ab7b..7e0b3cd 100644 --- a/src/3rdparty/phonon/ds9/backendnode.cpp +++ b/src/3rdparty/phonon/ds9/backendnode.cpp @@ -57,25 +57,6 @@ namespace Phonon BackendNode::~BackendNode() { - //this will remove the filter from the graph - FILTER_INFO info; - for(int i = 0; i < FILTER_COUNT; ++i) { - const Filter &filter = m_filters[i]; - if (!filter) - continue; - filter->QueryFilterInfo(&info); - if (info.pGraph) { - HRESULT hr = info.pGraph->RemoveFilter(filter); - - if (FAILED(hr) && m_mediaObject) { - m_mediaObject->ensureStopped(); - - hr = info.pGraph->RemoveFilter(filter); - } - Q_ASSERT(SUCCEEDED(hr)); - info.pGraph->Release(); - } - } } void BackendNode::setMediaObject(MediaObject *mo) diff --git a/src/3rdparty/phonon/ds9/ds9.desktop b/src/3rdparty/phonon/ds9/ds9.desktop index 764390e..1bc3451 100644 --- a/src/3rdparty/phonon/ds9/ds9.desktop +++ b/src/3rdparty/phonon/ds9/ds9.desktop @@ -5,12 +5,13 @@ MimeType=application/x-annodex;video/quicktime;video/x-quicktime;audio/x-m4a;app X-KDE-Library=phonon_ds9 X-KDE-PhononBackendInfo-InterfaceVersion=1 X-KDE-PhononBackendInfo-Version=0.1 -X-KDE-PhononBackendInfo-Website=http://qt.nokia.com/ +X-KDE-PhononBackendInfo-Website=http://www.trolltech.com/ InitialPreference=15 Name=DirectShow9 Name[bg]=DirectShow9 Name[ca]=DirectShow9 +Name[ca@valencia]=DirectShow9 Name[cs]=DirectShow9 Name[da]=DirectShow9 Name[de]=DirectShow9 @@ -19,11 +20,14 @@ Name[en_GB]=DirectShow9 Name[es]=DirectShow9 Name[et]=DirectShow9 Name[eu]=DirectShow9 +Name[fi]=DirectShow9 Name[fr]=DirectShow9 Name[ga]=DirectShow9 Name[gl]=DirectShow9 +Name[hr]=DirectShow9 Name[hsb]=DirectShow9 Name[hu]=DirectShow9 +Name[id]=DirectShow9 Name[is]=DirectShow9 Name[it]=DirectShow9 Name[ja]=DirectShow9 @@ -31,6 +35,7 @@ Name[ko]=DirectShow9 Name[ku]=DirectShow9 Name[lt]=DirectShow9 Name[lv]=DirectShow9 +Name[nb]=DirectShow9 Name[nds]=DirectShow9 Name[nl]=DirectShow9 Name[nn]=DirectShow9 @@ -38,10 +43,13 @@ Name[pa]=ਡਾਇਰੈਕਸ਼ੋ9 Name[pl]=DirectShow9 Name[pt]=DirectShow9 Name[pt_BR]=DirectShow9 +Name[ru]=DirectShow9 Name[se]=DirectShow9 Name[sk]=DirectShow 9 Name[sl]=DirectShow 9 Name[sr]=Директшоу‑9 +Name[sr@ijekavian]=Директшоу‑9 +Name[sr@ijekavianlatin]=DirectShow‑9 Name[sr@latin]=DirectShow‑9 Name[sv]=Directshow 9 Name[tr]=DirectShow9 @@ -53,6 +61,7 @@ Name[zh_TW]=DirectShow9 Comment=Phonon DirectShow9 backend Comment[bg]=Phonon DirectShow9 Comment[ca]=Dorsal DirectShow9 del Phonon +Comment[ca@valencia]=Dorsal DirectShow9 del Phonon Comment[cs]=Phonon DirectShow9 backend Comment[da]=DirectShow9-backend til Phonon Comment[de]=Phonon-Treiber für DirectShow9 @@ -61,11 +70,13 @@ Comment[en_GB]=Phonon DirectShow9 backend Comment[es]=Motor DirectShow9 para Phonon Comment[et]=Phononi DirectShow9 taustaprogramm Comment[eu]=Phonon DirectShow9 backend +Comment[fi]=Phonon DirectShow9-taustaohjelma Comment[fr]=Système de gestion DirectShow9 pour Phonon Comment[ga]=Inneall DirectShow9 le haghaidh Phonon Comment[gl]=Infraestrutura de DirectShow9 para Phonon Comment[hsb]=Phonon DirectShow9 backend Comment[hu]=Phonon DirectShow9 modul +Comment[id]=Phonon DirectShow9 backend Comment[is]=Phonon DirectShow9 bakendi Comment[it]=Motore DirectShow9 di Phonon Comment[ja]=Phonon DirectShow9 バックエンド @@ -73,6 +84,7 @@ Comment[ko]=Phonon DirectShow9 백엔드 Comment[ku]=Binesaza Phonon DirectShow9 Comment[lt]=Phonon DirectShow9 galinė sąsaja Comment[lv]=Phonon DirectShow9 aizmugure +Comment[nb]=Phonon-motor for DirectShow9 Comment[nds]=Phonon-Hülpprogrmm DirectShow9 Comment[nl]=DirectShow9-backend (Phonon) Comment[nn]=Phonon-motor for DirectShow9 @@ -80,10 +92,13 @@ Comment[pa]=ਫੋਨੋਨ ਡਾਇਰੈਕਟਸ਼ੋ9 ਬੈਕਐਂਡ Comment[pl]=Obsługa DirectShow9 przez Phonon Comment[pt]=Infra-estrutura do DirectShow9 para o Phonon Comment[pt_BR]=Infraestrutura Phonon DirectShow9 +Comment[ru]=Механизм DirectShow9 для Phonon Comment[se]=Phonon DirectShow9 duogášmohtor Comment[sk]=Phonon DirectShow 9 podsystém Comment[sl]=Phononova Hrbtenica DirectShow 9 Comment[sr]=Директшоу‑9 као позадина Фонона +Comment[sr@ijekavian]=Директшоу‑9 као позадина Фонона +Comment[sr@ijekavianlatin]=DirectShow‑9 kao pozadina Phonona Comment[sr@latin]=DirectShow‑9 kao pozadina Phonona Comment[sv]=Phonon Directshow 9-gränssnitt Comment[tr]=Phonon DirectShow9 arka ucu diff --git a/src/3rdparty/phonon/ds9/effect.cpp b/src/3rdparty/phonon/ds9/effect.cpp index ebe976b..104a3c1 100644 --- a/src/3rdparty/phonon/ds9/effect.cpp +++ b/src/3rdparty/phonon/ds9/effect.cpp @@ -82,7 +82,7 @@ namespace Phonon current += wcslen(current) + 1; //skip the name current += wcslen(current) + 1; //skip the unit for(; *current; current += wcslen(current) + 1) { - values.append( QString::fromWCharArray(current) ); + values.append( QString::fromUtf16((unsigned short*)current) ); } } //FALLTHROUGH @@ -107,7 +107,7 @@ namespace Phonon Phonon::EffectParameter::Hints hint = info.mopCaps == MP_CAPS_CURVE_INVSQUARE ? Phonon::EffectParameter::LogarithmicHint : Phonon::EffectParameter::Hints(0); - const QString n = QString::fromWCharArray(name); + const QString n = QString::fromUtf16((unsigned short*)name); ret.append(Phonon::EffectParameter(i, n, hint, def, min, max, values)); ::CoTaskMemFree(name); //let's free the memory } diff --git a/src/3rdparty/phonon/ds9/fakesource.cpp b/src/3rdparty/phonon/ds9/fakesource.cpp index 4dce138..9a61a2e 100644 --- a/src/3rdparty/phonon/ds9/fakesource.cpp +++ b/src/3rdparty/phonon/ds9/fakesource.cpp @@ -29,10 +29,8 @@ namespace Phonon namespace DS9 { static WAVEFORMATEX g_defaultWaveFormat = {WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0}; - static VIDEOINFOHEADER2 g_defaultVideoInfo = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, {0}, 0, {sizeof(BITMAPINFOHEADER), 1, 1, 1, 0, 0, 0, 0, 0, 0, 0} }; - - static const AM_MEDIA_TYPE g_fakeAudioType = {MEDIATYPE_Audio, MEDIASUBTYPE_PCM, 0, 0, 2, FORMAT_WaveFormatEx, 0, sizeof(WAVEFORMATEX), reinterpret_cast<BYTE*>(&g_defaultWaveFormat)}; - static const AM_MEDIA_TYPE g_fakeVideoType = {MEDIATYPE_Video, MEDIASUBTYPE_RGB32, TRUE, FALSE, 0, FORMAT_VideoInfo2, 0, sizeof(VIDEOINFOHEADER2), reinterpret_cast<BYTE*>(&g_defaultVideoInfo)}; + static BITMAPINFOHEADER g_defautBitmapHeader = { sizeof(BITMAPINFOHEADER), 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}; + static VIDEOINFOHEADER2 g_defaultVideoInfo = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; class FakePin : public QPin { @@ -130,12 +128,36 @@ namespace Phonon void FakeSource::createFakeAudioPin() { - new FakePin(this, g_fakeAudioType); + AM_MEDIA_TYPE mt; + qMemSet(&mt, 0, sizeof(AM_MEDIA_TYPE)); + mt.majortype = MEDIATYPE_Audio; + mt.subtype = MEDIASUBTYPE_PCM; + mt.formattype = FORMAT_WaveFormatEx; + mt.lSampleSize = 2; + + //fake the format (stereo 44.1 khz stereo 16 bits) + mt.cbFormat = sizeof(WAVEFORMATEX); + mt.pbFormat = reinterpret_cast<BYTE*>(&g_defaultWaveFormat); + + new FakePin(this, mt); } void FakeSource::createFakeVideoPin() { - new FakePin(this, g_fakeVideoType); + AM_MEDIA_TYPE mt; + qMemSet(&mt, 0, sizeof(AM_MEDIA_TYPE)); + mt.majortype = MEDIATYPE_Video; + mt.subtype = MEDIASUBTYPE_RGB32; + mt.formattype = FORMAT_VideoInfo2; + mt.bFixedSizeSamples = 1; + + g_defaultVideoInfo.bmiHeader = g_defautBitmapHeader; + + //fake the format + mt.cbFormat = sizeof(VIDEOINFOHEADER2); + mt.pbFormat = reinterpret_cast<BYTE*>(&g_defaultVideoInfo); + + new FakePin(this, mt); } } diff --git a/src/3rdparty/phonon/ds9/iodevicereader.cpp b/src/3rdparty/phonon/ds9/iodevicereader.cpp index 695af59..2dff1fe 100644 --- a/src/3rdparty/phonon/ds9/iodevicereader.cpp +++ b/src/3rdparty/phonon/ds9/iodevicereader.cpp @@ -36,20 +36,18 @@ namespace Phonon //these mediatypes define a stream, its type will be autodetected by DirectShow static QVector<AM_MEDIA_TYPE> getMediaTypes() { - //the order here is important because otherwise, - //directshow might not be able to detect the stream type correctly - - AM_MEDIA_TYPE mt = { MEDIATYPE_Stream, MEDIASUBTYPE_Avi, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0}; + AM_MEDIA_TYPE mt = { MEDIATYPE_Stream, MEDIASUBTYPE_NULL, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0}; QVector<AM_MEDIA_TYPE> ret; + //normal auto-detect stream + mt.subtype = MEDIASUBTYPE_NULL; + ret << mt; //AVI stream + mt.subtype = MEDIASUBTYPE_Avi; ret << mt; //WAVE stream mt.subtype = MEDIASUBTYPE_WAVE; ret << mt; - //normal auto-detect stream (must be at the end!) - mt.subtype = MEDIASUBTYPE_NULL; - ret << mt; return ret; } @@ -66,6 +64,7 @@ namespace Phonon //for Phonon::StreamInterface void writeData(const QByteArray &data) { + QWriteLocker locker(&m_lock); m_pos += data.size(); m_buffer += data; } @@ -76,22 +75,54 @@ namespace Phonon void setStreamSize(qint64 newSize) { - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); m_size = newSize; } + qint64 streamSize() const + { + QReadLocker locker(&m_lock); + return m_size; + } + void setStreamSeekable(bool s) { - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); m_seekable = s; } + bool streamSeekable() const + { + QReadLocker locker(&m_lock); + return m_seekable; + } + + void setCurrentPos(qint64 pos) + { + QWriteLocker locker(&m_lock); + m_pos = pos; + seekStream(pos); + m_buffer.clear(); + } + + qint64 currentPos() const + { + QReadLocker locker(&m_lock); + return m_pos; + } + + int currentBufferSize() const + { + QReadLocker locker(&m_lock); + return m_buffer.size(); + } + //virtual pure members //implementation from IAsyncReader STDMETHODIMP Length(LONGLONG *total, LONGLONG *available) { - QMutexLocker locker(&m_mutex); + QReadLocker locker(&m_lock); if (total) { *total = m_size; } @@ -106,42 +137,44 @@ namespace Phonon HRESULT read(LONGLONG pos, LONG length, BYTE *buffer, LONG *actual) { - Q_ASSERT(!m_mutex.tryLock()); + QMutexLocker locker(&m_mutexRead); + if (m_mediaGraph->isStopping()) { return VFW_E_WRONG_STATE; } - if(m_size != 1 && pos + length > m_size) { + if(streamSize() != 1 && pos + length > streamSize()) { //it tries to read outside of the boundaries return E_FAIL; } - if (m_pos - m_buffer.size() != pos) { - if (!m_seekable) { + if (currentPos() - currentBufferSize() != pos) { + if (!streamSeekable()) { return S_FALSE; } - m_pos = pos; - seekStream(pos); - m_buffer.clear(); + setCurrentPos(pos); } - int oldSize = m_buffer.size(); - while (m_buffer.size() < int(length)) { + int oldSize = currentBufferSize(); + while (currentBufferSize() < int(length)) { needData(); if (m_mediaGraph->isStopping()) { return VFW_E_WRONG_STATE; } - if (oldSize == m_buffer.size()) { + if (oldSize == currentBufferSize()) { break; //we didn't get any data } - oldSize = m_buffer.size(); + oldSize = currentBufferSize(); } - int bytesRead = qMin(m_buffer.size(), int(length)); - qMemCopy(buffer, m_buffer.data(), bytesRead); - //truncate the buffer - m_buffer = m_buffer.mid(bytesRead); + DWORD bytesRead = qMin(currentBufferSize(), int(length)); + { + QWriteLocker locker(&m_lock); + qMemCopy(buffer, m_buffer.data(), bytesRead); + //truncate the buffer + m_buffer = m_buffer.mid(bytesRead); + } if (actual) { *actual = bytesRead; //initialization @@ -157,6 +190,7 @@ namespace Phonon qint64 m_pos; qint64 m_size; + QMutex m_mutexRead; const MediaGraph *m_mediaGraph; }; @@ -170,6 +204,14 @@ namespace Phonon IODeviceReader::~IODeviceReader() { } + + STDMETHODIMP IODeviceReader::Stop() + { + HRESULT hr = QBaseFilter::Stop(); + m_streamReader->enoughData(); //this asks to cancel any blocked call to needData + return hr; + } + } } diff --git a/src/3rdparty/phonon/ds9/iodevicereader.h b/src/3rdparty/phonon/ds9/iodevicereader.h index c8b91c3..af4b271 100644 --- a/src/3rdparty/phonon/ds9/iodevicereader.h +++ b/src/3rdparty/phonon/ds9/iodevicereader.h @@ -41,6 +41,7 @@ namespace Phonon public: IODeviceReader(const MediaSource &source, const MediaGraph *); ~IODeviceReader(); + STDMETHODIMP Stop(); private: StreamReader *m_streamReader; diff --git a/src/3rdparty/phonon/ds9/mediagraph.cpp b/src/3rdparty/phonon/ds9/mediagraph.cpp index 3e7a68b..db0ec84 100644 --- a/src/3rdparty/phonon/ds9/mediagraph.cpp +++ b/src/3rdparty/phonon/ds9/mediagraph.cpp @@ -68,8 +68,6 @@ namespace Phonon return ret; } - -/* static HRESULT saveToFile(Graph graph, const QString &filepath) { const WCHAR wszStreamName[] = L"ActiveMovieGraph"; @@ -105,7 +103,7 @@ namespace Phonon return hr; } -*/ + MediaGraph::MediaGraph(MediaObject *mo, short index) : m_graph(CLSID_FilterGraph, IID_IGraphBuilder), @@ -379,12 +377,11 @@ namespace Phonon FILTER_INFO info; filter->QueryFilterInfo(&info); #ifdef GRAPH_DEBUG - qDebug() << "removeFilter" << QString((const QChar *)info.achName); + qDebug() << "removeFilter" << QString::fromUtf16(info.achName); #endif if (info.pGraph) { info.pGraph->Release(); - if (info.pGraph == m_graph) - return m_graph->RemoveFilter(filter); + return m_graph->RemoveFilter(filter); } //already removed @@ -540,11 +537,11 @@ namespace Phonon const QList<OutputPin> outputs = BackendNode::pins(filter, PINDIR_OUTPUT); for(int i = 0; i < outputs.count(); ++i) { const OutputPin &pin = outputs.at(i); - if (HRESULT(VFW_E_NOT_CONNECTED) == pin->ConnectedTo(inPin.pparam())) { + if (VFW_E_NOT_CONNECTED == pin->ConnectedTo(inPin.pparam())) { return SUCCEEDED(pin->Connect(newIn, 0)); } } - //we shoud never go here + //we should never go here return false; } else { QAMMediaType type; @@ -682,6 +679,7 @@ namespace Phonon #ifndef QT_NO_PHONON_MEDIACONTROLLER } else if (source.discType() == Phonon::Cd) { m_realSource = Filter(new QAudioCDPlayer); + m_result = m_graph->AddFilter(m_realSource, 0); #endif //QT_NO_PHONON_MEDIACONTROLLER } else { @@ -811,7 +809,7 @@ namespace Phonon for (int i = 0; i < outputs.count(); ++i) { const OutputPin &out = outputs.at(i); InputPin pin; - if (out->ConnectedTo(pin.pparam()) == HRESULT(VFW_E_NOT_CONNECTED)) { + if (out->ConnectedTo(pin.pparam()) == VFW_E_NOT_CONNECTED) { m_decoderPins += out; //unconnected outputs can be decoded outputs } } @@ -822,7 +820,7 @@ namespace Phonon //let's reestablish the connections for (int i = 0; i < connections.count(); ++i) { const GraphConnection &connection = connections.at(i); - //check if we shoud transfer the sink node + //check if we should transfer the sink node grabFilter(connection.input); grabFilter(connection.output); @@ -875,7 +873,7 @@ namespace Phonon { FILTER_INFO info; filter->QueryFilterInfo(&info); - qDebug() << Q_FUNC_INFO << QString((const QChar *)info.achName); + qDebug() << Q_FUNC_INFO << QString::fromUtf16(info.achName); if (info.pGraph) { info.pGraph->Release(); } @@ -921,7 +919,7 @@ namespace Phonon { FILTER_INFO info; filter->QueryFilterInfo(&info); - qDebug() << "found a decoder filter" << QString((const QChar *)info.achName); + qDebug() << "found a decoder filter" << QString::fromUtf16(info.achName); if (info.pGraph) { info.pGraph->Release(); } @@ -937,7 +935,7 @@ namespace Phonon { FILTER_INFO info; filter->QueryFilterInfo(&info); - qDebug() << Q_FUNC_INFO << QString((const QChar *)info.achName); + qDebug() << Q_FUNC_INFO << QString::fromUtf16(info.achName); if (info.pGraph) { info.pGraph->Release(); } @@ -956,7 +954,7 @@ namespace Phonon { FILTER_INFO info; filter->QueryFilterInfo(&info); - qDebug() << Q_FUNC_INFO << QString((const QChar *)info.achName); + qDebug() << Q_FUNC_INFO << QString::fromUtf16(info.achName); if (info.pGraph) { info.pGraph->Release(); } @@ -990,7 +988,7 @@ namespace Phonon { FILTER_INFO info; filter->QueryFilterInfo(&info); - qDebug() << "found a demuxer filter" << QString((const QChar *)info.achName); + qDebug() << "found a demuxer filter" << QString::fromUtf16(info.achName); if (info.pGraph) { info.pGraph->Release(); } @@ -1008,27 +1006,27 @@ namespace Phonon BSTR str; HRESULT hr = mediaContent->get_AuthorName(&str); if (SUCCEEDED(hr)) { - ret.insert(QLatin1String("ARTIST"), QString::fromWCharArray(str)); + ret.insert(QLatin1String("ARTIST"), QString::fromUtf16((const unsigned short*)str)); SysFreeString(str); } hr = mediaContent->get_Title(&str); if (SUCCEEDED(hr)) { - ret.insert(QLatin1String("TITLE"), QString::fromWCharArray(str)); + ret.insert(QLatin1String("TITLE"), QString::fromUtf16((const unsigned short*)str)); SysFreeString(str); } hr = mediaContent->get_Description(&str); if (SUCCEEDED(hr)) { - ret.insert(QLatin1String("DESCRIPTION"), QString::fromWCharArray(str)); + ret.insert(QLatin1String("DESCRIPTION"), QString::fromUtf16((const unsigned short*)str)); SysFreeString(str); } hr = mediaContent->get_Copyright(&str); if (SUCCEEDED(hr)) { - ret.insert(QLatin1String("COPYRIGHT"), QString::fromWCharArray(str)); + ret.insert(QLatin1String("COPYRIGHT"), QString::fromUtf16((const unsigned short*)str)); SysFreeString(str); } hr = mediaContent->get_MoreInfoText(&str); if (SUCCEEDED(hr)) { - ret.insert(QLatin1String("MOREINFO"), QString::fromWCharArray(str)); + ret.insert(QLatin1String("MOREINFO"), QString::fromUtf16((const unsigned short*)str)); SysFreeString(str); } } diff --git a/src/3rdparty/phonon/ds9/mediaobject.cpp b/src/3rdparty/phonon/ds9/mediaobject.cpp index 34f92c2..d1e15c0 100644 --- a/src/3rdparty/phonon/ds9/mediaobject.cpp +++ b/src/3rdparty/phonon/ds9/mediaobject.cpp @@ -23,10 +23,11 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #ifndef Q_CC_MSVC #include <dshow.h> -#endif +#endif //Q_CC_MSVC #include <objbase.h> #include <initguid.h> #include <qnetwork.h> +#include <comdef.h> #include <evcode.h> #include "mediaobject.h" @@ -49,7 +50,7 @@ namespace Phonon //first the definition of the WorkerThread class WorkerThread::WorkerThread() - : QThread(), m_finished(false), m_currentWorkId(1) + : QThread(), m_currentRenderId(0), m_finished(false), m_currentWorkId(1) { } @@ -57,6 +58,24 @@ namespace Phonon { } + WorkerThread::Work WorkerThread::dequeueWork() + { + QMutexLocker locker(&m_mutex); + if (m_finished) { + return Work(); + } + Work ret = m_queue.dequeue(); + + //we ensure to have the wait condition in the right state + if (m_queue.isEmpty()) { + m_waitCondition.reset(); + } else { + m_waitCondition.set(); + } + + return ret; + } + void WorkerThread::run() { while (m_finished == false) { @@ -70,6 +89,11 @@ namespace Phonon } DWORD result = ::WaitForMultipleObjects(count, handles, FALSE, INFINITE); if (result == WAIT_OBJECT_0) { + if (m_finished) { + //that's the end of the thread execution + return; + } + handleTask(); } else { //this is the event management @@ -157,7 +181,6 @@ namespace Phonon //we create a new graph w.graph = Graph(CLSID_FilterGraph, IID_IGraphBuilder); w.filter = filter; - w.graph->AddFilter(filter, 0); w.id = m_currentWorkId++; m_queue.enqueue(w); m_waitCondition.set(); @@ -177,29 +200,23 @@ namespace Phonon void WorkerThread::handleTask() { - QMutexLocker locker(Backend::directShowMutex); - { - QMutexLocker locker(&m_mutex); - if (m_finished || m_queue.isEmpty()) { - return; - } - - m_currentWork = m_queue.dequeue(); + const Work w = dequeueWork(); - //we ensure to have the wait condition in the right state - if (m_queue.isEmpty()) { - m_waitCondition.reset(); - } else { - m_waitCondition.set(); - } + if (m_finished) { + return; } HRESULT hr = S_OK; - if (m_currentWork.task == ReplaceGraph) { + 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 == m_currentWork.oldGraph) { + if (m_graphHandle[i].graph == w.oldGraph) { m_graphHandle[i].graph = Graph(); index = i; break; @@ -212,40 +229,51 @@ namespace Phonon Q_ASSERT(index != -1); //add the new graph - HANDLE h; - if (SUCCEEDED(ComPointer<IMediaEvent>(m_currentWork.graph, IID_IMediaEvent) + if (SUCCEEDED(ComPointer<IMediaEvent>(w.graph, IID_IMediaEvent) ->GetEventHandle(reinterpret_cast<OAEVENT*>(&h)))) { - m_graphHandle[index].graph = m_currentWork.graph; + m_graphHandle[index].graph = w.graph; m_graphHandle[index].handle = h; } - } else if (m_currentWork.task == Render) { - if (m_currentWork.filter) { + } else if (w.task == Render) { + if (w.filter) { //let's render pins - const QList<OutputPin> outputs = BackendNode::pins(m_currentWork.filter, PINDIR_OUTPUT); - for (int i = 0; SUCCEEDED(hr) && i < outputs.count(); ++i) { - hr = m_currentWork.graph->Render(outputs.at(i)); + 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 (!m_currentWork.url.isEmpty()) { + } else if (!w.url.isEmpty()) { //let's render a url (blocking call) - hr = m_currentWork.graph->RenderFile(reinterpret_cast<const wchar_t *>(m_currentWork.url.utf16()), 0); + hr = w.graph->RenderFile(reinterpret_cast<const wchar_t *>(w.url.utf16()), 0); } if (hr != E_ABORT) { - emit asyncRenderFinished(m_currentWork.id, hr, m_currentWork.graph); + emit asyncRenderFinished(w.id, hr, w.graph); } - } else if (m_currentWork.task == Seek) { + } else if (w.task == Seek) { //that's a seekrequest - ComPointer<IMediaSeeking> mediaSeeking(m_currentWork.graph, IID_IMediaSeeking); - qint64 newtime = m_currentWork.time * 10000; + ComPointer<IMediaSeeking> mediaSeeking(w.graph, IID_IMediaSeeking); + qint64 newtime = w.time * 10000; hr = mediaSeeking->SetPositions(&newtime, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning); - emit asyncSeekingFinished(m_currentWork.id, newtime / 10000); + qint64 currentTime = -1; + if (SUCCEEDED(hr)) { + hr = mediaSeeking->GetCurrentPosition(¤tTime); + if (SUCCEEDED(hr)) { + currentTime /= 10000; //convert to ms + } + } + emit asyncSeekingFinished(w.id, currentTime); hr = E_ABORT; //to avoid emitting asyncRenderFinished - } else if (m_currentWork.task == ChangeState) { + } else if (w.task == ChangeState) { //remove useless decoders QList<Filter> unused; - for (int i = 0; i < m_currentWork.decoders.count(); ++i) { - const Filter &filter = m_currentWork.decoders.at(i); + 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) { @@ -262,15 +290,15 @@ namespace Phonon //we can get the state for (int i = 0; i < unused.count(); ++i) { //we should remove this filter from the graph - m_currentWork.graph->RemoveFilter(unused.at(i)); + w.graph->RemoveFilter(unused.at(i)); } //we can get the state - ComPointer<IMediaControl> mc(m_currentWork.graph, IID_IMediaControl); + ComPointer<IMediaControl> mc(w.graph, IID_IMediaControl); //we change the state here - switch(m_currentWork.state) + switch(w.state) { case State_Stopped: mc->Stop(); @@ -288,38 +316,36 @@ namespace Phonon if (SUCCEEDED(hr)) { if (s == State_Stopped) { - emit stateReady(m_currentWork.graph, Phonon::StoppedState); + emit stateReady(w.graph, Phonon::StoppedState); } else if (s == State_Paused) { - emit stateReady(m_currentWork.graph, Phonon::PausedState); + emit stateReady(w.graph, Phonon::PausedState); } else /*if (s == State_Running)*/ { - emit stateReady(m_currentWork.graph, Phonon::PlayingState); + emit stateReady(w.graph, Phonon::PlayingState); } } } - { - QMutexLocker locker(&m_mutex); - m_currentWork = Work(); //reinitialize - } + m_currentRender = Graph(); + m_currentRenderId = 0; + } - void WorkerThread::abortCurrentRender(qint16 renderId) - { + void WorkerThread::abortCurrentRender(qint16 renderId) + { QMutexLocker locker(&m_mutex); - if (m_currentWork.id == renderId) { - m_currentWork.graph->Abort(); - } bool found = false; + //we try to see if there is already an attempt to seek and we remove it for(int i = 0; !found && i < m_queue.size(); ++i) { const Work &w = m_queue.at(i); if (w.id == renderId) { found = true; m_queue.removeAt(i); - if (m_queue.isEmpty()) { - m_waitCondition.reset(); - } } } + + if (m_currentRender && m_currentRenderId == renderId) { + m_currentRender->Abort(); + } } //tells the thread to stop processing @@ -327,9 +353,9 @@ namespace Phonon { QMutexLocker locker(&m_mutex); m_queue.clear(); - if (m_currentWork.graph) { + if (m_currentRender) { //in case we're currently rendering something - m_currentWork.graph->Abort(); + m_currentRender->Abort(); } @@ -361,17 +387,17 @@ namespace Phonon m_graphs[i] = new MediaGraph(this, i); } - connect(&m_thread, SIGNAL(stateReady(Graph,Phonon::State)), - SLOT(slotStateReady(Graph,Phonon::State))); + connect(&m_thread, SIGNAL(stateReady(Graph, Phonon::State)), + SLOT(slotStateReady(Graph, Phonon::State))); - connect(&m_thread, SIGNAL(eventReady(Graph,long,long)), - SLOT(handleEvents(Graph,long,long))); + connect(&m_thread, SIGNAL(eventReady(Graph, long, long)), + SLOT(handleEvents(Graph, long, long))); - connect(&m_thread, SIGNAL(asyncRenderFinished(quint16,HRESULT,Graph)), - SLOT(finishLoading(quint16,HRESULT,Graph))); + connect(&m_thread, SIGNAL(asyncRenderFinished(quint16, HRESULT, Graph)), + SLOT(finishLoading(quint16, HRESULT, Graph))); - connect(&m_thread, SIGNAL(asyncSeekingFinished(quint16,qint64)), - SLOT(finishSeeking(quint16,qint64))); + connect(&m_thread, SIGNAL(asyncSeekingFinished(quint16, qint64)), + SLOT(finishSeeking(quint16, qint64))); //really special case m_mediaObject = this; m_thread.start(); @@ -494,18 +520,6 @@ namespace Phonon qSwap(m_graphs[0], m_graphs[1]); //swap the graphs - if (m_transitionTime >= 0) - m_graphs[1]->stop(); //make sure we stop the previous graph - - if (currentGraph()->mediaSource().type() != Phonon::MediaSource::Invalid && - catchComError(currentGraph()->renderResult())) { - setState(Phonon::ErrorState); - return; - } - - //we need to play the next media - play(); - //we tell the video widgets to switch now to the new source #ifndef QT_NO_PHONON_VIDEO for (int i = 0; i < m_videoWidgets.count(); ++i) { @@ -514,6 +528,15 @@ namespace Phonon #endif //QT_NO_PHONON_VIDEO emit currentSourceChanged(currentGraph()->mediaSource()); + + if (currentGraph()->isLoading()) { + //will simply tell that when loading is finished + //it should start the playback + play(); + } + + + emit metaDataChanged(currentGraph()->metadata()); if (nextGraph()->hasVideo() != currentGraph()->hasVideo()) { @@ -526,6 +549,15 @@ namespace Phonon #ifndef QT_NO_PHONON_MEDIACONTROLLER setTitles(currentGraph()->titles()); #endif //QT_NO_PHONON_MEDIACONTROLLER + + //this manages only gapless transitions + if (currentGraph()->mediaSource().type() != Phonon::MediaSource::Invalid) { + if (catchComError(currentGraph()->renderResult())) { + setState(Phonon::ErrorState); + } else { + play(); + } + } } Phonon::State MediaObject::state() const @@ -760,16 +792,15 @@ namespace Phonon case Phonon::PausedState: pause(); break; + case Phonon::StoppedState: + stop(); + break; case Phonon::PlayingState: play(); break; case Phonon::ErrorState: setState(Phonon::ErrorState); break; - case Phonon::StoppedState: - default: - stop(); - break; } } } @@ -817,11 +848,11 @@ namespace Phonon #endif LPAMGETERRORTEXT getErrorText = (LPAMGETERRORTEXT)QLibrary::resolve(QLatin1String("quartz"), "AMGetErrorTextW"); - WCHAR buffer[MAX_ERROR_TEXT_LEN]; - if (getErrorText && getErrorText(hr, buffer, MAX_ERROR_TEXT_LEN)) { - m_errorString = QString::fromWCharArray(buffer); + ushort buffer[MAX_ERROR_TEXT_LEN]; + if (getErrorText && getErrorText(hr, (WCHAR*)buffer, MAX_ERROR_TEXT_LEN)) { + m_errorString = QString::fromUtf16(buffer); } else { - m_errorString = QString::fromLatin1("Unknown error"); + m_errorString = QString::fromUtf16((ushort*)_com_error(hr).ErrorMessage()); } const QString comError = QString::number(uint(hr), 16); if (!m_errorString.toLower().contains(comError.toLower())) { diff --git a/src/3rdparty/phonon/ds9/mediaobject.h b/src/3rdparty/phonon/ds9/mediaobject.h index 34aa666..2c34ffc 100644 --- a/src/3rdparty/phonon/ds9/mediaobject.h +++ b/src/3rdparty/phonon/ds9/mediaobject.h @@ -114,7 +114,6 @@ namespace Phonon enum Task { - None, Render, Seek, ChangeState, @@ -123,7 +122,6 @@ namespace Phonon struct Work { - Work() : task(None), id(0), time(0) { } Task task; quint16 id; Graph graph; @@ -137,14 +135,16 @@ namespace Phonon }; QList<Filter> decoders; //for the state change requests }; + Work dequeueWork(); void handleTask(); - Work m_currentWork; + Graph m_currentRender; + qint16 m_currentRenderId; QQueue<Work> m_queue; bool m_finished; quint16 m_currentWorkId; QWinWaitCondition m_waitCondition; - QMutex m_mutex; // mutex for the m_queue, m_finished and m_currentWorkId + QMutex m_mutex; //this is for WaitForMultipleObjects struct diff --git a/src/3rdparty/phonon/ds9/qasyncreader.cpp b/src/3rdparty/phonon/ds9/qasyncreader.cpp index a3f9cda..68ec1f8 100644 --- a/src/3rdparty/phonon/ds9/qasyncreader.cpp +++ b/src/3rdparty/phonon/ds9/qasyncreader.cpp @@ -15,6 +15,8 @@ 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 <QtCore/QFile> + #include "qasyncreader.h" #include "qbasefilter.h" @@ -78,7 +80,8 @@ namespace Phonon STDMETHODIMP QAsyncReader::Request(IMediaSample *sample,DWORD_PTR user) { - QMutexLocker locker(&m_mutex); + QMutexLocker mutexLocker(&m_mutexWait); + QWriteLocker locker(&m_lock); if (m_flushing) { return VFW_E_WRONG_STATE; } @@ -90,28 +93,33 @@ namespace Phonon STDMETHODIMP QAsyncReader::WaitForNext(DWORD timeout, IMediaSample **sample, DWORD_PTR *user) { - QMutexLocker locker(&m_mutex); + QMutexLocker locker(&m_mutexWait); 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()) { + AsyncRequest r = getNextRequest(); + + if (r.sample == 0) { + //there is no request in the queue + if (isFlushing()) { return VFW_E_WRONG_STATE; + } else { + //First we need to lock the mutex + if (m_requestWait.wait(&m_mutexWait, timeout) == false) { + return VFW_E_TIMEOUT; + } + if (isFlushing()) { + return VFW_E_WRONG_STATE; + } + + r = getNextRequest(); } } - AsyncRequest r = m_requestQueue.dequeue(); - //at this point we're sure to have a request to proceed if (r.sample == 0) { return E_FAIL; @@ -119,12 +127,14 @@ namespace Phonon *sample = r.sample; *user = r.user; - return syncReadAlignedUnlocked(r.sample); + + return SyncReadAligned(r.sample); } STDMETHODIMP QAsyncReader::BeginFlush() { - QMutexLocker locker(&m_mutex); + QMutexLocker mutexLocker(&m_mutexWait); + QWriteLocker locker(&m_lock); m_flushing = true; m_requestWait.wakeOne(); return S_OK; @@ -132,28 +142,13 @@ namespace Phonon STDMETHODIMP QAsyncReader::EndFlush() { - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); 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; } @@ -180,6 +175,23 @@ namespace Phonon return sample->SetActualDataLength(actual); } + STDMETHODIMP QAsyncReader::SyncRead(LONGLONG pos, LONG length, BYTE *buffer) + { + return read(pos, length, buffer, 0); + } + + + //addition + QAsyncReader::AsyncRequest QAsyncReader::getNextRequest() + { + QWriteLocker locker(&m_lock); + AsyncRequest ret; + if (!m_requestQueue.isEmpty()) { + ret = m_requestQueue.dequeue(); + } + + return ret; + } } } diff --git a/src/3rdparty/phonon/ds9/qasyncreader.h b/src/3rdparty/phonon/ds9/qasyncreader.h index 95872f9..cb789ee 100644 --- a/src/3rdparty/phonon/ds9/qasyncreader.h +++ b/src/3rdparty/phonon/ds9/qasyncreader.h @@ -48,12 +48,11 @@ namespace Phonon STDMETHODIMP WaitForNext(DWORD,IMediaSample **,DWORD_PTR *); STDMETHODIMP SyncReadAligned(IMediaSample *); STDMETHODIMP SyncRead(LONGLONG,LONG,BYTE *); - STDMETHODIMP Length(LONGLONG *,LONGLONG *) = 0; + virtual STDMETHODIMP Length(LONGLONG *,LONGLONG *) = 0; STDMETHODIMP BeginFlush(); STDMETHODIMP EndFlush(); protected: - STDMETHODIMP syncReadAlignedUnlocked(IMediaSample *); virtual HRESULT read(LONGLONG pos, LONG length, BYTE *buffer, LONG *actual) = 0; private: @@ -63,6 +62,9 @@ namespace Phonon IMediaSample *sample; DWORD_PTR user; }; + AsyncRequest getNextRequest(); + + QMutex m_mutexWait; QQueue<AsyncRequest> m_requestQueue; QWaitCondition m_requestWait; diff --git a/src/3rdparty/phonon/ds9/qaudiocdreader.cpp b/src/3rdparty/phonon/ds9/qaudiocdreader.cpp index 6d0f335..b9f9fd6 100644 --- a/src/3rdparty/phonon/ds9/qaudiocdreader.cpp +++ b/src/3rdparty/phonon/ds9/qaudiocdreader.cpp @@ -103,8 +103,8 @@ namespace Phonon private: HANDLE m_cddrive; - CDROM_TOC m_toc; - WaveStructure m_waveHeader; + CDROM_TOC *m_toc; + WaveStructure *m_waveHeader; qint64 m_trackAddress; }; @@ -112,8 +112,19 @@ namespace Phonon #define SECTOR_SIZE 2352 #define NB_SECTORS_READ 20 - static const AM_MEDIA_TYPE audioCDMediaType = { MEDIATYPE_Stream, MEDIASUBTYPE_WAVE, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0}; - + static AM_MEDIA_TYPE getAudioCDMediaType() + { + AM_MEDIA_TYPE mt; + qMemSet(&mt, 0, sizeof(AM_MEDIA_TYPE)); + mt.majortype = MEDIATYPE_Stream; + mt.subtype = MEDIASUBTYPE_WAVE; + mt.bFixedSizeSamples = TRUE; + mt.bTemporalCompression = FALSE; + mt.lSampleSize = 1; + mt.formattype = GUID_NULL; + return mt; + } + int addressToSectors(UCHAR address[4]) { return ((address[0] * 60 + address[1]) * 60 + address[2]) * 75 + address[3] - 150; @@ -130,8 +141,11 @@ namespace Phonon } - QAudioCDReader::QAudioCDReader(QBaseFilter *parent, QChar drive) : QAsyncReader(parent, QVector<AM_MEDIA_TYPE>() << audioCDMediaType) + QAudioCDReader::QAudioCDReader(QBaseFilter *parent, QChar drive) : QAsyncReader(parent, QVector<AM_MEDIA_TYPE>() << getAudioCDMediaType()) { + m_toc = new CDROM_TOC; + m_waveHeader = new WaveStructure; + //now open the cd-drive QString path; if (drive.isNull()) { @@ -140,30 +154,36 @@ namespace Phonon path = QString::fromLatin1("\\\\.\\%1:").arg(drive); } - m_cddrive = ::CreateFile((const wchar_t *)path.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + m_cddrive = QT_WA_INLINE ( + ::CreateFile( (TCHAR*)path.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ), + ::CreateFileA( path.toLocal8Bit().constData(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ) + ); - qMemSet(&m_toc, 0, sizeof(CDROM_TOC)); + qMemSet(m_toc, 0, sizeof(CDROM_TOC)); //read the TOC DWORD bytesRead = 0; - bool tocRead = ::DeviceIoControl(m_cddrive, IOCTL_CDROM_READ_TOC, 0, 0, &m_toc, sizeof(CDROM_TOC), &bytesRead, 0); + bool tocRead = ::DeviceIoControl(m_cddrive, IOCTL_CDROM_READ_TOC, 0, 0, m_toc, sizeof(CDROM_TOC), &bytesRead, 0); if (!tocRead) { qWarning("unable to load the TOC from the CD"); return; } - m_trackAddress = addressToSectors(m_toc.TrackData[0].Address); - const qint32 nbSectorsToRead = (addressToSectors(m_toc.TrackData[m_toc.LastTrack + 1 - m_toc.FirstTrack].Address) + m_trackAddress = addressToSectors(m_toc->TrackData[0].Address); + const qint32 nbSectorsToRead = (addressToSectors(m_toc->TrackData[m_toc->LastTrack + 1 - m_toc->FirstTrack].Address) - m_trackAddress); const qint32 dataLength = nbSectorsToRead * SECTOR_SIZE; - m_waveHeader.chunksize = 4 + (8 + m_waveHeader.chunksize2) + (8 + dataLength); - m_waveHeader.dataLength = dataLength; + m_waveHeader->chunksize = 4 + (8 + m_waveHeader->chunksize2) + (8 + dataLength); + m_waveHeader->dataLength = dataLength; } QAudioCDReader::~QAudioCDReader() { ::CloseHandle(m_cddrive); + delete m_toc; + delete m_waveHeader; + } STDMETHODIMP_(ULONG) QAudioCDReader::AddRef() @@ -179,7 +199,7 @@ namespace Phonon STDMETHODIMP QAudioCDReader::Length(LONGLONG *total,LONGLONG *available) { - const LONGLONG length = sizeof(WaveStructure) + m_waveHeader.dataLength; + const LONGLONG length = sizeof(WaveStructure) + m_waveHeader->dataLength; if (total) { *total = length; } @@ -218,11 +238,11 @@ namespace Phonon if (pos < sizeof(WaveStructure)) { //we first copy the content of the structure nbRead = qMin(LONG(sizeof(WaveStructure) - pos), length); - qMemCopy(buffer, reinterpret_cast<char*>(&m_waveHeader) + pos, nbRead); + qMemCopy(buffer, reinterpret_cast<char*>(m_waveHeader) + pos, nbRead); } const LONGLONG posInTrack = pos - sizeof(WaveStructure) + nbRead; - const int bytesLeft = qMin(m_waveHeader.dataLength - posInTrack, LONGLONG(length - nbRead)); + const int bytesLeft = qMin(m_waveHeader->dataLength - posInTrack, LONGLONG(length - nbRead)); if (bytesLeft > 0) { @@ -277,8 +297,8 @@ namespace Phonon { QList<qint64> ret; ret << 0; - for(int i = m_toc.FirstTrack; i <= m_toc.LastTrack ; ++i) { - const uchar *address = m_toc.TrackData[i].Address; + for(int i = m_toc->FirstTrack; i <= m_toc->LastTrack ; ++i) { + const uchar *address = m_toc->TrackData[i].Address; ret << ((address[0] * 60 + address[1]) * 60 + address[2]) * 1000 + address[3]*1000/75 - 2000; } diff --git a/src/3rdparty/phonon/ds9/qaudiocdreader.h b/src/3rdparty/phonon/ds9/qaudiocdreader.h index eff845d..9049b66 100644 --- a/src/3rdparty/phonon/ds9/qaudiocdreader.h +++ b/src/3rdparty/phonon/ds9/qaudiocdreader.h @@ -31,7 +31,7 @@ namespace Phonon { struct CDROM_TOC; struct WaveStructure; - EXTERN_C const IID IID_ITitleInterface; + extern const IID IID_ITitleInterface; //interface for the Titles struct ITitleInterface : public IUnknown diff --git a/src/3rdparty/phonon/ds9/qbasefilter.cpp b/src/3rdparty/phonon/ds9/qbasefilter.cpp index 78b8b8f..95cab92 100644 --- a/src/3rdparty/phonon/ds9/qbasefilter.cpp +++ b/src/3rdparty/phonon/ds9/qbasefilter.cpp @@ -92,8 +92,8 @@ namespace Phonon return E_POINTER; } - uint nbfetched = 0; - while (nbfetched < count && m_index < m_pins.count()) { + int nbfetched = 0; + while (nbfetched < int(count) && m_index < m_pins.count()) { IPin *current = m_pins[m_index]; current->AddRef(); ret[nbfetched] = current; @@ -166,19 +166,19 @@ namespace Phonon const QList<QPin *> QBaseFilter::pins() const { - QMutexLocker locker(&m_mutex); + QReadLocker locker(&m_lock); return m_pins; } void QBaseFilter::addPin(QPin *pin) { - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); m_pins.append(pin); } void QBaseFilter::removePin(QPin *pin) { - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); m_pins.removeAll(pin); } @@ -211,8 +211,7 @@ namespace Phonon } else if (iid == IID_IMediaPosition || iid == IID_IMediaSeeking) { if (inputPins().isEmpty()) { - *out = getUpStreamInterface(iid); - if (*out) { + if (*out = getUpStreamInterface(iid)) { return S_OK; //we return here to avoid adding a reference } else { hr = E_NOINTERFACE; @@ -251,35 +250,35 @@ namespace Phonon STDMETHODIMP QBaseFilter::GetClassID(CLSID *clsid) { - QMutexLocker locker(&m_mutex); + QReadLocker locker(&m_lock); *clsid = m_clsid; return S_OK; } STDMETHODIMP QBaseFilter::Stop() { - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); m_state = State_Stopped; return S_OK; } STDMETHODIMP QBaseFilter::Pause() { - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); m_state = State_Paused; return S_OK; } STDMETHODIMP QBaseFilter::Run(REFERENCE_TIME) { - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); m_state = State_Running; return S_OK; } STDMETHODIMP QBaseFilter::GetState(DWORD, FILTER_STATE *state) { - QMutexLocker locker(&m_mutex); + QReadLocker locker(&m_lock); if (!state) { return E_POINTER; } @@ -290,7 +289,7 @@ namespace Phonon STDMETHODIMP QBaseFilter::SetSyncSource(IReferenceClock *clock) { - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); if (clock) { clock->AddRef(); } @@ -303,7 +302,7 @@ namespace Phonon STDMETHODIMP QBaseFilter::GetSyncSource(IReferenceClock **clock) { - QMutexLocker locker(&m_mutex); + QReadLocker locker(&m_lock); if (!clock) { return E_POINTER; } @@ -342,7 +341,7 @@ namespace Phonon STDMETHODIMP QBaseFilter::QueryFilterInfo(FILTER_INFO *info ) { - QMutexLocker locker(&m_mutex); + QReadLocker locker(&m_lock); if (!info) { return E_POINTER; } @@ -356,9 +355,9 @@ namespace Phonon STDMETHODIMP QBaseFilter::JoinFilterGraph(IFilterGraph *graph, LPCWSTR name) { - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); m_graph = graph; - m_name = QString::fromWCharArray(name); + m_name = QString::fromUtf16((const unsigned short*)name); return S_OK; } diff --git a/src/3rdparty/phonon/ds9/qbasefilter.h b/src/3rdparty/phonon/ds9/qbasefilter.h index a72d6fe..85f1431 100644 --- a/src/3rdparty/phonon/ds9/qbasefilter.h +++ b/src/3rdparty/phonon/ds9/qbasefilter.h @@ -22,7 +22,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include <QtCore/QString> #include <QtCore/QList> -#include <QtCore/QMutex> +#include <QtCore/QReadWriteLock> #include <dshow.h> @@ -127,7 +127,7 @@ namespace Phonon IFilterGraph *m_graph; FILTER_STATE m_state; QList<QPin *> m_pins; - mutable QMutex m_mutex; + mutable QReadWriteLock m_lock; }; } } diff --git a/src/3rdparty/phonon/ds9/qevr9.h b/src/3rdparty/phonon/ds9/qevr9.h deleted file mode 100644 index 8599fce..0000000 --- a/src/3rdparty/phonon/ds9/qevr9.h +++ /dev/null @@ -1,143 +0,0 @@ -/* 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 <d3d9.h> - -#define DXVA2_ProcAmp_Brightness 1 -#define DXVA2_ProcAmp_Contrast 2 -#define DXVA2_ProcAmp_Hue 4 -#define DXVA2_ProcAmp_Saturation 8 - -typedef enum { - MFVideoARMode_None = 0x00000000, - MFVideoARMode_PreservePicture = 0x00000001, - MFVideoARMode_PreservePixel = 0x00000002, - MFVideoARMode_NonLinearStretch = 0x00000004, - MFVideoARMode_Mask = 0x00000007 -} MFVideoAspectRatioMode; - -typedef struct { - float left; - float top; - float right; - float bottom; -} MFVideoNormalizedRect; - -typedef struct { - UINT DeviceCaps; - D3DPOOL InputPool; - UINT NumForwardRefSamples; - UINT NumBackwardRefSamples; - UINT Reserved; - UINT DeinterlaceTechnology; - UINT ProcAmpControlCaps; - UINT VideoProcessorOperations; - UINT NoiseFilterTechnology; - UINT DetailFilterTechnology; -} DXVA2_VideoProcessorCaps; - -typedef struct { - union { - struct { - USHORT Fraction; - SHORT Value; - }; - LONG ll; - }; -} DXVA2_Fixed32; - -typedef struct { - DXVA2_Fixed32 MinValue; - DXVA2_Fixed32 MaxValue; - DXVA2_Fixed32 DefaultValue; - DXVA2_Fixed32 StepSize; -} DXVA2_ValueRange; - -typedef struct { - DXVA2_Fixed32 Brightness; - DXVA2_Fixed32 Contrast; - DXVA2_Fixed32 Hue; - DXVA2_Fixed32 Saturation; -} DXVA2_ProcAmpValues; - -DXVA2_Fixed32 DXVA2FloatToFixed(const float _float_) -{ - DXVA2_Fixed32 _fixed_; - _fixed_.Fraction = LOWORD(_float_ * 0x10000); - _fixed_.Value = HIWORD(_float_ * 0x10000); - return _fixed_; -} - -float DXVA2FixedToFloat(const DXVA2_Fixed32 _fixed_) -{ - return (FLOAT)_fixed_.Value + (FLOAT)_fixed_.Fraction / 0x10000; -} - -#undef INTERFACE -#define INTERFACE IMFVideoDisplayControl -DECLARE_INTERFACE_(IMFVideoDisplayControl, IUnknown) -{ - STDMETHOD(GetNativeVideoSize)(THIS_ SIZE* pszVideo, SIZE* pszARVideo) PURE; - STDMETHOD(GetIdealVideoSize)(THIS_ SIZE* pszMin, SIZE* pszMax) PURE; - STDMETHOD(SetVideoPosition)(THIS_ const MFVideoNormalizedRect* pnrcSource, const LPRECT prcDest) PURE; - STDMETHOD(GetVideoPosition)(THIS_ MFVideoNormalizedRect* pnrcSource, LPRECT prcDest) PURE; - STDMETHOD(SetAspectRatioMode)(THIS_ DWORD dwAspectRatioMode) PURE; - STDMETHOD(GetAspectRatioMode)(THIS_ DWORD* pdwAspectRatioMode) PURE; - STDMETHOD(SetVideoWindow)(THIS_ HWND hwndVideo) PURE; - STDMETHOD(GetVideoWindow)(THIS_ HWND* phwndVideo) PURE; - STDMETHOD(RepaintVideo)(THIS_) PURE; - STDMETHOD(GetCurrentImage)(THIS_ BITMAPINFOHEADER* pBih, BYTE** pDib, DWORD* pcbDib, LONGLONG* pTimeStamp) PURE; - STDMETHOD(SetBorderColor)(THIS_ COLORREF Clr) PURE; - STDMETHOD(GetBorderColor)(THIS_ COLORREF* pClr) PURE; - STDMETHOD(SetRenderingPrefs)(THIS_ DWORD dwRenderFlags) PURE; - STDMETHOD(GetRenderingPrefs)(THIS_ DWORD* pdwRenderFlags) PURE; - STDMETHOD(SetFullScreen)(THIS_ BOOL fFullscreen) PURE; - STDMETHOD(GetFullScreen)(THIS_ BOOL* pfFullscreen) PURE; -}; -#undef INTERFACE -#define INTERFACE IMFVideoMixerControl -DECLARE_INTERFACE_(IMFVideoMixerControl, IUnknown) -{ - STDMETHOD(SetStreamZOrder)(THIS_ DWORD dwStreamID, DWORD dwZ) PURE; - STDMETHOD(GetStreamZOrder)(THIS_ DWORD dwStreamID, DWORD* pdwZ) PURE; - STDMETHOD(SetStreamOutputRect)(THIS_ DWORD dwStreamID, const MFVideoNormalizedRect* pnrcOutput) PURE; - STDMETHOD(GetStreamOutputRect)(THIS_ DWORD dwStreamID, MFVideoNormalizedRect* pnrcOutput) PURE; -}; -#undef INTERFACE -#define INTERFACE IMFVideoProcessor -DECLARE_INTERFACE_(IMFVideoProcessor, IUnknown) -{ - STDMETHOD(GetAvailableVideoProcessorModes)(THIS_ UINT* lpdwNumProcessingModes, GUID** ppVideoProcessingModes) PURE; - STDMETHOD(GetVideoProcessorCaps)(THIS_ LPGUID lpVideoProcessorMode, DXVA2_VideoProcessorCaps* lpVideoProcessorCaps) PURE; - STDMETHOD(GetVideoProcessorMode)(THIS_ LPGUID lpMode) PURE; - STDMETHOD(SetVideoProcessorMode)(THIS_ LPGUID lpMode) PURE; - STDMETHOD(GetProcAmpRange)(THIS_ DWORD dwProperty, DXVA2_ValueRange* pPropRange) PURE; - STDMETHOD(GetProcAmpValues)(THIS_ DWORD dwFlags, DXVA2_ProcAmpValues* Values) PURE; - STDMETHOD(SetProcAmpValues)(THIS_ DWORD dwFlags, DXVA2_ProcAmpValues* pValues) PURE; - STDMETHOD(GetFilteringRange)(THIS_ DWORD dwProperty, DXVA2_ValueRange* pPropRange) PURE; - STDMETHOD(GetFilteringValue)(THIS_ DWORD dwProperty, DXVA2_Fixed32* pValue) PURE; - STDMETHOD(SetFilteringValue)(THIS_ DWORD dwProperty, DXVA2_Fixed32* pValue) PURE; - STDMETHOD(GetBackgroundColor)(THIS_ COLORREF* lpClrBkg) PURE; - STDMETHOD(SetBackgroundColor)(THIS_ COLORREF ClrBkg) PURE; -}; -#undef INTERFACE -#define INTERFACE IMFGetService -DECLARE_INTERFACE_(IMFGetService, IUnknown) -{ - STDMETHOD(GetService)(THIS_ REFGUID guidService, REFIID riid, LPVOID* ppvObject) PURE; -}; -#undef INTERFACE diff --git a/src/3rdparty/phonon/ds9/qmeminputpin.cpp b/src/3rdparty/phonon/ds9/qmeminputpin.cpp index a21fbe7..dca99db 100644 --- a/src/3rdparty/phonon/ds9/qmeminputpin.cpp +++ b/src/3rdparty/phonon/ds9/qmeminputpin.cpp @@ -28,8 +28,8 @@ namespace Phonon namespace DS9 { - QMemInputPin::QMemInputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt, bool transform, QPin *output) : - QPin(parent, PINDIR_INPUT, mt), m_shouldDuplicateSamples(true), m_transform(transform), m_output(output) + QMemInputPin::QMemInputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt, bool transform) : + QPin(parent, PINDIR_INPUT, mt), m_shouldDuplicateSamples(true), m_transform(transform) { } @@ -66,9 +66,11 @@ namespace Phonon { //this allows to serialize with Receive calls QMutexLocker locker(&m_mutexReceive); - IPin *conn = m_output ? m_output->connected() : 0; - if (conn) { - conn->EndOfStream(); + for(int i = 0; i < m_outputs.count(); ++i) { + IPin *conn = m_outputs.at(i)->connected(); + if (conn) { + conn->EndOfStream(); + } } return S_OK; } @@ -76,11 +78,13 @@ namespace Phonon STDMETHODIMP QMemInputPin::BeginFlush() { //pass downstream - IPin *conn = m_output ? m_output->connected() : 0; - if (conn) { - conn->BeginFlush(); + for(int i = 0; i < m_outputs.count(); ++i) { + IPin *conn = m_outputs.at(i)->connected(); + if (conn) { + conn->BeginFlush(); + } } - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); m_flushing = true; return S_OK; } @@ -88,19 +92,22 @@ namespace Phonon STDMETHODIMP QMemInputPin::EndFlush() { //pass downstream - IPin *conn = m_output ? m_output->connected() : 0; - if (conn) { - conn->EndFlush(); + for(int i = 0; i < m_outputs.count(); ++i) { + IPin *conn = m_outputs.at(i)->connected(); + if (conn) { + conn->EndFlush(); + } } - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); m_flushing = false; return S_OK; } STDMETHODIMP QMemInputPin::NewSegment(REFERENCE_TIME start, REFERENCE_TIME stop, double rate) { - if (m_output) - m_output->NewSegment(start, stop, rate); + for(int i = 0; i < m_outputs.count(); ++i) { + m_outputs.at(i)->NewSegment(start, stop, rate); + } return S_OK; } @@ -112,9 +119,14 @@ namespace Phonon if (hr == S_OK && mt->majortype != MEDIATYPE_NULL && mt->subtype != MEDIASUBTYPE_NULL && - mt->formattype != GUID_NULL && m_output) { - //we tell the output pin that it should connect with this type - hr = m_output->setAcceptedMediaType(connectedType()); + mt->formattype != GUID_NULL) { + //we tell the output pins that they should connect with this type + for(int i = 0; i < m_outputs.count(); ++i) { + hr = m_outputs.at(i)->setAcceptedMediaType(connectedType()); + if (FAILED(hr)) { + break; + } + } } return hr; } @@ -125,8 +137,7 @@ namespace Phonon return E_POINTER; } - *alloc = memoryAllocator(true); - if (*alloc) { + if (*alloc = memoryAllocator(true)) { return S_OK; } @@ -140,15 +151,18 @@ namespace Phonon } { - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); m_shouldDuplicateSamples = m_transform && readonly; } setMemoryAllocator(alloc); - if (m_output) { - ComPointer<IMemInputPin> input(m_output, IID_IMemInputPin); - input->NotifyAllocator(alloc, m_shouldDuplicateSamples); + for(int i = 0; i < m_outputs.count(); ++i) { + IPin *pin = m_outputs.at(i)->connected(); + if (pin) { + ComPointer<IMemInputPin> input(pin, IID_IMemInputPin); + input->NotifyAllocator(alloc, m_shouldDuplicateSamples); + } } return S_OK; @@ -187,18 +201,22 @@ namespace Phonon } } - if (m_output) { + for (int i = 0; i < m_outputs.count(); ++i) { + QPin *current = m_outputs.at(i); IMediaSample *outSample = m_shouldDuplicateSamples ? - duplicateSampleForOutput(sample, m_output->memoryAllocator()) + duplicateSampleForOutput(sample, current->memoryAllocator()) : sample; if (m_shouldDuplicateSamples) { m_parent->processSample(outSample); } - ComPointer<IMemInputPin> input(m_output->connected(), IID_IMemInputPin); - if (input) { - input->Receive(outSample); + IPin *pin = current->connected(); + if (pin) { + ComPointer<IMemInputPin> input(pin, IID_IMemInputPin); + if (input) { + input->Receive(outSample); + } } if (m_shouldDuplicateSamples) { @@ -229,16 +247,39 @@ namespace Phonon STDMETHODIMP QMemInputPin::ReceiveCanBlock() { - //we test the output to see if it can block - if (m_output) { - ComPointer<IMemInputPin> meminput(m_output->connected(), IID_IMemInputPin); - if (meminput && meminput->ReceiveCanBlock() != S_FALSE) { - return S_OK; + //we test the output to see if they can block + for(int i = 0; i < m_outputs.count(); ++i) { + IPin *input = m_outputs.at(i)->connected(); + if (input) { + ComPointer<IMemInputPin> meminput(input, IID_IMemInputPin); + if (meminput && meminput->ReceiveCanBlock() != S_FALSE) { + return S_OK; + } } } return S_FALSE; } + //addition + //this should be used by the filter to tell its input pins to which output they should route the samples + + void QMemInputPin::addOutput(QPin *output) + { + QWriteLocker locker(&m_lock); + m_outputs += output; + } + + void QMemInputPin::removeOutput(QPin *output) + { + QWriteLocker locker(&m_lock); + m_outputs.removeOne(output); + } + + QList<QPin*> QMemInputPin::outputs() const + { + QReadLocker locker(&m_lock); + return m_outputs; + } ALLOCATOR_PROPERTIES QMemInputPin::getDefaultAllocatorProperties() const { @@ -253,7 +294,7 @@ namespace Phonon LONG length = sample->GetActualDataLength(); HRESULT hr = alloc->Commit(); - if (hr == HRESULT(VFW_E_SIZENOTSET)) { + if (hr == VFW_E_SIZENOTSET) { ALLOCATOR_PROPERTIES prop = getDefaultAllocatorProperties(); prop.cbBuffer = qMax(prop.cbBuffer, length); ALLOCATOR_PROPERTIES actual; @@ -283,7 +324,7 @@ namespace Phonon { LONGLONG start, end; hr = sample->GetMediaTime(&start, &end); - if (hr != HRESULT(VFW_E_MEDIA_TIME_NOT_SET)) { + if (hr != VFW_E_MEDIA_TIME_NOT_SET) { hr = out->SetMediaTime(&start, &end); Q_ASSERT(SUCCEEDED(hr)); } diff --git a/src/3rdparty/phonon/ds9/qmeminputpin.h b/src/3rdparty/phonon/ds9/qmeminputpin.h index d74c451..c449721 100644 --- a/src/3rdparty/phonon/ds9/qmeminputpin.h +++ b/src/3rdparty/phonon/ds9/qmeminputpin.h @@ -37,7 +37,7 @@ namespace Phonon class QMemInputPin : public QPin, public IMemInputPin { public: - QMemInputPin(QBaseFilter *, const QVector<AM_MEDIA_TYPE> &, bool transform, QPin *output); + QMemInputPin(QBaseFilter *, const QVector<AM_MEDIA_TYPE> &, bool transform); ~QMemInputPin(); //reimplementation from IUnknown @@ -60,13 +60,18 @@ namespace Phonon STDMETHODIMP ReceiveMultiple(IMediaSample **,long,long *); STDMETHODIMP ReceiveCanBlock(); + //addition + void addOutput(QPin *output); + void removeOutput(QPin *output); + QList<QPin*> outputs() const; + private: IMediaSample *duplicateSampleForOutput(IMediaSample *, IMemAllocator *); ALLOCATOR_PROPERTIES getDefaultAllocatorProperties() const; bool m_shouldDuplicateSamples; const bool m_transform; //defines if the pin is transforming the samples - QPin* const m_output; + QList<QPin*> m_outputs; QMutex m_mutexReceive; }; } diff --git a/src/3rdparty/phonon/ds9/qpin.cpp b/src/3rdparty/phonon/ds9/qpin.cpp index b4afd10..37fe48d 100644 --- a/src/3rdparty/phonon/ds9/qpin.cpp +++ b/src/3rdparty/phonon/ds9/qpin.cpp @@ -28,7 +28,20 @@ namespace Phonon namespace DS9 { - static const AM_MEDIA_TYPE defaultMediaType = { MEDIATYPE_NULL, MEDIASUBTYPE_NULL, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0}; + static const AM_MEDIA_TYPE defaultMediaType() + { + AM_MEDIA_TYPE ret; + ret.majortype = MEDIATYPE_NULL; + ret.subtype = MEDIASUBTYPE_NULL; + ret.bFixedSizeSamples = TRUE; + ret.bTemporalCompression = FALSE; + ret.lSampleSize = 1; + ret.formattype = GUID_NULL; + ret.pUnk = 0; + ret.cbFormat = 0; + ret.pbFormat = 0; + return ret; + } class QEnumMediaTypes : public IEnumMediaTypes { @@ -91,8 +104,8 @@ namespace Phonon return E_INVALIDARG; } - uint nbFetched = 0; - while (nbFetched < count && m_index < m_pin->mediaTypes().count()) { + int nbFetched = 0; + while (nbFetched < int(count) && m_index < m_pin->mediaTypes().count()) { //the caller will deallocate the memory *out = static_cast<AM_MEDIA_TYPE *>(::CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE))); const AM_MEDIA_TYPE original = m_pin->mediaTypes().at(m_index); @@ -145,9 +158,9 @@ namespace Phonon QPin::QPin(QBaseFilter *parent, PIN_DIRECTION dir, const QVector<AM_MEDIA_TYPE> &mt) : - m_parent(parent), m_flushing(false), m_refCount(1), m_connected(0), - m_direction(dir), m_mediaTypes(mt), m_connectedType(defaultMediaType), - m_memAlloc(0) + m_memAlloc(0), m_parent(parent), m_refCount(1), m_connected(0), + m_direction(dir), m_mediaTypes(mt), m_connectedType(defaultMediaType()), + m_flushing(false) { Q_ASSERT(m_parent); m_parent->addPin(this); @@ -260,7 +273,7 @@ namespace Phonon if (FAILED(hr)) { setConnected(0); - setConnectedType(defaultMediaType); + setConnectedType(defaultMediaType()); } else { ComPointer<IMemInputPin> input(pin, IID_IMemInputPin); if (input) { @@ -302,8 +315,10 @@ namespace Phonon } setConnected(0); - setConnectedType(defaultMediaType); - setMemoryAllocator(0); + setConnectedType(defaultMediaType()); + if (m_direction == PINDIR_INPUT) { + setMemoryAllocator(0); + } return S_OK; } @@ -323,7 +338,7 @@ namespace Phonon STDMETHODIMP QPin::ConnectionMediaType(AM_MEDIA_TYPE *type) { - QMutexLocker locker(&m_mutex); + QReadLocker locker(&m_lock); if (!type) { return E_POINTER; } @@ -338,6 +353,7 @@ namespace Phonon STDMETHODIMP QPin::QueryPinInfo(PIN_INFO *info) { + QReadLocker locker(&m_lock); if (!info) { return E_POINTER; } @@ -345,12 +361,14 @@ namespace Phonon info->dir = m_direction; info->pFilter = m_parent; m_parent->AddRef(); - info->achName[0] = 0; + qMemCopy(info->achName, m_name.utf16(), qMin(MAX_FILTER_NAME, m_name.length()+1) *2); + return S_OK; } STDMETHODIMP QPin::QueryDirection(PIN_DIRECTION *dir) { + QReadLocker locker(&m_lock); if (!dir) { return E_POINTER; } @@ -361,18 +379,20 @@ namespace Phonon STDMETHODIMP QPin::QueryId(LPWSTR *id) { + QReadLocker locker(&m_lock); if (!id) { return E_POINTER; } - *id = static_cast<LPWSTR>(::CoTaskMemAlloc(2)); - *id[0] = 0; + int nbBytes = (m_name.length()+1)*2; + *id = static_cast<LPWSTR>(::CoTaskMemAlloc(nbBytes)); + qMemCopy(*id, m_name.utf16(), nbBytes); return S_OK; } STDMETHODIMP QPin::QueryAccept(const AM_MEDIA_TYPE *type) { - QMutexLocker locker(&m_mutex); + QReadLocker locker(&m_lock); if (!type) { return E_POINTER; } @@ -419,7 +439,7 @@ namespace Phonon STDMETHODIMP QPin::NewSegment(REFERENCE_TIME start, REFERENCE_TIME stop, double rate) { - QMutexLocker locker(&m_mutex); + QReadLocker locker(&m_lock); if (m_direction == PINDIR_OUTPUT && m_connected) { //we deliver this downstream m_connected->NewSegment(start, stop, rate); @@ -436,8 +456,8 @@ namespace Phonon HRESULT QPin::checkOutputMediaTypesConnection(IPin *pin) { - ComPointer<IEnumMediaTypes> emt; - HRESULT hr = pin->EnumMediaTypes(emt.pparam()); + IEnumMediaTypes *emt = 0; + HRESULT hr = pin->EnumMediaTypes(&emt); if (hr != S_OK) { return hr; } @@ -450,7 +470,7 @@ namespace Phonon freeMediaType(type); return S_OK; } else { - setConnectedType(defaultMediaType); + setConnectedType(defaultMediaType()); freeMediaType(type); } } @@ -500,7 +520,7 @@ namespace Phonon void QPin::setConnectedType(const AM_MEDIA_TYPE &type) { - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); //1st we free memory freeMediaType(m_connectedType); @@ -510,13 +530,13 @@ namespace Phonon const AM_MEDIA_TYPE &QPin::connectedType() const { - QMutexLocker locker(&m_mutex); + QReadLocker locker(&m_lock); return m_connectedType; } void QPin::setConnected(IPin *pin) { - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); if (pin) { pin->AddRef(); } @@ -528,7 +548,7 @@ namespace Phonon IPin *QPin::connected(bool addref) const { - QMutexLocker locker(&m_mutex); + QReadLocker locker(&m_lock); if (addref && m_connected) { m_connected->AddRef(); } @@ -537,12 +557,13 @@ namespace Phonon bool QPin::isFlushing() const { - QMutexLocker locker(&m_mutex); + QReadLocker locker(&m_lock); return m_flushing; } FILTER_STATE QPin::filterState() const { + QReadLocker locker(&m_lock); FILTER_STATE fstate = State_Stopped; m_parent->GetState(0, &fstate); return fstate; @@ -550,7 +571,7 @@ namespace Phonon QVector<AM_MEDIA_TYPE> QPin::mediaTypes() const { - QMutexLocker locker(&m_mutex); + QReadLocker locker(&m_lock); return m_mediaTypes; } @@ -586,7 +607,7 @@ namespace Phonon void QPin::setMemoryAllocator(IMemAllocator *alloc) { - QMutexLocker locker(&m_mutex); + QWriteLocker locker(&m_lock); if (alloc) { alloc->AddRef(); } @@ -598,7 +619,7 @@ namespace Phonon IMemAllocator *QPin::memoryAllocator(bool addref) const { - QMutexLocker locker(&m_mutex); + QReadLocker locker(&m_lock); if (addref && m_memAlloc) { m_memAlloc->AddRef(); } diff --git a/src/3rdparty/phonon/ds9/qpin.h b/src/3rdparty/phonon/ds9/qpin.h index 280ad61..a3287c4 100644 --- a/src/3rdparty/phonon/ds9/qpin.h +++ b/src/3rdparty/phonon/ds9/qpin.h @@ -22,7 +22,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include <QtCore/QString> #include <QtCore/QVector> -#include <QtCore/QMutex> +#include <QtCore/QReadWriteLock> #include <dshow.h> @@ -85,8 +85,8 @@ namespace Phonon protected: //this can be used by sub-classes - mutable QMutex m_mutex; - QBaseFilter * const m_parent; + mutable QReadWriteLock m_lock; + QBaseFilter *m_parent; bool m_flushing; private: @@ -98,6 +98,7 @@ namespace Phonon const PIN_DIRECTION m_direction; QVector<AM_MEDIA_TYPE> m_mediaTypes; //accepted media types AM_MEDIA_TYPE m_connectedType; + QString m_name; IMemAllocator *m_memAlloc; }; diff --git a/src/3rdparty/phonon/ds9/videorenderer_default.cpp b/src/3rdparty/phonon/ds9/videorenderer_default.cpp deleted file mode 100644 index 0045a49..0000000 --- a/src/3rdparty/phonon/ds9/videorenderer_default.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* 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 "videorenderer_default.h" - -#ifndef QT_NO_PHONON_VIDEO - -#include <QtGui/QWidget> -#include <QtGui/QPainter> - -#include <uuids.h> - -QT_BEGIN_NAMESPACE - - -namespace Phonon -{ - namespace DS9 - { - VideoRendererDefault::~VideoRendererDefault() - { - } - - bool VideoRendererDefault::isNative() const - { - return true; - } - - - VideoRendererDefault::VideoRendererDefault(QWidget *target) : m_target(target) - { - m_target->setAttribute(Qt::WA_PaintOnScreen, true); - m_filter = Filter(CLSID_VideoRenderer, IID_IBaseFilter); - } - - QSize VideoRendererDefault::videoSize() const - { - LONG w = 0, - h = 0; - ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo); - if (basic) { - basic->GetVideoSize( &w, &h); - } - return QSize(w, h); - } - - void VideoRendererDefault::repaintCurrentFrame(QWidget * /*target*/, const QRect & /*rect*/) - { - //nothing to do here: the renderer paints everything - } - - void VideoRendererDefault::notifyResize(const QSize &size, Phonon::VideoWidget::AspectRatio aspectRatio, - Phonon::VideoWidget::ScaleMode scaleMode) - { - if (!isActive()) { - ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo); - if (basic) { - basic->SetDestinationPosition(0, 0, 0, 0); - } - return; - } - - ComPointer<IVideoWindow> video(m_filter, IID_IVideoWindow); - - OAHWND owner; - HRESULT hr = video->get_Owner(&owner); - if (FAILED(hr)) { - return; - } - - const OAHWND newOwner = reinterpret_cast<OAHWND>(m_target->winId()); - if (owner != newOwner) { - video->put_Owner(newOwner); - video->put_MessageDrain(newOwner); - video->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); - } - - //make sure the widget takes the whole size of the parent - video->SetWindowPosition(0, 0, size.width(), size.height()); - - const QSize vsize = videoSize(); - internalNotifyResize(size, vsize, aspectRatio, scaleMode); - - ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo); - if (basic) { - basic->SetDestinationPosition(m_dstX, m_dstY, m_dstWidth, m_dstHeight); - } - } - - void VideoRendererDefault::applyMixerSettings(qreal /*brightness*/, qreal /*contrast*/, qreal /*m_hue*/, qreal /*saturation*/) - { - //this can't be supported for the default renderer - } - - QImage VideoRendererDefault::snapshot() const - { - ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo); - if (basic) { - LONG bufferSize = 0; - //1st we get the buffer size - basic->GetCurrentImage(&bufferSize, 0); - - QByteArray buffer; - buffer.resize(bufferSize); - HRESULT hr = basic->GetCurrentImage(&bufferSize, reinterpret_cast<long*>(buffer.data())); - - if (SUCCEEDED(hr)) { - - const BITMAPINFOHEADER *bmi = reinterpret_cast<const BITMAPINFOHEADER*>(buffer.constData()); - - const int w = qAbs(bmi->biWidth), - h = qAbs(bmi->biHeight); - - // Create image and copy data into image. - QImage ret(w, h, QImage::Format_RGB32); - - if (!ret.isNull()) { - const char *data = buffer.constData() + bmi->biSize; - const int bytes_per_line = w * sizeof(QRgb); - for (int y = h - 1; y >= 0; --y) { - qMemCopy(ret.scanLine(y), //destination - data, //source - bytes_per_line); - data += bytes_per_line; - } - } - return ret; - } - } - return QImage(); - } - - } -} - -QT_END_NAMESPACE - -#endif //QT_NO_PHONON_VIDEO diff --git a/src/3rdparty/phonon/ds9/videorenderer_default.h b/src/3rdparty/phonon/ds9/videorenderer_default.h deleted file mode 100644 index 43768d9..0000000 --- a/src/3rdparty/phonon/ds9/videorenderer_default.h +++ /dev/null @@ -1,55 +0,0 @@ -/* 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/>. -*/ - -#ifndef PHONON_VIDEORENDERER_DEFAULT_H -#define PHONON_VIDEORENDERER_DEFAULT_H - -#include "abstractvideorenderer.h" - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_PHONON_VIDEO - -namespace Phonon -{ - namespace DS9 - { - class VideoRendererDefault : public AbstractVideoRenderer - { - public: - VideoRendererDefault(QWidget *target); - ~VideoRendererDefault(); - - //Implementation from AbstractVideoRenderer - void repaintCurrentFrame(QWidget *target, const QRect &rect); - void notifyResize(const QSize&, Phonon::VideoWidget::AspectRatio, Phonon::VideoWidget::ScaleMode); - QSize videoSize() const; - QImage snapshot() const; - void applyMixerSettings(qreal brightness, qreal contrast, qreal m_hue, qreal saturation); - bool isNative() const; - private: - QWidget *m_target; - }; - } -} - -#endif //QT_NO_PHONON_VIDEO - -QT_END_NAMESPACE - -#endif - diff --git a/src/3rdparty/phonon/ds9/videorenderer_evr.cpp b/src/3rdparty/phonon/ds9/videorenderer_evr.cpp deleted file mode 100644 index d23d9ce..0000000 --- a/src/3rdparty/phonon/ds9/videorenderer_evr.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* 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 "videorenderer_evr.h" -#include "qevr9.h" - -#ifndef QT_NO_PHONON_VIDEO - -#include <QtGui/QWidget> -#include <QtGui/QPainter> - -QT_BEGIN_NAMESPACE - -namespace Phonon -{ - namespace DS9 - { - //we have to define them here because not all compilers/sdk have them - static const GUID MR_VIDEO_RENDER_SERVICE = {0x1092a86c, 0xab1a, 0x459a, {0xa3, 0x36, 0x83, 0x1f, 0xbc, 0x4d, 0x11, 0xff} }; - static const GUID MR_VIDEO_MIXER_SERVICE = { 0x73cd2fc, 0x6cf4, 0x40b7, {0x88, 0x59, 0xe8, 0x95, 0x52, 0xc8, 0x41, 0xf8} }; - static const IID IID_IMFVideoDisplayControl = {0xa490b1e4, 0xab84, 0x4d31, {0xa1, 0xb2, 0x18, 0x1e, 0x03, 0xb1, 0x07, 0x7a} }; - static const IID IID_IMFVideoMixerControl = {0xA5C6C53F, 0xC202, 0x4aa5, {0x96, 0x95, 0x17, 0x5B, 0xA8, 0xC5, 0x08, 0xA5} }; - static const IID IID_IMFVideoProcessor = {0x6AB0000C, 0xFECE, 0x4d1f, {0xA2, 0xAC, 0xA9, 0x57, 0x35, 0x30, 0x65, 0x6E} }; - static const IID IID_IMFGetService = {0xFA993888, 0x4383, 0x415A, {0xA9, 0x30, 0xDD, 0x47, 0x2A, 0x8C, 0xF6, 0xF7} }; - static const GUID CLSID_EnhancedVideoRenderer = {0xfa10746c, 0x9b63, 0x4b6c, {0xbc, 0x49, 0xfc, 0x30, 0xe, 0xa5, 0xf2, 0x56} }; - - template <typename T> ComPointer<T> getService(const Filter &filter, REFGUID guidService, REFIID riid) - { - //normally we should use IID_IMFGetService but this introduces another dependency - //so here we simply define our own IId with the same value - ComPointer<IMFGetService> getService(filter, IID_IMFGetService); - Q_ASSERT(getService); - T *ptr = 0; - HRESULT hr = getService->GetService(guidService, riid, reinterpret_cast<void **>(&ptr)); - if (!SUCCEEDED(hr) || ptr == 0) - Q_ASSERT(!SUCCEEDED(hr) && ptr != 0); - ComPointer<T> service(ptr); - return service; - } - - VideoRendererEVR::~VideoRendererEVR() - { - } - - bool VideoRendererEVR::isNative() const - { - return true; - } - - VideoRendererEVR::VideoRendererEVR(QWidget *target) : m_target(target) - { - m_filter = Filter(CLSID_EnhancedVideoRenderer, IID_IBaseFilter); - if (!m_filter) { - return; - } - - ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl); - - filterControl->SetVideoWindow(reinterpret_cast<HWND>(target->winId())); - filterControl->SetAspectRatioMode(MFVideoARMode_None); // We're in control of the size - } - - QImage VideoRendererEVR::snapshot() const - { - // This will always capture black areas where no video is drawn, if any are present. - // Due to the hack in notifyResize() - ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl); - if (filterControl) { - BITMAPINFOHEADER bmi; - BYTE *buffer = 0; - DWORD bufferSize; - LONGLONG timeStamp; - - bmi.biSize = sizeof(BITMAPINFOHEADER); - - HRESULT hr = filterControl->GetCurrentImage(&bmi, &buffer, &bufferSize, &timeStamp); - if (SUCCEEDED(hr)) { - - const int w = qAbs(bmi.biWidth), - h = qAbs(bmi.biHeight); - - // Create image and copy data into image. - QImage ret(w, h, QImage::Format_RGB32); - - if (!ret.isNull()) { - uchar *data = buffer; - const int bytes_per_line = w * sizeof(QRgb); - for (int y = h - 1; y >= 0; --y) { - qMemCopy(ret.scanLine(y), //destination - data, //source - bytes_per_line); - data += bytes_per_line; - } - } - ::CoTaskMemFree(buffer); - return ret; - } - } - return QImage(); - } - - QSize VideoRendererEVR::videoSize() const - { - SIZE nativeSize; - SIZE aspectRatioSize; - - ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl); - - filterControl->GetNativeVideoSize(&nativeSize, &aspectRatioSize); - - return QSize(nativeSize.cx, nativeSize.cy); - } - - void VideoRendererEVR::repaintCurrentFrame(QWidget *target, const QRect &rect) - { - // repaint the video - ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl); - // All failed results can be safely ignored - filterControl->RepaintVideo(); - } - - void VideoRendererEVR::notifyResize(const QSize &size, Phonon::VideoWidget::AspectRatio aspectRatio, - Phonon::VideoWidget::ScaleMode scaleMode) - { - if (!isActive()) { - RECT dummyRect = { 0, 0, 0, 0}; - ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl); - filterControl->SetVideoPosition(0, &dummyRect); - return; - } - - const QSize vsize = videoSize(); - internalNotifyResize(size, vsize, aspectRatio, scaleMode); - - RECT dstRectWin = { 0, 0, size.width(), size.height()}; - - // Resize the Stream output rect instead of the destination rect. - // Hacky workaround for flicker in the areas outside of the destination rect - // This way these areas don't exist - MFVideoNormalizedRect streamOutputRect = { float(m_dstX) / float(size.width()), float(m_dstY) / float(size.height()), - float(m_dstWidth + m_dstX) / float(size.width()), float(m_dstHeight + m_dstY) / float(size.height())}; - - ComPointer<IMFVideoMixerControl> filterMixer = getService<IMFVideoMixerControl>(m_filter, MR_VIDEO_MIXER_SERVICE, IID_IMFVideoMixerControl); - ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl); - - filterMixer->SetStreamOutputRect(0, &streamOutputRect); - filterControl->SetVideoPosition(0, &dstRectWin); - } - - void VideoRendererEVR::applyMixerSettings(qreal brightness, qreal contrast, qreal hue, qreal saturation) - { - InputPin sink = BackendNode::pins(m_filter, PINDIR_INPUT).first(); - OutputPin source; - if (FAILED(sink->ConnectedTo(source.pparam()))) { - return; //it must be connected to work - } - - // Get the "Video Processor" (used for brightness/contrast/saturation/hue) - ComPointer<IMFVideoProcessor> processor = getService<IMFVideoProcessor>(m_filter, MR_VIDEO_MIXER_SERVICE, IID_IMFVideoProcessor); - Q_ASSERT(processor); - - DXVA2_ValueRange contrastRange; - DXVA2_ValueRange brightnessRange; - DXVA2_ValueRange saturationRange; - DXVA2_ValueRange hueRange; - - if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Contrast, &contrastRange))) - return; - if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Brightness, &brightnessRange))) - return; - if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Saturation, &saturationRange))) - return; - if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Hue, &hueRange))) - return; - - DXVA2_ProcAmpValues values; - - values.Contrast = DXVA2FloatToFixed(((contrast < 0 - ? DXVA2FixedToFloat(contrastRange.MinValue) : DXVA2FixedToFloat(contrastRange.MaxValue)) - - DXVA2FixedToFloat(contrastRange.DefaultValue)) * qAbs(contrast) + DXVA2FixedToFloat(contrastRange.DefaultValue)); - values.Brightness = DXVA2FloatToFixed(((brightness < 0 - ? DXVA2FixedToFloat(brightnessRange.MinValue) : DXVA2FixedToFloat(brightnessRange.MaxValue)) - - DXVA2FixedToFloat(brightnessRange.DefaultValue)) * qAbs(brightness) + DXVA2FixedToFloat(brightnessRange.DefaultValue)); - values.Saturation = DXVA2FloatToFixed(((saturation < 0 - ? DXVA2FixedToFloat(saturationRange.MinValue) : DXVA2FixedToFloat(saturationRange.MaxValue)) - - DXVA2FixedToFloat(saturationRange.DefaultValue)) * qAbs(saturation) + DXVA2FixedToFloat(saturationRange.DefaultValue)); - values.Hue = DXVA2FloatToFixed(((hue < 0 - ? DXVA2FixedToFloat(hueRange.MinValue) : DXVA2FixedToFloat(hueRange.MaxValue)) - - DXVA2FixedToFloat(hueRange.DefaultValue)) * qAbs(hue) + DXVA2FixedToFloat(hueRange.DefaultValue)); - - //finally set the settings - processor->SetProcAmpValues(DXVA2_ProcAmp_Contrast | DXVA2_ProcAmp_Brightness | DXVA2_ProcAmp_Saturation | DXVA2_ProcAmp_Hue, &values); - - } - } -} - -QT_END_NAMESPACE - -#endif //QT_NO_PHONON_VIDEO diff --git a/src/3rdparty/phonon/ds9/videorenderer_evr.h b/src/3rdparty/phonon/ds9/videorenderer_evr.h deleted file mode 100644 index 229c36d..0000000 --- a/src/3rdparty/phonon/ds9/videorenderer_evr.h +++ /dev/null @@ -1,56 +0,0 @@ -/* 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/>. -*/ - -#ifndef PHONON_VIDEORENDERER_EVR_H -#define PHONON_VIDEORENDERER_EVR_H - -#include "abstractvideorenderer.h" -#include "compointer.h" - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_PHONON_VIDEO - -namespace Phonon -{ - namespace DS9 - { - class VideoRendererEVR : public AbstractVideoRenderer - { - public: - VideoRendererEVR(QWidget *target); - ~VideoRendererEVR(); - - //Implementation from AbstractVideoRenderer - void repaintCurrentFrame(QWidget *target, const QRect &rect); - void notifyResize(const QSize&, Phonon::VideoWidget::AspectRatio, Phonon::VideoWidget::ScaleMode); - QSize videoSize() const; - QImage snapshot() const; - void applyMixerSettings(qreal brightness, qreal contrast, qreal m_hue, qreal saturation); - bool isNative() const; - private: - QWidget *m_target; - }; - } -} - -#endif //QT_NO_PHONON_VIDEO - -QT_END_NAMESPACE - -#endif - diff --git a/src/3rdparty/phonon/ds9/videorenderer_soft.cpp b/src/3rdparty/phonon/ds9/videorenderer_soft.cpp index 9c7993c..491d1bd 100644 --- a/src/3rdparty/phonon/ds9/videorenderer_soft.cpp +++ b/src/3rdparty/phonon/ds9/videorenderer_soft.cpp @@ -194,8 +194,8 @@ namespace Phonon m_sampleBuffer = ComPointer<IMediaSample>(); #ifndef QT_NO_OPENGL freeGLResources(); - m_textureUploaded = false; #endif // QT_NO_OPENGL + m_textureUploaded = false; } void endOfStream() @@ -314,6 +314,7 @@ namespace Phonon REFERENCE_TIME m_start; HANDLE m_renderEvent, m_receiveCanWait; // Signals sample to render QSize m_size; + bool m_textureUploaded; //mixer settings qreal m_brightness, @@ -355,7 +356,6 @@ namespace Phonon bool m_checkedPrograms; bool m_usingOpenGL; - bool m_textureUploaded; GLuint m_program[2]; GLuint m_texture[3]; #endif @@ -365,7 +365,7 @@ namespace Phonon { public: VideoRendererSoftPin(VideoRendererSoftFilter *parent) : - QMemInputPin(parent, videoMediaTypes(), false /*no transformation of the samples*/, 0), + QMemInputPin(parent, videoMediaTypes(), false /*no transformation of the samples*/), m_renderer(parent) { } @@ -436,7 +436,7 @@ namespace Phonon QBaseFilter(CLSID_NULL), m_inputPin(new VideoRendererSoftPin(this)), m_renderer(renderer), m_start(0) #ifndef QT_NO_OPENGL - , m_checkedPrograms(false), m_usingOpenGL(false), m_textureUploaded(false) + ,m_usingOpenGL(false), m_checkedPrograms(false), m_textureUploaded(false) #endif { m_renderEvent = ::CreateEvent(0, 0, 0, 0); @@ -661,10 +661,7 @@ namespace Phonon #ifndef QT_NO_OPENGL - if (painter.paintEngine() && - (painter.paintEngine()->type() == QPaintEngine::OpenGL || painter.paintEngine()->type() == QPaintEngine::OpenGL2) - && checkGLPrograms()) { - + if (painter.paintEngine() && painter.paintEngine()->type() == QPaintEngine::OpenGL && checkGLPrograms()) { //for now we only support YUV (both YV12 and YUY2) updateTexture(); @@ -676,7 +673,6 @@ namespace Phonon } //let's draw the texture - painter.beginNativePainting(); //Let's pass the other arguments const Program prog = (m_inputPin->connectedType().subtype == MEDIASUBTYPE_YV12) ? YV12toRGB : YUY2toRGB; @@ -726,7 +722,6 @@ namespace Phonon glDisableClientState(GL_VERTEX_ARRAY); glDisable(GL_FRAGMENT_PROGRAM_ARB); - painter.endNativePainting(); return; } else #endif diff --git a/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp b/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp index 545b31e..298e9fa 100644 --- a/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp +++ b/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp @@ -22,9 +22,14 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include <QtGui/QWidget> #include <QtGui/QPainter> +#include <QtCore/QTimerEvent> +#ifndef Q_OS_WINCE #include <d3d9.h> #include <vmr9.h> +#else +#include <uuids.h> +#endif QT_BEGIN_NAMESPACE @@ -43,10 +48,116 @@ namespace Phonon } +#ifdef Q_OS_WINCE + VideoRendererVMR9::VideoRendererVMR9(QWidget *target) : m_target(target) + { + m_target->setAttribute(Qt::WA_PaintOnScreen, true); + m_filter = Filter(CLSID_VideoRenderer, IID_IBaseFilter); + } + + QSize VideoRendererVMR9::videoSize() const + { + LONG w = 0, + h = 0; + ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo); + if (basic) { + basic->GetVideoSize( &w, &h); + } + return QSize(w, h); + } + + void VideoRendererVMR9::repaintCurrentFrame(QWidget * /*target*/, const QRect & /*rect*/) + { + //nothing to do here: the renderer paints everything + } + + void VideoRendererVMR9::notifyResize(const QSize &size, Phonon::VideoWidget::AspectRatio aspectRatio, + Phonon::VideoWidget::ScaleMode scaleMode) + { + if (!isActive()) { + ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo); + if (basic) { + basic->SetDestinationPosition(0, 0, 0, 0); + } + return; + } + + ComPointer<IVideoWindow> video(m_filter, IID_IVideoWindow); + + OAHWND owner; + HRESULT hr = video->get_Owner(&owner); + if (FAILED(hr)) { + return; + } + + const OAHWND newOwner = reinterpret_cast<OAHWND>(m_target->winId()); + if (owner != newOwner) { + video->put_Owner(newOwner); + video->put_MessageDrain(newOwner); + video->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + } + + //make sure the widget takes the whole size of the parent + video->SetWindowPosition(0, 0, size.width(), size.height()); + + const QSize vsize = videoSize(); + internalNotifyResize(size, vsize, aspectRatio, scaleMode); + + ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo); + if (basic) { + basic->SetDestinationPosition(m_dstX, m_dstY, m_dstWidth, m_dstHeight); + } + } + + void VideoRendererVMR9::applyMixerSettings(qreal /*brightness*/, qreal /*contrast*/, qreal /*m_hue*/, qreal /*saturation*/) + { + //this can't be supported for WinCE + } + + QImage VideoRendererVMR9::snapshot() const + { + ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo); + if (basic) { + LONG bufferSize = 0; + //1st we get the buffer size + basic->GetCurrentImage(&bufferSize, 0); + + QByteArray buffer; + buffer.resize(bufferSize); + HRESULT hr = basic->GetCurrentImage(&bufferSize, reinterpret_cast<long*>(buffer.data())); + + if (SUCCEEDED(hr)) { + + const BITMAPINFOHEADER *bmi = reinterpret_cast<const BITMAPINFOHEADER*>(buffer.constData()); + + const int w = qAbs(bmi->biWidth), + h = qAbs(bmi->biHeight); + + // Create image and copy data into image. + QImage ret(w, h, QImage::Format_RGB32); + + if (!ret.isNull()) { + const char *data = buffer.constData() + bmi->biSize; + const int bytes_per_line = w * sizeof(QRgb); + for (int y = h - 1; y >= 0; --y) { + qMemCopy(ret.scanLine(y), //destination + data, //source + bytes_per_line); + data += bytes_per_line; + } + } + return ret; + } + } + return QImage(); + } + +#else VideoRendererVMR9::VideoRendererVMR9(QWidget *target) : m_target(target) { m_filter = Filter(CLSID_VideoMixingRenderer9, IID_IBaseFilter); if (!m_filter) { + qWarning("the video widget could not be initialized correctly"); return; } @@ -58,7 +169,6 @@ namespace Phonon Q_ASSERT(SUCCEEDED(hr)); ComPointer<IVMRWindowlessControl9> windowlessControl(m_filter, IID_IVMRWindowlessControl9); windowlessControl->SetVideoClippingWindow(reinterpret_cast<HWND>(target->winId())); - windowlessControl->SetAspectRatioMode(VMR9ARMode_None); //we're in control of the size } QImage VideoRendererVMR9::snapshot() const @@ -214,6 +324,7 @@ namespace Phonon //finally set the settings mixer->SetProcAmpControl(0, &ctrl); } +#endif } } diff --git a/src/3rdparty/phonon/ds9/videorenderer_vmr9.h b/src/3rdparty/phonon/ds9/videorenderer_vmr9.h index 516d79d..4eb237e 100644 --- a/src/3rdparty/phonon/ds9/videorenderer_vmr9.h +++ b/src/3rdparty/phonon/ds9/videorenderer_vmr9.h @@ -19,6 +19,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #define PHONON_VIDEORENDERER_VMR9_H #include "abstractvideorenderer.h" +#include "compointer.h" QT_BEGIN_NAMESPACE diff --git a/src/3rdparty/phonon/ds9/videowidget.cpp b/src/3rdparty/phonon/ds9/videowidget.cpp index 09d42a4..de7ce5f 100644 --- a/src/3rdparty/phonon/ds9/videowidget.cpp +++ b/src/3rdparty/phonon/ds9/videowidget.cpp @@ -24,12 +24,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include "mediaobject.h" -#ifndef Q_OS_WINCE -#include "videorenderer_evr.h" #include "videorenderer_vmr9.h" -#else -#include "videorenderer_default.h" -#endif #include "videorenderer_soft.h" QT_BEGIN_NAMESPACE @@ -89,19 +84,7 @@ namespace Phonon void setCurrentRenderer(AbstractVideoRenderer *renderer) { m_currentRenderer = renderer; - //we disallow repaint on that widget for just a fraction of second - //this allows better transition between videos - setUpdatesEnabled(false); - m_flickerFreeTimer.start(20, this); - } - - void timerEvent(QTimerEvent *e) - { - if (e->timerId() == m_flickerFreeTimer.timerId()) { - m_flickerFreeTimer.stop(); - setUpdatesEnabled(true); - } - QWidget::timerEvent(e); + update(); } QSize sizeHint() const @@ -123,8 +106,6 @@ namespace Phonon void paintEvent(QPaintEvent *e) { - if (!updatesEnabled()) - return; //this avoids repaint from native events checkCurrentRenderingMode(); m_currentRenderer->repaintCurrentFrame(this, e->rect()); } @@ -172,14 +153,13 @@ namespace Phonon } } else if (!isEmbedded()) { m_currentRenderer = m_node->switchRendering(m_currentRenderer); - setAttribute(Qt::WA_PaintOnScreen, false); + setAttribute(Qt::WA_PaintOnScreen, true); } } VideoWidget *m_node; AbstractVideoRenderer *m_currentRenderer; QVariant m_restoreScreenSaverActive; - QBasicTimer m_flickerFreeTimer; }; VideoWidget::VideoWidget(QWidget *parent) @@ -223,9 +203,6 @@ namespace Phonon if (toNative && m_noNativeRendererSupported) return current; //no switch here - if (!mediaObject()) - return current; - //firt we delete the renderer //initialization of the widgets for(int i = 0; i < FILTER_COUNT; ++i) { @@ -284,7 +261,6 @@ namespace Phonon { m_aspectRatio = aspectRatio; updateVideoSize(); - m_widget->update(); } Phonon::VideoWidget::ScaleMode VideoWidget::scaleMode() const @@ -303,7 +279,6 @@ namespace Phonon { m_scaleMode = scaleMode; updateVideoSize(); - m_widget->update(); } void VideoWidget::setBrightness(qreal b) @@ -357,29 +332,14 @@ namespace Phonon int index = graphIndex * 2 + type; if (m_renderers[index] == 0 && autoCreate) { AbstractVideoRenderer *renderer = 0; - if (type == Native) { -#ifndef Q_OS_WINCE - renderer = new VideoRendererEVR(m_widget); - if (renderer->getFilter() == 0) { - delete renderer; - //EVR not present, let's try VMR - renderer = new VideoRendererVMR9(m_widget); - if (renderer->getFilter() == 0) { - //instanciating the renderer might fail - m_noNativeRendererSupported = true; - delete renderer; - renderer = 0; - } - } -#else - renderer = new VideoRendererDefault(m_widget); + if (type == Native) { + renderer = new VideoRendererVMR9(m_widget); if (renderer->getFilter() == 0) { - //instanciating the renderer might fail + //instanciating the renderer might fail with error VFW_E_DDRAW_CAPS_NOT_SUITABLE (0x80040273) m_noNativeRendererSupported = true; delete renderer; renderer = 0; } -#endif } if (renderer == 0) { diff --git a/src/3rdparty/phonon/ds9/volumeeffect.cpp b/src/3rdparty/phonon/ds9/volumeeffect.cpp index a93b074..b9a5fce 100644 --- a/src/3rdparty/phonon/ds9/volumeeffect.cpp +++ b/src/3rdparty/phonon/ds9/volumeeffect.cpp @@ -76,7 +76,7 @@ namespace Phonon class VolumeMemInputPin : public QMemInputPin { public: - VolumeMemInputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt, QPin *output) : QMemInputPin(parent, mt, true /*transform*/, output) + VolumeMemInputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt) : QMemInputPin(parent, mt, true /*transform*/) { } @@ -139,7 +139,8 @@ namespace Phonon //then creating the input mt << audioMediaType(); - m_input = new VolumeMemInputPin(this, mt, m_output); + m_input = new VolumeMemInputPin(this, mt); + m_input->addOutput(m_output); //make the connection here } void VolumeEffectFilter::treatOneSamplePerChannel(BYTE **buffer, int sampleSize, int channelCount, int frequency) diff --git a/src/3rdparty/phonon/ds9/volumeeffect.h b/src/3rdparty/phonon/ds9/volumeeffect.h index d1b0186..39b20d0 100644 --- a/src/3rdparty/phonon/ds9/volumeeffect.h +++ b/src/3rdparty/phonon/ds9/volumeeffect.h @@ -47,7 +47,7 @@ namespace Phonon private: float m_volume; - //paramaters used to fade + //parameters used to fade Phonon::VolumeFaderEffect::FadeCurve m_fadeCurve; bool m_fading; //determines if we should be fading. |