Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
sourceresolver.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <mfstream_p.h>
7
8#include <QtMultimedia/qmediaplayer.h>
9#include <QtCore/qdebug.h>
10#include <QtCore/qfile.h>
11
12#include <mutex>
13
14QT_BEGIN_NAMESPACE
15
16/*
17 SourceResolver is separated from MFPlayerSession to handle the work of resolving a media source
18 asynchronously. You call SourceResolver::load to request resolving a media source asynchronously,
19 and it will emit mediaSourceReady() when resolving is done. You can call SourceResolver::cancel to
20 stop the previous load operation if there is any.
21*/
22
23SourceResolver::SourceResolver() = default;
24
29
30
31HRESULT STDMETHODCALLTYPE SourceResolver::Invoke(IMFAsyncResult *pAsyncResult)
32{
33 std::lock_guard lock(m_mutex);
34
35 if (!m_sourceResolver)
36 return S_OK;
37
38 MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID;
39 ComPtr<IUnknown> pSource;
40 State *state = static_cast<State*>(pAsyncResult->GetStateNoAddRef());
41
42 HRESULT hr = S_OK;
43 if (state->fromStream())
44 hr = m_sourceResolver->EndCreateObjectFromByteStream(pAsyncResult, &ObjectType, &pSource);
45 else
46 hr = m_sourceResolver->EndCreateObjectFromURL(pAsyncResult, &ObjectType, &pSource);
47
48 if (state->sourceResolver() != m_sourceResolver) {
49 //This is a cancelled one
50 return S_OK;
51 }
52
53 m_cancelCookie = nullptr;
54
55 if (FAILED(hr)) {
56 emit error(hr);
57 return S_OK;
58 }
59
60 hr = pSource.As(&m_mediaSource);
61 if (FAILED(hr)) {
62 emit error(hr);
63 return S_OK;
64 }
65
66 emit mediaSourceReady();
67
68 return S_OK;
69}
70
71HRESULT STDMETHODCALLTYPE SourceResolver::GetParameters(DWORD*, DWORD*)
72{
73 return E_NOTIMPL;
74}
75
76void SourceResolver::load(const QUrl &url, QIODevice* stream)
77{
78 std::lock_guard lock(m_mutex);
79 HRESULT hr = S_OK;
80 if (!m_sourceResolver)
81 hr = MFCreateSourceResolver(&m_sourceResolver);
82
83 m_stream = nullptr;
84
85 if (FAILED(hr)) {
86 qWarning() << "Failed to create Source Resolver!";
87 emit error(hr);
88 } else if (stream) {
89 QString urlString = url.toString();
90 m_stream = makeComObject<MFStream>(stream, false);
91 hr = m_sourceResolver->BeginCreateObjectFromByteStream(
92 m_stream.Get(), urlString.isEmpty() ? 0 : reinterpret_cast<LPCWSTR>(urlString.utf16()),
93 MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE
94 , NULL, &m_cancelCookie, this, makeComObject<State>(m_sourceResolver, true).Get());
95 if (FAILED(hr)) {
96 qWarning() << "Unsupported stream!";
97 emit error(hr);
98 }
99 } else {
100#ifdef DEBUG_MEDIAFOUNDATION
101 qDebug() << "loading :" << url;
102 qDebug() << "url path =" << url.path().mid(1);
103#endif
104#ifdef TEST_STREAMING
105 //Testing stream function
106 if (url.scheme() == u"file") {
107 stream = new QFile(url.path().mid(1));
108 if (stream->open(QIODevice::ReadOnly)) {
109 m_stream = makeComObject<MFStream>(stream, true);
110 hr = m_sourceResolver->BeginCreateObjectFromByteStream(
111 m_stream.Get(), reinterpret_cast<const OLECHAR *>(url.toString().utf16()),
112 MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE,
113 NULL, &m_cancelCookie, this, makeComObject<State>(m_sourceResolver, true).Get());
114 if (FAILED(hr)) {
115 qWarning() << "Unsupported stream!";
116 emit error(hr);
117 }
118 } else {
119 delete stream;
120 emit error(QMediaPlayer::FormatError);
121 }
122 } else
123#endif
124 if (url.scheme() == u"qrc") {
125 // If the canonical URL refers to a Qt resource, open with QFile and use
126 // the stream playback capability to play.
127 stream = new QFile(QLatin1Char(':') + url.path());
128 if (stream->open(QIODevice::ReadOnly)) {
129 m_stream = makeComObject<MFStream>(stream, true);
130 hr = m_sourceResolver->BeginCreateObjectFromByteStream(
131 m_stream.Get(), reinterpret_cast<const OLECHAR *>(url.toString().utf16()),
132 MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE,
133 NULL, &m_cancelCookie, this, makeComObject<State>(m_sourceResolver, true).Get());
134 if (FAILED(hr)) {
135 qWarning() << "Unsupported stream!";
136 emit error(hr);
137 }
138 } else {
139 delete stream;
140 emit error(QMediaPlayer::FormatError);
141 }
142 } else {
143 hr = m_sourceResolver->BeginCreateObjectFromURL(
144 reinterpret_cast<const OLECHAR *>(url.toString().utf16()),
145 MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE,
146 NULL, &m_cancelCookie, this, makeComObject<State>(m_sourceResolver, false).Get());
147 if (FAILED(hr)) {
148 qWarning() << "Unsupported url scheme!";
149 emit error(hr);
150 }
151 }
152 }
153}
154
156{
157 std::lock_guard lock(m_mutex);
158 if (m_cancelCookie) {
159 m_sourceResolver->CancelObjectCreation(m_cancelCookie.Get());
160 m_cancelCookie = nullptr;
161 m_sourceResolver = nullptr;
162 }
163}
164
166{
167 std::lock_guard lock(m_mutex);
168 if (m_mediaSource) {
169 m_mediaSource->Shutdown();
170 m_mediaSource = nullptr;
171 }
172
173 m_stream = nullptr;
174}
175
177{
178 std::lock_guard lock(m_mutex);
179 return m_mediaSource;
180}
181
182/////////////////////////////////////////////////////////////////////////////////
183SourceResolver::State::State(ComPtr<IMFSourceResolver> sourceResolver, bool fromStream)
184 : m_sourceResolver(std::move(sourceResolver)), m_fromStream(fromStream)
185{
186}
187
188SourceResolver::State::~State() = default;
189
190ComPtr<IMFSourceResolver> SourceResolver::State::sourceResolver() const
191{
192 return m_sourceResolver;
193}
194
195bool SourceResolver::State::fromStream() const
196{
197 return m_fromStream;
198}
199
200QT_END_NAMESPACE
201
202#include "moc_sourceresolver_p.cpp"
ComPtr< IMFMediaSource > mediaSource() const
void load(const QUrl &url, QIODevice *stream)