47 #include "directshowplayercontrol.h" |
47 #include "directshowplayercontrol.h" |
48 #include "directshowvideooutputcontrol.h" |
48 #include "directshowvideooutputcontrol.h" |
49 #include "directshowvideorenderercontrol.h" |
49 #include "directshowvideorenderercontrol.h" |
50 #include "vmr9videowindowcontrol.h" |
50 #include "vmr9videowindowcontrol.h" |
51 |
51 |
52 #include <qmediacontent.h> |
52 #include "../../src/multimedia/qmediacontent.h" |
53 |
53 |
54 #include <QtCore/qcoreapplication.h> |
54 #include <QtCore/qcoreapplication.h> |
55 #include <QtCore/qdatetime.h> |
55 #include <QtCore/qdatetime.h> |
56 #include <QtCore/qthread.h> |
56 #include <QtCore/qthread.h> |
57 #include <QtCore/qvarlengtharray.h> |
57 #include <QtCore/qvarlengtharray.h> |
58 |
58 |
59 #include <uuids.h> |
59 Q_GLOBAL_STATIC(DirectShowEventLoop, qt_directShowEventLoop) |
60 |
|
61 |
60 |
62 class DirectShowPlayerServiceThread : public QThread |
61 class DirectShowPlayerServiceThread : public QThread |
63 { |
62 { |
64 public: |
63 public: |
65 DirectShowPlayerServiceThread(DirectShowPlayerService *service) |
64 DirectShowPlayerServiceThread(DirectShowPlayerService *service) |
75 }; |
74 }; |
76 |
75 |
77 DirectShowPlayerService::DirectShowPlayerService(QObject *parent) |
76 DirectShowPlayerService::DirectShowPlayerService(QObject *parent) |
78 : QMediaService(parent) |
77 : QMediaService(parent) |
79 , m_playerControl(0) |
78 , m_playerControl(0) |
80 , m_audioEndpointControl(0) |
|
81 , m_metaDataControl(0) |
79 , m_metaDataControl(0) |
82 , m_videoOutputControl(0) |
80 , m_videoOutputControl(0) |
83 , m_videoRendererControl(0) |
81 , m_videoRendererControl(0) |
84 , m_videoWindowControl(0) |
82 , m_videoWindowControl(0) |
|
83 , m_audioEndpointControl(0) |
85 , m_taskThread(0) |
84 , m_taskThread(0) |
|
85 , m_loop(qt_directShowEventLoop()) |
86 , m_pendingTasks(0) |
86 , m_pendingTasks(0) |
87 , m_executingTask(0) |
87 , m_executingTask(0) |
88 , m_executedTasks(0) |
88 , m_executedTasks(0) |
89 , m_taskHandle(::CreateEvent(0, 0, 0, 0)) |
89 , m_taskHandle(::CreateEvent(0, 0, 0, 0)) |
90 , m_eventHandle(0) |
90 , m_eventHandle(0) |
103 { |
103 { |
104 m_playerControl = new DirectShowPlayerControl(this); |
104 m_playerControl = new DirectShowPlayerControl(this); |
105 m_metaDataControl = new DirectShowMetaDataControl(this); |
105 m_metaDataControl = new DirectShowMetaDataControl(this); |
106 m_videoOutputControl = new DirectShowVideoOutputControl; |
106 m_videoOutputControl = new DirectShowVideoOutputControl; |
107 m_audioEndpointControl = new DirectShowAudioEndpointControl(this); |
107 m_audioEndpointControl = new DirectShowAudioEndpointControl(this); |
108 m_videoRendererControl = new DirectShowVideoRendererControl(&m_loop); |
108 m_videoRendererControl = new DirectShowVideoRendererControl(m_loop); |
109 m_videoWindowControl = new Vmr9VideoWindowControl; |
109 m_videoWindowControl = new Vmr9VideoWindowControl; |
110 |
110 |
111 m_taskThread = new DirectShowPlayerServiceThread(this); |
111 m_taskThread = new DirectShowPlayerServiceThread(this); |
112 m_taskThread->start(); |
112 m_taskThread->start(); |
113 |
113 |
189 if (m_resources.isEmpty() && !stream) { |
192 if (m_resources.isEmpty() && !stream) { |
190 m_pendingTasks = 0; |
193 m_pendingTasks = 0; |
191 m_graphStatus = NoMedia; |
194 m_graphStatus = NoMedia; |
192 |
195 |
193 m_url.clear(); |
196 m_url.clear(); |
|
197 } else if (stream && (!stream->isReadable() || stream->isSequential())) { |
|
198 m_pendingTasks = 0; |
|
199 m_graphStatus = InvalidMedia; |
|
200 m_error = QMediaPlayer::ResourceError; |
194 } else { |
201 } else { |
|
202 // {36b73882-c2c8-11cf-8b46-00805f6cef60} |
|
203 static const GUID iid_IFilterGraph2 = { |
|
204 0x36b73882, 0xc2c8, 0x11cf, {0x8b, 0x46, 0x00, 0x80, 0x5f, 0x6c, 0xef, 0x60} }; |
195 m_graphStatus = Loading; |
205 m_graphStatus = Loading; |
196 |
206 |
197 m_graph = com_new<IFilterGraph2>(CLSID_FilterGraph); |
207 m_graph = com_new<IFilterGraph2>(CLSID_FilterGraph, iid_IFilterGraph2); |
198 |
208 |
199 if (stream) |
209 if (stream) |
200 m_pendingTasks = SetStreamSource; |
210 m_pendingTasks = SetStreamSource; |
201 else |
211 else |
202 m_pendingTasks = SetUrlSource; |
212 m_pendingTasks = SetUrlSource; |
203 |
213 |
204 ::SetEvent(m_taskHandle); |
214 ::SetEvent(m_taskHandle); |
205 } |
215 } |
206 |
216 |
|
217 m_playerControl->updateError(m_error, m_errorString); |
207 m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); |
218 m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); |
208 m_playerControl->updateState(QMediaPlayer::StoppedState); |
219 m_playerControl->updateState(QMediaPlayer::StoppedState); |
|
220 m_playerControl->updatePosition(m_position); |
209 updateStatus(); |
221 updateStatus(); |
210 } |
222 } |
211 |
223 |
212 void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker) |
224 void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker) |
213 { |
225 { |
216 QMediaResource resource = m_resources.takeFirst(); |
228 QMediaResource resource = m_resources.takeFirst(); |
217 QUrl url = resource.url(); |
229 QUrl url = resource.url(); |
218 |
230 |
219 HRESULT hr = E_FAIL; |
231 HRESULT hr = E_FAIL; |
220 |
232 |
221 #ifndef QT_NO_WMSDK |
|
222 if (url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("https")) { |
233 if (url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("https")) { |
223 if (IFileSourceFilter *fileSource = com_new<IFileSourceFilter>(CLSID_WMAsfReader)) { |
234 static const GUID clsid_WMAsfReader = { |
|
235 0x187463a0, 0x5bb7, 0x11d3, {0xac, 0xbe, 0x00, 0x80, 0xc7, 0x5e, 0x24, 0x6e} }; |
|
236 |
|
237 // {56a868a6-0ad4-11ce-b03a-0020af0ba770} |
|
238 static const GUID iid_IFileSourceFilter = { |
|
239 0x56a868a6, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} }; |
|
240 |
|
241 if (IFileSourceFilter *fileSource = com_new<IFileSourceFilter>( |
|
242 clsid_WMAsfReader, iid_IFileSourceFilter)) { |
224 locker->unlock(); |
243 locker->unlock(); |
225 hr = fileSource->Load(url.toString().utf16(), 0); |
244 hr = fileSource->Load(reinterpret_cast<const OLECHAR *>(url.toString().utf16()), 0); |
226 locker->relock(); |
245 locker->relock(); |
227 |
246 |
228 if (SUCCEEDED(hr)) { |
247 if (SUCCEEDED(hr)) { |
229 source = com_cast<IBaseFilter>(fileSource); |
248 source = com_cast<IBaseFilter>(fileSource, IID_IBaseFilter); |
230 |
249 |
231 if (!SUCCEEDED(hr = m_graph->AddFilter(source, L"Source")) && source) { |
250 if (!SUCCEEDED(hr = m_graph->AddFilter(source, L"Source")) && source) { |
232 source->Release(); |
251 source->Release(); |
233 source = 0; |
252 source = 0; |
234 } |
253 } |
235 } |
254 } |
236 |
255 |
237 fileSource->Release(); |
256 fileSource->Release(); |
238 } |
257 } |
|
258 } else if (url.scheme() == QLatin1String("qrc")) { |
|
259 DirectShowRcSource *rcSource = new DirectShowRcSource(m_loop); |
|
260 |
|
261 if (rcSource->open(url) && SUCCEEDED(hr = m_graph->AddFilter(rcSource, L"Source"))) |
|
262 source = rcSource; |
|
263 else |
|
264 rcSource->Release(); |
239 } |
265 } |
240 |
266 |
241 if (!SUCCEEDED(hr)) { |
267 if (!SUCCEEDED(hr)) { |
242 #endif |
|
243 locker->unlock(); |
268 locker->unlock(); |
244 hr = m_graph->AddSourceFilter(url.toString().utf16(), L"Source", &source); |
269 hr = m_graph->AddSourceFilter( |
|
270 reinterpret_cast<const OLECHAR *>(url.toString().utf16()), L"Source", &source); |
245 locker->relock(); |
271 locker->relock(); |
246 #ifndef QT_NO_WMSDK |
272 } |
247 } |
|
248 #endif |
|
249 |
273 |
250 if (SUCCEEDED(hr)) { |
274 if (SUCCEEDED(hr)) { |
251 m_executedTasks = SetSource; |
275 m_executedTasks = SetSource; |
252 m_pendingTasks |= Render; |
276 m_pendingTasks |= Render; |
253 |
277 |
267 m_graphStatus = InvalidMedia; |
291 m_graphStatus = InvalidMedia; |
268 |
292 |
269 switch (hr) { |
293 switch (hr) { |
270 case VFW_E_UNKNOWN_FILE_TYPE: |
294 case VFW_E_UNKNOWN_FILE_TYPE: |
271 m_error = QMediaPlayer::FormatError; |
295 m_error = QMediaPlayer::FormatError; |
|
296 m_errorString = QString(); |
272 break; |
297 break; |
273 case E_OUTOFMEMORY: |
298 case E_OUTOFMEMORY: |
274 case VFW_E_CANNOT_LOAD_SOURCE_FILTER: |
299 case VFW_E_CANNOT_LOAD_SOURCE_FILTER: |
275 case VFW_E_NOT_FOUND: |
300 case VFW_E_NOT_FOUND: |
276 m_error = QMediaPlayer::ResourceError; |
301 m_error = QMediaPlayer::ResourceError; |
|
302 m_errorString = QString(); |
277 default: |
303 default: |
278 m_error = QMediaPlayer::ResourceError; |
304 m_error = QMediaPlayer::ResourceError; |
279 qWarning("DirectShowPlayerService::doSetUrlSource: Unresolved error code %x", hr); |
305 m_errorString = QString(); |
|
306 qWarning("DirectShowPlayerService::doSetUrlSource: Unresolved error code %x", uint(hr)); |
280 break; |
307 break; |
281 } |
308 } |
282 |
309 |
283 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); |
310 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); |
284 } |
311 } |
285 } |
312 } |
286 |
313 |
287 void DirectShowPlayerService::doSetStreamSource(QMutexLocker *locker) |
314 void DirectShowPlayerService::doSetStreamSource(QMutexLocker *locker) |
288 { |
315 { |
289 IBaseFilter *source = new DirectShowIOSource(m_stream, &m_loop); |
316 DirectShowIOSource *source = new DirectShowIOSource(m_loop); |
|
317 source->setDevice(m_stream); |
290 |
318 |
291 if (SUCCEEDED(m_graph->AddFilter(source, L"Source"))) { |
319 if (SUCCEEDED(m_graph->AddFilter(source, L"Source"))) { |
292 m_executedTasks = SetSource; |
320 m_executedTasks = SetSource; |
293 m_pendingTasks |= Render; |
321 m_pendingTasks |= Render; |
294 |
322 |
306 |
334 |
307 m_pendingTasks = 0; |
335 m_pendingTasks = 0; |
308 m_graphStatus = InvalidMedia; |
336 m_graphStatus = InvalidMedia; |
309 |
337 |
310 m_error = QMediaPlayer::ResourceError; |
338 m_error = QMediaPlayer::ResourceError; |
|
339 m_errorString = QString(); |
311 |
340 |
312 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); |
341 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); |
313 } |
342 } |
314 } |
343 } |
315 |
344 |
316 void DirectShowPlayerService::doRender(QMutexLocker *locker) |
345 void DirectShowPlayerService::doRender(QMutexLocker *locker) |
317 { |
346 { |
|
347 m_pendingTasks |= m_executedTasks & (Play | Pause); |
|
348 |
|
349 if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) { |
|
350 control->Stop(); |
|
351 control->Release(); |
|
352 } |
|
353 |
318 if (m_pendingTasks & SetAudioOutput) { |
354 if (m_pendingTasks & SetAudioOutput) { |
319 m_graph->AddFilter(m_audioOutput, L"AudioOutput"); |
355 m_graph->AddFilter(m_audioOutput, L"AudioOutput"); |
320 |
356 |
321 m_pendingTasks ^= SetAudioOutput; |
357 m_pendingTasks ^= SetAudioOutput; |
322 m_executedTasks |= SetAudioOutput; |
358 m_executedTasks |= SetAudioOutput; |
352 ++outputs; |
388 ++outputs; |
353 |
389 |
354 IPin *peer = 0; |
390 IPin *peer = 0; |
355 if (pin->ConnectedTo(&peer) == S_OK) { |
391 if (pin->ConnectedTo(&peer) == S_OK) { |
356 PIN_INFO peerInfo; |
392 PIN_INFO peerInfo; |
357 if (peer->QueryPinInfo(&peerInfo) == S_OK) |
393 if (SUCCEEDED(peer->QueryPinInfo(&peerInfo))) |
358 filters.append(peerInfo.pFilter); |
394 filters.append(peerInfo.pFilter); |
359 peer->Release(); |
395 peer->Release(); |
360 } else { |
396 } else { |
361 locker->unlock(); |
397 locker->unlock(); |
362 HRESULT hr; |
398 HRESULT hr; |
363 if (SUCCEEDED(hr = graph->RenderEx( |
399 if (SUCCEEDED(hr = graph->RenderEx( |
364 pin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, 0))) { |
400 pin, /*AM_RENDEREX_RENDERTOEXISTINGRENDERERS*/ 1, 0))) { |
365 rendered = true; |
401 rendered = true; |
366 } else if (renderHr == S_OK || renderHr == VFW_E_NO_DECOMPRESSOR){ |
402 } else if (renderHr == S_OK || renderHr == VFW_E_NO_DECOMPRESSOR){ |
367 renderHr = hr; |
403 renderHr = hr; |
368 } |
404 } |
369 locker->relock(); |
405 locker->relock(); |
370 } |
406 } |
371 } |
407 } |
372 } |
408 } |
|
409 |
|
410 pins->Release(); |
|
411 |
373 if (outputs == 0) |
412 if (outputs == 0) |
374 rendered = true; |
413 rendered = true; |
375 } |
414 } |
376 filter->Release(); |
415 filter->Release(); |
377 } |
416 } |
378 |
|
379 |
417 |
380 if (m_audioOutput && !isConnected(m_audioOutput, PINDIR_INPUT)) { |
418 if (m_audioOutput && !isConnected(m_audioOutput, PINDIR_INPUT)) { |
381 graph->RemoveFilter(m_audioOutput); |
419 graph->RemoveFilter(m_audioOutput); |
382 |
420 |
383 m_executedTasks &= ~SetAudioOutput; |
421 m_executedTasks &= ~SetAudioOutput; |
400 |
438 |
401 m_graphStatus = InvalidMedia; |
439 m_graphStatus = InvalidMedia; |
402 |
440 |
403 if (!m_audioOutput && !m_videoOutput) { |
441 if (!m_audioOutput && !m_videoOutput) { |
404 m_error = QMediaPlayer::ResourceError; |
442 m_error = QMediaPlayer::ResourceError; |
|
443 m_errorString = QString(); |
405 } else { |
444 } else { |
406 switch (renderHr) { |
445 switch (renderHr) { |
407 case VFW_E_UNSUPPORTED_AUDIO: |
446 case VFW_E_UNSUPPORTED_AUDIO: |
408 case VFW_E_UNSUPPORTED_VIDEO: |
447 case VFW_E_UNSUPPORTED_VIDEO: |
409 case VFW_E_UNSUPPORTED_STREAM: |
448 case VFW_E_UNSUPPORTED_STREAM: |
410 m_error = QMediaPlayer::FormatError; |
449 m_error = QMediaPlayer::FormatError; |
|
450 m_errorString = QString(); |
411 default: |
451 default: |
412 m_error = QMediaPlayer::ResourceError; |
452 m_error = QMediaPlayer::ResourceError; |
|
453 m_errorString = QString(); |
413 qWarning("DirectShowPlayerService::doRender: Unresolved error code %x", |
454 qWarning("DirectShowPlayerService::doRender: Unresolved error code %x", |
414 renderHr); |
455 uint(renderHr)); |
415 } |
456 } |
416 } |
457 } |
417 |
458 |
418 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); |
459 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); |
419 } |
460 } |
420 |
461 |
421 m_executedTasks |= Render; |
462 m_executedTasks |= Render; |
422 } |
463 } |
423 |
464 |
424 m_loop.wake(); |
465 m_loop->wake(); |
425 } |
466 } |
426 |
467 |
427 void DirectShowPlayerService::doFinalizeLoad(QMutexLocker *locker) |
468 void DirectShowPlayerService::doFinalizeLoad(QMutexLocker *locker) |
428 { |
469 { |
429 if (m_graphStatus != Loaded) { |
470 if (m_graphStatus != Loaded) { |
430 if (IMediaEvent *event = com_cast<IMediaEvent>(m_graph)) { |
471 if (IMediaEvent *event = com_cast<IMediaEvent>(m_graph, IID_IMediaEvent)) { |
431 event->GetEventHandle(reinterpret_cast<OAEVENT *>(&m_eventHandle)); |
472 event->GetEventHandle(reinterpret_cast<OAEVENT *>(&m_eventHandle)); |
432 event->Release(); |
473 event->Release(); |
433 } |
474 } |
434 if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph)) { |
475 if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { |
435 LONGLONG duration = 0; |
476 LONGLONG duration = 0; |
436 seeking->GetDuration(&duration); |
477 seeking->GetDuration(&duration); |
437 m_duration = duration / 10; |
478 m_duration = duration / 10; |
438 |
479 |
439 DWORD capabilities = 0; |
480 DWORD capabilities = 0; |
459 |
500 |
460 void DirectShowPlayerService::releaseGraph() |
501 void DirectShowPlayerService::releaseGraph() |
461 { |
502 { |
462 if (m_graph) { |
503 if (m_graph) { |
463 if (m_executingTask != 0) { |
504 if (m_executingTask != 0) { |
464 if (IAMOpenProgress *progress = com_cast<IAMOpenProgress>(m_graph)) { |
505 // {8E1C39A1-DE53-11cf-AA63-0080C744528D} |
|
506 static const GUID iid_IAMOpenProgress = { |
|
507 0x8E1C39A1, 0xDE53, 0x11cf, {0xAA, 0x63, 0x00, 0x80, 0xC7, 0x44, 0x52, 0x8D} }; |
|
508 |
|
509 if (IAMOpenProgress *progress = com_cast<IAMOpenProgress>( |
|
510 m_graph, iid_IAMOpenProgress)) { |
465 progress->AbortOperation(); |
511 progress->AbortOperation(); |
466 progress->Release(); |
512 progress->Release(); |
467 } |
513 } |
468 m_graph->Abort(); |
514 m_graph->Abort(); |
469 } |
515 } |
470 |
516 |
471 m_pendingTasks = ReleaseGraph; |
517 m_pendingTasks = ReleaseGraph; |
472 |
518 |
473 ::SetEvent(m_taskHandle); |
519 ::SetEvent(m_taskHandle); |
474 |
520 |
475 m_loop.wait(&m_mutex); |
521 m_loop->wait(&m_mutex); |
476 } |
522 } |
477 } |
523 } |
478 |
524 |
479 void DirectShowPlayerService::doReleaseGraph(QMutexLocker *locker) |
525 void DirectShowPlayerService::doReleaseGraph(QMutexLocker *locker) |
480 { |
526 { |
481 Q_UNUSED(locker); |
527 Q_UNUSED(locker); |
482 |
528 |
483 if (IMediaControl *control = com_cast<IMediaControl>(m_graph)) { |
529 if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) { |
484 control->Stop(); |
530 control->Stop(); |
485 control->Release(); |
531 control->Release(); |
486 } |
532 } |
487 |
533 |
488 if (m_source) { |
534 if (m_source) { |
593 } |
639 } |
594 } |
640 } |
595 |
641 |
596 void DirectShowPlayerService::doPlay(QMutexLocker *locker) |
642 void DirectShowPlayerService::doPlay(QMutexLocker *locker) |
597 { |
643 { |
598 if (IMediaControl *control = com_cast<IMediaControl>(m_graph)) { |
644 if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) { |
599 locker->unlock(); |
645 locker->unlock(); |
600 HRESULT hr = control->Run(); |
646 HRESULT hr = control->Run(); |
601 locker->relock(); |
647 locker->relock(); |
602 |
648 |
603 control->Release(); |
649 control->Release(); |
604 |
650 |
605 if (SUCCEEDED(hr)) |
|
606 m_executedTasks |= Play; |
|
607 |
|
608 if (SUCCEEDED(hr)) { |
651 if (SUCCEEDED(hr)) { |
609 m_executedTasks |= Play; |
652 m_executedTasks |= Play; |
610 |
653 |
611 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); |
654 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); |
612 } else { |
655 } else { |
613 m_error = QMediaPlayer::ResourceError; |
656 m_error = QMediaPlayer::ResourceError; |
614 qWarning("DirectShowPlayerService::doPlay: Unresolved error code %x", hr); |
657 m_errorString = QString(); |
|
658 qWarning("DirectShowPlayerService::doPlay: Unresolved error code %x", uint(hr)); |
615 |
659 |
616 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); |
660 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); |
617 } |
661 } |
618 } |
662 } |
619 } |
663 } |
637 } |
681 } |
638 } |
682 } |
639 |
683 |
640 void DirectShowPlayerService::doPause(QMutexLocker *locker) |
684 void DirectShowPlayerService::doPause(QMutexLocker *locker) |
641 { |
685 { |
642 if (IMediaControl *control = com_cast<IMediaControl>(m_graph)) { |
686 if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) { |
643 locker->unlock(); |
687 locker->unlock(); |
644 HRESULT hr = control->Pause(); |
688 HRESULT hr = control->Pause(); |
645 locker->relock(); |
689 locker->relock(); |
646 |
690 |
647 control->Release(); |
691 control->Release(); |
648 |
692 |
649 if (SUCCEEDED(hr)) { |
693 if (SUCCEEDED(hr)) { |
|
694 if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { |
|
695 LONGLONG position = 0; |
|
696 |
|
697 seeking->GetCurrentPosition(&position); |
|
698 seeking->Release(); |
|
699 |
|
700 m_position = position / 10; |
|
701 } else { |
|
702 m_position = 0; |
|
703 } |
|
704 |
650 m_executedTasks |= Pause; |
705 m_executedTasks |= Pause; |
651 |
706 |
652 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); |
707 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); |
653 } else { |
708 } else { |
654 m_error = QMediaPlayer::ResourceError; |
709 m_error = QMediaPlayer::ResourceError; |
655 qWarning("DirectShowPlayerService::doPause: Unresolved error code %x", hr); |
710 m_errorString = QString(); |
|
711 qWarning("DirectShowPlayerService::doPause: Unresolved error code %x", uint(hr)); |
656 |
712 |
657 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); |
713 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); |
658 } |
714 } |
659 } |
715 } |
660 } |
716 } |
663 { |
719 { |
664 QMutexLocker locker(&m_mutex); |
720 QMutexLocker locker(&m_mutex); |
665 |
721 |
666 m_pendingTasks &= ~(Play | Pause | Seek); |
722 m_pendingTasks &= ~(Play | Pause | Seek); |
667 |
723 |
668 if (m_executedTasks & Render) { |
724 if ((m_executingTask | m_executedTasks) & (Play | Pause | Seek)) { |
669 if (m_executingTask & (Play | Pause | Seek)) { |
725 m_pendingTasks |= Stop; |
670 m_pendingTasks |= Stop; |
726 |
671 |
727 ::SetEvent(m_taskHandle); |
672 m_loop.wait(&m_mutex); |
728 |
673 } |
729 m_loop->wait(&m_mutex); |
674 |
730 } |
675 if (m_executedTasks & (Play | Pause)) { |
731 |
676 if (IMediaControl *control = com_cast<IMediaControl>(m_graph)) { |
732 } |
677 control->Stop(); |
733 |
678 control->Release(); |
734 void DirectShowPlayerService::doStop(QMutexLocker *locker) |
679 } |
735 { |
680 m_executedTasks &= ~(Play | Pause); |
736 if (m_executedTasks & (Play | Pause)) { |
681 } |
737 if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) { |
|
738 control->Stop(); |
|
739 control->Release(); |
|
740 } |
|
741 |
|
742 if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { |
|
743 LONGLONG position = 0; |
|
744 |
|
745 seeking->GetCurrentPosition(&position); |
|
746 seeking->Release(); |
|
747 |
|
748 m_position = position / 10; |
|
749 } else { |
|
750 m_position = 0; |
|
751 } |
|
752 |
|
753 m_executedTasks &= ~(Play | Pause); |
|
754 |
|
755 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); |
682 } |
756 } |
683 |
757 |
684 m_executedTasks |= Stop; |
758 m_executedTasks |= Stop; |
|
759 |
|
760 m_loop->wake(); |
685 } |
761 } |
686 |
762 |
687 void DirectShowPlayerService::setRate(qreal rate) |
763 void DirectShowPlayerService::setRate(qreal rate) |
688 { |
764 { |
689 QMutexLocker locker(&m_mutex); |
765 QMutexLocker locker(&m_mutex); |
696 ::SetEvent(m_taskHandle); |
772 ::SetEvent(m_taskHandle); |
697 } |
773 } |
698 |
774 |
699 void DirectShowPlayerService::doSetRate(QMutexLocker *locker) |
775 void DirectShowPlayerService::doSetRate(QMutexLocker *locker) |
700 { |
776 { |
701 if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph)) { |
777 if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { |
702 // Cache current values as we can't query IMediaSeeking during a seek due to the |
778 // Cache current values as we can't query IMediaSeeking during a seek due to the |
703 // possibility of a deadlock when flushing the VideoSurfaceFilter. |
779 // possibility of a deadlock when flushing the VideoSurfaceFilter. |
704 LONGLONG currentPosition = 0; |
780 LONGLONG currentPosition = 0; |
705 seeking->GetCurrentPosition(¤tPosition); |
781 seeking->GetCurrentPosition(¤tPosition); |
706 m_position = currentPosition / 10; |
782 m_position = currentPosition / 10; |
734 QMutexLocker locker(const_cast<QMutex *>(&m_mutex)); |
810 QMutexLocker locker(const_cast<QMutex *>(&m_mutex)); |
735 |
811 |
736 if (m_graphStatus == Loaded) { |
812 if (m_graphStatus == Loaded) { |
737 if (m_executingTask == Seek || m_executingTask == SetRate) { |
813 if (m_executingTask == Seek || m_executingTask == SetRate) { |
738 return m_position; |
814 return m_position; |
739 } else if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph)) { |
815 } else if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { |
740 LONGLONG position = 0; |
816 LONGLONG position = 0; |
741 |
817 |
742 seeking->GetCurrentPosition(&position); |
818 seeking->GetCurrentPosition(&position); |
743 seeking->Release(); |
819 seeking->Release(); |
744 |
820 |
745 return position / 10; |
821 const_cast<qint64 &>(m_position) = position / 10; |
|
822 |
|
823 return m_position; |
746 } |
824 } |
747 } |
825 } |
748 return 0; |
826 return 0; |
749 } |
827 } |
750 |
828 |
753 QMutexLocker locker(const_cast<QMutex *>(&m_mutex)); |
831 QMutexLocker locker(const_cast<QMutex *>(&m_mutex)); |
754 |
832 |
755 if (m_graphStatus == Loaded) { |
833 if (m_graphStatus == Loaded) { |
756 if (m_executingTask == Seek || m_executingTask == SetRate) { |
834 if (m_executingTask == Seek || m_executingTask == SetRate) { |
757 return m_playbackRange; |
835 return m_playbackRange; |
758 } else if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph)) { |
836 } else if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { |
759 LONGLONG minimum = 0; |
837 LONGLONG minimum = 0; |
760 LONGLONG maximum = 0; |
838 LONGLONG maximum = 0; |
761 |
839 |
762 HRESULT hr = seeking->GetAvailable(&minimum, &maximum); |
840 HRESULT hr = seeking->GetAvailable(&minimum, &maximum); |
763 seeking->Release(); |
841 seeking->Release(); |
781 ::SetEvent(m_taskHandle); |
859 ::SetEvent(m_taskHandle); |
782 } |
860 } |
783 |
861 |
784 void DirectShowPlayerService::doSeek(QMutexLocker *locker) |
862 void DirectShowPlayerService::doSeek(QMutexLocker *locker) |
785 { |
863 { |
786 if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph)) { |
864 if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { |
787 LONGLONG seekPosition = LONGLONG(m_position) * 10; |
865 LONGLONG seekPosition = LONGLONG(m_position) * 10; |
788 |
866 |
789 // Cache current values as we can't query IMediaSeeking during a seek due to the |
867 // Cache current values as we can't query IMediaSeeking during a seek due to the |
790 // possibility of a deadlock when flushing the VideoSurfaceFilter. |
868 // possibility of a deadlock when flushing the VideoSurfaceFilter. |
791 LONGLONG currentPosition = 0; |
869 LONGLONG currentPosition = 0; |
801 locker->unlock(); |
879 locker->unlock(); |
802 seeking->SetPositions( |
880 seeking->SetPositions( |
803 &seekPosition, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning); |
881 &seekPosition, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning); |
804 locker->relock(); |
882 locker->relock(); |
805 |
883 |
|
884 seeking->GetCurrentPosition(¤tPosition); |
|
885 m_position = currentPosition / 10; |
|
886 |
806 seeking->Release(); |
887 seeking->Release(); |
807 } |
888 } else { |
|
889 m_position = 0; |
|
890 } |
|
891 |
|
892 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PositionChange))); |
808 } |
893 } |
809 |
894 |
810 int DirectShowPlayerService::bufferStatus() const |
895 int DirectShowPlayerService::bufferStatus() const |
811 { |
896 { |
812 #ifndef QT_NO_WMSDK |
897 #ifndef QT_NO_WMSDK |
813 QMutexLocker locker(const_cast<QMutex *>(&m_mutex)); |
898 QMutexLocker locker(const_cast<QMutex *>(&m_mutex)); |
814 |
899 |
815 if (IWMReaderAdvanced2 *reader = com_cast<IWMReaderAdvanced2>(m_source)) { |
900 if (IWMReaderAdvanced2 *reader = com_cast<IWMReaderAdvanced2>( |
|
901 m_source, IID_IWMReaderAdvanced2)) { |
816 DWORD percentage = 0; |
902 DWORD percentage = 0; |
817 |
903 |
818 reader->GetBufferProgress(&percentage, 0); |
904 reader->GetBufferProgress(&percentage, 0); |
819 reader->Release(); |
905 reader->Release(); |
820 |
906 |
836 if (m_executedTasks & SetAudioOutput) { |
922 if (m_executedTasks & SetAudioOutput) { |
837 m_pendingTasks |= ReleaseAudioOutput; |
923 m_pendingTasks |= ReleaseAudioOutput; |
838 |
924 |
839 ::SetEvent(m_taskHandle); |
925 ::SetEvent(m_taskHandle); |
840 |
926 |
841 m_loop.wait(&m_mutex); |
927 m_loop->wait(&m_mutex); |
842 } |
928 } |
843 m_audioOutput->Release(); |
929 m_audioOutput->Release(); |
844 } |
930 } |
845 |
931 |
846 m_audioOutput = filter; |
932 m_audioOutput = filter; |
847 |
933 |
848 if (m_audioOutput) { |
934 if (m_audioOutput) { |
849 m_audioOutput->AddRef(); |
935 m_audioOutput->AddRef(); |
850 |
936 |
851 m_pendingTasks |= SetAudioOutput; |
937 m_pendingTasks |= SetAudioOutput; |
|
938 |
|
939 if (m_executedTasks & SetSource) { |
|
940 m_pendingTasks |= Render; |
|
941 |
|
942 ::SetEvent(m_taskHandle); |
|
943 } |
852 } else { |
944 } else { |
853 m_pendingTasks &= ~ SetAudioOutput; |
945 m_pendingTasks &= ~ SetAudioOutput; |
854 } |
|
855 |
|
856 if (m_executedTasks & SetSource) { |
|
857 m_pendingTasks |= Render; |
|
858 |
|
859 ::SetEvent(m_taskHandle); |
|
860 } |
946 } |
861 } else { |
947 } else { |
862 if (m_audioOutput) |
948 if (m_audioOutput) |
863 m_audioOutput->Release(); |
949 m_audioOutput->Release(); |
864 |
950 |
873 |
959 |
874 void DirectShowPlayerService::doReleaseAudioOutput(QMutexLocker *locker) |
960 void DirectShowPlayerService::doReleaseAudioOutput(QMutexLocker *locker) |
875 { |
961 { |
876 m_pendingTasks |= m_executedTasks & (Play | Pause); |
962 m_pendingTasks |= m_executedTasks & (Play | Pause); |
877 |
963 |
878 if (IMediaControl *control = com_cast<IMediaControl>(m_graph)) { |
964 if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) { |
879 control->Stop(); |
965 control->Stop(); |
880 control->Release(); |
966 control->Release(); |
881 } |
967 } |
882 |
968 |
883 m_graph->RemoveFilter(m_audioOutput); |
969 IBaseFilter *decoder = getConnected(m_audioOutput, PINDIR_INPUT); |
|
970 if (!decoder) { |
|
971 decoder = m_audioOutput; |
|
972 decoder->AddRef(); |
|
973 } |
|
974 |
|
975 // {DCFBDCF6-0DC2-45f5-9AB2-7C330EA09C29} |
|
976 static const GUID iid_IFilterChain = { |
|
977 0xDCFBDCF6, 0x0DC2, 0x45f5, {0x9A, 0xB2, 0x7C, 0x33, 0x0E, 0xA0, 0x9C, 0x29} }; |
|
978 |
|
979 if (IFilterChain *chain = com_cast<IFilterChain>(m_graph, iid_IFilterChain)) { |
|
980 chain->RemoveChain(decoder, m_audioOutput); |
|
981 chain->Release(); |
|
982 } else { |
|
983 m_graph->RemoveFilter(m_audioOutput); |
|
984 } |
|
985 |
|
986 decoder->Release(); |
884 |
987 |
885 m_executedTasks &= ~SetAudioOutput; |
988 m_executedTasks &= ~SetAudioOutput; |
886 |
989 |
887 m_loop.wake(); |
990 m_loop->wake(); |
888 } |
991 } |
889 |
992 |
890 void DirectShowPlayerService::setVideoOutput(IBaseFilter *filter) |
993 void DirectShowPlayerService::setVideoOutput(IBaseFilter *filter) |
891 { |
994 { |
892 QMutexLocker locker(&m_mutex); |
995 QMutexLocker locker(&m_mutex); |
896 if (m_executedTasks & SetVideoOutput) { |
999 if (m_executedTasks & SetVideoOutput) { |
897 m_pendingTasks |= ReleaseVideoOutput; |
1000 m_pendingTasks |= ReleaseVideoOutput; |
898 |
1001 |
899 ::SetEvent(m_taskHandle); |
1002 ::SetEvent(m_taskHandle); |
900 |
1003 |
901 m_loop.wait(&m_mutex); |
1004 m_loop->wait(&m_mutex); |
902 } |
1005 } |
903 m_videoOutput->Release(); |
1006 m_videoOutput->Release(); |
904 } |
1007 } |
905 |
1008 |
906 m_videoOutput = filter; |
1009 m_videoOutput = filter; |
907 |
1010 |
908 if (m_videoOutput) { |
1011 if (m_videoOutput) { |
909 m_videoOutput->AddRef(); |
1012 m_videoOutput->AddRef(); |
910 |
1013 |
911 m_pendingTasks |= SetVideoOutput; |
1014 m_pendingTasks |= SetVideoOutput; |
912 } else { |
1015 |
913 m_pendingTasks &= ~ SetVideoOutput; |
1016 if (m_executedTasks & SetSource) { |
914 } |
1017 m_pendingTasks |= Render; |
915 |
1018 |
916 if (m_executedTasks & SetSource) { |
1019 ::SetEvent(m_taskHandle); |
917 m_pendingTasks |= Render; |
1020 } |
918 |
|
919 ::SetEvent(m_taskHandle); |
|
920 } |
1021 } |
921 } else { |
1022 } else { |
922 if (m_videoOutput) |
1023 if (m_videoOutput) |
923 m_videoOutput->Release(); |
1024 m_videoOutput->Release(); |
924 |
1025 |
931 |
1032 |
932 void DirectShowPlayerService::doReleaseVideoOutput(QMutexLocker *locker) |
1033 void DirectShowPlayerService::doReleaseVideoOutput(QMutexLocker *locker) |
933 { |
1034 { |
934 m_pendingTasks |= m_executedTasks & (Play | Pause); |
1035 m_pendingTasks |= m_executedTasks & (Play | Pause); |
935 |
1036 |
936 if (IMediaControl *control = com_cast<IMediaControl>(m_graph)) { |
1037 if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) { |
937 control->Stop(); |
1038 control->Stop(); |
938 control->Release(); |
1039 control->Release(); |
939 } |
1040 } |
940 |
1041 |
941 m_graph->RemoveFilter(m_videoOutput); |
1042 IBaseFilter *intermediate = 0; |
|
1043 if (!SUCCEEDED(m_graph->FindFilterByName(L"Color Space Converter", &intermediate))) { |
|
1044 intermediate = m_videoOutput; |
|
1045 intermediate->AddRef(); |
|
1046 } |
|
1047 |
|
1048 IBaseFilter *decoder = getConnected(intermediate, PINDIR_INPUT); |
|
1049 if (!decoder) { |
|
1050 decoder = intermediate; |
|
1051 decoder->AddRef(); |
|
1052 } |
|
1053 |
|
1054 // {DCFBDCF6-0DC2-45f5-9AB2-7C330EA09C29} |
|
1055 static const GUID iid_IFilterChain = { |
|
1056 0xDCFBDCF6, 0x0DC2, 0x45f5, {0x9A, 0xB2, 0x7C, 0x33, 0x0E, 0xA0, 0x9C, 0x29} }; |
|
1057 |
|
1058 if (IFilterChain *chain = com_cast<IFilterChain>(m_graph, iid_IFilterChain)) { |
|
1059 chain->RemoveChain(decoder, m_videoOutput); |
|
1060 chain->Release(); |
|
1061 } else { |
|
1062 m_graph->RemoveFilter(m_videoOutput); |
|
1063 } |
|
1064 |
|
1065 intermediate->Release(); |
|
1066 decoder->Release(); |
942 |
1067 |
943 m_executedTasks &= ~SetVideoOutput; |
1068 m_executedTasks &= ~SetVideoOutput; |
944 |
1069 |
945 m_loop.wake(); |
1070 m_loop->wake(); |
946 } |
1071 } |
947 |
1072 |
948 void DirectShowPlayerService::customEvent(QEvent *event) |
1073 void DirectShowPlayerService::customEvent(QEvent *event) |
949 { |
1074 { |
950 if (event->type() == QEvent::Type(FinalizedLoad)) { |
1075 if (event->type() == QEvent::Type(FinalizedLoad)) { |
953 m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); |
1078 m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); |
954 m_metaDataControl->updateGraph(m_graph, m_source); |
1079 m_metaDataControl->updateGraph(m_graph, m_source); |
955 |
1080 |
956 updateStatus(); |
1081 updateStatus(); |
957 } else if (event->type() == QEvent::Type(Error)) { |
1082 } else if (event->type() == QEvent::Type(Error)) { |
958 QMediaPlayer::Error error; |
1083 QMutexLocker locker(&m_mutex); |
959 { |
1084 |
960 QMutexLocker locker(&m_mutex); |
1085 if (m_error != QMediaPlayer::NoError) { |
961 error = m_error; |
1086 m_playerControl->updateError(m_error, m_errorString); |
962 |
1087 m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); |
963 if (error != QMediaPlayer::NoError) { |
1088 m_playerControl->updateState(QMediaPlayer::StoppedState); |
964 m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); |
1089 updateStatus(); |
965 m_playerControl->updateState(QMediaPlayer::StoppedState); |
1090 } |
966 updateStatus(); |
|
967 } |
|
968 } |
|
969 m_playerControl->error(error, QString()); |
|
970 } else if (event->type() == QEvent::Type(RateChange)) { |
1091 } else if (event->type() == QEvent::Type(RateChange)) { |
971 QMutexLocker locker(&m_mutex); |
1092 QMutexLocker locker(&m_mutex); |
972 |
1093 |
973 m_playerControl->updatePlaybackRate(m_rate); |
1094 m_playerControl->updatePlaybackRate(m_rate); |
974 } else if (event->type() == QEvent::Type(StatusChange)) { |
1095 } else if (event->type() == QEvent::Type(StatusChange)) { |
975 QMutexLocker locker(&m_mutex); |
1096 QMutexLocker locker(&m_mutex); |
976 |
1097 |
977 updateStatus(); |
1098 updateStatus(); |
|
1099 m_playerControl->updatePosition(m_position); |
978 } else if (event->type() == QEvent::Type(DurationChange)) { |
1100 } else if (event->type() == QEvent::Type(DurationChange)) { |
979 QMutexLocker locker(&m_mutex); |
1101 QMutexLocker locker(&m_mutex); |
980 |
1102 |
981 m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); |
1103 m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); |
982 } else if (event->type() == QEvent::Type(EndOfMedia)) { |
1104 } else if (event->type() == QEvent::Type(EndOfMedia)) { |
983 QMutexLocker locker(&m_mutex); |
1105 QMutexLocker locker(&m_mutex); |
984 |
1106 |
985 if (m_atEnd) { |
1107 if (m_atEnd) { |
986 m_playerControl->updateState(QMediaPlayer::StoppedState); |
1108 m_playerControl->updateState(QMediaPlayer::StoppedState); |
987 m_playerControl->updateStatus(QMediaPlayer::EndOfMedia); |
1109 m_playerControl->updateStatus(QMediaPlayer::EndOfMedia); |
988 } |
1110 m_playerControl->updatePosition(m_position); |
|
1111 } |
|
1112 } else if (event->type() == QEvent::Type(PositionChange)) { |
|
1113 QMutexLocker locker(&m_mutex); |
|
1114 |
|
1115 m_playerControl->updatePosition(m_position); |
989 } else { |
1116 } else { |
990 QMediaService::customEvent(event); |
1117 QMediaService::customEvent(event); |
991 } |
1118 } |
992 } |
1119 } |
993 |
1120 |
1028 m_executedTasks |= Stop; |
1155 m_executedTasks |= Stop; |
1029 |
1156 |
1030 m_buffering = false; |
1157 m_buffering = false; |
1031 m_atEnd = true; |
1158 m_atEnd = true; |
1032 |
1159 |
|
1160 if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { |
|
1161 LONGLONG position = 0; |
|
1162 |
|
1163 seeking->GetCurrentPosition(&position); |
|
1164 seeking->Release(); |
|
1165 |
|
1166 m_position = position / 10; |
|
1167 } |
|
1168 |
1033 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(EndOfMedia))); |
1169 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(EndOfMedia))); |
1034 break; |
1170 break; |
1035 case EC_LENGTH_CHANGED: |
1171 case EC_LENGTH_CHANGED: |
1036 if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph)) { |
1172 if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { |
1037 LONGLONG duration = 0; |
1173 LONGLONG duration = 0; |
1038 seeking->GetDuration(&duration); |
1174 seeking->GetDuration(&duration); |
1039 m_duration = duration / 10; |
1175 m_duration = duration / 10; |
1040 |
1176 |
1041 DWORD capabilities = 0; |
1177 DWORD capabilities = 0; |
1105 pins->Release(); |
1241 pins->Release(); |
1106 } |
1242 } |
1107 return connected; |
1243 return connected; |
1108 } |
1244 } |
1109 |
1245 |
|
1246 IBaseFilter *DirectShowPlayerService::getConnected( |
|
1247 IBaseFilter *filter, PIN_DIRECTION direction) const |
|
1248 { |
|
1249 IBaseFilter *connected = 0; |
|
1250 |
|
1251 IEnumPins *pins = 0; |
|
1252 |
|
1253 if (SUCCEEDED(filter->EnumPins(&pins))) { |
|
1254 for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) { |
|
1255 PIN_DIRECTION dir; |
|
1256 if (SUCCEEDED(pin->QueryDirection(&dir)) && dir == direction) { |
|
1257 IPin *peer = 0; |
|
1258 if (SUCCEEDED(pin->ConnectedTo(&peer))) { |
|
1259 PIN_INFO info; |
|
1260 |
|
1261 if (SUCCEEDED(peer->QueryPinInfo(&info))) { |
|
1262 if (connected) { |
|
1263 qWarning("DirectShowPlayerService::getConnected: " |
|
1264 "Multiple connected filters"); |
|
1265 connected->Release(); |
|
1266 } |
|
1267 connected = info.pFilter; |
|
1268 } |
|
1269 peer->Release(); |
|
1270 } |
|
1271 } |
|
1272 } |
|
1273 pins->Release(); |
|
1274 } |
|
1275 return connected; |
|
1276 } |
|
1277 |
1110 void DirectShowPlayerService::run() |
1278 void DirectShowPlayerService::run() |
1111 { |
1279 { |
1112 QMutexLocker locker(&m_mutex); |
1280 QMutexLocker locker(&m_mutex); |
1113 |
1281 |
1114 for (;;) { |
1282 for (;;) { |
1169 } else if (m_pendingTasks & FinalizeLoad) { |
1337 } else if (m_pendingTasks & FinalizeLoad) { |
1170 m_pendingTasks ^= FinalizeLoad; |
1338 m_pendingTasks ^= FinalizeLoad; |
1171 m_executingTask = FinalizeLoad; |
1339 m_executingTask = FinalizeLoad; |
1172 |
1340 |
1173 doFinalizeLoad(&locker); |
1341 doFinalizeLoad(&locker); |
|
1342 } else if (m_pendingTasks & Stop) { |
|
1343 m_pendingTasks ^= Stop; |
|
1344 m_executingTask = Stop; |
|
1345 |
|
1346 doStop(&locker); |
1174 } else if (m_pendingTasks & SetRate) { |
1347 } else if (m_pendingTasks & SetRate) { |
1175 m_pendingTasks ^= SetRate; |
1348 m_pendingTasks ^= SetRate; |
1176 m_executingTask = SetRate; |
1349 m_executingTask = SetRate; |
1177 |
1350 |
1178 doSetRate(&locker); |
1351 doSetRate(&locker); |
1179 } else if (m_pendingTasks & Stop) { |
|
1180 m_pendingTasks ^= Stop; |
|
1181 |
|
1182 m_loop.wake(); |
|
1183 } else if (m_pendingTasks & Pause) { |
1352 } else if (m_pendingTasks & Pause) { |
1184 m_pendingTasks ^= Pause; |
1353 m_pendingTasks ^= Pause; |
1185 m_executingTask = Pause; |
1354 m_executingTask = Pause; |
1186 |
1355 |
1187 doPause(&locker); |
1356 doPause(&locker); |