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
mfstream.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 <QtCore/qcoreapplication.h>
6
8//MFStream is added for supporting QIODevice type of media source.
9//It is used to delegate invocations from media foundation(through IMFByteStream) to QIODevice.
10
12 : m_cRef(1)
13 , m_stream(stream)
14 , m_ownStream(ownStream)
15 , m_currentReadResult(0)
16{
17 //Move to the thread of the stream object
18 //to make sure invocations on stream
19 //are happened in the same thread of stream object
20 this->moveToThread(stream->thread());
21}
22
24{
26 m_currentReadResult->Release();
27 if (m_ownStream)
28 m_stream->deleteLater();
29}
30
31//from IUnknown
32STDMETHODIMP MFStream::QueryInterface(REFIID riid, LPVOID *ppvObject)
33{
34 if (!ppvObject)
35 return E_POINTER;
36 if (riid == IID_IMFByteStream) {
37 *ppvObject = static_cast<IMFByteStream*>(this);
38 } else if (riid == IID_IUnknown) {
39 *ppvObject = static_cast<IUnknown*>(this);
40 } else {
41 *ppvObject = NULL;
42 return E_NOINTERFACE;
43 }
44 AddRef();
45 return S_OK;
46}
47
48STDMETHODIMP_(ULONG) MFStream::AddRef(void)
49{
50 return InterlockedIncrement(&m_cRef);
51}
52
53STDMETHODIMP_(ULONG) MFStream::Release(void)
54{
55 LONG cRef = InterlockedDecrement(&m_cRef);
56 if (cRef == 0) {
57 this->deleteLater();
58 }
59 return cRef;
60}
61
62
63//from IMFByteStream
64STDMETHODIMP MFStream::GetCapabilities(DWORD *pdwCapabilities)
65{
66 if (!pdwCapabilities)
67 return E_INVALIDARG;
68 *pdwCapabilities = MFBYTESTREAM_IS_READABLE;
69 if (!m_stream->isSequential())
70 *pdwCapabilities |= MFBYTESTREAM_IS_SEEKABLE;
71 return S_OK;
72}
73
74STDMETHODIMP MFStream::GetLength(QWORD *pqwLength)
75{
76 if (!pqwLength)
77 return E_INVALIDARG;
78 QMutexLocker locker(&m_mutex);
79 *pqwLength = QWORD(m_stream->size());
80 return S_OK;
81}
82
83STDMETHODIMP MFStream::SetLength(QWORD)
84{
85 return E_NOTIMPL;
86}
87
88STDMETHODIMP MFStream::GetCurrentPosition(QWORD *pqwPosition)
89{
90 if (!pqwPosition)
91 return E_INVALIDARG;
92 QMutexLocker locker(&m_mutex);
93 *pqwPosition = m_stream->pos();
94 return S_OK;
95}
96
97STDMETHODIMP MFStream::SetCurrentPosition(QWORD qwPosition)
98{
99 QMutexLocker locker(&m_mutex);
100 //SetCurrentPosition may happend during the BeginRead/EndRead pair,
101 //refusing to execute SetCurrentPosition during that time seems to be
102 //the simplest workable solution
104 return S_FALSE;
105
106 bool seekOK = m_stream->seek(qint64(qwPosition));
107 if (seekOK)
108 return S_OK;
109 else
110 return S_FALSE;
111}
112
113STDMETHODIMP MFStream::IsEndOfStream(BOOL *pfEndOfStream)
114{
115 if (!pfEndOfStream)
116 return E_INVALIDARG;
117 QMutexLocker locker(&m_mutex);
118 *pfEndOfStream = m_stream->atEnd() ? TRUE : FALSE;
119 return S_OK;
120}
121
122STDMETHODIMP MFStream::Read(BYTE *pb, ULONG cb, ULONG *pcbRead)
123{
124 QMutexLocker locker(&m_mutex);
125 qint64 read = m_stream->read((char*)(pb), qint64(cb));
126 if (pcbRead)
127 *pcbRead = ULONG(read);
128 return S_OK;
129}
130
131STDMETHODIMP MFStream::BeginRead(BYTE *pb, ULONG cb, IMFAsyncCallback *pCallback,
132 IUnknown *punkState)
133{
134 if (!pCallback || !pb)
135 return E_INVALIDARG;
136
138
139 AsyncReadState *state = new (std::nothrow) AsyncReadState(pb, cb);
140 if (state == NULL)
141 return E_OUTOFMEMORY;
142
143 HRESULT hr = MFCreateAsyncResult(state, pCallback, punkState, &m_currentReadResult);
144 state->Release();
145 if (FAILED(hr))
146 return hr;
147
149 return hr;
150}
151
152STDMETHODIMP MFStream::EndRead(IMFAsyncResult* pResult, ULONG *pcbRead)
153{
154 if (!pcbRead)
155 return E_INVALIDARG;
156 IUnknown *pUnk;
157 pResult->GetObject(&pUnk);
158 AsyncReadState *state = static_cast<AsyncReadState*>(pUnk);
159 *pcbRead = state->bytesRead();
160 pUnk->Release();
161
162 m_currentReadResult->Release();
163 m_currentReadResult = NULL;
164
165 return S_OK;
166}
167
168STDMETHODIMP MFStream::Write(const BYTE *, ULONG, ULONG *)
169{
170 return E_NOTIMPL;
171}
172
173STDMETHODIMP MFStream::BeginWrite(const BYTE *, ULONG ,
174 IMFAsyncCallback *,
175 IUnknown *)
176{
177 return E_NOTIMPL;
178}
179
180STDMETHODIMP MFStream::EndWrite(IMFAsyncResult *,
181 ULONG *)
182{
183 return E_NOTIMPL;
184}
185
186STDMETHODIMP MFStream::Seek(
187 MFBYTESTREAM_SEEK_ORIGIN SeekOrigin,
188 LONGLONG llSeekOffset,
189 DWORD,
190 QWORD *pqwCurrentPosition)
191{
192 QMutexLocker locker(&m_mutex);
194 return S_FALSE;
195
196 qint64 pos = qint64(llSeekOffset);
197 switch (SeekOrigin) {
198 case msoBegin:
199 break;
200 case msoCurrent:
201 pos += m_stream->pos();
202 break;
203 }
204 bool seekOK = m_stream->seek(pos);
205 if (pqwCurrentPosition)
206 *pqwCurrentPosition = pos;
207 if (seekOK)
208 return S_OK;
209 else
210 return S_FALSE;
211}
212
213STDMETHODIMP MFStream::Flush()
214{
215 return E_NOTIMPL;
216}
217
218STDMETHODIMP MFStream::Close()
219{
220 QMutexLocker locker(&m_mutex);
221 if (m_ownStream)
222 m_stream->close();
223 return S_OK;
224}
225
226void MFStream::doRead()
227{
228 if (!m_stream)
229 return;
230
231 bool readDone = true;
232 IUnknown *pUnk = NULL;
233 HRESULT hr = m_currentReadResult->GetObject(&pUnk);
234 if (SUCCEEDED(hr)) {
235 //do actual read
236 AsyncReadState *state = static_cast<AsyncReadState*>(pUnk);
237 ULONG cbRead;
238 Read(state->pb(), state->cb() - state->bytesRead(), &cbRead);
239 pUnk->Release();
240
241 state->setBytesRead(cbRead + state->bytesRead());
242 if (state->cb() > state->bytesRead() && !m_stream->atEnd()) {
243 readDone = false;
244 }
245 }
246
247 if (readDone) {
248 //now inform the original caller
249 m_currentReadResult->SetStatus(hr);
250 MFInvokeCallback(m_currentReadResult);
251 }
252}
253
255{
256 if (event->type() != QEvent::User) {
258 return;
259 }
260 doRead();
261}
262
263//AsyncReadState is a helper class used in BeginRead for asynchronous operation
264//to record some BeginRead parameters, so these parameters could be
265//used later when actually executing the read operation in another thread.
266MFStream::AsyncReadState::AsyncReadState(BYTE *pb, ULONG cb)
267 : m_cRef(1)
268 , m_pb(pb)
269 , m_cb(cb)
270 , m_cbRead(0)
271{
272}
273
274//from IUnknown
275STDMETHODIMP MFStream::AsyncReadState::QueryInterface(REFIID riid, LPVOID *ppvObject)
276{
277 if (!ppvObject)
278 return E_POINTER;
279
280 if (riid == IID_IUnknown) {
281 *ppvObject = static_cast<IUnknown*>(this);
282 } else {
283 *ppvObject = NULL;
284 return E_NOINTERFACE;
285 }
286 AddRef();
287 return S_OK;
288}
289
290STDMETHODIMP_(ULONG) MFStream::AsyncReadState::AddRef(void)
291{
292 return InterlockedIncrement(&m_cRef);
293}
294
295STDMETHODIMP_(ULONG) MFStream::AsyncReadState::Release(void)
296{
297 LONG cRef = InterlockedDecrement(&m_cRef);
298 if (cRef == 0)
299 delete this;
300 // For thread safety, return a temporary variable.
301 return cRef;
302}
303
304BYTE* MFStream::AsyncReadState::pb() const
305{
306 return m_pb;
307}
308
309ULONG MFStream::AsyncReadState::cb() const
310{
311 return m_cb;
312}
313
314ULONG MFStream::AsyncReadState::bytesRead() const
315{
316 return m_cbRead;
317}
318
319void MFStream::AsyncReadState::setBytesRead(ULONG cbRead)
320{
321 m_cbRead = cbRead;
322}
323
325
326#include "moc_mfstream_p.cpp"
STDMETHODIMP SetLength(QWORD) override
Definition mfstream.cpp:83
STDMETHODIMP EndWrite(IMFAsyncResult *, ULONG *) override
Definition mfstream.cpp:180
STDMETHODIMP Flush() override
Definition mfstream.cpp:213
STDMETHODIMP Write(const BYTE *, ULONG, ULONG *) override
Definition mfstream.cpp:168
STDMETHODIMP SetCurrentPosition(QWORD qwPosition) override
Definition mfstream.cpp:97
STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppvObject) override
Definition mfstream.cpp:32
MFStream(QIODevice *stream, bool ownStream)
Definition mfstream.cpp:11
void customEvent(QEvent *event) override
This event handler can be reimplemented in a subclass to receive custom events.
Definition mfstream.cpp:254
IMFAsyncResult * m_currentReadResult
Definition mfstream_p.h:119
STDMETHODIMP GetCapabilities(DWORD *pdwCapabilities) override
Definition mfstream.cpp:64
STDMETHODIMP_(ULONG) AddRef(void) override
STDMETHODIMP Seek(MFBYTESTREAM_SEEK_ORIGIN SeekOrigin, LONGLONG llSeekOffset, DWORD, QWORD *pqwCurrentPosition) override
Definition mfstream.cpp:186
STDMETHODIMP GetCurrentPosition(QWORD *pqwPosition) override
Definition mfstream.cpp:88
STDMETHODIMP Close() override
Definition mfstream.cpp:218
STDMETHODIMP BeginRead(BYTE *pb, ULONG cb, IMFAsyncCallback *pCallback, IUnknown *punkState) override
Definition mfstream.cpp:131
STDMETHODIMP IsEndOfStream(BOOL *pfEndOfStream) override
Definition mfstream.cpp:113
STDMETHODIMP Read(BYTE *pb, ULONG cb, ULONG *pcbRead) override
Definition mfstream.cpp:122
STDMETHODIMP BeginWrite(const BYTE *, ULONG, IMFAsyncCallback *, IUnknown *) override
Definition mfstream.cpp:173
STDMETHODIMP EndRead(IMFAsyncResult *pResult, ULONG *pcbRead) override
Definition mfstream.cpp:152
STDMETHODIMP GetLength(QWORD *pqwLength) override
Definition mfstream.cpp:74
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
\inmodule QtCore
Definition qcoreevent.h:45
\inmodule QtCore \reentrant
Definition qiodevice.h:34
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from.
virtual bool isSequential() const
Returns true if this device is sequential; otherwise returns false.
virtual void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success,...
virtual bool atEnd() const
Returns true if the current read and write position is at the end of the device (i....
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
\inmodule QtCore
Definition qmutex.h:313
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1598
bool moveToThread(QThread *thread QT6_DECL_NEW_OVERLOAD_TAIL)
Changes the thread affinity for this object and its children and returns true on success.
Definition qobject.cpp:1643
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
virtual void customEvent(QEvent *event)
This event handler can be reimplemented in a subclass to receive custom events.
Definition qobject.cpp:1522
else opt state
[0]
STDMETHODIMP_(ULONG) MFStream
Definition mfstream.cpp:48
Combined button and popup list for selecting options.
EGLStreamKHR stream
struct _cl_event * event
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
long long qint64
Definition qtypes.h:60
ReturnedValue read(const char *data)
IUIViewSettingsInterop __RPC__in REFIID riid
long HRESULT