regedit: Hebrew translation fix.
[wine/testsucceed.git] / dlls / quartz / transform.c
blobe904f50bc6d59281b17a7990c708a916b65db936
1 /*
2 * Transform Filter (Base for decoders, etc...)
4 * Copyright 2005 Christian Costa
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
23 #include "quartz_private.h"
24 #include "control_private.h"
25 #include "pin.h"
27 #include "amvideo.h"
28 #include "windef.h"
29 #include "winbase.h"
30 #include "dshow.h"
31 #include "strmif.h"
32 #include "vfw.h"
34 #include <assert.h>
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 #include "transform.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
43 static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
44 static const WCHAR wcsOutputPinName[] = {'o','u','t','p','u','t',' ','p','i','n',0};
46 static const IBaseFilterVtbl TransformFilter_Vtbl;
47 static const IPinVtbl TransformFilter_InputPin_Vtbl;
48 static const IPinVtbl TransformFilter_OutputPin_Vtbl;
50 static HRESULT WINAPI TransformFilter_Input_CheckMediaType(IPin *iface, const AM_MEDIA_TYPE * pmt)
52 TransformFilterImpl* This = (TransformFilterImpl *)((BasePin *)iface)->pinInfo.pFilter;
53 TRACE("%p\n", iface);
54 dump_AM_MEDIA_TYPE(pmt);
56 if (This->pFuncsTable->pfnQueryConnect)
57 return This->pFuncsTable->pfnQueryConnect(This, pmt);
58 /* Assume OK if there's no query method (the connection will fail if
59 needed) */
60 return S_OK;
64 static HRESULT WINAPI TransformFilter_Output_QueryAccept(IPin *iface, const AM_MEDIA_TYPE * pmt)
66 BasePin *This = (BasePin *)iface;
67 TransformFilterImpl *pTransformFilter = (TransformFilterImpl *)This->pinInfo.pFilter;
68 AM_MEDIA_TYPE* outpmt = &pTransformFilter->pmt;
69 TRACE("%p\n", iface);
71 if (IsEqualIID(&pmt->majortype, &outpmt->majortype)
72 && (IsEqualIID(&pmt->subtype, &outpmt->subtype) || IsEqualIID(&outpmt->subtype, &GUID_NULL)))
73 return S_OK;
74 return S_FALSE;
77 HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSID* pClsid, const TransformFuncsTable* pFuncsTable)
79 HRESULT hr;
80 PIN_INFO piInput;
81 PIN_INFO piOutput;
83 /* pTransformFilter is already allocated */
84 pTransformFilter->clsid = *pClsid;
85 pTransformFilter->pFuncsTable = pFuncsTable;
87 pTransformFilter->lpVtbl = &TransformFilter_Vtbl;
89 pTransformFilter->refCount = 1;
90 InitializeCriticalSection(&pTransformFilter->csFilter);
91 pTransformFilter->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TransformFilterImpl.csFilter");
92 pTransformFilter->state = State_Stopped;
93 pTransformFilter->pClock = NULL;
94 ZeroMemory(&pTransformFilter->filterInfo, sizeof(FILTER_INFO));
95 ZeroMemory(&pTransformFilter->pmt, sizeof(pTransformFilter->pmt));
96 pTransformFilter->npins = 2;
98 pTransformFilter->ppPins = CoTaskMemAlloc(2 * sizeof(IPin *));
100 /* construct input pin */
101 piInput.dir = PINDIR_INPUT;
102 piInput.pFilter = (IBaseFilter *)pTransformFilter;
103 lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
104 piOutput.dir = PINDIR_OUTPUT;
105 piOutput.pFilter = (IBaseFilter *)pTransformFilter;
106 lstrcpynW(piOutput.achName, wcsOutputPinName, sizeof(piOutput.achName) / sizeof(piOutput.achName[0]));
108 hr = BaseInputPin_Construct(&TransformFilter_InputPin_Vtbl, &piInput, TransformFilter_Input_CheckMediaType, pFuncsTable->pfnProcessSampleData, &pTransformFilter->csFilter, NULL, &pTransformFilter->ppPins[0]);
110 if (SUCCEEDED(hr))
112 ALLOCATOR_PROPERTIES props;
113 props.cbAlign = 1;
114 props.cbPrefix = 0;
115 props.cbBuffer = 0; /* Will be updated at connection time */
116 props.cBuffers = 1;
118 hr = BaseOutputPin_Construct(&TransformFilter_OutputPin_Vtbl, sizeof(BaseOutputPin), &piOutput, &props, NULL, &pTransformFilter->csFilter, &pTransformFilter->ppPins[1]);
120 if (FAILED(hr))
121 ERR("Cannot create output pin (%x)\n", hr);
122 else
124 ISeekingPassThru *passthru;
125 hr = CoCreateInstance(&CLSID_SeekingPassThru, (IUnknown*)pTransformFilter, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&pTransformFilter->seekthru_unk);
126 IUnknown_QueryInterface(pTransformFilter->seekthru_unk, &IID_ISeekingPassThru, (void**)&passthru);
127 ISeekingPassThru_Init(passthru, FALSE, (IPin*)pTransformFilter->ppPins[0]);
128 ISeekingPassThru_Release(passthru);
131 if (FAILED(hr))
133 CoTaskMemFree(pTransformFilter->ppPins);
134 pTransformFilter->csFilter.DebugInfo->Spare[0] = 0;
135 DeleteCriticalSection(&pTransformFilter->csFilter);
136 CoTaskMemFree(pTransformFilter);
139 return hr;
142 static HRESULT WINAPI TransformFilter_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
144 TransformFilterImpl *This = (TransformFilterImpl *)iface;
145 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
147 *ppv = NULL;
149 if (IsEqualIID(riid, &IID_IUnknown))
150 *ppv = This;
151 else if (IsEqualIID(riid, &IID_IPersist))
152 *ppv = This;
153 else if (IsEqualIID(riid, &IID_IMediaFilter))
154 *ppv = This;
155 else if (IsEqualIID(riid, &IID_IBaseFilter))
156 *ppv = This;
157 else if (IsEqualIID(riid, &IID_IMediaSeeking))
158 return IUnknown_QueryInterface(This->seekthru_unk, riid, ppv);
160 if (*ppv)
162 IUnknown_AddRef((IUnknown *)(*ppv));
163 return S_OK;
166 if (!IsEqualIID(riid, &IID_IPin) && !IsEqualIID(riid, &IID_IVideoWindow))
167 FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
169 return E_NOINTERFACE;
172 static ULONG WINAPI TransformFilter_AddRef(IBaseFilter * iface)
174 TransformFilterImpl *This = (TransformFilterImpl *)iface;
175 ULONG refCount = InterlockedIncrement(&This->refCount);
177 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
179 return refCount;
182 static ULONG WINAPI TransformFilter_Release(IBaseFilter * iface)
184 TransformFilterImpl *This = (TransformFilterImpl *)iface;
185 ULONG refCount = InterlockedDecrement(&This->refCount);
187 TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
189 if (!refCount)
191 ULONG i;
193 if (This->pClock)
194 IReferenceClock_Release(This->pClock);
196 for (i = 0; i < This->npins; i++)
198 IPin *pConnectedTo;
200 if (SUCCEEDED(IPin_ConnectedTo(This->ppPins[i], &pConnectedTo)))
202 IPin_Disconnect(pConnectedTo);
203 IPin_Release(pConnectedTo);
205 IPin_Disconnect(This->ppPins[i]);
207 IPin_Release(This->ppPins[i]);
210 CoTaskMemFree(This->ppPins);
211 This->lpVtbl = NULL;
213 This->csFilter.DebugInfo->Spare[0] = 0;
214 DeleteCriticalSection(&This->csFilter);
216 TRACE("Destroying transform filter\n");
217 FreeMediaType(&This->pmt);
218 CoTaskMemFree(This);
220 return 0;
222 else
223 return refCount;
226 /** IPersist methods **/
228 static HRESULT WINAPI TransformFilter_GetClassID(IBaseFilter * iface, CLSID * pClsid)
230 TransformFilterImpl *This = (TransformFilterImpl *)iface;
232 TRACE("(%p/%p)->(%p)\n", This, iface, pClsid);
234 *pClsid = This->clsid;
236 return S_OK;
239 /** IMediaFilter methods **/
241 static HRESULT WINAPI TransformFilter_Stop(IBaseFilter * iface)
243 TransformFilterImpl *This = (TransformFilterImpl *)iface;
244 HRESULT hr = S_OK;
246 TRACE("(%p/%p)\n", This, iface);
248 EnterCriticalSection(&This->csFilter);
250 This->state = State_Stopped;
251 if (This->pFuncsTable->pfnProcessEnd)
252 hr = This->pFuncsTable->pfnProcessEnd(This);
254 LeaveCriticalSection(&This->csFilter);
256 return hr;
259 static HRESULT WINAPI TransformFilter_Pause(IBaseFilter * iface)
261 TransformFilterImpl *This = (TransformFilterImpl *)iface;
262 HRESULT hr;
264 TRACE("(%p/%p)->()\n", This, iface);
266 EnterCriticalSection(&This->csFilter);
268 if (This->state == State_Stopped)
269 hr = IBaseFilter_Run(iface, -1);
270 else
271 hr = S_OK;
273 if (SUCCEEDED(hr))
274 This->state = State_Paused;
276 LeaveCriticalSection(&This->csFilter);
278 return hr;
281 static HRESULT WINAPI TransformFilter_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
283 HRESULT hr = S_OK;
284 TransformFilterImpl *This = (TransformFilterImpl *)iface;
286 TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
288 EnterCriticalSection(&This->csFilter);
290 if (This->state == State_Stopped)
292 ((BaseInputPin *)This->ppPins[0])->end_of_stream = 0;
293 if (This->pFuncsTable->pfnProcessBegin)
294 hr = This->pFuncsTable->pfnProcessBegin(This);
295 if (SUCCEEDED(hr))
296 hr = BaseOutputPinImpl_Active((BaseOutputPin *)This->ppPins[1]);
299 if (SUCCEEDED(hr))
301 This->rtStreamStart = tStart;
302 This->state = State_Running;
305 LeaveCriticalSection(&This->csFilter);
307 return hr;
310 static HRESULT WINAPI TransformFilter_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
312 TransformFilterImpl *This = (TransformFilterImpl *)iface;
314 TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState);
316 EnterCriticalSection(&This->csFilter);
318 *pState = This->state;
320 LeaveCriticalSection(&This->csFilter);
322 return S_OK;
325 static HRESULT WINAPI TransformFilter_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
327 TransformFilterImpl *This = (TransformFilterImpl *)iface;
329 TRACE("(%p/%p)->(%p)\n", This, iface, pClock);
331 EnterCriticalSection(&This->csFilter);
333 if (This->pClock)
334 IReferenceClock_Release(This->pClock);
335 This->pClock = pClock;
336 if (This->pClock)
337 IReferenceClock_AddRef(This->pClock);
339 LeaveCriticalSection(&This->csFilter);
341 return S_OK;
344 static HRESULT WINAPI TransformFilter_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
346 TransformFilterImpl *This = (TransformFilterImpl *)iface;
348 TRACE("(%p/%p)->(%p)\n", This, iface, ppClock);
350 EnterCriticalSection(&This->csFilter);
352 *ppClock = This->pClock;
353 if (This->pClock)
354 IReferenceClock_AddRef(This->pClock);
356 LeaveCriticalSection(&This->csFilter);
358 return S_OK;
361 /** IBaseFilter implementation **/
363 static IPin* WINAPI TransformFilter_GetPin(IBaseFilter *iface, int pos)
365 TransformFilterImpl *This = (TransformFilterImpl *)iface;
367 if (pos >= This->npins || pos < 0)
368 return NULL;
370 IPin_AddRef(This->ppPins[pos]);
371 return This->ppPins[pos];
374 static LONG WINAPI TransformFilter_GetPinCount(IBaseFilter *iface)
376 TransformFilterImpl *This = (TransformFilterImpl *)iface;
378 return (This->npins+1);
381 static LONG WINAPI TransformFilter_GetPinVersion(IBaseFilter *iface)
383 /* Our pins are static, not changing so setting static tick count is ok */
384 return 0;
387 static HRESULT WINAPI TransformFilter_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
389 TransformFilterImpl *This = (TransformFilterImpl *)iface;
391 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
393 return EnumPins_Construct(iface, TransformFilter_GetPin, TransformFilter_GetPinCount, TransformFilter_GetPinVersion, ppEnum);
396 static HRESULT WINAPI TransformFilter_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
398 TransformFilterImpl *This = (TransformFilterImpl *)iface;
400 TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin);
402 return E_NOTIMPL;
405 static HRESULT WINAPI TransformFilter_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
407 TransformFilterImpl *This = (TransformFilterImpl *)iface;
409 TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
411 strcpyW(pInfo->achName, This->filterInfo.achName);
412 pInfo->pGraph = This->filterInfo.pGraph;
414 if (pInfo->pGraph)
415 IFilterGraph_AddRef(pInfo->pGraph);
417 return S_OK;
420 static HRESULT WINAPI TransformFilter_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
422 HRESULT hr = S_OK;
423 TransformFilterImpl *This = (TransformFilterImpl *)iface;
425 TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName));
427 EnterCriticalSection(&This->csFilter);
429 if (pName)
430 strcpyW(This->filterInfo.achName, pName);
431 else
432 *This->filterInfo.achName = '\0';
433 This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
435 LeaveCriticalSection(&This->csFilter);
437 return hr;
440 static HRESULT WINAPI TransformFilter_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
442 TransformFilterImpl *This = (TransformFilterImpl *)iface;
443 TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo);
444 return E_NOTIMPL;
447 static const IBaseFilterVtbl TransformFilter_Vtbl =
449 TransformFilter_QueryInterface,
450 TransformFilter_AddRef,
451 TransformFilter_Release,
452 TransformFilter_GetClassID,
453 TransformFilter_Stop,
454 TransformFilter_Pause,
455 TransformFilter_Run,
456 TransformFilter_GetState,
457 TransformFilter_SetSyncSource,
458 TransformFilter_GetSyncSource,
459 TransformFilter_EnumPins,
460 TransformFilter_FindPin,
461 TransformFilter_QueryFilterInfo,
462 TransformFilter_JoinFilterGraph,
463 TransformFilter_QueryVendorInfo
466 static HRESULT WINAPI TransformFilter_InputPin_EndOfStream(IPin * iface)
468 BaseInputPin* This = (BaseInputPin*) iface;
469 TransformFilterImpl* pTransform;
470 IPin* ppin;
471 HRESULT hr;
473 TRACE("(%p)->()\n", iface);
475 /* Since we process samples synchronously, just forward notification downstream */
476 pTransform = (TransformFilterImpl*)This->pin.pinInfo.pFilter;
477 if (!pTransform)
478 hr = E_FAIL;
479 else
480 hr = IPin_ConnectedTo(pTransform->ppPins[1], &ppin);
481 if (SUCCEEDED(hr))
483 hr = IPin_EndOfStream(ppin);
484 IPin_Release(ppin);
487 if (FAILED(hr))
488 ERR("%x\n", hr);
489 return hr;
492 static HRESULT WINAPI TransformFilter_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
494 BaseInputPin* This = (BaseInputPin*) iface;
495 TransformFilterImpl* pTransform;
496 HRESULT hr;
498 TRACE("(%p)->(%p, %p)\n", iface, pReceivePin, pmt);
500 pTransform = (TransformFilterImpl*)This->pin.pinInfo.pFilter;
502 hr = pTransform->pFuncsTable->pfnConnectInput(This, pmt);
503 if (SUCCEEDED(hr))
505 hr = BaseInputPinImpl_ReceiveConnection(iface, pReceivePin, pmt);
506 if (FAILED(hr))
507 pTransform->pFuncsTable->pfnCleanup(This);
510 return hr;
513 static HRESULT WINAPI TransformFilter_InputPin_Disconnect(IPin * iface)
515 BaseInputPin* This = (BaseInputPin*) iface;
516 TransformFilterImpl* pTransform;
518 TRACE("(%p)->()\n", iface);
520 pTransform = (TransformFilterImpl*)This->pin.pinInfo.pFilter;
521 pTransform->pFuncsTable->pfnCleanup(This);
523 return BasePinImpl_Disconnect(iface);
526 static HRESULT WINAPI TransformFilter_InputPin_BeginFlush(IPin * iface)
528 BaseInputPin* This = (BaseInputPin*) iface;
529 TransformFilterImpl* pTransform;
530 HRESULT hr = S_OK;
532 TRACE("(%p)->()\n", iface);
534 pTransform = (TransformFilterImpl*)This->pin.pinInfo.pFilter;
535 EnterCriticalSection(&pTransform->csFilter);
536 if (pTransform->pFuncsTable->pfnBeginFlush)
537 hr = pTransform->pFuncsTable->pfnBeginFlush(This);
538 if (SUCCEEDED(hr))
539 hr = BaseInputPinImpl_BeginFlush(iface);
540 LeaveCriticalSection(&pTransform->csFilter);
541 return hr;
544 static HRESULT WINAPI TransformFilter_InputPin_EndFlush(IPin * iface)
546 BaseInputPin* This = (BaseInputPin*) iface;
547 TransformFilterImpl* pTransform;
548 HRESULT hr = S_OK;
550 TRACE("(%p)->()\n", iface);
552 pTransform = (TransformFilterImpl*)This->pin.pinInfo.pFilter;
553 EnterCriticalSection(&pTransform->csFilter);
554 if (pTransform->pFuncsTable->pfnEndFlush)
555 hr = pTransform->pFuncsTable->pfnEndFlush(This);
556 if (SUCCEEDED(hr))
557 hr = BaseInputPinImpl_EndFlush(iface);
558 LeaveCriticalSection(&pTransform->csFilter);
559 return hr;
562 static HRESULT WINAPI TransformFilter_InputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
564 BaseInputPin* This = (BaseInputPin*) iface;
565 TransformFilterImpl* pTransform;
566 HRESULT hr = S_OK;
568 TRACE("(%p)->()\n", iface);
570 pTransform = (TransformFilterImpl*)This->pin.pinInfo.pFilter;
571 EnterCriticalSection(&pTransform->csFilter);
572 if (pTransform->pFuncsTable->pfnNewSegment)
573 hr = pTransform->pFuncsTable->pfnNewSegment(This, tStart, tStop, dRate);
574 if (SUCCEEDED(hr))
575 hr = BaseInputPinImpl_NewSegment(iface, tStart, tStop, dRate);
576 LeaveCriticalSection(&pTransform->csFilter);
577 return hr;
580 static const IPinVtbl TransformFilter_InputPin_Vtbl =
582 BaseInputPinImpl_QueryInterface,
583 BasePinImpl_AddRef,
584 BaseInputPinImpl_Release,
585 BaseInputPinImpl_Connect,
586 TransformFilter_InputPin_ReceiveConnection,
587 TransformFilter_InputPin_Disconnect,
588 BasePinImpl_ConnectedTo,
589 BasePinImpl_ConnectionMediaType,
590 BasePinImpl_QueryPinInfo,
591 BasePinImpl_QueryDirection,
592 BasePinImpl_QueryId,
593 BaseInputPinImpl_QueryAccept,
594 BasePinImpl_EnumMediaTypes,
595 BasePinImpl_QueryInternalConnections,
596 TransformFilter_InputPin_EndOfStream,
597 TransformFilter_InputPin_BeginFlush,
598 TransformFilter_InputPin_EndFlush,
599 TransformFilter_InputPin_NewSegment
602 static HRESULT WINAPI TransformFilter_Output_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt)
604 BasePin *This = (BasePin *)iface;
605 TransformFilterImpl *pTransform = (TransformFilterImpl *)This->pinInfo.pFilter;
607 if (iPosition < 0)
608 return E_INVALIDARG;
609 if (iPosition > 0)
610 return VFW_S_NO_MORE_ITEMS;
611 CopyMediaType(pmt, &pTransform->pmt);
612 return S_OK;
615 static HRESULT WINAPI TransformFilter_Output_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
617 BasePin *This = (BasePin *)iface;
618 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
620 return EnumMediaTypes_Construct(iface, TransformFilter_Output_GetMediaType, BasePinImpl_GetMediaTypeVersion, ppEnum);
623 static const IPinVtbl TransformFilter_OutputPin_Vtbl =
625 BaseOutputPinImpl_QueryInterface,
626 BasePinImpl_AddRef,
627 BaseOutputPinImpl_Release,
628 BaseOutputPinImpl_Connect,
629 BaseOutputPinImpl_ReceiveConnection,
630 BaseOutputPinImpl_Disconnect,
631 BasePinImpl_ConnectedTo,
632 BasePinImpl_ConnectionMediaType,
633 BasePinImpl_QueryPinInfo,
634 BasePinImpl_QueryDirection,
635 BasePinImpl_QueryId,
636 TransformFilter_Output_QueryAccept,
637 TransformFilter_Output_EnumMediaTypes,
638 BasePinImpl_QueryInternalConnections,
639 BaseOutputPinImpl_EndOfStream,
640 BaseOutputPinImpl_BeginFlush,
641 BaseOutputPinImpl_EndFlush,
642 BaseOutputPinImpl_NewSegment