diff options
Diffstat (limited to 'src/3rdparty/phonon')
46 files changed, 670 insertions, 643 deletions
diff --git a/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp b/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp index e932e70..a9d0694 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 245749a..6ed0145 100644 --- a/src/3rdparty/phonon/ds9/backend.cpp +++ b/src/3rdparty/phonon/ds9/backend.cpp @@ -50,7 +50,7 @@ namespace Phonon Backend::Backend(QObject *parent, const QVariantList &) : QObject(parent) { - ::CoInitialize(0); + ::CoInitialize(0); //registering meta types qRegisterMetaType<HRESULT>("HRESULT"); @@ -61,7 +61,12 @@ namespace Phonon { m_audioOutputs.clear(); m_audioEffects.clear(); - ::CoUninitialize(); + ::CoUninitialize(); + } + + QMutex *Backend::directShowMutex() + { + return &qobject_cast<Backend*>(qt_plugin_instance())->m_directShowMutex; } QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args) @@ -131,6 +136,7 @@ namespace Phonon QList<int> Backend::objectDescriptionIndexes(Phonon::ObjectDescriptionType type) const { + QMutexLocker locker(&m_directShowMutex); QList<int> ret; switch(type) @@ -157,7 +163,7 @@ namespace Phonon while (S_OK == enumMon->Next(1, mon.pparam(), 0)) { LPOLESTR str = 0; mon->GetDisplayName(0,0,&str); - const QString name = QString::fromUtf16((unsigned short*)str); + const QString name = QString::fromWCharArray(str); ComPointer<IMalloc> alloc; ::CoGetMalloc(1, alloc.pparam()); alloc->Free(str); @@ -204,6 +210,7 @@ namespace Phonon QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(Phonon::ObjectDescriptionType type, int index) const { + QMutexLocker locker(&m_directShowMutex); QHash<QByteArray, QVariant> ret; switch (type) { @@ -216,7 +223,7 @@ namespace Phonon LPOLESTR str = 0; HRESULT hr = mon->GetDisplayName(0,0, &str); if (SUCCEEDED(hr)) { - QString name = QString::fromUtf16((unsigned short*)str); + QString name = QString::fromWCharArray(str); ComPointer<IMalloc> alloc; ::CoGetMalloc(1, alloc.pparam()); alloc->Free(str); @@ -231,7 +238,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::fromUtf16((unsigned short*)name); + ret["name"] = QString::fromWCharArray(name); } } break; diff --git a/src/3rdparty/phonon/ds9/backend.h b/src/3rdparty/phonon/ds9/backend.h index ad638f2..8b020c2 100644 --- a/src/3rdparty/phonon/ds9/backend.h +++ b/src/3rdparty/phonon/ds9/backend.h @@ -23,6 +23,7 @@ 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" @@ -63,6 +64,8 @@ namespace Phonon Filter getAudioOutputFilter(int index) const; + static QMutex *directShowMutex(); + Q_SIGNALS: void objectDescriptionChanged(ObjectDescriptionType); @@ -74,6 +77,7 @@ namespace Phonon }; mutable QVector<AudioMoniker> m_audioOutputs; mutable QVector<CLSID> m_audioEffects; + mutable QMutex m_directShowMutex; }; } } diff --git a/src/3rdparty/phonon/ds9/effect.cpp b/src/3rdparty/phonon/ds9/effect.cpp index dc4ac3d..ebe976b 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::fromUtf16((unsigned short*)current) ); + values.append( QString::fromWCharArray(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::fromUtf16((unsigned short*)name); + const QString n = QString::fromWCharArray(name); ret.append(Phonon::EffectParameter(i, n, hint, def, min, max, values)); ::CoTaskMemFree(name); //let's free the memory } @@ -138,8 +138,7 @@ namespace Phonon ComPointer<IMediaParams> params(filter, IID_IMediaParams); Q_ASSERT(params); - MP_DATA data = float(v.toDouble()); - params->SetParam(p.id(), data); + params->SetParam(p.id(), v.toFloat()); } } diff --git a/src/3rdparty/phonon/ds9/fakesource.cpp b/src/3rdparty/phonon/ds9/fakesource.cpp index 9a61a2e..4dce138 100644 --- a/src/3rdparty/phonon/ds9/fakesource.cpp +++ b/src/3rdparty/phonon/ds9/fakesource.cpp @@ -29,8 +29,10 @@ namespace Phonon namespace DS9 { static WAVEFORMATEX g_defaultWaveFormat = {WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0}; - 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}; + 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)}; class FakePin : public QPin { @@ -128,36 +130,12 @@ namespace Phonon void FakeSource::createFakeAudioPin() { - 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); + new FakePin(this, g_fakeAudioType); } void FakeSource::createFakeVideoPin() { - 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); + new FakePin(this, g_fakeVideoType); } } diff --git a/src/3rdparty/phonon/ds9/iodevicereader.cpp b/src/3rdparty/phonon/ds9/iodevicereader.cpp index ec10278..e0c505c 100644 --- a/src/3rdparty/phonon/ds9/iodevicereader.cpp +++ b/src/3rdparty/phonon/ds9/iodevicereader.cpp @@ -36,19 +36,10 @@ namespace Phonon //these mediatypes define a stream, its type will be autodetected by DirectShow static QVector<AM_MEDIA_TYPE> getMediaTypes() { - AM_MEDIA_TYPE mt; - mt.majortype = MEDIATYPE_Stream; - mt.bFixedSizeSamples = TRUE; - mt.bTemporalCompression = FALSE; - mt.lSampleSize = 1; - mt.formattype = GUID_NULL; - mt.pUnk = 0; - mt.cbFormat = 0; - mt.pbFormat = 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; @@ -72,7 +63,6 @@ namespace Phonon //for Phonon::StreamInterface void writeData(const QByteArray &data) { - QWriteLocker locker(&m_lock); m_pos += data.size(); m_buffer += data; } @@ -83,54 +73,22 @@ namespace Phonon void setStreamSize(qint64 newSize) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_size = newSize; } - qint64 streamSize() const - { - QReadLocker locker(&m_lock); - return m_size; - } - void setStreamSeekable(bool s) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); 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) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (total) { *total = m_size; } @@ -145,44 +103,42 @@ namespace Phonon HRESULT read(LONGLONG pos, LONG length, BYTE *buffer, LONG *actual) { - QMutexLocker locker(&m_mutexRead); - + Q_ASSERT(!m_mutex.tryLock()); if (m_mediaGraph->isStopping()) { return VFW_E_WRONG_STATE; } - if(streamSize() != 1 && pos + length > streamSize()) { + if(m_size != 1 && pos + length > m_size) { //it tries to read outside of the boundaries return E_FAIL; } - if (currentPos() - currentBufferSize() != pos) { - if (!streamSeekable()) { + if (m_pos - m_buffer.size() != pos) { + if (!m_seekable) { return S_FALSE; } - setCurrentPos(pos); + m_pos = pos; + seekStream(pos); + m_buffer.clear(); } - int oldSize = currentBufferSize(); - while (currentBufferSize() < int(length)) { + int oldSize = m_buffer.size(); + while (m_buffer.size() < int(length)) { needData(); if (m_mediaGraph->isStopping()) { return VFW_E_WRONG_STATE; } - if (oldSize == currentBufferSize()) { + if (oldSize == m_buffer.size()) { break; //we didn't get any data } - oldSize = currentBufferSize(); + oldSize = m_buffer.size(); } - 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); - } + int bytesRead = qMin(m_buffer.size(), int(length)); + qMemCopy(buffer, m_buffer.data(), bytesRead); + //truncate the buffer + m_buffer = m_buffer.mid(bytesRead); if (actual) { *actual = bytesRead; //initialization @@ -198,7 +154,6 @@ namespace Phonon qint64 m_pos; qint64 m_size; - QMutex m_mutexRead; const MediaGraph *m_mediaGraph; }; @@ -212,14 +167,6 @@ 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 af4b271..c8b91c3 100644 --- a/src/3rdparty/phonon/ds9/iodevicereader.h +++ b/src/3rdparty/phonon/ds9/iodevicereader.h @@ -41,7 +41,6 @@ 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 31a0622..a467dd7 100644 --- a/src/3rdparty/phonon/ds9/mediagraph.cpp +++ b/src/3rdparty/phonon/ds9/mediagraph.cpp @@ -68,6 +68,8 @@ namespace Phonon return ret; } + +/* static HRESULT saveToFile(Graph graph, const QString &filepath) { const WCHAR wszStreamName[] = L"ActiveMovieGraph"; @@ -103,7 +105,7 @@ namespace Phonon return hr; } - +*/ MediaGraph::MediaGraph(MediaObject *mo, short index) : m_graph(CLSID_FilterGraph, IID_IGraphBuilder), @@ -381,7 +383,8 @@ namespace Phonon #endif if (info.pGraph) { info.pGraph->Release(); - return m_graph->RemoveFilter(filter); + if (info.pGraph == m_graph) + return m_graph->RemoveFilter(filter); } //already removed @@ -537,7 +540,7 @@ 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 (VFW_E_NOT_CONNECTED == pin->ConnectedTo(inPin.pparam())) { + if (HRESULT(VFW_E_NOT_CONNECTED) == pin->ConnectedTo(inPin.pparam())) { return SUCCEEDED(pin->Connect(newIn, 0)); } } @@ -679,7 +682,6 @@ 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 { @@ -809,7 +811,7 @@ namespace Phonon for (int i = 0; i < outputs.count(); ++i) { const OutputPin &out = outputs.at(i); InputPin pin; - if (out->ConnectedTo(pin.pparam()) == VFW_E_NOT_CONNECTED) { + if (out->ConnectedTo(pin.pparam()) == HRESULT(VFW_E_NOT_CONNECTED)) { m_decoderPins += out; //unconnected outputs can be decoded outputs } } @@ -1006,27 +1008,27 @@ namespace Phonon BSTR str; HRESULT hr = mediaContent->get_AuthorName(&str); if (SUCCEEDED(hr)) { - ret.insert(QLatin1String("ARTIST"), QString::fromUtf16((const unsigned short*)str)); + ret.insert(QLatin1String("ARTIST"), QString::fromWCharArray(str)); SysFreeString(str); } hr = mediaContent->get_Title(&str); if (SUCCEEDED(hr)) { - ret.insert(QLatin1String("TITLE"), QString::fromUtf16((const unsigned short*)str)); + ret.insert(QLatin1String("TITLE"), QString::fromWCharArray(str)); SysFreeString(str); } hr = mediaContent->get_Description(&str); if (SUCCEEDED(hr)) { - ret.insert(QLatin1String("DESCRIPTION"), QString::fromUtf16((const unsigned short*)str)); + ret.insert(QLatin1String("DESCRIPTION"), QString::fromWCharArray(str)); SysFreeString(str); } hr = mediaContent->get_Copyright(&str); if (SUCCEEDED(hr)) { - ret.insert(QLatin1String("COPYRIGHT"), QString::fromUtf16((const unsigned short*)str)); + ret.insert(QLatin1String("COPYRIGHT"), QString::fromWCharArray(str)); SysFreeString(str); } hr = mediaContent->get_MoreInfoText(&str); if (SUCCEEDED(hr)) { - ret.insert(QLatin1String("MOREINFO"), QString::fromUtf16((const unsigned short*)str)); + ret.insert(QLatin1String("MOREINFO"), QString::fromWCharArray(str)); SysFreeString(str); } } diff --git a/src/3rdparty/phonon/ds9/mediaobject.cpp b/src/3rdparty/phonon/ds9/mediaobject.cpp index f7fd6ae..250b94a 100644 --- a/src/3rdparty/phonon/ds9/mediaobject.cpp +++ b/src/3rdparty/phonon/ds9/mediaobject.cpp @@ -23,7 +23,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #ifndef Q_CC_MSVC #include <dshow.h> -#endif //Q_CC_MSVC +#endif #include <objbase.h> #include <initguid.h> #include <qnetwork.h> @@ -36,7 +36,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include <QtCore/QDebug> -#define TIMER_INTERVAL 16 //... ms for the timer that polls the current state (we use the multimedia timer +#define TIMER_INTERVAL 16 //... ms for the timer that polls the current state (we use the multimedia timer) #define PRELOAD_TIME 2000 // 2 seconds to load a source QT_BEGIN_NAMESPACE @@ -49,7 +49,7 @@ namespace Phonon //first the definition of the WorkerThread class WorkerThread::WorkerThread() - : QThread(), m_currentRenderId(0), m_finished(false), m_currentWorkId(1) + : QThread(), m_finished(false), m_currentWorkId(1) { } @@ -157,6 +157,7 @@ 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(); @@ -176,33 +177,29 @@ namespace Phonon void WorkerThread::handleTask() { - QMutexLocker locker(&m_mutex); - if (m_finished || m_queue.isEmpty()) { - return; - } + QMutexLocker locker(Backend::directShowMutex()); + { + QMutexLocker locker(&m_mutex); + if (m_finished || m_queue.isEmpty()) { + return; + } - const Work w = m_queue.dequeue(); + m_currentWork = 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(); + //we ensure to have the wait condition in the right state + if (m_queue.isEmpty()) { + m_waitCondition.reset(); + } else { + m_waitCondition.set(); + } } HRESULT hr = S_OK; - { - QMutexLocker locker(&m_currentMutex); - m_currentRender = w.graph; - m_currentRenderId = w.id; - } - if (w.task == ReplaceGraph) { - HANDLE h; - + if (m_currentWork.task == ReplaceGraph) { int index = -1; for(int i = 0; i < FILTER_COUNT; ++i) { - if (m_graphHandle[i].graph == w.oldGraph) { + if (m_graphHandle[i].graph == m_currentWork.oldGraph) { m_graphHandle[i].graph = Graph(); index = i; break; @@ -215,51 +212,40 @@ namespace Phonon Q_ASSERT(index != -1); //add the new graph - if (SUCCEEDED(ComPointer<IMediaEvent>(w.graph, IID_IMediaEvent) + HANDLE h; + if (SUCCEEDED(ComPointer<IMediaEvent>(m_currentWork.graph, IID_IMediaEvent) ->GetEventHandle(reinterpret_cast<OAEVENT*>(&h)))) { - m_graphHandle[index].graph = w.graph; + m_graphHandle[index].graph = m_currentWork.graph; m_graphHandle[index].handle = h; } - } else if (w.task == Render) { - if (w.filter) { + } else if (m_currentWork.task == Render) { + if (m_currentWork.filter) { //let's render pins - w.graph->AddFilter(w.filter, 0); - const QList<OutputPin> outputs = BackendNode::pins(w.filter, PINDIR_OUTPUT); - for (int i = 0; i < outputs.count(); ++i) { - //blocking call - hr = w.graph->Render(outputs.at(i)); - if (FAILED(hr)) { - break; - } + 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)); } - } else if (!w.url.isEmpty()) { + } else if (!m_currentWork.url.isEmpty()) { //let's render a url (blocking call) - hr = w.graph->RenderFile(reinterpret_cast<const wchar_t *>(w.url.utf16()), 0); + hr = m_currentWork.graph->RenderFile(reinterpret_cast<const wchar_t *>(m_currentWork.url.utf16()), 0); } if (hr != E_ABORT) { - emit asyncRenderFinished(w.id, hr, w.graph); + emit asyncRenderFinished(m_currentWork.id, hr, m_currentWork.graph); } - } else if (w.task == Seek) { + } else if (m_currentWork.task == Seek) { //that's a seekrequest - ComPointer<IMediaSeeking> mediaSeeking(w.graph, IID_IMediaSeeking); - qint64 newtime = w.time * 10000; + ComPointer<IMediaSeeking> mediaSeeking(m_currentWork.graph, IID_IMediaSeeking); + qint64 newtime = m_currentWork.time * 10000; hr = mediaSeeking->SetPositions(&newtime, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning); - 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 (w.task == ChangeState) { + emit asyncSeekingFinished(m_currentWork.id, newtime / 10000); + hr = E_ABORT; //to avoid emitting asyncRenderFinished + } else if (m_currentWork.task == ChangeState) { //remove useless decoders QList<Filter> unused; - for (int i = 0; i < w.decoders.count(); ++i) { - const Filter &filter = w.decoders.at(i); + for (int i = 0; i < m_currentWork.decoders.count(); ++i) { + const Filter &filter = m_currentWork.decoders.at(i); bool used = false; const QList<OutputPin> pins = BackendNode::pins(filter, PINDIR_OUTPUT); for( int i = 0; i < pins.count(); ++i) { @@ -276,15 +262,15 @@ namespace Phonon //we can get the state for (int i = 0; i < unused.count(); ++i) { //we should remove this filter from the graph - w.graph->RemoveFilter(unused.at(i)); + m_currentWork.graph->RemoveFilter(unused.at(i)); } //we can get the state - ComPointer<IMediaControl> mc(w.graph, IID_IMediaControl); + ComPointer<IMediaControl> mc(m_currentWork.graph, IID_IMediaControl); //we change the state here - switch(w.state) + switch(m_currentWork.state) { case State_Stopped: mc->Stop(); @@ -302,34 +288,28 @@ namespace Phonon if (SUCCEEDED(hr)) { if (s == State_Stopped) { - emit stateReady(w.graph, Phonon::StoppedState); + emit stateReady(m_currentWork.graph, Phonon::StoppedState); } else if (s == State_Paused) { - emit stateReady(w.graph, Phonon::PausedState); + emit stateReady(m_currentWork.graph, Phonon::PausedState); } else /*if (s == State_Running)*/ { - emit stateReady(w.graph, Phonon::PlayingState); + emit stateReady(m_currentWork.graph, Phonon::PlayingState); } } } { - QMutexLocker locker(&m_currentMutex); - m_currentRender = Graph(); - m_currentRenderId = 0; + QMutexLocker locker(&m_mutex); + m_currentWork = Work(); //reinitialize } } void WorkerThread::abortCurrentRender(qint16 renderId) { - { - QMutexLocker locker(&m_currentMutex); - if (m_currentRender && m_currentRenderId == renderId) { - m_currentRender->Abort(); - } - } - 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) { @@ -347,9 +327,9 @@ namespace Phonon { QMutexLocker locker(&m_mutex); m_queue.clear(); - if (m_currentRender) { + if (m_currentWork.graph) { //in case we're currently rendering something - m_currentRender->Abort(); + m_currentWork.graph->Abort(); } @@ -378,13 +358,13 @@ namespace Phonon { for(int i = 0; i < FILTER_COUNT; ++i) { - m_graphs[i] = new MediaGraph(this, i); + m_graphs[i] = new MediaGraph(this, i); } - connect(&m_thread, SIGNAL(stateReady(Graph, Phonon::State)), + connect(&m_thread, SIGNAL(stateReady(Graph, Phonon::State)), SLOT(slotStateReady(Graph, Phonon::State))); - connect(&m_thread, SIGNAL(eventReady(Graph, long, long)), + connect(&m_thread, SIGNAL(eventReady(Graph, long, long)), SLOT(handleEvents(Graph, long, long))); connect(&m_thread, SIGNAL(asyncRenderFinished(quint16, HRESULT, Graph)), @@ -479,7 +459,7 @@ namespace Phonon } if (!m_aboutToFinishSent && remaining < PRELOAD_TIME - m_transitionTime + TIMER_INTERVAL/2) { - //let's take a 2 seconds time time to actually load the next file + //let's take a 2 seconds time to actually load the next file #ifdef GRAPH_DEBUG qDebug() << "DS9: emit aboutToFinish" << remaining << QTime::currentTime().toString(); #endif @@ -514,6 +494,9 @@ 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); @@ -568,7 +551,7 @@ namespace Phonon { #ifndef QT_NO_PHONON_MEDIACONTROLLER //1st, check if there is more titles after - const qint64 ret = (m_currentTitle < _iface_availableTitles() - 1) ? + const qint64 ret = (m_currentTitle < _iface_availableTitles() - 1) ? titleAbsolutePosition(m_currentTitle+1) : currentGraph()->absoluteTotalTime(); //this is the duration of the current title @@ -581,7 +564,7 @@ namespace Phonon qint64 MediaObject::currentTime() const { //this handles inaccuracy when stopping on a title - return currentGraph()->absoluteCurrentTime() + return currentGraph()->absoluteCurrentTime() #ifndef QT_NO_PHONON_MEDIACONTROLLER - titleAbsolutePosition(m_currentTitle) #endif //QT_NO_PHONON_MEDIACONTROLLER @@ -731,7 +714,7 @@ namespace Phonon m_oldHasVideo = currentGraph()->hasVideo(); setState(Phonon::LoadingState); //After loading we go into stopped state - m_nextState = Phonon::StoppedState; + m_nextState = Phonon::StoppedState; catchComError(currentGraph()->loadSource(source)); emit currentSourceChanged(source); } @@ -745,7 +728,7 @@ namespace Phonon void MediaObject::loadingFinished(MediaGraph *mg) { - if (mg == currentGraph()) { + if (mg == currentGraph()) { #ifndef QT_NO_PHONON_MEDIACONTROLLER //Title interface m_currentTitle = 0; @@ -777,15 +760,16 @@ 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; } } } @@ -802,7 +786,7 @@ namespace Phonon void MediaObject::seekingFinished(MediaGraph *mg) { - if (mg == currentGraph()) { + if (mg == currentGraph()) { updateTargetTick(); if (currentTime() < totalTime() - m_prefinishMark) { @@ -833,9 +817,9 @@ namespace Phonon #endif LPAMGETERRORTEXT getErrorText = (LPAMGETERRORTEXT)QLibrary::resolve(QLatin1String("quartz"), "AMGetErrorTextW"); - ushort buffer[MAX_ERROR_TEXT_LEN]; - if (getErrorText && getErrorText(hr, (WCHAR*)buffer, MAX_ERROR_TEXT_LEN)) { - m_errorString = QString::fromUtf16(buffer); + WCHAR buffer[MAX_ERROR_TEXT_LEN]; + if (getErrorText && getErrorText(hr, buffer, MAX_ERROR_TEXT_LEN)) { + m_errorString = QString::fromWCharArray(buffer); } else { m_errorString = QString::fromLatin1("Unknown error"); } @@ -877,7 +861,7 @@ namespace Phonon #ifndef QT_NO_PHONON_VIDEO if (VideoWidget *video = qobject_cast<VideoWidget*>(sink)) { m_videoWidgets += video; - } else + } else #endif //QT_NO_PHONON_VIDEO if (AudioOutput *audio = qobject_cast<AudioOutput*>(sink)) { m_audioOutputs += audio; @@ -896,7 +880,7 @@ namespace Phonon #ifndef QT_NO_PHONON_VIDEO if (VideoWidget *video = qobject_cast<VideoWidget*>(sink)) { m_videoWidgets.removeOne(video); - } else + } else #endif //QT_NO_PHONON_VIDEO if (AudioOutput *audio = qobject_cast<AudioOutput*>(sink)) { m_audioOutputs.removeOne(audio); @@ -978,7 +962,7 @@ namespace Phonon emit stateChanged(state(), m_state); } break; - case EC_LENGTH_CHANGED: + case EC_LENGTH_CHANGED: if (graph == currentGraph()->graph()) { emit totalTimeChanged( totalTime() ); } diff --git a/src/3rdparty/phonon/ds9/mediaobject.h b/src/3rdparty/phonon/ds9/mediaobject.h index a6beb5f..34aa666 100644 --- a/src/3rdparty/phonon/ds9/mediaobject.h +++ b/src/3rdparty/phonon/ds9/mediaobject.h @@ -114,6 +114,7 @@ namespace Phonon enum Task { + None, Render, Seek, ChangeState, @@ -122,6 +123,7 @@ namespace Phonon struct Work { + Work() : task(None), id(0), time(0) { } Task task; quint16 id; Graph graph; @@ -137,14 +139,12 @@ namespace Phonon }; void handleTask(); - Graph m_currentRender; - qint16 m_currentRenderId; + Work m_currentWork; 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_currentMutex; //mutex for current renderer and id //this is for WaitForMultipleObjects struct diff --git a/src/3rdparty/phonon/ds9/qasyncreader.cpp b/src/3rdparty/phonon/ds9/qasyncreader.cpp index 68ec1f8..a3f9cda 100644 --- a/src/3rdparty/phonon/ds9/qasyncreader.cpp +++ b/src/3rdparty/phonon/ds9/qasyncreader.cpp @@ -15,8 +15,6 @@ 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" @@ -80,8 +78,7 @@ namespace Phonon STDMETHODIMP QAsyncReader::Request(IMediaSample *sample,DWORD_PTR user) { - QMutexLocker mutexLocker(&m_mutexWait); - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (m_flushing) { return VFW_E_WRONG_STATE; } @@ -93,33 +90,28 @@ namespace Phonon STDMETHODIMP QAsyncReader::WaitForNext(DWORD timeout, IMediaSample **sample, DWORD_PTR *user) { - QMutexLocker locker(&m_mutexWait); + QMutexLocker locker(&m_mutex); if (!sample ||!user) { return E_POINTER; } + //msdn says to return immediately if we're flushing but that doesn't seem to be true + //since it triggers a dead-lock somewhere inside directshow (see task 258830) + *sample = 0; *user = 0; - AsyncRequest r = getNextRequest(); - - if (r.sample == 0) { - //there is no request in the queue - if (isFlushing()) { + if (m_requestQueue.isEmpty()) { + if (m_requestWait.wait(&m_mutex, timeout) == false) { + return VFW_E_TIMEOUT; + } + if (m_requestQueue.isEmpty()) { return VFW_E_WRONG_STATE; - } 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; @@ -127,14 +119,12 @@ namespace Phonon *sample = r.sample; *user = r.user; - - return SyncReadAligned(r.sample); + return syncReadAlignedUnlocked(r.sample); } STDMETHODIMP QAsyncReader::BeginFlush() { - QMutexLocker mutexLocker(&m_mutexWait); - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_flushing = true; m_requestWait.wakeOne(); return S_OK; @@ -142,13 +132,28 @@ namespace Phonon STDMETHODIMP QAsyncReader::EndFlush() { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_flushing = false; return S_OK; } STDMETHODIMP QAsyncReader::SyncReadAligned(IMediaSample *sample) { + QMutexLocker locker(&m_mutex); + return syncReadAlignedUnlocked(sample); + } + + STDMETHODIMP QAsyncReader::SyncRead(LONGLONG pos, LONG length, BYTE *buffer) + { + QMutexLocker locker(&m_mutex); + return read(pos, length, buffer, 0); + } + + + STDMETHODIMP QAsyncReader::syncReadAlignedUnlocked(IMediaSample *sample) + { + Q_ASSERT(!m_mutex.tryLock()); + if (!sample) { return E_POINTER; } @@ -175,23 +180,6 @@ 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 cb789ee..95872f9 100644 --- a/src/3rdparty/phonon/ds9/qasyncreader.h +++ b/src/3rdparty/phonon/ds9/qasyncreader.h @@ -48,11 +48,12 @@ namespace Phonon STDMETHODIMP WaitForNext(DWORD,IMediaSample **,DWORD_PTR *); STDMETHODIMP SyncReadAligned(IMediaSample *); STDMETHODIMP SyncRead(LONGLONG,LONG,BYTE *); - virtual STDMETHODIMP Length(LONGLONG *,LONGLONG *) = 0; + 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: @@ -62,9 +63,6 @@ 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 b9f9fd6..6d0f335 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,19 +112,8 @@ namespace Phonon #define SECTOR_SIZE 2352 #define NB_SECTORS_READ 20 - 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; - } - + static const AM_MEDIA_TYPE audioCDMediaType = { MEDIATYPE_Stream, MEDIASUBTYPE_WAVE, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0}; + int addressToSectors(UCHAR address[4]) { return ((address[0] * 60 + address[1]) * 60 + address[2]) * 75 + address[3] - 150; @@ -141,11 +130,8 @@ namespace Phonon } - QAudioCDReader::QAudioCDReader(QBaseFilter *parent, QChar drive) : QAsyncReader(parent, QVector<AM_MEDIA_TYPE>() << getAudioCDMediaType()) + QAudioCDReader::QAudioCDReader(QBaseFilter *parent, QChar drive) : QAsyncReader(parent, QVector<AM_MEDIA_TYPE>() << audioCDMediaType) { - m_toc = new CDROM_TOC; - m_waveHeader = new WaveStructure; - //now open the cd-drive QString path; if (drive.isNull()) { @@ -154,36 +140,30 @@ namespace Phonon path = QString::fromLatin1("\\\\.\\%1:").arg(drive); } - 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 ) - ); + m_cddrive = ::CreateFile((const wchar_t *)path.utf16(), 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() @@ -199,7 +179,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; } @@ -238,11 +218,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) { @@ -297,8 +277,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/qbasefilter.cpp b/src/3rdparty/phonon/ds9/qbasefilter.cpp index 95cab92..78b8b8f 100644 --- a/src/3rdparty/phonon/ds9/qbasefilter.cpp +++ b/src/3rdparty/phonon/ds9/qbasefilter.cpp @@ -92,8 +92,8 @@ namespace Phonon return E_POINTER; } - int nbfetched = 0; - while (nbfetched < int(count) && m_index < m_pins.count()) { + uint nbfetched = 0; + while (nbfetched < 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 { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); return m_pins; } void QBaseFilter::addPin(QPin *pin) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_pins.append(pin); } void QBaseFilter::removePin(QPin *pin) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_pins.removeAll(pin); } @@ -211,7 +211,8 @@ namespace Phonon } else if (iid == IID_IMediaPosition || iid == IID_IMediaSeeking) { if (inputPins().isEmpty()) { - if (*out = getUpStreamInterface(iid)) { + *out = getUpStreamInterface(iid); + if (*out) { return S_OK; //we return here to avoid adding a reference } else { hr = E_NOINTERFACE; @@ -250,35 +251,35 @@ namespace Phonon STDMETHODIMP QBaseFilter::GetClassID(CLSID *clsid) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); *clsid = m_clsid; return S_OK; } STDMETHODIMP QBaseFilter::Stop() { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_state = State_Stopped; return S_OK; } STDMETHODIMP QBaseFilter::Pause() { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_state = State_Paused; return S_OK; } STDMETHODIMP QBaseFilter::Run(REFERENCE_TIME) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_state = State_Running; return S_OK; } STDMETHODIMP QBaseFilter::GetState(DWORD, FILTER_STATE *state) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (!state) { return E_POINTER; } @@ -289,7 +290,7 @@ namespace Phonon STDMETHODIMP QBaseFilter::SetSyncSource(IReferenceClock *clock) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (clock) { clock->AddRef(); } @@ -302,7 +303,7 @@ namespace Phonon STDMETHODIMP QBaseFilter::GetSyncSource(IReferenceClock **clock) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (!clock) { return E_POINTER; } @@ -341,7 +342,7 @@ namespace Phonon STDMETHODIMP QBaseFilter::QueryFilterInfo(FILTER_INFO *info ) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (!info) { return E_POINTER; } @@ -355,9 +356,9 @@ namespace Phonon STDMETHODIMP QBaseFilter::JoinFilterGraph(IFilterGraph *graph, LPCWSTR name) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_graph = graph; - m_name = QString::fromUtf16((const unsigned short*)name); + m_name = QString::fromWCharArray(name); return S_OK; } diff --git a/src/3rdparty/phonon/ds9/qbasefilter.h b/src/3rdparty/phonon/ds9/qbasefilter.h index 85f1431..a72d6fe 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/QReadWriteLock> +#include <QtCore/QMutex> #include <dshow.h> @@ -127,7 +127,7 @@ namespace Phonon IFilterGraph *m_graph; FILTER_STATE m_state; QList<QPin *> m_pins; - mutable QReadWriteLock m_lock; + mutable QMutex m_mutex; }; } } diff --git a/src/3rdparty/phonon/ds9/qmeminputpin.cpp b/src/3rdparty/phonon/ds9/qmeminputpin.cpp index 0af1bfd..a21fbe7 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(parent, PINDIR_INPUT, mt), m_shouldDuplicateSamples(true), m_transform(transform) + 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) { } @@ -66,11 +66,9 @@ namespace Phonon { //this allows to serialize with Receive calls QMutexLocker locker(&m_mutexReceive); - for(int i = 0; i < m_outputs.count(); ++i) { - IPin *conn = m_outputs.at(i)->connected(); - if (conn) { - conn->EndOfStream(); - } + IPin *conn = m_output ? m_output->connected() : 0; + if (conn) { + conn->EndOfStream(); } return S_OK; } @@ -78,13 +76,11 @@ namespace Phonon STDMETHODIMP QMemInputPin::BeginFlush() { //pass downstream - for(int i = 0; i < m_outputs.count(); ++i) { - IPin *conn = m_outputs.at(i)->connected(); - if (conn) { - conn->BeginFlush(); - } + IPin *conn = m_output ? m_output->connected() : 0; + if (conn) { + conn->BeginFlush(); } - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_flushing = true; return S_OK; } @@ -92,22 +88,19 @@ namespace Phonon STDMETHODIMP QMemInputPin::EndFlush() { //pass downstream - for(int i = 0; i < m_outputs.count(); ++i) { - IPin *conn = m_outputs.at(i)->connected(); - if (conn) { - conn->EndFlush(); - } + IPin *conn = m_output ? m_output->connected() : 0; + if (conn) { + conn->EndFlush(); } - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_flushing = false; return S_OK; } STDMETHODIMP QMemInputPin::NewSegment(REFERENCE_TIME start, REFERENCE_TIME stop, double rate) { - for(int i = 0; i < m_outputs.count(); ++i) { - m_outputs.at(i)->NewSegment(start, stop, rate); - } + if (m_output) + m_output->NewSegment(start, stop, rate); return S_OK; } @@ -119,14 +112,9 @@ namespace Phonon if (hr == S_OK && mt->majortype != MEDIATYPE_NULL && mt->subtype != MEDIASUBTYPE_NULL && - 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; - } - } + mt->formattype != GUID_NULL && m_output) { + //we tell the output pin that it should connect with this type + hr = m_output->setAcceptedMediaType(connectedType()); } return hr; } @@ -137,7 +125,8 @@ namespace Phonon return E_POINTER; } - if (*alloc = memoryAllocator(true)) { + *alloc = memoryAllocator(true); + if (*alloc) { return S_OK; } @@ -151,18 +140,15 @@ namespace Phonon } { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_shouldDuplicateSamples = m_transform && readonly; } setMemoryAllocator(alloc); - 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); - } + if (m_output) { + ComPointer<IMemInputPin> input(m_output, IID_IMemInputPin); + input->NotifyAllocator(alloc, m_shouldDuplicateSamples); } return S_OK; @@ -201,22 +187,18 @@ namespace Phonon } } - for (int i = 0; i < m_outputs.count(); ++i) { - QPin *current = m_outputs.at(i); - IMediaSample *outSample = m_shouldDuplicateSamples ? - duplicateSampleForOutput(sample, current->memoryAllocator()) + if (m_output) { + IMediaSample *outSample = m_shouldDuplicateSamples ? + duplicateSampleForOutput(sample, m_output->memoryAllocator()) : sample; if (m_shouldDuplicateSamples) { m_parent->processSample(outSample); } - IPin *pin = current->connected(); - if (pin) { - ComPointer<IMemInputPin> input(pin, IID_IMemInputPin); - if (input) { - input->Receive(outSample); - } + ComPointer<IMemInputPin> input(m_output->connected(), IID_IMemInputPin); + if (input) { + input->Receive(outSample); } if (m_shouldDuplicateSamples) { @@ -247,39 +229,16 @@ namespace Phonon STDMETHODIMP QMemInputPin::ReceiveCanBlock() { - //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; - } + //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; } } return S_FALSE; } - //addition - //this should be used by the filter to tell it's 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 { @@ -294,7 +253,7 @@ namespace Phonon LONG length = sample->GetActualDataLength(); HRESULT hr = alloc->Commit(); - if (hr == VFW_E_SIZENOTSET) { + if (hr == HRESULT(VFW_E_SIZENOTSET)) { ALLOCATOR_PROPERTIES prop = getDefaultAllocatorProperties(); prop.cbBuffer = qMax(prop.cbBuffer, length); ALLOCATOR_PROPERTIES actual; @@ -324,7 +283,7 @@ namespace Phonon { LONGLONG start, end; hr = sample->GetMediaTime(&start, &end); - if (hr != VFW_E_MEDIA_TIME_NOT_SET) { + if (hr != HRESULT(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 c449721..d74c451 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); + QMemInputPin(QBaseFilter *, const QVector<AM_MEDIA_TYPE> &, bool transform, QPin *output); ~QMemInputPin(); //reimplementation from IUnknown @@ -60,18 +60,13 @@ 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 - QList<QPin*> m_outputs; + QPin* const m_output; QMutex m_mutexReceive; }; } diff --git a/src/3rdparty/phonon/ds9/qpin.cpp b/src/3rdparty/phonon/ds9/qpin.cpp index f652502..b4afd10 100644 --- a/src/3rdparty/phonon/ds9/qpin.cpp +++ b/src/3rdparty/phonon/ds9/qpin.cpp @@ -28,20 +28,7 @@ namespace Phonon namespace DS9 { - 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; - } + static const AM_MEDIA_TYPE defaultMediaType = { MEDIATYPE_NULL, MEDIASUBTYPE_NULL, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0}; class QEnumMediaTypes : public IEnumMediaTypes { @@ -104,8 +91,8 @@ namespace Phonon return E_INVALIDARG; } - int nbFetched = 0; - while (nbFetched < int(count) && m_index < m_pin->mediaTypes().count()) { + uint nbFetched = 0; + while (nbFetched < 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); @@ -158,9 +145,9 @@ namespace Phonon QPin::QPin(QBaseFilter *parent, PIN_DIRECTION dir, const QVector<AM_MEDIA_TYPE> &mt) : - m_memAlloc(0), m_parent(parent), m_refCount(1), m_connected(0), - m_direction(dir), m_mediaTypes(mt), m_connectedType(defaultMediaType()), - m_flushing(false) + m_parent(parent), m_flushing(false), m_refCount(1), m_connected(0), + m_direction(dir), m_mediaTypes(mt), m_connectedType(defaultMediaType), + m_memAlloc(0) { Q_ASSERT(m_parent); m_parent->addPin(this); @@ -273,7 +260,7 @@ namespace Phonon if (FAILED(hr)) { setConnected(0); - setConnectedType(defaultMediaType()); + setConnectedType(defaultMediaType); } else { ComPointer<IMemInputPin> input(pin, IID_IMemInputPin); if (input) { @@ -315,10 +302,8 @@ namespace Phonon } setConnected(0); - setConnectedType(defaultMediaType()); - if (m_direction == PINDIR_INPUT) { - setMemoryAllocator(0); - } + setConnectedType(defaultMediaType); + setMemoryAllocator(0); return S_OK; } @@ -338,7 +323,7 @@ namespace Phonon STDMETHODIMP QPin::ConnectionMediaType(AM_MEDIA_TYPE *type) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (!type) { return E_POINTER; } @@ -353,7 +338,6 @@ namespace Phonon STDMETHODIMP QPin::QueryPinInfo(PIN_INFO *info) { - QReadLocker locker(&m_lock); if (!info) { return E_POINTER; } @@ -361,14 +345,12 @@ namespace Phonon info->dir = m_direction; info->pFilter = m_parent; m_parent->AddRef(); - qMemCopy(info->achName, m_name.utf16(), qMin(MAX_FILTER_NAME, m_name.length()+1) *2); - + info->achName[0] = 0; return S_OK; } STDMETHODIMP QPin::QueryDirection(PIN_DIRECTION *dir) { - QReadLocker locker(&m_lock); if (!dir) { return E_POINTER; } @@ -379,20 +361,18 @@ namespace Phonon STDMETHODIMP QPin::QueryId(LPWSTR *id) { - QReadLocker locker(&m_lock); if (!id) { return E_POINTER; } - int nbBytes = (m_name.length()+1)*2; - *id = static_cast<LPWSTR>(::CoTaskMemAlloc(nbBytes)); - qMemCopy(*id, m_name.utf16(), nbBytes); + *id = static_cast<LPWSTR>(::CoTaskMemAlloc(2)); + *id[0] = 0; return S_OK; } STDMETHODIMP QPin::QueryAccept(const AM_MEDIA_TYPE *type) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (!type) { return E_POINTER; } @@ -439,7 +419,7 @@ namespace Phonon STDMETHODIMP QPin::NewSegment(REFERENCE_TIME start, REFERENCE_TIME stop, double rate) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (m_direction == PINDIR_OUTPUT && m_connected) { //we deliver this downstream m_connected->NewSegment(start, stop, rate); @@ -470,7 +450,7 @@ namespace Phonon freeMediaType(type); return S_OK; } else { - setConnectedType(defaultMediaType()); + setConnectedType(defaultMediaType); freeMediaType(type); } } @@ -520,7 +500,7 @@ namespace Phonon void QPin::setConnectedType(const AM_MEDIA_TYPE &type) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); //1st we free memory freeMediaType(m_connectedType); @@ -530,13 +510,13 @@ namespace Phonon const AM_MEDIA_TYPE &QPin::connectedType() const { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); return m_connectedType; } void QPin::setConnected(IPin *pin) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (pin) { pin->AddRef(); } @@ -548,7 +528,7 @@ namespace Phonon IPin *QPin::connected(bool addref) const { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (addref && m_connected) { m_connected->AddRef(); } @@ -557,13 +537,12 @@ namespace Phonon bool QPin::isFlushing() const { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); return m_flushing; } FILTER_STATE QPin::filterState() const { - QReadLocker locker(&m_lock); FILTER_STATE fstate = State_Stopped; m_parent->GetState(0, &fstate); return fstate; @@ -571,7 +550,7 @@ namespace Phonon QVector<AM_MEDIA_TYPE> QPin::mediaTypes() const { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); return m_mediaTypes; } @@ -607,7 +586,7 @@ namespace Phonon void QPin::setMemoryAllocator(IMemAllocator *alloc) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (alloc) { alloc->AddRef(); } @@ -619,7 +598,7 @@ namespace Phonon IMemAllocator *QPin::memoryAllocator(bool addref) const { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (addref && m_memAlloc) { m_memAlloc->AddRef(); } diff --git a/src/3rdparty/phonon/ds9/qpin.h b/src/3rdparty/phonon/ds9/qpin.h index a3287c4..280ad61 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/QReadWriteLock> +#include <QtCore/QMutex> #include <dshow.h> @@ -85,8 +85,8 @@ namespace Phonon protected: //this can be used by sub-classes - mutable QReadWriteLock m_lock; - QBaseFilter *m_parent; + mutable QMutex m_mutex; + QBaseFilter * const m_parent; bool m_flushing; private: @@ -98,7 +98,6 @@ 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_soft.cpp b/src/3rdparty/phonon/ds9/videorenderer_soft.cpp index dd6e076..82d6235 100644 --- a/src/3rdparty/phonon/ds9/videorenderer_soft.cpp +++ b/src/3rdparty/phonon/ds9/videorenderer_soft.cpp @@ -63,9 +63,9 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. static const char yv12ToRgb[] = "!!ARBfp1.0" "PARAM c[5] = { program.local[0..1]," -" { 1.164, 0, 1.596, 0.5 }," -" { 0.0625, 1.164, -0.391, -0.81300002 }," -" { 1.164, 2.0179999, 0 } };" +"{ 1.164, 0, 1.596, 0.5 }," +"{ 0.0625, 1.164, -0.391, -0.81300002 }," +"{ 1.164, 2.0179999, 0 } };" "TEMP R0;" "TEX R0.x, fragment.texcoord[0], texture[1], 2D;" "ADD R0.y, R0.x, -c[2].w;" @@ -89,11 +89,11 @@ static const char yv12ToRgb[] = "END"; static const char yuy2ToRgb[] = - "!!ARBfp1.0" +"!!ARBfp1.0" "PARAM c[5] = { program.local[0..1]," -" { 0.5, 2, 1, 0.0625 }," -" { 1.164, 0, 1.596, 2.0179999 }," -" { 1.164, -0.391, -0.81300002 } };" +"{ 0.5, 2, 1, 0.0625 }," +"{ 1.164, 0, 1.596, 2.0179999 }," +"{ 1.164, -0.391, -0.81300002 } };" "TEMP R0;" "TEMP R1;" "TEMP R2;" @@ -149,24 +149,16 @@ namespace Phonon { static const QVector<AM_MEDIA_TYPE> videoMediaTypes() { - AM_MEDIA_TYPE mt; - qMemSet(&mt, 0, sizeof(AM_MEDIA_TYPE)); - mt.majortype = MEDIATYPE_Video; - - //we accept any video format - mt.formattype = GUID_NULL; - mt.cbFormat = 0; - mt.pbFormat = 0; + AM_MEDIA_TYPE mt = { MEDIATYPE_Video, MEDIASUBTYPE_YV12, 0, 0, 0, GUID_NULL, 0, 0, 0 }; QVector<AM_MEDIA_TYPE> ret; - //we support YUV (YV12 and YUY2) and RGB32 - mt.subtype = MEDIASUBTYPE_YV12; - ret << mt; + //we add all the subtypes we support + ret << mt; //YV12 mt.subtype = MEDIASUBTYPE_YUY2; - ret << mt; + ret << mt; //YUY2 mt.subtype = MEDIASUBTYPE_RGB32; - ret << mt; + ret << mt; //RGB32 return ret; } @@ -202,8 +194,8 @@ namespace Phonon m_sampleBuffer = ComPointer<IMediaSample>(); #ifndef QT_NO_OPENGL freeGLResources(); -#endif // QT_NO_OPENGL m_textureUploaded = false; +#endif // QT_NO_OPENGL } void endOfStream() @@ -322,7 +314,6 @@ 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, @@ -364,6 +355,7 @@ namespace Phonon bool m_checkedPrograms; bool m_usingOpenGL; + bool m_textureUploaded; GLuint m_program[2]; GLuint m_texture[3]; #endif @@ -373,7 +365,7 @@ namespace Phonon { public: VideoRendererSoftPin(VideoRendererSoftFilter *parent) : - QMemInputPin(parent, videoMediaTypes(), false /*no transformation of the samples*/), + QMemInputPin(parent, videoMediaTypes(), false /*no transformation of the samples*/, 0), m_renderer(parent) { } @@ -444,7 +436,7 @@ namespace Phonon QBaseFilter(CLSID_NULL), m_inputPin(new VideoRendererSoftPin(this)), m_renderer(renderer), m_start(0) #ifndef QT_NO_OPENGL - ,m_usingOpenGL(false), m_checkedPrograms(false), m_textureUploaded(false) + , m_checkedPrograms(false), m_usingOpenGL(false), m_textureUploaded(false) #endif { m_renderEvent = ::CreateEvent(0, 0, 0, 0); diff --git a/src/3rdparty/phonon/ds9/videowidget.cpp b/src/3rdparty/phonon/ds9/videowidget.cpp index 0ef653f..091be16 100644 --- a/src/3rdparty/phonon/ds9/videowidget.cpp +++ b/src/3rdparty/phonon/ds9/videowidget.cpp @@ -84,7 +84,19 @@ namespace Phonon void setCurrentRenderer(AbstractVideoRenderer *renderer) { m_currentRenderer = renderer; - update(); + //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); } QSize sizeHint() const @@ -106,6 +118,8 @@ namespace Phonon void paintEvent(QPaintEvent *e) { + if (!updatesEnabled()) + return; //this avoids repaint from native events checkCurrentRenderingMode(); m_currentRenderer->repaintCurrentFrame(this, e->rect()); } @@ -153,13 +167,14 @@ namespace Phonon } } else if (!isEmbedded()) { m_currentRenderer = m_node->switchRendering(m_currentRenderer); - setAttribute(Qt::WA_PaintOnScreen, true); + setAttribute(Qt::WA_PaintOnScreen, false); } } VideoWidget *m_node; AbstractVideoRenderer *m_currentRenderer; QVariant m_restoreScreenSaverActive; + QBasicTimer m_flickerFreeTimer; }; VideoWidget::VideoWidget(QWidget *parent) diff --git a/src/3rdparty/phonon/ds9/volumeeffect.cpp b/src/3rdparty/phonon/ds9/volumeeffect.cpp index 2fd1afc..a93b074 100644 --- a/src/3rdparty/phonon/ds9/volumeeffect.cpp +++ b/src/3rdparty/phonon/ds9/volumeeffect.cpp @@ -68,17 +68,7 @@ namespace Phonon static const QVector<AM_MEDIA_TYPE> audioMediaType() { QVector<AM_MEDIA_TYPE> ret; - - AM_MEDIA_TYPE mt; - mt.majortype = MEDIATYPE_Audio; - mt.subtype = MEDIASUBTYPE_PCM; - mt.bFixedSizeSamples = 1; - mt.bTemporalCompression = 0; - mt.pUnk = 0; - mt.lSampleSize = 1; - mt.cbFormat = 0; - mt.pbFormat = 0; - mt.formattype = GUID_NULL; + AM_MEDIA_TYPE mt = { MEDIATYPE_Audio, MEDIASUBTYPE_PCM, 1, 0, 1, GUID_NULL, 0, 0, 0}; ret << mt; return ret; } @@ -86,7 +76,7 @@ namespace Phonon class VolumeMemInputPin : public QMemInputPin { public: - VolumeMemInputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt) : QMemInputPin(parent, mt, true /*transform*/) + VolumeMemInputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt, QPin *output) : QMemInputPin(parent, mt, true /*transform*/, output) { } @@ -149,8 +139,7 @@ namespace Phonon //then creating the input mt << audioMediaType(); - m_input = new VolumeMemInputPin(this, mt); - m_input->addOutput(m_output); //make the connection here + m_input = new VolumeMemInputPin(this, mt, m_output); } void VolumeEffectFilter::treatOneSamplePerChannel(BYTE **buffer, int sampleSize, int channelCount, int frequency) diff --git a/src/3rdparty/phonon/gstreamer/backend.cpp b/src/3rdparty/phonon/gstreamer/backend.cpp index d05f6a6..cd49454 100644 --- a/src/3rdparty/phonon/gstreamer/backend.cpp +++ b/src/3rdparty/phonon/gstreamer/backend.cpp @@ -60,7 +60,7 @@ Backend::Backend(QObject *parent, const QVariantList &) setProperty("backendName", QLatin1String("Gstreamer")); setProperty("backendComment", QLatin1String("Gstreamer plugin for Phonon")); setProperty("backendVersion", QLatin1String("0.2")); - setProperty("backendWebsite", QLatin1String("http://qtsoftware.com/")); + setProperty("backendWebsite", QLatin1String("http://qt.nokia.com/")); //check if we should enable debug output QString debugLevelString = qgetenv("PHONON_GST_DEBUG"); diff --git a/src/3rdparty/phonon/phonon/abstractmediastream.cpp b/src/3rdparty/phonon/phonon/abstractmediastream.cpp index a661702..5b860f3 100644 --- a/src/3rdparty/phonon/phonon/abstractmediastream.cpp +++ b/src/3rdparty/phonon/phonon/abstractmediastream.cpp @@ -49,7 +49,6 @@ AbstractMediaStream::AbstractMediaStream(AbstractMediaStreamPrivate &dd, QObject AbstractMediaStream::~AbstractMediaStream() { - delete d_ptr; } qint64 AbstractMediaStream::streamSize() const diff --git a/src/3rdparty/phonon/phonon/abstractmediastream.h b/src/3rdparty/phonon/phonon/abstractmediastream.h index 0daa92a..c4cde85 100644 --- a/src/3rdparty/phonon/phonon/abstractmediastream.h +++ b/src/3rdparty/phonon/phonon/abstractmediastream.h @@ -214,7 +214,7 @@ class PHONON_EXPORT AbstractMediaStream : public QObject virtual void seekStream(qint64 offset); AbstractMediaStream(AbstractMediaStreamPrivate &dd, QObject *parent); - AbstractMediaStreamPrivate *d_ptr; + QScopedPointer<AbstractMediaStreamPrivate> d_ptr; }; } // namespace Phonon diff --git a/src/3rdparty/phonon/phonon/abstractmediastream_p.h b/src/3rdparty/phonon/phonon/abstractmediastream_p.h index a9d6489..0e87c4d 100644 --- a/src/3rdparty/phonon/phonon/abstractmediastream_p.h +++ b/src/3rdparty/phonon/phonon/abstractmediastream_p.h @@ -45,6 +45,7 @@ class PHONON_EXPORT AbstractMediaStreamPrivate : private MediaNodeDestructionHan public: void setStreamInterface(StreamInterface *); void setMediaObjectPrivate(MediaObjectPrivate *); + ~AbstractMediaStreamPrivate(); protected: AbstractMediaStreamPrivate() @@ -56,7 +57,6 @@ class PHONON_EXPORT AbstractMediaStreamPrivate : private MediaNodeDestructionHan errorType(NoError) { } - ~AbstractMediaStreamPrivate(); virtual void setStreamSize(qint64 newSize); virtual void setStreamSeekable(bool s); diff --git a/src/3rdparty/phonon/phonon/audiooutput.cpp b/src/3rdparty/phonon/phonon/audiooutput.cpp index 752580a..00b2ebd 100644 --- a/src/3rdparty/phonon/phonon/audiooutput.cpp +++ b/src/3rdparty/phonon/phonon/audiooutput.cpp @@ -264,8 +264,8 @@ void AudioOutputPrivate::setupBackendObject() if (deviceList.isEmpty()) { return; } - foreach (int devIndex, deviceList) { - const AudioOutputDevice &dev = AudioOutputDevice::fromIndex(devIndex); + for (int i = 0; i < deviceList.count(); ++i) { + const AudioOutputDevice &dev = AudioOutputDevice::fromIndex(deviceList.at(i)); if (callSetOutputDevice(this, dev)) { handleAutomaticDeviceChange(dev, AudioOutputPrivate::FallbackChange); return; // found one that works @@ -305,8 +305,9 @@ void AudioOutputPrivate::_k_audioDeviceFailed() pDebug() << Q_FUNC_INFO; // outputDeviceIndex identifies a failing device // fall back in the preference list of output devices - QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices); - foreach (int devIndex, deviceList) { + const QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices); + for (int i = 0; i < deviceList.count(); ++i) { + const int devIndex = deviceList.at(i); // if it's the same device as the one that failed, ignore it if (device.index() != devIndex) { const AudioOutputDevice &info = AudioOutputDevice::fromIndex(devIndex); @@ -326,9 +327,10 @@ void AudioOutputPrivate::_k_deviceListChanged() { pDebug() << Q_FUNC_INFO; // let's see if there's a usable device higher in the preference list - QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings); + const QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings); DeviceChangeType changeType = HigherPreferenceChange; - foreach (int devIndex, deviceList) { + for (int i = 0; i < deviceList.count(); ++i) { + const int devIndex = deviceList.at(i); const AudioOutputDevice &info = AudioOutputDevice::fromIndex(devIndex); if (!info.property("available").toBool()) { if (device.index() == devIndex) { diff --git a/src/3rdparty/phonon/phonon/backendcapabilities.cpp b/src/3rdparty/phonon/phonon/backendcapabilities.cpp index 5dee6a0..62c9cc9 100644 --- a/src/3rdparty/phonon/phonon/backendcapabilities.cpp +++ b/src/3rdparty/phonon/phonon/backendcapabilities.cpp @@ -76,8 +76,8 @@ QList<AudioOutputDevice> BackendCapabilities::availableAudioOutputDevices() { QList<AudioOutputDevice> ret; const QList<int> deviceIndexes = GlobalConfig().audioOutputDeviceListFor(Phonon::NoCategory); - foreach (int i, deviceIndexes) { - ret.append(AudioOutputDevice::fromIndex(i)); + for (int i = 0; i < deviceIndexes.count(); ++i) { + ret.append(AudioOutputDevice::fromIndex(deviceIndexes.at(i))); } return ret; } @@ -88,8 +88,8 @@ QList<AudioCaptureDevice> BackendCapabilities::availableAudioCaptureDevices() { QList<AudioCaptureDevice> ret; const QList<int> deviceIndexes = GlobalConfig().audioCaptureDeviceListFor(Phonon::NoCategory); - foreach (int i, deviceIndexes) { - ret.append(AudioCaptureDevice::fromIndex(i)); + for (int i = 0; i < deviceIndexes.count(); ++i) { + ret.append(AudioCaptureDevice::fromIndex(deviceIndexes.at(i))); } return ret; } @@ -101,9 +101,9 @@ QList<EffectDescription> BackendCapabilities::availableAudioEffects() BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend()); QList<EffectDescription> ret; if (backendIface) { - QList<int> deviceIndexes = backendIface->objectDescriptionIndexes(Phonon::EffectType); - foreach (int i, deviceIndexes) { - ret.append(EffectDescription::fromIndex(i)); + const QList<int> deviceIndexes = backendIface->objectDescriptionIndexes(Phonon::EffectType); + for (int i = 0; i < deviceIndexes.count(); ++i) { + ret.append(EffectDescription::fromIndex(deviceIndexes.at(i))); } } return ret; diff --git a/src/3rdparty/phonon/phonon/backendcapabilities.h b/src/3rdparty/phonon/phonon/backendcapabilities.h index 65b2830..36454a3 100644 --- a/src/3rdparty/phonon/phonon/backendcapabilities.h +++ b/src/3rdparty/phonon/phonon/backendcapabilities.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Trolltech ASA (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -15,7 +15,7 @@ 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 + 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/>. */ @@ -88,19 +88,18 @@ namespace BackendCapabilities }; /** - * Use this function to get a QObject pointer to connect to the capabilitiesChanged signal. + * Use this function to get a QObject pointer to connect to one of the Notifier signals. * * \return a pointer to a QObject. * - * The capabilitiesChanged signal is emitted if the capabilities have changed. This can - * happen if the user has requested a backend change. - * - * To connect to this signal do the following: + * To connect to the signal do the following: * \code * QObject::connect(BackendCapabilities::notifier(), SIGNAL(capabilitiesChanged()), ... * \endcode * * \see Notifier::capabilitiesChanged() + * \see Notifier::availableAudioOutputDevicesChanged() + * \see Notifier::availableAudioCaptureDevicesChanged() */ PHONON_EXPORT Notifier *notifier(); diff --git a/src/3rdparty/phonon/phonon/effect.cpp b/src/3rdparty/phonon/phonon/effect.cpp index c125232..98662a5 100644 --- a/src/3rdparty/phonon/phonon/effect.cpp +++ b/src/3rdparty/phonon/phonon/effect.cpp @@ -107,7 +107,8 @@ bool EffectPrivate::aboutToDeleteBackendObject() { if (m_backendObject) { const QList<EffectParameter> parameters = pINTERFACE_CALL(parameters()); - foreach (const EffectParameter &p, parameters) { + for (int i = 0; i < parameters.count(); ++i) { + const EffectParameter &p = parameters.at(i); parameterValues[p] = pINTERFACE_CALL(parameterValue(p)); } } @@ -120,7 +121,8 @@ void EffectPrivate::setupBackendObject() // set up attributes const QList<EffectParameter> parameters = pINTERFACE_CALL(parameters()); - foreach (const EffectParameter &p, parameters) { + for (int i = 0; i < parameters.count(); ++i) { + const EffectParameter &p = parameters.at(i); pINTERFACE_CALL(setParameterValue(p, parameterValues[p])); } } diff --git a/src/3rdparty/phonon/phonon/effectwidget.cpp b/src/3rdparty/phonon/phonon/effectwidget.cpp index d5c6c81..fb9cf6e 100644 --- a/src/3rdparty/phonon/phonon/effectwidget.cpp +++ b/src/3rdparty/phonon/phonon/effectwidget.cpp @@ -97,7 +97,8 @@ void EffectWidgetPrivate::autogenerateUi() Q_Q(EffectWidget); QVBoxLayout *mainLayout = new QVBoxLayout(q); mainLayout->setMargin(0); - foreach (const EffectParameter ¶, effect->parameters()) { + for (int i = 0; i < effect->parameters().count(); ++i) { + const EffectParameter ¶ = effect->parameters().at(i); QVariant value = effect->parameterValue(para); QHBoxLayout *pLayout = new QHBoxLayout; mainLayout->addLayout(pLayout); @@ -117,13 +118,14 @@ void EffectWidgetPrivate::autogenerateUi() control = cb; if (value.type() == QVariant::Int) { //value just defines the item index - foreach (const QVariant &item, para.possibleValues()) { - cb->addItem(item.toString()); + for (int i = 0; i < para.possibleValues().count(); ++i) { + cb->addItem(para.possibleValues().at(i).toString()); } cb->setCurrentIndex(value.toInt()); QObject::connect(cb, SIGNAL(currentIndexChanged(int)), q, SLOT(_k_setIntParameter(int))); } else { - foreach (const QVariant &item, para.possibleValues()) { + for (int i = 0; i < para.possibleValues().count(); ++i) { + const QVariant &item = para.possibleValues().at(i); cb->addItem(item.toString()); if (item == value) { cb->setCurrentIndex(cb->count() - 1); @@ -155,19 +157,20 @@ void EffectWidgetPrivate::autogenerateUi() QObject::connect(sb, SIGNAL(valueChanged(int)), q, SLOT(_k_setIntParameter(int))); } break; + case QMetaType::Float: case QVariant::Double: { - const double minValue = (para.minimumValue().type() == QVariant::Double ? - para.minimumValue().toDouble() : DEFAULT_MIN); - const double maxValue = (para.maximumValue().type() == QVariant::Double ? - para.maximumValue().toDouble() : DEFAULT_MAX); + const qreal minValue = para.minimumValue().canConvert(QVariant::Double) ? + para.minimumValue().toReal() : DEFAULT_MIN; + const qreal maxValue = para.maximumValue().canConvert(QVariant::Double) ? + para.maximumValue().toReal() : DEFAULT_MAX; if (minValue == -1. && maxValue == 1.) { //Special case values between -1 and 1.0 to use a slider for improved usability QSlider *slider = new QSlider(Qt::Horizontal, q); control = slider; slider->setRange(-SLIDER_RANGE, +SLIDER_RANGE); - slider->setValue(int(SLIDER_RANGE * value.toDouble())); + slider->setValue(int(SLIDER_RANGE * value.toReal())); slider->setTickPosition(QSlider::TicksBelow); slider->setTickInterval(TICKINTERVAL); QObject::connect(slider, SIGNAL(valueChanged(int)), q, SLOT(_k_setSliderParameter(int))); diff --git a/src/3rdparty/phonon/phonon/factory.cpp b/src/3rdparty/phonon/phonon/factory.cpp index 43c45ee..fef88f0 100644 --- a/src/3rdparty/phonon/phonon/factory.cpp +++ b/src/3rdparty/phonon/phonon/factory.cpp @@ -124,15 +124,18 @@ bool FactoryPrivate::createBackend() // could not load a backend through the platform plugin. Falling back to the default // (finding the first loadable backend). const QLatin1String suffix("/phonon_backend/"); - foreach (QString libPath, QCoreApplication::libraryPaths()) { - libPath += suffix; + const QStringList paths = QCoreApplication::libraryPaths(); + for (int i = 0; i < paths.count(); ++i) { + const QString libPath = paths.at(i) + suffix; const QDir dir(libPath); if (!dir.exists()) { pDebug() << Q_FUNC_INFO << dir.absolutePath() << "does not exist"; continue; } - foreach (const QString &pluginName, dir.entryList(QDir::Files)) { - QPluginLoader pluginLoader(libPath + pluginName); + + const QStringList files = dir.entryList(QDir::Files); + for (int i = 0; i < files.count(); ++i) { + QPluginLoader pluginLoader(libPath + files.at(i)); if (!pluginLoader.load()) { pDebug() << Q_FUNC_INFO << " load failed:" << pluginLoader.errorString(); @@ -183,14 +186,8 @@ FactoryPrivate::FactoryPrivate() FactoryPrivate::~FactoryPrivate() { - foreach (QObject *o, objects) { - MediaObject *m = qobject_cast<MediaObject *>(o); - if (m) { - m->stop(); - } - } - foreach (MediaNodePrivate *bp, mediaNodePrivateList) { - bp->deleteBackendObject(); + for (int i = 0; i < mediaNodePrivateList.count(); ++i) { + mediaNodePrivateList.at(i)->deleteBackendObject(); } if (objects.size() > 0) { pError() << "The backend objects are not deleted as was requested."; @@ -258,8 +255,8 @@ void Factory::deregisterFrontendObject(MediaNodePrivate *bp) void FactoryPrivate::phononBackendChanged() { if (m_backendObject) { - foreach (MediaNodePrivate *bp, mediaNodePrivateList) { - bp->deleteBackendObject(); + for (int i = 0; i < mediaNodePrivateList.count(); ++i) { + mediaNodePrivateList.at(i)->deleteBackendObject(); } if (objects.size() > 0) { pDebug() << "WARNING: we were asked to change the backend but the application did\n" @@ -268,8 +265,8 @@ void FactoryPrivate::phononBackendChanged() "backendswitching possible."; // in case there were objects deleted give 'em a chance to recreate // them now - foreach (MediaNodePrivate *bp, mediaNodePrivateList) { - bp->createBackendObject(); + for (int i = 0; i < mediaNodePrivateList.count(); ++i) { + mediaNodePrivateList.at(i)->createBackendObject(); } return; } @@ -277,8 +274,8 @@ void FactoryPrivate::phononBackendChanged() m_backendObject = 0; } createBackend(); - foreach (MediaNodePrivate *bp, mediaNodePrivateList) { - bp->createBackendObject(); + for (int i = 0; i < mediaNodePrivateList.count(); ++i) { + mediaNodePrivateList.at(i)->createBackendObject(); } emit backendChanged(); } @@ -362,15 +359,17 @@ PlatformPlugin *FactoryPrivate::platformPlugin() QStringList()) ); dir.setFilter(QDir::Files); + const QStringList libPaths = QCoreApplication::libraryPaths(); forever { - foreach (QString libPath, QCoreApplication::libraryPaths()) { - libPath += suffix; + for (int i = 0; i < libPaths.count(); ++i) { + const QString libPath = libPaths.at(i) + suffix; dir.setPath(libPath); if (!dir.exists()) { continue; } - foreach (const QString &pluginName, dir.entryList()) { - QPluginLoader pluginLoader(libPath + pluginName); + const QStringList files = dir.entryList(QDir::Files); + for (int i = 0; i < files.count(); ++i) { + QPluginLoader pluginLoader(libPath + files.at(i)); if (!pluginLoader.load()) { pDebug() << Q_FUNC_INFO << " platform plugin load failed:" << pluginLoader.errorString(); diff --git a/src/3rdparty/phonon/phonon/medianode.cpp b/src/3rdparty/phonon/phonon/medianode.cpp index 4693cb8..63fa2e3 100644 --- a/src/3rdparty/phonon/phonon/medianode.cpp +++ b/src/3rdparty/phonon/phonon/medianode.cpp @@ -67,8 +67,8 @@ bool MediaNode::isValid() const MediaNodePrivate::~MediaNodePrivate() { - foreach (MediaNodeDestructionHandler *handler, handlers) { - handler->phononObjectDestroyed(this); + for (int i = 0 ; i < handlers.count(); ++i) { + handlers.at(i)->phononObjectDestroyed(this); } Factory::deregisterFrontendObject(this); delete m_backendObject; diff --git a/src/3rdparty/phonon/phonon/mediaobject.cpp b/src/3rdparty/phonon/phonon/mediaobject.cpp index de5fbc8..10fefbd 100644 --- a/src/3rdparty/phonon/phonon/mediaobject.cpp +++ b/src/3rdparty/phonon/phonon/mediaobject.cpp @@ -300,15 +300,15 @@ void MediaObject::enqueue(const MediaSource &source) void MediaObject::enqueue(const QList<MediaSource> &sources) { - foreach (const MediaSource &m, sources) { - enqueue(m); + for (int i = 0; i < sources.count(); ++i) { + enqueue(sources.at(i)); } } void MediaObject::enqueue(const QList<QUrl> &urls) { - foreach (const QUrl &url, urls) { - enqueue(url); + for (int i = 0; i < urls.count(); ++i) { + enqueue(urls.at(i)); } } @@ -502,8 +502,8 @@ void MediaObjectPrivate::setupBackendObject() } #ifndef QT_NO_PHONON_MEDIACONTROLLER - foreach (FrontendInterfacePrivate *f, interfaceList) { - f->_backendObjectChanged(); + for (int i = 0 ; i < interfaceList.count(); ++i) { + interfaceList.at(i)->_backendObjectChanged(); } #endif //QT_NO_PHONON_MEDIACONTROLLER diff --git a/src/3rdparty/phonon/phonon/mediaobject.h b/src/3rdparty/phonon/phonon/mediaobject.h index 5cbddbb..c56b6b5 100644 --- a/src/3rdparty/phonon/phonon/mediaobject.h +++ b/src/3rdparty/phonon/phonon/mediaobject.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Trolltech ASA (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -15,7 +15,7 @@ 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 + 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/>. */ @@ -58,7 +58,7 @@ namespace Phonon * media->play(); * \endcode * - * If you want to play more that one media file (one after another) you can + * If you want to play more than one media file (one after another) you can * either tell MediaObject about all those files * \code * media->setCurrentSource(":/sounds/startsound.ogg"); @@ -198,18 +198,18 @@ namespace Phonon * Check whether the current media may be seeked. * * \warning This information cannot be known immediately. It is best - * to also listen to the hasVideoChanged signal. + * to also listen to the seekableChanged signal. * * \code - * connect(media, SIGNAL(hasVideoChanged(bool)), hasVideoChanged(bool)); + * connect(media, SIGNAL(seekableChanged(bool)), seekableChanged(bool)); * media->setCurrentSource("somevideo.avi"); - * media->hasVideo(); // returns false; + * media->isSeekable(); // returns false; * } * - * void hasVideoChanged(bool b) + * void seekableChanged(bool b) * { * // b == true - * media->hasVideo(); // returns true; + * media->isSeekable(); // returns true; * } * \endcode * @@ -301,7 +301,7 @@ namespace Phonon void setCurrentSource(const MediaSource &source); /** - * Returns the queued media sources. This does list does not include + * Returns the queued media sources. This list does not include * the current source (returned by currentSource). */ QList<MediaSource> queue() const; @@ -456,8 +456,6 @@ namespace Phonon Q_SIGNALS: /** * Emitted when the state of the MediaObject has changed. - * In case you're not interested in the old state you can also - * connect to a slot that only has one State argument. * * @param newstate The state the Player is in now. * @param oldstate The state the Player was in before. @@ -587,7 +585,7 @@ namespace Phonon /** * This signal is emitted as soon as the total time of the media file is * known or has changed. For most non-local media data the total - * time of the media can only be known after some time. At that time the + * time of the media can only be known after some time. Initially the * totalTime function can not return useful information. You have * to wait for this signal to know the real total time. * diff --git a/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp b/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp index e989d0c..b67344f 100644 --- a/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp +++ b/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp @@ -321,8 +321,8 @@ bool ObjectDescriptionModelData::dropMimeData(ObjectDescriptionType type, const } } d->model->beginInsertRows(QModelIndex(), row, row + toInsert.size() - 1); - foreach (const QExplicitlySharedDataPointer<ObjectDescriptionData> &obj, toInsert) { - d->data.insert(row, obj); + for (int i = 0 ; i < toInsert.count(); ++i) { + d->data.insert(row, toInsert.at(i)); } d->model->endInsertRows(); return true; diff --git a/src/3rdparty/phonon/phonon/objectdescriptionmodel.h b/src/3rdparty/phonon/phonon/objectdescriptionmodel.h index 84dc0bb..ba3cb42 100644 --- a/src/3rdparty/phonon/phonon/objectdescriptionmodel.h +++ b/src/3rdparty/phonon/phonon/objectdescriptionmodel.h @@ -292,8 +292,8 @@ namespace Phonon */ inline void setModelData(const QList<ObjectDescription<type> > &data) { //krazy:exclude=inline QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > list; - Q_FOREACH (const ObjectDescription<type> &desc, data) { - list << desc.d; + for (int i = 0; i < data.count(); ++i) { + list += data.at(i).d; } d->setModelData(list); } @@ -307,8 +307,8 @@ namespace Phonon inline QList<ObjectDescription<type> > modelData() const { //krazy:exclude=inline QList<ObjectDescription<type> > ret; QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > list = d->modelData(); - Q_FOREACH (const QExplicitlySharedDataPointer<ObjectDescriptionData> &data, list) { - ret << ObjectDescription<type>(data); + for (int i = 0; i < list.count(); ++i) { + ret << ObjectDescription<type>(list.at(i)); } return ret; } diff --git a/src/3rdparty/phonon/phonon/path.cpp b/src/3rdparty/phonon/phonon/path.cpp index b46d30a..aec8d05 100644 --- a/src/3rdparty/phonon/phonon/path.cpp +++ b/src/3rdparty/phonon/phonon/path.cpp @@ -58,8 +58,8 @@ class ConnectionTransaction PathPrivate::~PathPrivate() { #ifndef QT_NO_PHONON_EFFECT - foreach (Effect *e, effects) { - e->k_ptr->removeDestructionHandler(this); + for (int i = 0; i < effects.count(); ++i) { + effects.at(i)->k_ptr->removeDestructionHandler(this); } delete effectsParent; #endif @@ -233,8 +233,8 @@ bool Path::disconnect() if (d->sourceNode) list << d->sourceNode->k_ptr->backendObject(); #ifndef QT_NO_PHONON_EFFECT - foreach(Effect *e, d->effects) { - list << e->k_ptr->backendObject(); + for (int i = 0; i < d->effects.count(); ++i) { + list << d->effects.at(i)->k_ptr->backendObject(); } #endif if (d->sinkNode) { @@ -260,8 +260,8 @@ bool Path::disconnect() d->sourceNode = 0; #ifndef QT_NO_PHONON_EFFECT - foreach(Effect *e, d->effects) { - e->k_ptr->removeDestructionHandler(d.data()); + for (int i = 0; i < d->effects.count(); ++i) { + d->effects.at(i)->k_ptr->removeDestructionHandler(d.data()); } d->effects.clear(); #endif @@ -292,11 +292,13 @@ MediaNode *Path::sink() const bool PathPrivate::executeTransaction( const QList<QObjectPair> &disconnections, const QList<QObjectPair> &connections) { QSet<QObject*> nodesForTransaction; - foreach(const QObjectPair &pair, disconnections) { + for (int i = 0; i < disconnections.count(); ++i) { + const QObjectPair &pair = disconnections.at(i); nodesForTransaction << pair.first; nodesForTransaction << pair.second; } - foreach(const QObjectPair &pair, connections) { + for (int i = 0; i < connections.count(); ++i) { + const QObjectPair &pair = connections.at(i); nodesForTransaction << pair.first; nodesForTransaction << pair.second; } @@ -338,7 +340,8 @@ bool PathPrivate::executeTransaction( const QList<QObjectPair> &disconnections, } //and now let's reconnect the nodes that were disconnected: rollback - foreach(const QObjectPair &pair, disconnections) { + for (int i = 0; i < disconnections.count(); ++i) { + const QObjectPair &pair = disconnections.at(i); bool success = backend->connectNodes(pair.first, pair.second); Q_ASSERT(success); //a failure here means it is impossible to reestablish the connection Q_UNUSED(success); @@ -417,7 +420,8 @@ void PathPrivate::phononObjectDestroyed(MediaNodePrivate *mediaNodePrivate) sinkNode = 0; } else { #ifndef QT_NO_PHONON_EFFECT - foreach (Effect *e, effects) { + for (int i = 0; i < effects.count(); ++i) { + Effect *e = effects.at(i); if (e->k_ptr == mediaNodePrivate) { removeEffect(e); } diff --git a/src/3rdparty/phonon/phonon/phonon_export.h b/src/3rdparty/phonon/phonon/phonon_export.h index e579f67..5f93ea0 100644 --- a/src/3rdparty/phonon/phonon/phonon_export.h +++ b/src/3rdparty/phonon/phonon/phonon_export.h @@ -32,7 +32,11 @@ # define PHONON_EXPORT Q_DECL_IMPORT # endif # else /* UNIX */ -# define PHONON_EXPORT Q_DECL_EXPORT +# ifdef MAKE_PHONON_LIB /* We are building this library */ +# define PHONON_EXPORT Q_DECL_EXPORT +# else /* We are using this library */ +# define PHONON_EXPORT Q_DECL_IMPORT +# endif # endif #endif diff --git a/src/3rdparty/phonon/phonon/volumeslider.cpp b/src/3rdparty/phonon/phonon/volumeslider.cpp index b59f689..1888cb6 100644 --- a/src/3rdparty/phonon/phonon/volumeslider.cpp +++ b/src/3rdparty/phonon/phonon/volumeslider.cpp @@ -85,7 +85,7 @@ VolumeSlider::~VolumeSlider() bool VolumeSlider::isMuteVisible() const { - return k_ptr->muteButton.isVisible(); + return !k_ptr->muteButton.isHidden(); } void VolumeSlider::setMuteVisible(bool visible) diff --git a/src/3rdparty/phonon/qt7/backend.mm b/src/3rdparty/phonon/qt7/backend.mm index 327ddd7..b3ca106 100644 --- a/src/3rdparty/phonon/qt7/backend.mm +++ b/src/3rdparty/phonon/qt7/backend.mm @@ -59,7 +59,7 @@ Backend::Backend(QObject *parent, const QStringList &) : QObject(parent) setProperty("backendComment", QLatin1String("Developed by Trolltech")); setProperty("backendVersion", QLatin1String("0.1")); setProperty("backendIcon", QLatin1String("")); - setProperty("backendWebsite", QLatin1String("http://qtsoftware.com/")); + setProperty("backendWebsite", QLatin1String("http://qt.nokia.com/")); } Backend::~Backend() diff --git a/src/3rdparty/phonon/qt7/mediaobject.h b/src/3rdparty/phonon/qt7/mediaobject.h index d59ee77..c93eddc 100644 --- a/src/3rdparty/phonon/qt7/mediaobject.h +++ b/src/3rdparty/phonon/qt7/mediaobject.h @@ -25,6 +25,10 @@ #include "medianode.h" +#if QT_ALLOW_QUICKTIME + #include <QuickTime/QuickTime.h> +#endif + QT_BEGIN_NAMESPACE namespace Phonon @@ -95,6 +99,10 @@ namespace QT7 int videoOutputCount(); +#if QT_ALLOW_QUICKTIME + void displayLinkEvent(); +#endif + signals: void stateChanged(Phonon::State,Phonon::State); void tick(qint64); @@ -132,6 +140,14 @@ namespace QT7 QuickTimeAudioPlayer *m_nextAudioPlayer; MediaObjectAudioNode *m_mediaObjectAudioNode; +#if QT_ALLOW_QUICKTIME + CVDisplayLinkRef m_displayLink; + QMutex m_displayLinkMutex; + bool m_pendingDisplayLinkEvent; + void startDisplayLink(); + void stopDisplayLink(); +#endif + qint32 m_tickInterval; qint32 m_transitionTime; quint32 m_prefinishMark; @@ -139,7 +155,8 @@ namespace QT7 float m_percentageLoaded; int m_tickTimer; - int m_bufferTimer; + int m_videoTimer; + int m_audioTimer; int m_rapidTimer; bool m_waitNextSwap; @@ -154,8 +171,7 @@ namespace QT7 void pause_internal(); void play_internal(); void setupAudioSystem(); - void updateTimer(int &timer, int interval); - void bufferAudioVideo(); + void restartAudioVideoTimers(); void updateRapidly(); void updateCrossFade(); void updateAudioBuffers(); diff --git a/src/3rdparty/phonon/qt7/mediaobject.mm b/src/3rdparty/phonon/qt7/mediaobject.mm index 95859ef..677640c 100644 --- a/src/3rdparty/phonon/qt7/mediaobject.mm +++ b/src/3rdparty/phonon/qt7/mediaobject.mm @@ -63,15 +63,24 @@ MediaObject::MediaObject(QObject *parent) : MediaNode(AudioSource | VideoSource, m_errorType = Phonon::NoError; m_tickTimer = 0; - m_bufferTimer = 0; + m_videoTimer = 0; + m_audioTimer = 0; m_rapidTimer = 0; +#if QT_ALLOW_QUICKTIME + m_displayLink = 0; + m_pendingDisplayLinkEvent = false; +#endif + checkForError(); } MediaObject::~MediaObject() { - // m_mediaObjectAudioNode is owned by super class. + // m_mediaObjectAudioNode is owned by super class. +#if QT_ALLOW_QUICKTIME + stopDisplayLink(); +#endif m_audioPlayer->unsetVideoPlayer(); m_nextAudioPlayer->unsetVideoPlayer(); delete m_videoPlayer; @@ -87,7 +96,7 @@ bool MediaObject::setState(Phonon::State state) emit stateChanged(m_state, prevState); if (m_state != state){ // End-application did something - // upon receiving the signal. + // upon receiving the signal. return false; } } @@ -330,13 +339,91 @@ void MediaObject::swapCurrentWithNext(qint32 transitionTime) } } -void MediaObject::updateTimer(int &timer, int interval) +#if QT_ALLOW_QUICKTIME +static CVReturn displayLinkCallback(CVDisplayLinkRef /*displayLink*/, + const CVTimeStamp */*inNow*/, + const CVTimeStamp */*inOutputTime*/, + CVOptionFlags /*flagsIn*/, + CVOptionFlags */*flagsOut*/, + void *userData) { - if (timer) - killTimer(timer); - timer = 0; - if (interval >= 0) - timer = startTimer(interval); + MediaObject *mediaObject = static_cast<MediaObject *>(userData); + mediaObject->displayLinkEvent(); + return kCVReturnSuccess; +} + +void MediaObject::displayLinkEvent() +{ + // This function is called from a + // thread != gui thread. So we post the event. + // But we need to make sure that we don't post faster + // than the event loop can eat: + m_displayLinkMutex.lock(); + bool pending = m_pendingDisplayLinkEvent; + m_pendingDisplayLinkEvent = true; + m_displayLinkMutex.unlock(); + + if (!pending) + qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority); +} + +void MediaObject::startDisplayLink() +{ + if (m_displayLink) + return; + OSStatus err = CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &m_displayLink); + if (err != noErr) + goto fail; + err = CVDisplayLinkSetCurrentCGDisplay(m_displayLink, kCGDirectMainDisplay); + if (err != noErr) + goto fail; + err = CVDisplayLinkSetOutputCallback(m_displayLink, displayLinkCallback, this); + if (err != noErr) + goto fail; + err = CVDisplayLinkStart(m_displayLink); + if (err != noErr) + goto fail; + return; +fail: + stopDisplayLink(); +} + +void MediaObject::stopDisplayLink() +{ + if (!m_displayLink) + return; + CVDisplayLinkStop(m_displayLink); + CFRelease(m_displayLink); + m_displayLink = 0; +} +#endif + +void MediaObject::restartAudioVideoTimers() +{ + if (m_videoTimer) + killTimer(m_videoTimer); + if (m_audioTimer) + killTimer(m_audioTimer); + +#if QT_ALLOW_QUICKTIME + // We prefer to use a display link as timer if available, since + // it is more steady, and results in better and smoother frame drawing: + startDisplayLink(); + if (!m_displayLink){ + float fps = m_videoPlayer->staticFps(); + long videoUpdateFrequency = fps ? long(1000.0f / fps) : 0.001; + m_videoTimer = startTimer(videoUpdateFrequency); + } +#else + float fps = m_videoPlayer->staticFps(); + long videoUpdateFrequency = fps ? long(1000.0f / fps) : 0.001; + m_videoTimer = startTimer(videoUpdateFrequency); +#endif + + long audioUpdateFrequency = m_audioPlayer->regularTaskFrequency(); + m_audioTimer = startTimer(audioUpdateFrequency); + updateVideoFrames(); + updateAudioBuffers(); } void MediaObject::play_internal() @@ -350,8 +437,9 @@ void MediaObject::play_internal() m_nextVideoPlayer->play(); m_nextAudioPlayer->play(); } - bufferAudioVideo(); - updateTimer(m_rapidTimer, 100); + restartAudioVideoTimers(); + if (!m_rapidTimer) + m_rapidTimer = startTimer(100); } void MediaObject::pause_internal() @@ -361,9 +449,15 @@ void MediaObject::pause_internal() m_nextAudioPlayer->pause(); m_videoPlayer->pause(); m_nextVideoPlayer->pause(); - updateTimer(m_rapidTimer, -1); - updateTimer(m_bufferTimer, -1); - + killTimer(m_rapidTimer); + killTimer(m_videoTimer); + killTimer(m_audioTimer); + m_rapidTimer = 0; + m_videoTimer = 0; + m_audioTimer = 0; +#if QT_ALLOW_QUICKTIME + stopDisplayLink(); +#endif if (m_waitNextSwap) m_swapTimeLeft = m_swapTime.msecsTo(QTime::currentTime()); } @@ -771,16 +865,6 @@ void MediaObject::updateLipSynch(int allowedOffset) } } -void MediaObject::bufferAudioVideo() -{ - long nextVideoUpdate = m_videoPlayer->hasVideo() ? 30 : INT_MAX; - long nextAudioUpdate = m_audioPlayer->regularTaskFrequency(); - updateAudioBuffers(); - updateVideoFrames(); - if (m_state == Phonon::PlayingState) - updateTimer(m_bufferTimer, qMin(nextVideoUpdate, nextAudioUpdate)); -} - void MediaObject::updateRapidly() { updateCurrentTime(); @@ -805,8 +889,8 @@ void MediaObject::mediaNodeEvent(const MediaNodeEvent *event) synchAudioVideo(); checkForError(); m_mediaObjectAudioNode->setMute(false); - if (m_state == Phonon::PlayingState) - bufferAudioVideo(); + if (m_state == Phonon::PlayingState) + restartAudioVideoTimers(); break; case MediaNodeEvent::AudioGraphCannotPlay: case MediaNodeEvent::AudioGraphInitialized: @@ -817,7 +901,7 @@ void MediaObject::mediaNodeEvent(const MediaNodeEvent *event) checkForError(); m_mediaObjectAudioNode->setMute(false); } - break; + break; default: break; } @@ -826,16 +910,25 @@ void MediaObject::mediaNodeEvent(const MediaNodeEvent *event) bool MediaObject::event(QEvent *event) { switch (event->type()){ - case QEvent::Timer: { - QTimerEvent *timerEvent = static_cast<QTimerEvent *>(event); - if (timerEvent->timerId() == m_rapidTimer) +#if QT_ALLOW_QUICKTIME + case QEvent::User:{ + m_displayLinkMutex.lock(); + m_pendingDisplayLinkEvent = false; + m_displayLinkMutex.unlock(); + updateVideoFrames(); + break; } +#endif + case QEvent::Timer:{ + int timerId = static_cast<QTimerEvent *>(event)->timerId(); + if (timerId == m_rapidTimer) updateRapidly(); - else if (timerEvent->timerId() == m_tickTimer) + else if (timerId == m_tickTimer) emit tick(currentTime()); - else if (timerEvent->timerId() == m_bufferTimer) - bufferAudioVideo(); - } - break; + else if (timerId == m_videoTimer) + updateVideoFrames(); + else if (timerId == m_audioTimer) + updateAudioBuffers(); + break; } default: break; } diff --git a/src/3rdparty/phonon/qt7/quicktimevideoplayer.h b/src/3rdparty/phonon/qt7/quicktimevideoplayer.h index 8495e18..98eacb5 100644 --- a/src/3rdparty/phonon/qt7/quicktimevideoplayer.h +++ b/src/3rdparty/phonon/qt7/quicktimevideoplayer.h @@ -68,11 +68,13 @@ namespace QT7 GLuint currentFrameAsGLTexture(); void *currentFrameAsCIImage(); QImage currentFrameAsQImage(); + void releaseImageCache(); QRect videoRect() const; quint64 duration() const; quint64 currentTime() const; long timeScale() const; + float staticFps(); QString currentTimeString(); void setColors(qreal brightness = 0, qreal contrast = 1, qreal hue = 0, qreal saturation = 1); @@ -126,6 +128,9 @@ namespace QT7 QGLPixelBuffer *m_QImagePixelBuffer; QuickTimeMetaData *m_metaData; + CVOpenGLTextureRef m_cachedCVTextureRef; + QImage m_cachedQImage; + bool m_playbackRateSat; bool m_isDrmProtected; bool m_isDrmAuthorized; @@ -135,8 +140,10 @@ namespace QT7 float m_masterVolume; float m_relativeVolume; float m_playbackRate; + float m_staticFps; quint64 m_currentTime; MediaSource m_mediaSource; + void *m_primaryRenderingCIImage; qreal m_brightness; qreal m_contrast; @@ -171,6 +178,7 @@ namespace QT7 void setError(NSError *error); bool errorOccured(); void readProtection(); + void calculateStaticFps(); void checkIfVideoAwailable(); bool movieNotLoaded(); void waitStatePlayable(); diff --git a/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm b/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm index 02a594b..23c76e3 100644 --- a/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm +++ b/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm @@ -63,12 +63,14 @@ QuickTimeVideoPlayer::QuickTimeVideoPlayer() : QObject(0) m_mute = false; m_audioEnabled = false; m_hasVideo = false; + m_staticFps = 0; m_playbackRateSat = false; m_isDrmProtected = false; m_isDrmAuthorized = true; m_primaryRenderingTarget = 0; m_primaryRenderingCIImage = 0; m_QImagePixelBuffer = 0; + m_cachedCVTextureRef = 0; m_folderTracks = 0; m_currentTrack = 0; @@ -81,6 +83,7 @@ QuickTimeVideoPlayer::QuickTimeVideoPlayer() : QObject(0) QuickTimeVideoPlayer::~QuickTimeVideoPlayer() { + PhononAutoReleasePool pool; unsetCurrentMediaSource(); delete m_metaData; [(NSObject*)m_primaryRenderingTarget release]; @@ -91,6 +94,15 @@ QuickTimeVideoPlayer::~QuickTimeVideoPlayer() #endif } +void QuickTimeVideoPlayer::releaseImageCache() +{ + if (m_cachedCVTextureRef){ + CVOpenGLTextureRelease(m_cachedCVTextureRef); + m_cachedCVTextureRef = 0; + } + m_cachedQImage = QImage(); +} + void QuickTimeVideoPlayer::createVisualContext() { #ifdef QUICKTIME_C_API_AVAILABLE @@ -130,7 +142,10 @@ bool QuickTimeVideoPlayer::videoFrameChanged() return false; QTVisualContextTask(m_visualContext); - return QTVisualContextIsNewImageAvailable(m_visualContext, 0); + bool changed = QTVisualContextIsNewImageAvailable(m_visualContext, 0); + if (changed) + releaseImageCache(); + return changed; #elif defined(QT_MAC_USE_COCOA) return true; @@ -145,10 +160,11 @@ CVOpenGLTextureRef QuickTimeVideoPlayer::currentFrameAsCVTexture() #ifdef QUICKTIME_C_API_AVAILABLE if (!m_visualContext) return 0; - CVOpenGLTextureRef texture = 0; - OSStatus err = QTVisualContextCopyImageForTime(m_visualContext, 0, 0, &texture); - BACKEND_ASSERT3(err == noErr, "Could not copy image for time in QuickTime player", FATAL_ERROR, 0) - return texture; + if (!m_cachedCVTextureRef){ + OSStatus err = QTVisualContextCopyImageForTime(m_visualContext, 0, 0, &m_cachedCVTextureRef); + BACKEND_ASSERT3(err == noErr, "Could not copy image for time in QuickTime player", FATAL_ERROR, 0) + } + return m_cachedCVTextureRef; #else return 0; @@ -157,6 +173,9 @@ CVOpenGLTextureRef QuickTimeVideoPlayer::currentFrameAsCVTexture() QImage QuickTimeVideoPlayer::currentFrameAsQImage() { + if (!m_cachedQImage.isNull()) + return m_cachedQImage; + #ifdef QUICKTIME_C_API_AVAILABLE QGLContext *prevContext = const_cast<QGLContext *>(QGLContext::currentContext()); CVOpenGLTextureRef texture = currentFrameAsCVTexture(); @@ -186,12 +205,11 @@ QImage QuickTimeVideoPlayer::currentFrameAsQImage() glVertex2i(-1, -1); glEnd(); - QImage image = m_QImagePixelBuffer->toImage(); - CVOpenGLTextureRelease(texture); + m_cachedQImage = m_QImagePixelBuffer->toImage(); // Because of QuickTime, m_QImagePixelBuffer->doneCurrent() will fail. // So we store, and restore, the context our selves: prevContext->makeCurrent(); - return image; + return m_cachedQImage; #else CIImage *img = (CIImage *)currentFrameAsCIImage(); if (!img) @@ -200,10 +218,10 @@ QImage QuickTimeVideoPlayer::currentFrameAsQImage() NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img]; CGRect bounds = [img extent]; QImage qImg([bitmap bitmapData], bounds.size.width, bounds.size.height, QImage::Format_ARGB32); - QImage swapped = qImg.rgbSwapped(); + m_cachedQImage = qImg.rgbSwapped(); [bitmap release]; [img release]; - return swapped; + return m_cachedQImage; #endif } @@ -255,8 +273,7 @@ void *QuickTimeVideoPlayer::currentFrameAsCIImage() #ifdef QUICKTIME_C_API_AVAILABLE CVOpenGLTextureRef cvImg = currentFrameAsCVTexture(); CIImage *img = [[CIImage alloc] initWithCVImageBuffer:cvImg]; - CVOpenGLTextureRelease(cvImg); - return img; + return img; #else return 0; #endif @@ -278,7 +295,7 @@ GLuint QuickTimeVideoPlayer::currentFrameAsGLTexture() int samplesPerPixel = [bitmap samplesPerPixel]; if (![bitmap isPlanar] && (samplesPerPixel == 3 || samplesPerPixel == 4)){ - glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, + glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, samplesPerPixel == 4 ? GL_RGBA8 : GL_RGB8, [bitmap pixelsWide], [bitmap pixelsHigh], 0, samplesPerPixel == 4 ? GL_RGBA : GL_RGB, @@ -307,7 +324,7 @@ void QuickTimeVideoPlayer::setVolume(float masterVolume, float relativeVolume) m_masterVolume = masterVolume; m_relativeVolume = relativeVolume; if (!m_QTMovie || !m_audioEnabled || m_mute) - return; + return; [m_QTMovie setVolume:(m_masterVolume * m_relativeVolume)]; } @@ -318,7 +335,7 @@ void QuickTimeVideoPlayer::setMute(bool mute) return; // Work-around bug that happends if you set/unset mute - // before movie is playing, and audio is not played + // before movie is playing, and audio is not played // through graph. Then audio is delayed. [m_QTMovie setMuted:mute]; [m_QTMovie setVolume:(mute ? 0 : m_masterVolume * m_relativeVolume)]; @@ -331,7 +348,7 @@ void QuickTimeVideoPlayer::enableAudio(bool enable) return; // Work-around bug that happends if you set/unset mute - // before movie is playing, and audio is not played + // before movie is playing, and audio is not played // through graph. Then audio is delayed. [m_QTMovie setMuted:(!enable || m_mute)]; [m_QTMovie setVolume:((!enable || m_mute) ? 0 : m_masterVolume * m_relativeVolume)]; @@ -350,7 +367,7 @@ bool QuickTimeVideoPlayer::setAudioDevice(int id) #ifdef QUICKTIME_C_API_AVAILABLE // The following code will not work for some media codecs that // typically mingle audio/video frames (e.g mpeg). - CFStringRef idString = PhononCFString::toCFStringRef(AudioDevice::deviceUID(id)); + CFStringRef idString = PhononCFString::toCFStringRef(AudioDevice::deviceUID(id)); QTAudioContextRef context; QTAudioContextCreateForAudioDevice(kCFAllocatorDefault, idString, 0, &context); OSStatus err = SetMovieAudioContext([m_QTMovie quickTimeMovie], context); @@ -374,11 +391,16 @@ void QuickTimeVideoPlayer::setColors(qreal brightness, qreal contrast, qreal hue contrast += 1; saturation += 1; + if (m_brightness == brightness + && m_contrast == contrast + && m_hue == hue + && m_saturation == saturation) + return; + m_brightness = brightness; m_contrast = contrast; m_hue = hue; m_saturation = saturation; - #ifdef QUICKTIME_C_API_AVAILABLE Float32 value; value = brightness; @@ -390,6 +412,7 @@ void QuickTimeVideoPlayer::setColors(qreal brightness, qreal contrast, qreal hue value = saturation; SetMovieVisualSaturation([m_QTMovie quickTimeMovie], value, 0); #endif + releaseImageCache(); } QRect QuickTimeVideoPlayer::videoRect() const @@ -415,12 +438,15 @@ void QuickTimeVideoPlayer::unsetCurrentMediaSource() m_state = NoMedia; m_isDrmProtected = false; m_isDrmAuthorized = true; + m_hasVideo = false; + m_staticFps = 0; m_mediaSource = MediaSource(); m_movieCompactDiscPath.clear(); [(CIImage *)m_primaryRenderingCIImage release]; m_primaryRenderingCIImage = 0; delete m_QImagePixelBuffer; m_QImagePixelBuffer = 0; + releaseImageCache(); [m_folderTracks release]; m_folderTracks = 0; } @@ -572,6 +598,7 @@ void QuickTimeVideoPlayer::prepareCurrentMovieForPlayback() if (!m_playbackRateSat) m_playbackRate = prefferedPlaybackRate(); checkIfVideoAwailable(); + calculateStaticFps(); enableAudio(m_audioEnabled); setMute(m_mute); setVolume(m_masterVolume, m_relativeVolume); @@ -780,6 +807,44 @@ long QuickTimeVideoPlayer::timeScale() const return [[m_QTMovie attributeForKey:@"QTMovieTimeScaleAttribute"] longValue]; } +float QuickTimeVideoPlayer::staticFps() +{ + return m_staticFps; +} + +void QuickTimeVideoPlayer::calculateStaticFps() +{ + if (!m_hasVideo){ + m_staticFps = 0; + return; + } + +#ifdef QT_ALLOW_QUICKTIME + Boolean isMpeg = false; + Track videoTrack = GetMovieIndTrackType([m_QTMovie quickTimeMovie], 1, + FOUR_CHAR_CODE('vfrr'), // 'vfrr' means: has frame rate + movieTrackCharacteristic | movieTrackEnabledOnly); + Media media = GetTrackMedia(videoTrack); + MediaHandler mediaH = GetMediaHandler(media); + MediaHasCharacteristic(mediaH, FOUR_CHAR_CODE('mpeg'), &isMpeg); + + if (isMpeg){ + MHInfoEncodedFrameRateRecord frameRate; + Size frameRateSize = sizeof(frameRate); + MediaGetPublicInfo(mediaH, kMHInfoEncodedFrameRate, &frameRate, &frameRateSize); + m_staticFps = float(Fix2X(frameRate.encodedFrameRate)); + } else { + Media media = GetTrackMedia(videoTrack); + long sampleCount = GetMediaSampleCount(media); + TimeValue64 duration = GetMediaDisplayDuration(media); + TimeValue64 timeScale = GetMediaTimeScale(media); + m_staticFps = float((double)sampleCount * (double)timeScale / (double)duration); + } +#else + m_staticFps = 30.0f; +#endif +} + QString QuickTimeVideoPlayer::timeToString(quint64 ms) { int sec = ms/1000; diff --git a/src/3rdparty/phonon/qt7/videoframe.mm b/src/3rdparty/phonon/qt7/videoframe.mm index 92a3cd5..7b67b5e 100644 --- a/src/3rdparty/phonon/qt7/videoframe.mm +++ b/src/3rdparty/phonon/qt7/videoframe.mm @@ -20,6 +20,8 @@ #import <QuartzCore/CIFilter.h> #import <QuartzCore/CIContext.h> +//#define CACHE_CV_TEXTURE + QT_BEGIN_NAMESPACE namespace Phonon @@ -70,7 +72,9 @@ namespace QT7 void VideoFrame::copyMembers(const VideoFrame& frame) { +#ifdef CACHE_CV_TEXTURE m_cachedCVTextureRef = frame.m_cachedCVTextureRef; +#endif m_cachedCIImage = frame.m_cachedCIImage; m_cachedQImage = frame.m_cachedQImage; m_cachedNSBitmap = frame.m_cachedNSBitmap; @@ -105,11 +109,20 @@ namespace QT7 CVOpenGLTextureRef VideoFrame::cachedCVTexture() const { +#ifdef CACHE_CV_TEXTURE if (!m_cachedCVTextureRef && m_videoPlayer){ m_videoPlayer->setColors(m_brightness, m_contrast, m_hue, m_saturation); (const_cast<VideoFrame *>(this))->m_cachedCVTextureRef = m_videoPlayer->currentFrameAsCVTexture(); + CVOpenGLTextureRetain((const_cast<VideoFrame *>(this))->m_cachedCVTextureRef); } return m_cachedCVTextureRef; +#else + if (m_videoPlayer){ + m_videoPlayer->setColors(m_brightness, m_contrast, m_hue, m_saturation); + return m_videoPlayer->currentFrameAsCVTexture(); + } + return 0; +#endif } void *VideoFrame::cachedCIImage() const @@ -329,10 +342,12 @@ namespace QT7 void VideoFrame::invalidateImage() const { +#ifdef CACHE_CV_TEXTURE if (m_cachedCVTextureRef){ CVOpenGLTextureRelease(m_cachedCVTextureRef); (const_cast<VideoFrame *>(this))->m_cachedCVTextureRef = 0; } +#endif if (m_cachedCIImage){ [(CIImage *) m_cachedCIImage release]; (const_cast<VideoFrame *>(this))->m_cachedCIImage = 0; @@ -346,8 +361,10 @@ namespace QT7 void VideoFrame::retain() const { +#ifdef CACHE_CV_TEXTURE if (m_cachedCVTextureRef) CVOpenGLTextureRetain(m_cachedCVTextureRef); +#endif if (m_cachedCIImage) [(CIImage *) m_cachedCIImage retain]; if (m_backgroundFrame) @@ -358,8 +375,12 @@ namespace QT7 void VideoFrame::release() const { - if (m_cachedCVTextureRef) +#ifdef CACHE_CV_TEXTURE + if (m_cachedCVTextureRef){ CVOpenGLTextureRelease(m_cachedCVTextureRef); + (const_cast<VideoFrame *>(this))->m_cachedCVTextureRef = 0; + } +#endif if (m_cachedCIImage) [(CIImage *) m_cachedCIImage release]; if (m_backgroundFrame) @@ -368,7 +389,6 @@ namespace QT7 [m_cachedNSBitmap release]; (const_cast<VideoFrame *>(this))->m_backgroundFrame = 0; - (const_cast<VideoFrame *>(this))->m_cachedCVTextureRef = 0; (const_cast<VideoFrame *>(this))->m_cachedCIImage = 0; (const_cast<VideoFrame *>(this))->m_cachedNSBitmap = 0; } |