Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
4#include "mfstream_p.h"
5#include "sourceresolver_p.h"
6#include <mferror.h>
7#include <nserror.h>
8#include <QtCore/qfile.h>
9#include <QtCore/qdebug.h>
10#include <QtMultimedia/qmediaplayer.h>
11
13
14/*
15 SourceResolver is separated from MFPlayerSession to handle the work of resolving a media source
16 asynchronously. You call SourceResolver::load to request resolving a media source asynchronously,
17 and it will emit mediaSourceReady() when resolving is done. You can call SourceResolver::cancel to
18 stop the previous load operation if there is any.
19*/
20
22 : m_cRef(1)
23 , m_cancelCookie(0)
24 , m_sourceResolver(0)
25 , m_mediaSource(0)
26 , m_stream(0)
27{
28}
29
31{
32 shutdown();
33 if (m_mediaSource) {
34 m_mediaSource->Release();
35 m_mediaSource = NULL;
36 }
37
38 if (m_cancelCookie)
39 m_cancelCookie->Release();
40 if (m_sourceResolver)
41 m_sourceResolver->Release();
42}
43
44STDMETHODIMP SourceResolver::QueryInterface(REFIID riid, LPVOID *ppvObject)
45{
46 if (!ppvObject)
47 return E_POINTER;
48 if (riid == IID_IUnknown) {
49 *ppvObject = static_cast<IUnknown*>(this);
50 } else if (riid == IID_IMFAsyncCallback) {
51 *ppvObject = static_cast<IMFAsyncCallback*>(this);
52 } else {
53 *ppvObject = NULL;
54 return E_NOINTERFACE;
55 }
56 AddRef();
57 return S_OK;
58}
59
60STDMETHODIMP_(ULONG) SourceResolver::AddRef(void)
61{
62 return InterlockedIncrement(&m_cRef);
63}
64
65STDMETHODIMP_(ULONG) SourceResolver::Release(void)
66{
67 LONG cRef = InterlockedDecrement(&m_cRef);
68 if (cRef == 0)
69 this->deleteLater();
70 return cRef;
71}
72
73HRESULT STDMETHODCALLTYPE SourceResolver::Invoke(IMFAsyncResult *pAsyncResult)
74{
75 QMutexLocker locker(&m_mutex);
76
77 if (!m_sourceResolver)
78 return S_OK;
79
80 MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID;
81 IUnknown* pSource = NULL;
82 State *state = static_cast<State*>(pAsyncResult->GetStateNoAddRef());
83
84 HRESULT hr = S_OK;
85 if (state->fromStream())
86 hr = m_sourceResolver->EndCreateObjectFromByteStream(pAsyncResult, &ObjectType, &pSource);
87 else
88 hr = m_sourceResolver->EndCreateObjectFromURL(pAsyncResult, &ObjectType, &pSource);
89
90 if (state->sourceResolver() != m_sourceResolver) {
91 //This is a cancelled one
92 return S_OK;
93 }
94
95 if (m_cancelCookie) {
96 m_cancelCookie->Release();
97 m_cancelCookie = NULL;
98 }
99
100 if (FAILED(hr)) {
101 emit error(hr);
102 return S_OK;
103 }
104
105 if (m_mediaSource) {
106 m_mediaSource->Release();
107 m_mediaSource = NULL;
108 }
109
110 hr = pSource->QueryInterface(IID_PPV_ARGS(&m_mediaSource));
111 pSource->Release();
112 if (FAILED(hr)) {
113 emit error(hr);
114 return S_OK;
115 }
116
118
119 return S_OK;
120}
121
122HRESULT STDMETHODCALLTYPE SourceResolver::GetParameters(DWORD*, DWORD*)
123{
124 return E_NOTIMPL;
125}
126
128{
129 QMutexLocker locker(&m_mutex);
130 HRESULT hr = S_OK;
131 if (!m_sourceResolver)
132 hr = MFCreateSourceResolver(&m_sourceResolver);
133
134 if (m_stream) {
135 m_stream->Release();
136 m_stream = NULL;
137 }
138
139 if (FAILED(hr)) {
140 qWarning() << "Failed to create Source Resolver!";
141 emit error(hr);
142 } else if (stream) {
143 QString urlString = url.toString();
144 m_stream = new MFStream(stream, false);
145 hr = m_sourceResolver->BeginCreateObjectFromByteStream(
146 m_stream, urlString.isEmpty() ? 0 : reinterpret_cast<LPCWSTR>(urlString.utf16()),
147 MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE
148 , NULL, &m_cancelCookie, this, new State(m_sourceResolver, true));
149 if (FAILED(hr)) {
150 qWarning() << "Unsupported stream!";
151 emit error(hr);
152 }
153 } else {
154#ifdef DEBUG_MEDIAFOUNDATION
155 qDebug() << "loading :" << url;
156 qDebug() << "url path =" << url.path().mid(1);
157#endif
158#ifdef TEST_STREAMING
159 //Testing stream function
160 if (url.scheme() == QLatin1String("file")) {
161 stream = new QFile(url.path().mid(1));
162 if (stream->open(QIODevice::ReadOnly)) {
163 m_stream = new MFStream(stream, true);
164 hr = m_sourceResolver->BeginCreateObjectFromByteStream(
165 m_stream, reinterpret_cast<const OLECHAR *>(url.toString().utf16()),
166 MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE,
167 NULL, &m_cancelCookie, this, new State(m_sourceResolver, true));
168 if (FAILED(hr)) {
169 qWarning() << "Unsupported stream!";
170 emit error(hr);
171 }
172 } else {
173 delete stream;
175 }
176 } else
177#endif
178 if (url.scheme() == QLatin1String("qrc")) {
179 // If the canonical URL refers to a Qt resource, open with QFile and use
180 // the stream playback capability to play.
181 stream = new QFile(QLatin1Char(':') + url.path());
182 if (stream->open(QIODevice::ReadOnly)) {
183 m_stream = new MFStream(stream, true);
184 hr = m_sourceResolver->BeginCreateObjectFromByteStream(
185 m_stream, reinterpret_cast<const OLECHAR *>(url.toString().utf16()),
186 MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE,
187 NULL, &m_cancelCookie, this, new State(m_sourceResolver, true));
188 if (FAILED(hr)) {
189 qWarning() << "Unsupported stream!";
190 emit error(hr);
191 }
192 } else {
193 delete stream;
195 }
196 } else {
197 hr = m_sourceResolver->BeginCreateObjectFromURL(
198 reinterpret_cast<const OLECHAR *>(url.toString().utf16()),
199 MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE,
200 NULL, &m_cancelCookie, this, new State(m_sourceResolver, false));
201 if (FAILED(hr)) {
202 qWarning() << "Unsupported url scheme!";
203 emit error(hr);
204 }
205 }
206 }
207}
208
210{
211 QMutexLocker locker(&m_mutex);
212 if (m_cancelCookie) {
213 m_sourceResolver->CancelObjectCreation(m_cancelCookie);
214 m_cancelCookie->Release();
215 m_cancelCookie = NULL;
216 m_sourceResolver->Release();
217 m_sourceResolver = NULL;
218 }
219}
220
222{
223 if (m_mediaSource) {
224 m_mediaSource->Shutdown();
225 m_mediaSource->Release();
226 m_mediaSource = NULL;
227 }
228
229 if (m_stream) {
230 m_stream->Release();
231 m_stream = NULL;
232 }
233}
234
235IMFMediaSource* SourceResolver::mediaSource() const
236{
237 return m_mediaSource;
238}
239
241SourceResolver::State::State(IMFSourceResolver *sourceResolver, bool fromStream)
242 : m_cRef(0)
243 , m_sourceResolver(sourceResolver)
244 , m_fromStream(fromStream)
245{
246 sourceResolver->AddRef();
247}
248
249SourceResolver::State::~State()
250{
251 m_sourceResolver->Release();
252}
253
254STDMETHODIMP SourceResolver::State::QueryInterface(REFIID riid, LPVOID *ppvObject)
255{
256 if (!ppvObject)
257 return E_POINTER;
258 if (riid == IID_IUnknown) {
259 *ppvObject = static_cast<IUnknown*>(this);
260 } else {
261 *ppvObject = NULL;
262 return E_NOINTERFACE;
263 }
264 AddRef();
265 return S_OK;
266}
267
268STDMETHODIMP_(ULONG) SourceResolver::State::AddRef(void)
269{
270 return InterlockedIncrement(&m_cRef);
271}
272
273STDMETHODIMP_(ULONG) SourceResolver::State::Release(void)
274{
275 LONG cRef = InterlockedDecrement(&m_cRef);
276 if (cRef == 0)
277 delete this;
278 // For thread safety, return a temporary variable.
279 return cRef;
280}
281
282IMFSourceResolver* SourceResolver::State::sourceResolver() const
283{
284 return m_sourceResolver;
285}
286
287bool SourceResolver::State::fromStream() const
288{
289 return m_fromStream;
290}
291
293
294#include "moc_sourceresolver_p.cpp"
\inmodule QtCore
Definition qfile.h:93
\inmodule QtCore \reentrant
Definition qiodevice.h:34
\inmodule QtCore
Definition qmutex.h:313
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
Definition qstring.cpp:6995
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
\inmodule QtCore
Definition qurl.h:94
QString scheme() const
Returns the scheme of the URL.
Definition qurl.cpp:1991
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2831
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
Definition qurl.cpp:2468
HRESULT STDMETHODCALLTYPE GetParameters(DWORD *, DWORD *) override
STDMETHODIMP_(ULONG) AddRef(void) override
HRESULT STDMETHODCALLTYPE Invoke(IMFAsyncResult *pAsyncResult) override
void mediaSourceReady()
IMFMediaSource * mediaSource() const
STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppvObject) override
void load(const QUrl &url, QIODevice *stream)
else opt state
[0]
Combined button and popup list for selecting options.
DBusConnection const char DBusError * error
EGLStreamKHR stream
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
#define emit
IUIViewSettingsInterop __RPC__in REFIID riid
long HRESULT
STDMETHODIMP_(ULONG) SourceResolver
QUrl url("example.com")
[constructor-url-reference]
\inmodule QtCore \reentrant
Definition qchar.h:18