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