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
4#include "mfstream_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
21SourceResolver::SourceResolver()
22 : m_cRef(1)
23 , m_cancelCookie(0)
24 , m_sourceResolver(0)
25 , m_mediaSource(0)
26 , m_stream(0)
27{
28}
29
31{
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
44
45HRESULT STDMETHODCALLTYPE SourceResolver::Invoke(IMFAsyncResult *pAsyncResult)
46{
47 QMutexLocker locker(&m_mutex);
48
49 if (!m_sourceResolver)
50 return S_OK;
51
52 MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID;
53 IUnknown* pSource = NULL;
54 State *state = static_cast<State*>(pAsyncResult->GetStateNoAddRef());
55
56 HRESULT hr = S_OK;
57 if (state->fromStream())
58 hr = m_sourceResolver->EndCreateObjectFromByteStream(pAsyncResult, &ObjectType, &pSource);
59 else
60 hr = m_sourceResolver->EndCreateObjectFromURL(pAsyncResult, &ObjectType, &pSource);
61
62 if (state->sourceResolver() != m_sourceResolver) {
63 //This is a cancelled one
64 return S_OK;
65 }
66
67 if (m_cancelCookie) {
68 m_cancelCookie->Release();
69 m_cancelCookie = NULL;
70 }
71
72 if (FAILED(hr)) {
73 emit error(hr);
74 return S_OK;
75 }
76
77 if (m_mediaSource) {
78 m_mediaSource->Release();
79 m_mediaSource = NULL;
80 }
81
82 hr = pSource->QueryInterface(IID_PPV_ARGS(&m_mediaSource));
83 pSource->Release();
84 if (FAILED(hr)) {
85 emit error(hr);
86 return S_OK;
87 }
88
89 emit mediaSourceReady();
90
91 return S_OK;
92}
93
94HRESULT STDMETHODCALLTYPE SourceResolver::GetParameters(DWORD*, DWORD*)
95{
96 return E_NOTIMPL;
97}
98
99void SourceResolver::load(const QUrl &url, QIODevice* stream)
100{
101 QMutexLocker locker(&m_mutex);
102 HRESULT hr = S_OK;
103 if (!m_sourceResolver)
104 hr = MFCreateSourceResolver(&m_sourceResolver);
105
106 if (m_stream) {
107 m_stream->Release();
108 m_stream = NULL;
109 }
110
111 if (FAILED(hr)) {
112 qWarning() << "Failed to create Source Resolver!";
113 emit error(hr);
114 } else if (stream) {
115 QString urlString = url.toString();
116 m_stream = new MFStream(stream, false);
117 hr = m_sourceResolver->BeginCreateObjectFromByteStream(
118 m_stream, urlString.isEmpty() ? 0 : reinterpret_cast<LPCWSTR>(urlString.utf16()),
119 MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE
120 , NULL, &m_cancelCookie, this, new State(m_sourceResolver, true));
121 if (FAILED(hr)) {
122 qWarning() << "Unsupported stream!";
123 emit error(hr);
124 }
125 } else {
126#ifdef DEBUG_MEDIAFOUNDATION
127 qDebug() << "loading :" << url;
128 qDebug() << "url path =" << url.path().mid(1);
129#endif
130#ifdef TEST_STREAMING
131 //Testing stream function
132 if (url.scheme() == QLatin1String("file")) {
133 stream = new QFile(url.path().mid(1));
134 if (stream->open(QIODevice::ReadOnly)) {
135 m_stream = new MFStream(stream, true);
136 hr = m_sourceResolver->BeginCreateObjectFromByteStream(
137 m_stream, reinterpret_cast<const OLECHAR *>(url.toString().utf16()),
138 MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE,
139 NULL, &m_cancelCookie, this, new State(m_sourceResolver, true));
140 if (FAILED(hr)) {
141 qWarning() << "Unsupported stream!";
142 emit error(hr);
143 }
144 } else {
145 delete stream;
146 emit error(QMediaPlayer::FormatError);
147 }
148 } else
149#endif
150 if (url.scheme() == QLatin1String("qrc")) {
151 // If the canonical URL refers to a Qt resource, open with QFile and use
152 // the stream playback capability to play.
153 stream = new QFile(QLatin1Char(':') + url.path());
154 if (stream->open(QIODevice::ReadOnly)) {
155 m_stream = new MFStream(stream, true);
156 hr = m_sourceResolver->BeginCreateObjectFromByteStream(
157 m_stream, reinterpret_cast<const OLECHAR *>(url.toString().utf16()),
158 MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE,
159 NULL, &m_cancelCookie, this, new State(m_sourceResolver, true));
160 if (FAILED(hr)) {
161 qWarning() << "Unsupported stream!";
162 emit error(hr);
163 }
164 } else {
165 delete stream;
166 emit error(QMediaPlayer::FormatError);
167 }
168 } else {
169 hr = m_sourceResolver->BeginCreateObjectFromURL(
170 reinterpret_cast<const OLECHAR *>(url.toString().utf16()),
171 MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE,
172 NULL, &m_cancelCookie, this, new State(m_sourceResolver, false));
173 if (FAILED(hr)) {
174 qWarning() << "Unsupported url scheme!";
175 emit error(hr);
176 }
177 }
178 }
179}
180
182{
183 QMutexLocker locker(&m_mutex);
184 if (m_cancelCookie) {
185 m_sourceResolver->CancelObjectCreation(m_cancelCookie);
186 m_cancelCookie->Release();
187 m_cancelCookie = NULL;
188 m_sourceResolver->Release();
189 m_sourceResolver = NULL;
190 }
191}
192
194{
195 if (m_mediaSource) {
196 m_mediaSource->Shutdown();
197 m_mediaSource->Release();
198 m_mediaSource = NULL;
199 }
200
201 if (m_stream) {
202 m_stream->Release();
203 m_stream = NULL;
204 }
205}
206
208{
209 return m_mediaSource;
210}
211
212/////////////////////////////////////////////////////////////////////////////////
213SourceResolver::State::State(IMFSourceResolver *sourceResolver, bool fromStream)
214 : m_cRef(0)
215 , m_sourceResolver(sourceResolver)
216 , m_fromStream(fromStream)
217{
218 sourceResolver->AddRef();
219}
220
221SourceResolver::State::~State()
222{
223 m_sourceResolver->Release();
224}
225
226
227IMFSourceResolver* SourceResolver::State::sourceResolver() const
228{
229 return m_sourceResolver;
230}
231
232bool SourceResolver::State::fromStream() const
233{
234 return m_fromStream;
235}
236
237QT_END_NAMESPACE
238
239#include "moc_sourceresolver_p.cpp"
IMFMediaSource * mediaSource() const
void load(const QUrl &url, QIODevice *stream)
Combined button and popup list for selecting options.