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