Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
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
6
#
include
<
QtCore
/
qcoreapplication
.
h
>
7
8
QT_BEGIN_NAMESPACE
9
//MFStream is added for supporting QIODevice type of media source.
10
//It is used to delegate invocations from media foundation(through IMFByteStream) to QIODevice.
11
12
MFStream::MFStream(
QIODevice
*
stream
,
bool
ownStream
,
bool
synchronous
)
13
:
m_stream
(
stream
), m_ownStream(ownStream), m_synchronous(synchronous)
14
{
15
//Move to the thread of the stream object
16
//to make sure invocations on stream
17
//are happened in the same thread of stream object
18
if
(!synchronous)
19
this
->moveToThread(stream->thread());
20
}
21
22
MFStream::~MFStream()
23
{
24
if
(m_ownStream)
25
m_stream->deleteLater();
26
}
27
28
//from IMFByteStream
29
STDMETHODIMP MFStream::GetCapabilities(DWORD *pdwCapabilities)
30
{
31
if
(!pdwCapabilities)
32
return
E_INVALIDARG;
33
*pdwCapabilities = MFBYTESTREAM_IS_READABLE;
34
if
(!m_stream->isSequential())
35
*pdwCapabilities |= MFBYTESTREAM_IS_SEEKABLE;
36
return
S_OK;
37
}
38
39
STDMETHODIMP MFStream::GetLength(QWORD *pqwLength)
40
{
41
if
(!pqwLength)
42
return
E_INVALIDARG;
43
QMutexLocker locker(&m_mutex);
44
*pqwLength = QWORD(m_stream->size());
45
return
S_OK;
46
}
47
48
STDMETHODIMP MFStream::SetLength(QWORD)
49
{
50
return
E_NOTIMPL;
51
}
52
53
STDMETHODIMP MFStream::GetCurrentPosition(QWORD *pqwPosition)
54
{
55
if
(!pqwPosition)
56
return
E_INVALIDARG;
57
QMutexLocker locker(&m_mutex);
58
*pqwPosition = m_stream->pos();
59
return
S_OK;
60
}
61
62
STDMETHODIMP MFStream::SetCurrentPosition(QWORD qwPosition)
63
{
64
QMutexLocker locker(&m_mutex);
65
//SetCurrentPosition may happend during the BeginRead/EndRead pair,
66
//refusing to execute SetCurrentPosition during that time seems to be
67
//the simplest workable solution
68
if
(m_currentReadResult)
69
return
S_FALSE;
70
71
bool
seekOK = m_stream->seek(qint64(qwPosition));
72
if
(seekOK)
73
return
S_OK;
74
else
75
return
S_FALSE;
76
}
77
78
STDMETHODIMP MFStream::IsEndOfStream(BOOL *pfEndOfStream)
79
{
80
if
(!pfEndOfStream)
81
return
E_INVALIDARG;
82
QMutexLocker locker(&m_mutex);
83
*pfEndOfStream = m_stream->atEnd() ? TRUE : FALSE;
84
return
S_OK;
85
}
86
87
STDMETHODIMP MFStream::Read(BYTE *pb, ULONG cb, ULONG *pcbRead)
88
{
89
QMutexLocker locker(&m_mutex);
90
qint64 read = m_stream->read((
char
*)(pb), qint64(cb));
91
if
(pcbRead)
92
*pcbRead = ULONG(read);
93
return
S_OK;
94
}
95
96
STDMETHODIMP MFStream::BeginRead(BYTE *pb, ULONG cb, IMFAsyncCallback *pCallback,
97
IUnknown *punkState)
98
{
99
if
(!pCallback || !pb)
100
return
E_INVALIDARG;
101
102
if
(m_synchronous) {
103
// Synchronous mode: read immediately and invoke callback.
104
ULONG cbRead = 0;
105
Read(pb, cb, &cbRead);
106
107
ComPtr<IMFAsyncResult> result;
108
HRESULT hr = MFCreateAsyncResult(
nullptr
, pCallback, punkState, &result);
109
if
(FAILED(hr))
110
return
hr;
111
112
m_syncReadCount = cbRead;
113
result->SetStatus(S_OK);
114
hr = MFInvokeCallback(result.Get());
115
return
hr;
116
}
117
118
Q_ASSERT(m_currentReadResult ==
nullptr
);
119
120
ComPtr<AsyncReadState> state = makeComObject<AsyncReadState>(pb, cb);
121
122
HRESULT hr = MFCreateAsyncResult(state.Get(), pCallback, punkState, &m_currentReadResult);
123
if
(FAILED(hr))
124
return
hr;
125
126
QCoreApplication::postEvent(
this
,
new
QEvent(QEvent::User));
127
return
hr;
128
}
129
130
STDMETHODIMP MFStream::EndRead(IMFAsyncResult* pResult, ULONG *pcbRead)
131
{
132
if
(!pcbRead)
133
return
E_INVALIDARG;
134
135
if
(m_synchronous) {
136
*pcbRead = m_syncReadCount;
137
return
S_OK;
138
}
139
140
ComPtr<IUnknown> pUnk;
141
pResult->GetObject(&pUnk);
142
auto
*state =
static_cast
<AsyncReadState *>(pUnk.Get());
143
*pcbRead = state->bytesRead();
144
145
m_currentReadResult =
nullptr
;
146
147
return
S_OK;
148
}
149
150
STDMETHODIMP MFStream::Write(
const
BYTE *, ULONG, ULONG *)
151
{
152
return
E_NOTIMPL;
153
}
154
155
STDMETHODIMP MFStream::BeginWrite(
const
BYTE *, ULONG ,
156
IMFAsyncCallback *,
157
IUnknown *)
158
{
159
return
E_NOTIMPL;
160
}
161
162
STDMETHODIMP MFStream::EndWrite(IMFAsyncResult *,
163
ULONG *)
164
{
165
return
E_NOTIMPL;
166
}
167
168
STDMETHODIMP MFStream::Seek(
169
MFBYTESTREAM_SEEK_ORIGIN SeekOrigin,
170
LONGLONG llSeekOffset,
171
DWORD,
172
QWORD *pqwCurrentPosition)
173
{
174
QMutexLocker locker(&m_mutex);
175
if
(m_currentReadResult)
176
return
S_FALSE;
177
178
qint64 pos = qint64(llSeekOffset);
179
switch
(SeekOrigin) {
180
case
msoBegin:
181
break
;
182
case
msoCurrent:
183
pos += m_stream->pos();
184
break
;
185
}
186
bool
seekOK = m_stream->seek(pos);
187
if
(pqwCurrentPosition)
188
*pqwCurrentPosition = pos;
189
if
(seekOK)
190
return
S_OK;
191
else
192
return
S_FALSE;
193
}
194
195
STDMETHODIMP MFStream::Flush()
196
{
197
return
E_NOTIMPL;
198
}
199
200
STDMETHODIMP MFStream::Close()
201
{
202
QMutexLocker locker(&m_mutex);
203
if
(m_ownStream)
204
m_stream->close();
205
return
S_OK;
206
}
207
208
void
MFStream::doRead()
209
{
210
if
(!m_stream)
211
return
;
212
213
bool
readDone =
true
;
214
ComPtr<IUnknown> pUnk;
215
HRESULT hr = m_currentReadResult->GetObject(&pUnk);
216
if
(SUCCEEDED(hr)) {
217
//do actual read
218
auto
*state =
static_cast
<AsyncReadState *>(pUnk.Get());
219
ULONG cbRead;
220
Read(state->pb(), state->cb() - state->bytesRead(), &cbRead);
221
222
state->setBytesRead(cbRead + state->bytesRead());
223
if
(state->cb() > state->bytesRead() && !m_stream->atEnd()) {
224
readDone =
false
;
225
}
226
}
227
228
if
(readDone) {
229
//now inform the original caller
230
m_currentReadResult->SetStatus(hr);
231
MFInvokeCallback(m_currentReadResult.Get());
232
}
233
}
234
235
void
MFStream::customEvent(QEvent *event)
236
{
237
if
(event->type() != QEvent::User) {
238
QObject::customEvent(event);
239
return
;
240
}
241
doRead();
242
}
243
244
//AsyncReadState is a helper class used in BeginRead for asynchronous operation
245
//to record some BeginRead parameters, so these parameters could be
246
//used later when actually executing the read operation in another thread.
247
MFStream::AsyncReadState::AsyncReadState(BYTE *pb, ULONG cb)
248
: m_pb(pb)
249
, m_cb(cb)
250
, m_cbRead(0)
251
{
252
}
253
254
255
BYTE* MFStream::AsyncReadState::pb()
const
256
{
257
return
m_pb;
258
}
259
260
ULONG MFStream::AsyncReadState::cb()
const
261
{
262
return
m_cb;
263
}
264
265
ULONG MFStream::AsyncReadState::bytesRead()
const
266
{
267
return
m_cbRead;
268
}
269
270
void
MFStream::AsyncReadState::setBytesRead(ULONG cbRead)
271
{
272
m_cbRead = cbRead;
273
}
274
275
QT_END_NAMESPACE
276
277
#
include
"moc_mfstream_p.cpp"
QAbstractTestLogger::stream
FILE * stream
Definition
qabstracttestlogger_p.h:87
QIODevice
\inmodule QtCore \reentrant
Definition
qiodevice.h:38
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
qtmultimedia
src
plugins
multimedia
windows
mfstream.cpp
Generated on
for Qt by
1.18.0