--- a/qtmobility/plugins/multimedia/directshow/player/directshowplayerservice.cpp Fri Apr 16 15:51:22 2010 +0300
+++ b/qtmobility/plugins/multimedia/directshow/player/directshowplayerservice.cpp Mon May 03 13:18:40 2010 +0300
@@ -49,15 +49,14 @@
#include "directshowvideorenderercontrol.h"
#include "vmr9videowindowcontrol.h"
-#include <qmediacontent.h>
+#include "../../src/multimedia/qmediacontent.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qthread.h>
#include <QtCore/qvarlengtharray.h>
-#include <uuids.h>
-
+Q_GLOBAL_STATIC(DirectShowEventLoop, qt_directShowEventLoop)
class DirectShowPlayerServiceThread : public QThread
{
@@ -77,12 +76,13 @@
DirectShowPlayerService::DirectShowPlayerService(QObject *parent)
: QMediaService(parent)
, m_playerControl(0)
- , m_audioEndpointControl(0)
, m_metaDataControl(0)
, m_videoOutputControl(0)
, m_videoRendererControl(0)
, m_videoWindowControl(0)
+ , m_audioEndpointControl(0)
, m_taskThread(0)
+ , m_loop(qt_directShowEventLoop())
, m_pendingTasks(0)
, m_executingTask(0)
, m_executedTasks(0)
@@ -105,7 +105,7 @@
m_metaDataControl = new DirectShowMetaDataControl(this);
m_videoOutputControl = new DirectShowVideoOutputControl;
m_audioEndpointControl = new DirectShowAudioEndpointControl(this);
- m_videoRendererControl = new DirectShowVideoRendererControl(&m_loop);
+ m_videoRendererControl = new DirectShowVideoRendererControl(m_loop);
m_videoWindowControl = new Vmr9VideoWindowControl;
m_taskThread = new DirectShowPlayerServiceThread(this);
@@ -178,6 +178,9 @@
m_resources = media.resources();
m_stream = stream;
+ m_error = QMediaPlayer::NoError;
+ m_errorString = QString();
+ m_position = 0;
m_duration = 0;
m_streamTypes = 0;
m_executedTasks = 0;
@@ -191,10 +194,17 @@
m_graphStatus = NoMedia;
m_url.clear();
+ } else if (stream && (!stream->isReadable() || stream->isSequential())) {
+ m_pendingTasks = 0;
+ m_graphStatus = InvalidMedia;
+ m_error = QMediaPlayer::ResourceError;
} else {
+ // {36b73882-c2c8-11cf-8b46-00805f6cef60}
+ static const GUID iid_IFilterGraph2 = {
+ 0x36b73882, 0xc2c8, 0x11cf, {0x8b, 0x46, 0x00, 0x80, 0x5f, 0x6c, 0xef, 0x60} };
m_graphStatus = Loading;
- m_graph = com_new<IFilterGraph2>(CLSID_FilterGraph);
+ m_graph = com_new<IFilterGraph2>(CLSID_FilterGraph, iid_IFilterGraph2);
if (stream)
m_pendingTasks = SetStreamSource;
@@ -204,8 +214,10 @@
::SetEvent(m_taskHandle);
}
+ m_playerControl->updateError(m_error, m_errorString);
m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable);
m_playerControl->updateState(QMediaPlayer::StoppedState);
+ m_playerControl->updatePosition(m_position);
updateStatus();
}
@@ -218,15 +230,22 @@
HRESULT hr = E_FAIL;
-#ifndef QT_NO_WMSDK
if (url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("https")) {
- if (IFileSourceFilter *fileSource = com_new<IFileSourceFilter>(CLSID_WMAsfReader)) {
+ static const GUID clsid_WMAsfReader = {
+ 0x187463a0, 0x5bb7, 0x11d3, {0xac, 0xbe, 0x00, 0x80, 0xc7, 0x5e, 0x24, 0x6e} };
+
+ // {56a868a6-0ad4-11ce-b03a-0020af0ba770}
+ static const GUID iid_IFileSourceFilter = {
+ 0x56a868a6, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} };
+
+ if (IFileSourceFilter *fileSource = com_new<IFileSourceFilter>(
+ clsid_WMAsfReader, iid_IFileSourceFilter)) {
locker->unlock();
- hr = fileSource->Load(url.toString().utf16(), 0);
+ hr = fileSource->Load(reinterpret_cast<const OLECHAR *>(url.toString().utf16()), 0);
locker->relock();
if (SUCCEEDED(hr)) {
- source = com_cast<IBaseFilter>(fileSource);
+ source = com_cast<IBaseFilter>(fileSource, IID_IBaseFilter);
if (!SUCCEEDED(hr = m_graph->AddFilter(source, L"Source")) && source) {
source->Release();
@@ -236,16 +255,21 @@
fileSource->Release();
}
+ } else if (url.scheme() == QLatin1String("qrc")) {
+ DirectShowRcSource *rcSource = new DirectShowRcSource(m_loop);
+
+ if (rcSource->open(url) && SUCCEEDED(hr = m_graph->AddFilter(rcSource, L"Source")))
+ source = rcSource;
+ else
+ rcSource->Release();
}
if (!SUCCEEDED(hr)) {
-#endif
locker->unlock();
- hr = m_graph->AddSourceFilter(url.toString().utf16(), L"Source", &source);
+ hr = m_graph->AddSourceFilter(
+ reinterpret_cast<const OLECHAR *>(url.toString().utf16()), L"Source", &source);
locker->relock();
-#ifndef QT_NO_WMSDK
}
-#endif
if (SUCCEEDED(hr)) {
m_executedTasks = SetSource;
@@ -269,14 +293,17 @@
switch (hr) {
case VFW_E_UNKNOWN_FILE_TYPE:
m_error = QMediaPlayer::FormatError;
+ m_errorString = QString();
break;
case E_OUTOFMEMORY:
case VFW_E_CANNOT_LOAD_SOURCE_FILTER:
case VFW_E_NOT_FOUND:
m_error = QMediaPlayer::ResourceError;
+ m_errorString = QString();
default:
m_error = QMediaPlayer::ResourceError;
- qWarning("DirectShowPlayerService::doSetUrlSource: Unresolved error code %x", hr);
+ m_errorString = QString();
+ qWarning("DirectShowPlayerService::doSetUrlSource: Unresolved error code %x", uint(hr));
break;
}
@@ -286,7 +313,8 @@
void DirectShowPlayerService::doSetStreamSource(QMutexLocker *locker)
{
- IBaseFilter *source = new DirectShowIOSource(m_stream, &m_loop);
+ DirectShowIOSource *source = new DirectShowIOSource(m_loop);
+ source->setDevice(m_stream);
if (SUCCEEDED(m_graph->AddFilter(source, L"Source"))) {
m_executedTasks = SetSource;
@@ -308,6 +336,7 @@
m_graphStatus = InvalidMedia;
m_error = QMediaPlayer::ResourceError;
+ m_errorString = QString();
QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error)));
}
@@ -315,6 +344,13 @@
void DirectShowPlayerService::doRender(QMutexLocker *locker)
{
+ m_pendingTasks |= m_executedTasks & (Play | Pause);
+
+ if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) {
+ control->Stop();
+ control->Release();
+ }
+
if (m_pendingTasks & SetAudioOutput) {
m_graph->AddFilter(m_audioOutput, L"AudioOutput");
@@ -354,14 +390,14 @@
IPin *peer = 0;
if (pin->ConnectedTo(&peer) == S_OK) {
PIN_INFO peerInfo;
- if (peer->QueryPinInfo(&peerInfo) == S_OK)
+ if (SUCCEEDED(peer->QueryPinInfo(&peerInfo)))
filters.append(peerInfo.pFilter);
peer->Release();
} else {
locker->unlock();
HRESULT hr;
if (SUCCEEDED(hr = graph->RenderEx(
- pin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, 0))) {
+ pin, /*AM_RENDEREX_RENDERTOEXISTINGRENDERERS*/ 1, 0))) {
rendered = true;
} else if (renderHr == S_OK || renderHr == VFW_E_NO_DECOMPRESSOR){
renderHr = hr;
@@ -370,13 +406,15 @@
}
}
}
+
+ pins->Release();
+
if (outputs == 0)
rendered = true;
}
filter->Release();
}
-
if (m_audioOutput && !isConnected(m_audioOutput, PINDIR_INPUT)) {
graph->RemoveFilter(m_audioOutput);
@@ -402,16 +440,19 @@
if (!m_audioOutput && !m_videoOutput) {
m_error = QMediaPlayer::ResourceError;
+ m_errorString = QString();
} else {
switch (renderHr) {
case VFW_E_UNSUPPORTED_AUDIO:
case VFW_E_UNSUPPORTED_VIDEO:
case VFW_E_UNSUPPORTED_STREAM:
m_error = QMediaPlayer::FormatError;
+ m_errorString = QString();
default:
m_error = QMediaPlayer::ResourceError;
+ m_errorString = QString();
qWarning("DirectShowPlayerService::doRender: Unresolved error code %x",
- renderHr);
+ uint(renderHr));
}
}
@@ -421,17 +462,17 @@
m_executedTasks |= Render;
}
- m_loop.wake();
+ m_loop->wake();
}
void DirectShowPlayerService::doFinalizeLoad(QMutexLocker *locker)
{
if (m_graphStatus != Loaded) {
- if (IMediaEvent *event = com_cast<IMediaEvent>(m_graph)) {
+ if (IMediaEvent *event = com_cast<IMediaEvent>(m_graph, IID_IMediaEvent)) {
event->GetEventHandle(reinterpret_cast<OAEVENT *>(&m_eventHandle));
event->Release();
}
- if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph)) {
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
LONGLONG duration = 0;
seeking->GetDuration(&duration);
m_duration = duration / 10;
@@ -461,7 +502,12 @@
{
if (m_graph) {
if (m_executingTask != 0) {
- if (IAMOpenProgress *progress = com_cast<IAMOpenProgress>(m_graph)) {
+ // {8E1C39A1-DE53-11cf-AA63-0080C744528D}
+ static const GUID iid_IAMOpenProgress = {
+ 0x8E1C39A1, 0xDE53, 0x11cf, {0xAA, 0x63, 0x00, 0x80, 0xC7, 0x44, 0x52, 0x8D} };
+
+ if (IAMOpenProgress *progress = com_cast<IAMOpenProgress>(
+ m_graph, iid_IAMOpenProgress)) {
progress->AbortOperation();
progress->Release();
}
@@ -472,7 +518,7 @@
::SetEvent(m_taskHandle);
- m_loop.wait(&m_mutex);
+ m_loop->wait(&m_mutex);
}
}
@@ -480,7 +526,7 @@
{
Q_UNUSED(locker);
- if (IMediaControl *control = com_cast<IMediaControl>(m_graph)) {
+ if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) {
control->Stop();
control->Release();
}
@@ -495,7 +541,7 @@
m_graph->Release();
m_graph = 0;
- m_loop.wake();
+ m_loop->wake();
}
int DirectShowPlayerService::findStreamTypes(IBaseFilter *source) const
@@ -595,23 +641,21 @@
void DirectShowPlayerService::doPlay(QMutexLocker *locker)
{
- if (IMediaControl *control = com_cast<IMediaControl>(m_graph)) {
+ if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) {
locker->unlock();
HRESULT hr = control->Run();
locker->relock();
control->Release();
- if (SUCCEEDED(hr))
- m_executedTasks |= Play;
-
if (SUCCEEDED(hr)) {
m_executedTasks |= Play;
QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange)));
} else {
m_error = QMediaPlayer::ResourceError;
- qWarning("DirectShowPlayerService::doPlay: Unresolved error code %x", hr);
+ m_errorString = QString();
+ qWarning("DirectShowPlayerService::doPlay: Unresolved error code %x", uint(hr));
QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error)));
}
@@ -639,7 +683,7 @@
void DirectShowPlayerService::doPause(QMutexLocker *locker)
{
- if (IMediaControl *control = com_cast<IMediaControl>(m_graph)) {
+ if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) {
locker->unlock();
HRESULT hr = control->Pause();
locker->relock();
@@ -647,12 +691,24 @@
control->Release();
if (SUCCEEDED(hr)) {
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
+ LONGLONG position = 0;
+
+ seeking->GetCurrentPosition(&position);
+ seeking->Release();
+
+ m_position = position / 10;
+ } else {
+ m_position = 0;
+ }
+
m_executedTasks |= Pause;
QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange)));
} else {
m_error = QMediaPlayer::ResourceError;
- qWarning("DirectShowPlayerService::doPause: Unresolved error code %x", hr);
+ m_errorString = QString();
+ qWarning("DirectShowPlayerService::doPause: Unresolved error code %x", uint(hr));
QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error)));
}
@@ -665,23 +721,43 @@
m_pendingTasks &= ~(Play | Pause | Seek);
- if (m_executedTasks & Render) {
- if (m_executingTask & (Play | Pause | Seek)) {
- m_pendingTasks |= Stop;
+ if ((m_executingTask | m_executedTasks) & (Play | Pause | Seek)) {
+ m_pendingTasks |= Stop;
+
+ ::SetEvent(m_taskHandle);
+
+ m_loop->wait(&m_mutex);
+ }
- m_loop.wait(&m_mutex);
+}
+
+void DirectShowPlayerService::doStop(QMutexLocker *locker)
+{
+ if (m_executedTasks & (Play | Pause)) {
+ if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) {
+ control->Stop();
+ control->Release();
}
- if (m_executedTasks & (Play | Pause)) {
- if (IMediaControl *control = com_cast<IMediaControl>(m_graph)) {
- control->Stop();
- control->Release();
- }
- m_executedTasks &= ~(Play | Pause);
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
+ LONGLONG position = 0;
+
+ seeking->GetCurrentPosition(&position);
+ seeking->Release();
+
+ m_position = position / 10;
+ } else {
+ m_position = 0;
}
+
+ m_executedTasks &= ~(Play | Pause);
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange)));
}
m_executedTasks |= Stop;
+
+ m_loop->wake();
}
void DirectShowPlayerService::setRate(qreal rate)
@@ -698,7 +774,7 @@
void DirectShowPlayerService::doSetRate(QMutexLocker *locker)
{
- if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph)) {
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
// Cache current values as we can't query IMediaSeeking during a seek due to the
// possibility of a deadlock when flushing the VideoSurfaceFilter.
LONGLONG currentPosition = 0;
@@ -736,13 +812,15 @@
if (m_graphStatus == Loaded) {
if (m_executingTask == Seek || m_executingTask == SetRate) {
return m_position;
- } else if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph)) {
+ } else if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
LONGLONG position = 0;
seeking->GetCurrentPosition(&position);
seeking->Release();
- return position / 10;
+ const_cast<qint64 &>(m_position) = position / 10;
+
+ return m_position;
}
}
return 0;
@@ -755,7 +833,7 @@
if (m_graphStatus == Loaded) {
if (m_executingTask == Seek || m_executingTask == SetRate) {
return m_playbackRange;
- } else if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph)) {
+ } else if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
LONGLONG minimum = 0;
LONGLONG maximum = 0;
@@ -783,7 +861,7 @@
void DirectShowPlayerService::doSeek(QMutexLocker *locker)
{
- if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph)) {
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
LONGLONG seekPosition = LONGLONG(m_position) * 10;
// Cache current values as we can't query IMediaSeeking during a seek due to the
@@ -803,8 +881,15 @@
&seekPosition, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning);
locker->relock();
+ seeking->GetCurrentPosition(¤tPosition);
+ m_position = currentPosition / 10;
+
seeking->Release();
+ } else {
+ m_position = 0;
}
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PositionChange)));
}
int DirectShowPlayerService::bufferStatus() const
@@ -812,7 +897,8 @@
#ifndef QT_NO_WMSDK
QMutexLocker locker(const_cast<QMutex *>(&m_mutex));
- if (IWMReaderAdvanced2 *reader = com_cast<IWMReaderAdvanced2>(m_source)) {
+ if (IWMReaderAdvanced2 *reader = com_cast<IWMReaderAdvanced2>(
+ m_source, IID_IWMReaderAdvanced2)) {
DWORD percentage = 0;
reader->GetBufferProgress(&percentage, 0);
@@ -838,7 +924,7 @@
::SetEvent(m_taskHandle);
- m_loop.wait(&m_mutex);
+ m_loop->wait(&m_mutex);
}
m_audioOutput->Release();
}
@@ -849,15 +935,15 @@
m_audioOutput->AddRef();
m_pendingTasks |= SetAudioOutput;
+
+ if (m_executedTasks & SetSource) {
+ m_pendingTasks |= Render;
+
+ ::SetEvent(m_taskHandle);
+ }
} else {
m_pendingTasks &= ~ SetAudioOutput;
}
-
- if (m_executedTasks & SetSource) {
- m_pendingTasks |= Render;
-
- ::SetEvent(m_taskHandle);
- }
} else {
if (m_audioOutput)
m_audioOutput->Release();
@@ -875,16 +961,33 @@
{
m_pendingTasks |= m_executedTasks & (Play | Pause);
- if (IMediaControl *control = com_cast<IMediaControl>(m_graph)) {
+ if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) {
control->Stop();
control->Release();
}
- m_graph->RemoveFilter(m_audioOutput);
+ IBaseFilter *decoder = getConnected(m_audioOutput, PINDIR_INPUT);
+ if (!decoder) {
+ decoder = m_audioOutput;
+ decoder->AddRef();
+ }
+
+ // {DCFBDCF6-0DC2-45f5-9AB2-7C330EA09C29}
+ static const GUID iid_IFilterChain = {
+ 0xDCFBDCF6, 0x0DC2, 0x45f5, {0x9A, 0xB2, 0x7C, 0x33, 0x0E, 0xA0, 0x9C, 0x29} };
+
+ if (IFilterChain *chain = com_cast<IFilterChain>(m_graph, iid_IFilterChain)) {
+ chain->RemoveChain(decoder, m_audioOutput);
+ chain->Release();
+ } else {
+ m_graph->RemoveFilter(m_audioOutput);
+ }
+
+ decoder->Release();
m_executedTasks &= ~SetAudioOutput;
- m_loop.wake();
+ m_loop->wake();
}
void DirectShowPlayerService::setVideoOutput(IBaseFilter *filter)
@@ -898,7 +1001,7 @@
::SetEvent(m_taskHandle);
- m_loop.wait(&m_mutex);
+ m_loop->wait(&m_mutex);
}
m_videoOutput->Release();
}
@@ -909,14 +1012,12 @@
m_videoOutput->AddRef();
m_pendingTasks |= SetVideoOutput;
- } else {
- m_pendingTasks &= ~ SetVideoOutput;
- }
- if (m_executedTasks & SetSource) {
- m_pendingTasks |= Render;
+ if (m_executedTasks & SetSource) {
+ m_pendingTasks |= Render;
- ::SetEvent(m_taskHandle);
+ ::SetEvent(m_taskHandle);
+ }
}
} else {
if (m_videoOutput)
@@ -933,16 +1034,40 @@
{
m_pendingTasks |= m_executedTasks & (Play | Pause);
- if (IMediaControl *control = com_cast<IMediaControl>(m_graph)) {
+ if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) {
control->Stop();
control->Release();
}
- m_graph->RemoveFilter(m_videoOutput);
+ IBaseFilter *intermediate = 0;
+ if (!SUCCEEDED(m_graph->FindFilterByName(L"Color Space Converter", &intermediate))) {
+ intermediate = m_videoOutput;
+ intermediate->AddRef();
+ }
+
+ IBaseFilter *decoder = getConnected(intermediate, PINDIR_INPUT);
+ if (!decoder) {
+ decoder = intermediate;
+ decoder->AddRef();
+ }
+
+ // {DCFBDCF6-0DC2-45f5-9AB2-7C330EA09C29}
+ static const GUID iid_IFilterChain = {
+ 0xDCFBDCF6, 0x0DC2, 0x45f5, {0x9A, 0xB2, 0x7C, 0x33, 0x0E, 0xA0, 0x9C, 0x29} };
+
+ if (IFilterChain *chain = com_cast<IFilterChain>(m_graph, iid_IFilterChain)) {
+ chain->RemoveChain(decoder, m_videoOutput);
+ chain->Release();
+ } else {
+ m_graph->RemoveFilter(m_videoOutput);
+ }
+
+ intermediate->Release();
+ decoder->Release();
m_executedTasks &= ~SetVideoOutput;
- m_loop.wake();
+ m_loop->wake();
}
void DirectShowPlayerService::customEvent(QEvent *event)
@@ -955,18 +1080,14 @@
updateStatus();
} else if (event->type() == QEvent::Type(Error)) {
- QMediaPlayer::Error error;
- {
- QMutexLocker locker(&m_mutex);
- error = m_error;
+ QMutexLocker locker(&m_mutex);
- if (error != QMediaPlayer::NoError) {
- m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable);
- m_playerControl->updateState(QMediaPlayer::StoppedState);
- updateStatus();
- }
+ if (m_error != QMediaPlayer::NoError) {
+ m_playerControl->updateError(m_error, m_errorString);
+ m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable);
+ m_playerControl->updateState(QMediaPlayer::StoppedState);
+ updateStatus();
}
- m_playerControl->error(error, QString());
} else if (event->type() == QEvent::Type(RateChange)) {
QMutexLocker locker(&m_mutex);
@@ -975,6 +1096,7 @@
QMutexLocker locker(&m_mutex);
updateStatus();
+ m_playerControl->updatePosition(m_position);
} else if (event->type() == QEvent::Type(DurationChange)) {
QMutexLocker locker(&m_mutex);
@@ -985,7 +1107,12 @@
if (m_atEnd) {
m_playerControl->updateState(QMediaPlayer::StoppedState);
m_playerControl->updateStatus(QMediaPlayer::EndOfMedia);
+ m_playerControl->updatePosition(m_position);
}
+ } else if (event->type() == QEvent::Type(PositionChange)) {
+ QMutexLocker locker(&m_mutex);
+
+ m_playerControl->updatePosition(m_position);
} else {
QMediaService::customEvent(event);
}
@@ -1011,7 +1138,7 @@
void DirectShowPlayerService::graphEvent(QMutexLocker *locker)
{
- if (IMediaEvent *event = com_cast<IMediaEvent>(m_graph)) {
+ if (IMediaEvent *event = com_cast<IMediaEvent>(m_graph, IID_IMediaEvent)) {
long eventCode;
LONG_PTR param1;
LONG_PTR param2;
@@ -1030,10 +1157,19 @@
m_buffering = false;
m_atEnd = true;
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
+ LONGLONG position = 0;
+
+ seeking->GetCurrentPosition(&position);
+ seeking->Release();
+
+ m_position = position / 10;
+ }
+
QCoreApplication::postEvent(this, new QEvent(QEvent::Type(EndOfMedia)));
break;
case EC_LENGTH_CHANGED:
- if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph)) {
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
LONGLONG duration = 0;
seeking->GetDuration(&duration);
m_duration = duration / 10;
@@ -1107,6 +1243,38 @@
return connected;
}
+IBaseFilter *DirectShowPlayerService::getConnected(
+ IBaseFilter *filter, PIN_DIRECTION direction) const
+{
+ IBaseFilter *connected = 0;
+
+ IEnumPins *pins = 0;
+
+ if (SUCCEEDED(filter->EnumPins(&pins))) {
+ for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) {
+ PIN_DIRECTION dir;
+ if (SUCCEEDED(pin->QueryDirection(&dir)) && dir == direction) {
+ IPin *peer = 0;
+ if (SUCCEEDED(pin->ConnectedTo(&peer))) {
+ PIN_INFO info;
+
+ if (SUCCEEDED(peer->QueryPinInfo(&info))) {
+ if (connected) {
+ qWarning("DirectShowPlayerService::getConnected: "
+ "Multiple connected filters");
+ connected->Release();
+ }
+ connected = info.pFilter;
+ }
+ peer->Release();
+ }
+ }
+ }
+ pins->Release();
+ }
+ return connected;
+}
+
void DirectShowPlayerService::run()
{
QMutexLocker locker(&m_mutex);
@@ -1171,15 +1339,16 @@
m_executingTask = FinalizeLoad;
doFinalizeLoad(&locker);
+ } else if (m_pendingTasks & Stop) {
+ m_pendingTasks ^= Stop;
+ m_executingTask = Stop;
+
+ doStop(&locker);
} else if (m_pendingTasks & SetRate) {
m_pendingTasks ^= SetRate;
m_executingTask = SetRate;
doSetRate(&locker);
- } else if (m_pendingTasks & Stop) {
- m_pendingTasks ^= Stop;
-
- m_loop.wake();
} else if (m_pendingTasks & Pause) {
m_pendingTasks ^= Pause;
m_executingTask = Pause;