source: trunk/src/3rdparty/phonon/ds9/qmeminputpin.cpp

Last change on this file was 561, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 9.4 KB
Line 
1/* This file is part of the KDE project.
2
3Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
5This library is free software: you can redistribute it and/or modify
6it under the terms of the GNU Lesser General Public License as published by
7the Free Software Foundation, either version 2.1 or 3 of the License.
8
9This library is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU Lesser General Public License for more details.
13
14You should have received a copy of the GNU Lesser General Public License
15along with this library. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "qmeminputpin.h"
19#include "qbasefilter.h"
20#include "compointer.h"
21
22#include <QtCore/QDebug>
23
24QT_BEGIN_NAMESPACE
25
26namespace Phonon
27{
28 namespace DS9
29 {
30
31 QMemInputPin::QMemInputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt, bool transform, QPin *output) :
32 QPin(parent, PINDIR_INPUT, mt), m_shouldDuplicateSamples(true), m_transform(transform), m_output(output)
33 {
34 }
35
36 QMemInputPin::~QMemInputPin()
37 {
38 }
39
40 STDMETHODIMP QMemInputPin::QueryInterface(REFIID iid, void **out)
41 {
42 if (!out) {
43 return E_POINTER;
44 }
45
46 if (iid == IID_IMemInputPin) {
47 *out = static_cast<IMemInputPin*>(this);
48 AddRef();
49 return S_OK;
50 } else {
51 return QPin::QueryInterface(iid, out);
52 }
53 }
54
55 STDMETHODIMP_(ULONG) QMemInputPin::AddRef()
56 {
57 return QPin::AddRef();
58 }
59
60 STDMETHODIMP_(ULONG) QMemInputPin::Release()
61 {
62 return QPin::Release();
63 }
64
65 STDMETHODIMP QMemInputPin::EndOfStream()
66 {
67 //this allows to serialize with Receive calls
68 QMutexLocker locker(&m_mutexReceive);
69 IPin *conn = m_output ? m_output->connected() : 0;
70 if (conn) {
71 conn->EndOfStream();
72 }
73 return S_OK;
74 }
75
76 STDMETHODIMP QMemInputPin::BeginFlush()
77 {
78 //pass downstream
79 IPin *conn = m_output ? m_output->connected() : 0;
80 if (conn) {
81 conn->BeginFlush();
82 }
83 QMutexLocker locker(&m_mutex);
84 m_flushing = true;
85 return S_OK;
86 }
87
88 STDMETHODIMP QMemInputPin::EndFlush()
89 {
90 //pass downstream
91 IPin *conn = m_output ? m_output->connected() : 0;
92 if (conn) {
93 conn->EndFlush();
94 }
95 QMutexLocker locker(&m_mutex);
96 m_flushing = false;
97 return S_OK;
98 }
99
100 STDMETHODIMP QMemInputPin::NewSegment(REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
101 {
102 if (m_output)
103 m_output->NewSegment(start, stop, rate);
104 return S_OK;
105 }
106
107 //reimplementation to set the type for the output pin
108 //no need to make a deep copy here
109 STDMETHODIMP QMemInputPin::ReceiveConnection(IPin *pin ,const AM_MEDIA_TYPE *mt)
110 {
111 HRESULT hr = QPin::ReceiveConnection(pin, mt);
112 if (hr == S_OK &&
113 mt->majortype != MEDIATYPE_NULL &&
114 mt->subtype != MEDIASUBTYPE_NULL &&
115 mt->formattype != GUID_NULL && m_output) {
116 //we tell the output pin that it should connect with this type
117 hr = m_output->setAcceptedMediaType(connectedType());
118 }
119 return hr;
120 }
121
122 STDMETHODIMP QMemInputPin::GetAllocator(IMemAllocator **alloc)
123 {
124 if (!alloc) {
125 return E_POINTER;
126 }
127
128 *alloc = memoryAllocator(true);
129 if (*alloc) {
130 return S_OK;
131 }
132
133 return VFW_E_NO_ALLOCATOR;
134 }
135
136 STDMETHODIMP QMemInputPin::NotifyAllocator(IMemAllocator *alloc, BOOL readonly)
137 {
138 if (!alloc) {
139 return E_POINTER;
140 }
141
142 {
143 QMutexLocker locker(&m_mutex);
144 m_shouldDuplicateSamples = m_transform && readonly;
145 }
146
147 setMemoryAllocator(alloc);
148
149 if (m_output) {
150 ComPointer<IMemInputPin> input(m_output, IID_IMemInputPin);
151 input->NotifyAllocator(alloc, m_shouldDuplicateSamples);
152 }
153
154 return S_OK;
155 }
156
157 STDMETHODIMP QMemInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *prop)
158 {
159 if (!prop) {
160 return E_POINTER;
161 }
162
163 //we have no particular requirements
164 return E_NOTIMPL;
165 }
166
167 STDMETHODIMP QMemInputPin::Receive(IMediaSample *sample)
168 {
169 QMutexLocker locker(&m_mutexReceive);
170 if (!sample) {
171 return E_POINTER;
172 }
173
174 if (filterState() == State_Stopped) {
175 return VFW_E_WRONG_STATE;
176 }
177
178 if (isFlushing()) {
179 return S_FALSE; //we are still flushing
180 }
181
182 if (!m_shouldDuplicateSamples) {
183 //we do it just once
184 HRESULT hr = m_parent->processSample(sample);
185 if (!SUCCEEDED(hr)) {
186 return hr;
187 }
188 }
189
190 if (m_output) {
191 IMediaSample *outSample = m_shouldDuplicateSamples ?
192 duplicateSampleForOutput(sample, m_output->memoryAllocator())
193 : sample;
194
195 if (m_shouldDuplicateSamples) {
196 m_parent->processSample(outSample);
197 }
198
199 ComPointer<IMemInputPin> input(m_output->connected(), IID_IMemInputPin);
200 if (input) {
201 input->Receive(outSample);
202 }
203
204 if (m_shouldDuplicateSamples) {
205 outSample->Release();
206 }
207 }
208 return S_OK;
209 }
210
211 STDMETHODIMP QMemInputPin::ReceiveMultiple(IMediaSample **samples,long count,long *nbDone)
212 {
213 //no need to lock here: there is no access to member data
214 if (!samples || !nbDone) {
215 return E_POINTER;
216 }
217
218 *nbDone = 0; //initialization
219 while( *nbDone != count) {
220 HRESULT hr = Receive(samples[*nbDone]);
221 if (FAILED(hr)) {
222 return hr;
223 }
224 (*nbDone)++;
225 }
226
227 return S_OK;
228 }
229
230 STDMETHODIMP QMemInputPin::ReceiveCanBlock()
231 {
232 //we test the output to see if it can block
233 if (m_output) {
234 ComPointer<IMemInputPin> meminput(m_output->connected(), IID_IMemInputPin);
235 if (meminput && meminput->ReceiveCanBlock() != S_FALSE) {
236 return S_OK;
237 }
238 }
239 return S_FALSE;
240 }
241
242
243 ALLOCATOR_PROPERTIES QMemInputPin::getDefaultAllocatorProperties() const
244 {
245 //those values reduce buffering a lot (good for the volume effect)
246 ALLOCATOR_PROPERTIES prop = {4096, 1, 1, 0};
247 return prop;
248 }
249
250
251 IMediaSample *QMemInputPin::duplicateSampleForOutput(IMediaSample *sample, IMemAllocator *alloc)
252 {
253 LONG length = sample->GetActualDataLength();
254
255 HRESULT hr = alloc->Commit();
256 if (hr == HRESULT(VFW_E_SIZENOTSET)) {
257 ALLOCATOR_PROPERTIES prop = getDefaultAllocatorProperties();
258 prop.cbBuffer = qMax(prop.cbBuffer, length);
259 ALLOCATOR_PROPERTIES actual;
260 //we just try to set the properties...
261 alloc->SetProperties(&prop, &actual);
262 hr = alloc->Commit();
263 }
264
265 Q_ASSERT(SUCCEEDED(hr));
266
267 IMediaSample *out;
268 hr = alloc->GetBuffer(&out, 0, 0, AM_GBF_NOTASYNCPOINT);
269 Q_ASSERT(SUCCEEDED(hr));
270
271 //let's copy the sample
272 {
273 REFERENCE_TIME start, end;
274 sample->GetTime(&start, &end);
275 out->SetTime(&start, &end);
276 }
277
278 hr = out->SetActualDataLength(length);
279 Q_ASSERT(SUCCEEDED(hr));
280 hr = out->SetDiscontinuity(sample->IsDiscontinuity());
281 Q_ASSERT(SUCCEEDED(hr));
282
283 {
284 LONGLONG start, end;
285 hr = sample->GetMediaTime(&start, &end);
286 if (hr != HRESULT(VFW_E_MEDIA_TIME_NOT_SET)) {
287 hr = out->SetMediaTime(&start, &end);
288 Q_ASSERT(SUCCEEDED(hr));
289 }
290 }
291
292 AM_MEDIA_TYPE *type = 0;
293 hr = sample->GetMediaType(&type);
294 Q_ASSERT(SUCCEEDED(hr));
295 hr = out->SetMediaType(type);
296 Q_ASSERT(SUCCEEDED(hr));
297
298 hr = out->SetPreroll(sample->IsPreroll());
299 Q_ASSERT(SUCCEEDED(hr));
300 hr = out->SetSyncPoint(sample->IsSyncPoint());
301 Q_ASSERT(SUCCEEDED(hr));
302
303 BYTE *dest = 0, *src = 0;
304 hr = out->GetPointer(&dest);
305 Q_ASSERT(SUCCEEDED(hr));
306 hr = sample->GetPointer(&src);
307 Q_ASSERT(SUCCEEDED(hr));
308
309 qMemCopy(dest, src, sample->GetActualDataLength());
310
311 return out;
312 }
313 }
314}
315
316QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.