Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
f2a8d535
Commit
f2a8d535
authored
Sep 18, 2018
by
Zebediah Figura
Committed by
Alexandre Julliard
Sep 18, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
quartz/tests: Rewrite test_render_filter_priority().
Signed-off-by:
Zebediah Figura
<
z.figura12@gmail.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
22308340
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
527 additions
and
1195 deletions
+527
-1195
filtergraph.c
dlls/quartz/tests/filtergraph.c
+527
-1195
No files found.
dlls/quartz/tests/filtergraph.c
View file @
f2a8d535
...
@@ -22,9 +22,9 @@
...
@@ -22,9 +22,9 @@
#define COBJMACROS
#define COBJMACROS
#define CONST_VTABLE
#define CONST_VTABLE
#include "wine/test.h"
#include "dshow.h"
#include "dshow.h"
#include "control.h"
#include "wine/heap.h"
#include "wine/test.h"
typedef
struct
TestFilterImpl
typedef
struct
TestFilterImpl
{
{
...
@@ -783,1511 +783,843 @@ static void test_graph_builder(void)
...
@@ -783,1511 +783,843 @@ static void test_graph_builder(void)
IGraphBuilder_Release
(
pgraph
);
IGraphBuilder_Release
(
pgraph
);
}
}
/* IEnumMediaTypes implementation (supporting code for Render() test.) */
struct
testpin
static
void
FreeMediaType
(
AM_MEDIA_TYPE
*
pMediaType
)
{
if
(
pMediaType
->
pbFormat
)
{
CoTaskMemFree
(
pMediaType
->
pbFormat
);
pMediaType
->
pbFormat
=
NULL
;
}
if
(
pMediaType
->
pUnk
)
{
IUnknown_Release
(
pMediaType
->
pUnk
);
pMediaType
->
pUnk
=
NULL
;
}
}
static
HRESULT
CopyMediaType
(
AM_MEDIA_TYPE
*
pDest
,
const
AM_MEDIA_TYPE
*
pSrc
)
{
*
pDest
=
*
pSrc
;
if
(
!
pSrc
->
pbFormat
)
return
S_OK
;
if
(
!
(
pDest
->
pbFormat
=
CoTaskMemAlloc
(
pSrc
->
cbFormat
)))
return
E_OUTOFMEMORY
;
memcpy
(
pDest
->
pbFormat
,
pSrc
->
pbFormat
,
pSrc
->
cbFormat
);
if
(
pDest
->
pUnk
)
IUnknown_AddRef
(
pDest
->
pUnk
);
return
S_OK
;
}
static
AM_MEDIA_TYPE
*
CreateMediaType
(
AM_MEDIA_TYPE
const
*
pSrc
)
{
AM_MEDIA_TYPE
*
pDest
;
pDest
=
CoTaskMemAlloc
(
sizeof
(
AM_MEDIA_TYPE
));
if
(
!
pDest
)
return
NULL
;
if
(
FAILED
(
CopyMediaType
(
pDest
,
pSrc
)))
{
CoTaskMemFree
(
pDest
);
return
NULL
;
}
return
pDest
;
}
static
BOOL
CompareMediaTypes
(
const
AM_MEDIA_TYPE
*
pmt1
,
const
AM_MEDIA_TYPE
*
pmt2
,
BOOL
bWildcards
)
{
return
(((
bWildcards
&&
(
IsEqualGUID
(
&
pmt1
->
majortype
,
&
GUID_NULL
)
||
IsEqualGUID
(
&
pmt2
->
majortype
,
&
GUID_NULL
)))
||
IsEqualGUID
(
&
pmt1
->
majortype
,
&
pmt2
->
majortype
))
&&
((
bWildcards
&&
(
IsEqualGUID
(
&
pmt1
->
subtype
,
&
GUID_NULL
)
||
IsEqualGUID
(
&
pmt2
->
subtype
,
&
GUID_NULL
)))
||
IsEqualGUID
(
&
pmt1
->
subtype
,
&
pmt2
->
subtype
)));
}
static
void
DeleteMediaType
(
AM_MEDIA_TYPE
*
pMediaType
)
{
{
FreeMediaType
(
pMediaType
);
IPin
IPin_iface
;
CoTaskMemFree
(
pMediaType
);
LONG
ref
;
}
PIN_DIRECTION
dir
;
IBaseFilter
*
filter
;
IPin
*
peer
;
typedef
struct
IEnumMediaTypesImpl
{
IEnumMediaTypes
IEnumMediaTypes_iface
;
IEnumMediaTypes
IEnumMediaTypes_iface
;
LONG
refCount
;
const
AM_MEDIA_TYPE
*
types
;
AM_MEDIA_TYPE
*
pMediaTypes
;
unsigned
int
type_count
,
enum_idx
;
ULONG
cMediaTypes
;
};
ULONG
uIndex
;
}
IEnumMediaTypesImpl
;
static
const
struct
IEnumMediaTypesVtbl
IEnumMediaTypesImpl_Vtbl
;
static
inline
IEnumMediaTypesImpl
*
impl_from_IEnumMediaTypes
(
IEnumMediaTypes
*
iface
)
static
inline
struct
testpin
*
impl_from_IEnumMediaTypes
(
IEnumMediaTypes
*
iface
)
{
{
return
CONTAINING_RECORD
(
iface
,
IEnumMediaTypesImpl
,
IEnumMediaTypes_iface
);
return
CONTAINING_RECORD
(
iface
,
struct
testpin
,
IEnumMediaTypes_iface
);
}
}
static
HRESULT
IEnumMediaTypesImpl_Construct
(
const
AM_MEDIA_TYPE
*
pMediaTypes
,
ULONG
cMediaTypes
,
IEnumMediaTypes
**
ppEnum
)
static
HRESULT
WINAPI
testenummt_QueryInterface
(
IEnumMediaTypes
*
iface
,
REFIID
iid
,
void
**
out
)
{
{
ULONG
i
;
struct
testpin
*
pin
=
impl_from_IEnumMediaTypes
(
iface
);
IEnumMediaTypesImpl
*
pEnumMediaTypes
=
CoTaskMemAlloc
(
sizeof
(
IEnumMediaTypesImpl
));
if
(
winetest_debug
>
1
)
trace
(
"%p->QueryInterface(%s)
\n
"
,
pin
,
wine_dbgstr_guid
(
iid
));
if
(
!
pEnumMediaTypes
)
{
*
ppEnum
=
NULL
;
return
E_OUTOFMEMORY
;
}
pEnumMediaTypes
->
IEnumMediaTypes_iface
.
lpVtbl
=
&
IEnumMediaTypesImpl_Vtbl
;
pEnumMediaTypes
->
refCount
=
1
;
pEnumMediaTypes
->
uIndex
=
0
;
pEnumMediaTypes
->
cMediaTypes
=
cMediaTypes
;
pEnumMediaTypes
->
pMediaTypes
=
CoTaskMemAlloc
(
sizeof
(
AM_MEDIA_TYPE
)
*
cMediaTypes
);
for
(
i
=
0
;
i
<
cMediaTypes
;
i
++
)
if
(
FAILED
(
CopyMediaType
(
&
pEnumMediaTypes
->
pMediaTypes
[
i
],
&
pMediaTypes
[
i
])))
{
while
(
i
--
)
FreeMediaType
(
&
pEnumMediaTypes
->
pMediaTypes
[
i
]);
CoTaskMemFree
(
pEnumMediaTypes
->
pMediaTypes
);
return
E_OUTOFMEMORY
;
}
*
ppEnum
=
&
pEnumMediaTypes
->
IEnumMediaTypes_iface
;
return
S_OK
;
}
static
HRESULT
WINAPI
IEnumMediaTypesImpl_QueryInterface
(
IEnumMediaTypes
*
iface
,
REFIID
riid
,
LPVOID
*
ppv
)
{
*
ppv
=
NULL
;
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
))
*
ppv
=
iface
;
else
if
(
IsEqualIID
(
riid
,
&
IID_IEnumMediaTypes
))
*
ppv
=
iface
;
if
(
*
ppv
)
{
IUnknown_AddRef
((
IUnknown
*
)(
*
ppv
));
return
S_OK
;
}
*
out
=
NULL
;
return
E_NOINTERFACE
;
return
E_NOINTERFACE
;
}
}
static
ULONG
WINAPI
IEnumMediaTypesImpl_AddRef
(
IEnumMediaTypes
*
iface
)
static
ULONG
WINAPI
testenummt_AddRef
(
IEnumMediaTypes
*
iface
)
{
{
IEnumMediaTypesImpl
*
This
=
impl_from_IEnumMediaTypes
(
iface
);
struct
testpin
*
pin
=
impl_from_IEnumMediaTypes
(
iface
);
ULONG
refCount
=
InterlockedIncrement
(
&
This
->
refCount
);
return
InterlockedIncrement
(
&
pin
->
ref
);
return
refCount
;
}
}
static
ULONG
WINAPI
IEnumMediaTypesImpl_Release
(
IEnumMediaTypes
*
iface
)
static
ULONG
WINAPI
testenummt_Release
(
IEnumMediaTypes
*
iface
)
{
{
IEnumMediaTypesImpl
*
This
=
impl_from_IEnumMediaTypes
(
iface
);
struct
testpin
*
pin
=
impl_from_IEnumMediaTypes
(
iface
);
ULONG
refCount
=
InterlockedDecrement
(
&
This
->
refCount
);
return
InterlockedDecrement
(
&
pin
->
ref
);
if
(
!
refCount
)
{
int
i
;
for
(
i
=
0
;
i
<
This
->
cMediaTypes
;
i
++
)
FreeMediaType
(
&
This
->
pMediaTypes
[
i
]);
CoTaskMemFree
(
This
->
pMediaTypes
);
CoTaskMemFree
(
This
);
}
return
refCount
;
}
}
static
HRESULT
WINAPI
IEnumMediaTypesImpl_Next
(
IEnumMediaTypes
*
iface
,
ULONG
cMediaTypes
,
AM_MEDIA_TYPE
**
ppMediaTypes
,
ULONG
*
pcF
etched
)
static
HRESULT
WINAPI
testenummt_Next
(
IEnumMediaTypes
*
iface
,
ULONG
count
,
AM_MEDIA_TYPE
**
out
,
ULONG
*
f
etched
)
{
{
ULONG
cFetched
;
struct
testpin
*
pin
=
impl_from_IEnumMediaTypes
(
iface
);
IEnumMediaTypesImpl
*
This
=
impl_from_IEnumMediaTypes
(
iface
);
unsigned
int
i
;
cFetched
=
min
(
This
->
cMediaTypes
,
This
->
uIndex
+
cMediaTypes
)
-
This
->
uIndex
;
if
(
cFetched
>
0
)
for
(
i
=
0
;
i
<
count
;
++
i
)
{
{
ULONG
i
;
if
(
pin
->
enum_idx
+
i
>=
pin
->
type_count
)
for
(
i
=
0
;
i
<
cFetched
;
i
++
)
break
;
if
(
!
(
ppMediaTypes
[
i
]
=
CreateMediaType
(
&
This
->
pMediaTypes
[
This
->
uIndex
+
i
])))
{
while
(
i
--
)
DeleteMediaType
(
ppMediaTypes
[
i
]);
*
pcFetched
=
0
;
return
E_OUTOFMEMORY
;
}
}
if
((
cMediaTypes
!=
1
)
||
pcFetched
)
out
[
i
]
=
CoTaskMemAlloc
(
sizeof
(
*
out
[
i
]));
*
pcFetched
=
cFetched
;
*
out
[
i
]
=
pin
->
types
[
pin
->
enum_idx
+
i
];
}
This
->
uIndex
+=
cFetched
;
if
(
fetched
)
*
fetched
=
i
;
pin
->
enum_idx
+=
i
;
if
(
cFetched
!=
cMediaTypes
)
return
(
i
==
count
)
?
S_OK
:
S_FALSE
;
return
S_FALSE
;
return
S_OK
;
}
}
static
HRESULT
WINAPI
IEnumMediaTypesImpl_Skip
(
IEnumMediaTypes
*
iface
,
ULONG
cMediaTypes
)
static
HRESULT
WINAPI
testenummt_Skip
(
IEnumMediaTypes
*
iface
,
ULONG
count
)
{
{
IEnumMediaTypesImpl
*
This
=
impl_from_IEnumMediaTypes
(
iface
);
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
if
(
This
->
uIndex
+
cMediaTypes
<
This
->
cMediaTypes
)
{
This
->
uIndex
+=
cMediaTypes
;
return
S_OK
;
}
return
S_FALSE
;
}
}
static
HRESULT
WINAPI
IEnumMediaTypesImpl_Reset
(
IEnumMediaTypes
*
iface
)
static
HRESULT
WINAPI
testenummt_Reset
(
IEnumMediaTypes
*
iface
)
{
{
IEnumMediaTypesImpl
*
This
=
impl_from_IEnumMediaTypes
(
iface
);
struct
testpin
*
pin
=
impl_from_IEnumMediaTypes
(
iface
);
pin
->
enum_idx
=
0
;
This
->
uIndex
=
0
;
return
S_OK
;
return
S_OK
;
}
}
static
HRESULT
WINAPI
IEnumMediaTypesImpl_Clone
(
IEnumMediaTypes
*
iface
,
IEnumMediaTypes
**
ppEnum
)
static
HRESULT
WINAPI
testenummt_Clone
(
IEnumMediaTypes
*
iface
,
IEnumMediaTypes
**
out
)
{
{
HRESULT
hr
;
ok
(
0
,
"Unexpected call.
\n
"
);
IEnumMediaTypesImpl
*
This
=
impl_from_IEnumMediaTypes
(
iface
);
return
E_NOTIMPL
;
hr
=
IEnumMediaTypesImpl_Construct
(
This
->
pMediaTypes
,
This
->
cMediaTypes
,
ppEnum
);
if
(
FAILED
(
hr
))
return
hr
;
return
IEnumMediaTypes_Skip
(
*
ppEnum
,
This
->
uIndex
);
}
}
static
const
IEnumMediaTypesVtbl
IEnumMediaTypesImpl_V
tbl
=
static
const
IEnumMediaTypesVtbl
testenummt_v
tbl
=
{
{
IEnumMediaTypesImpl
_QueryInterface
,
testenummt
_QueryInterface
,
IEnumMediaTypesImpl
_AddRef
,
testenummt
_AddRef
,
IEnumMediaTypesImpl
_Release
,
testenummt
_Release
,
IEnumMediaTypesImpl
_Next
,
testenummt
_Next
,
IEnumMediaTypesImpl
_Skip
,
testenummt
_Skip
,
IEnumMediaTypesImpl
_Reset
,
testenummt
_Reset
,
IEnumMediaTypesImpl_Clone
testenummt_Clone
,
};
};
/* Implementation of a very stripped down pin for the test filter. Just enough
static
inline
struct
testpin
*
impl_from_IPin
(
IPin
*
iface
)
functionality for connecting and Render() to work. */
static
void
Copy_PinInfo
(
PIN_INFO
*
pDest
,
const
PIN_INFO
*
pSrc
)
{
{
lstrcpyW
(
pDest
->
achName
,
pSrc
->
achName
);
return
CONTAINING_RECORD
(
iface
,
struct
testpin
,
IPin_iface
);
pDest
->
dir
=
pSrc
->
dir
;
pDest
->
pFilter
=
pSrc
->
pFilter
;
}
}
typedef
struct
ITestPinImpl
static
HRESULT
WINAPI
testpin_QueryInterface
(
IPin
*
iface
,
REFIID
iid
,
void
**
out
)
{
{
IPin
IPin_iface
;
struct
testpin
*
pin
=
impl_from_IPin
(
iface
);
LONG
refCount
;
if
(
winetest_debug
>
1
)
trace
(
"%p->QueryInterface(%s)
\n
"
,
pin
,
wine_dbgstr_guid
(
iid
));
LPCRITICAL_SECTION
pCritSec
;
PIN_INFO
pinInfo
;
IPin
*
pConnectedTo
;
AM_MEDIA_TYPE
mtCurrent
;
LPVOID
pUserData
;
}
ITestPinImpl
;
static
inline
ITestPinImpl
*
impl_from_IPin
(
IPin
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
ITestPinImpl
,
IPin_iface
);
}
static
HRESULT
WINAPI
TestFilter_Pin_QueryInterface
(
IPin
*
iface
,
REFIID
riid
,
LPVOID
*
ppv
)
{
*
ppv
=
NULL
;
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
))
if
(
IsEqualGUID
(
iid
,
&
IID_IUnknown
)
||
IsEqualGUID
(
iid
,
&
IID_IPin
))
*
ppv
=
iface
;
else
if
(
IsEqualIID
(
riid
,
&
IID_IPin
))
*
ppv
=
iface
;
if
(
*
ppv
)
{
{
IUnknown_AddRef
((
IUnknown
*
)(
*
ppv
));
*
out
=
&
pin
->
IPin_iface
;
IPin_AddRef
(
*
out
);
return
S_OK
;
return
S_OK
;
}
}
*
out
=
NULL
;
return
E_NOINTERFACE
;
return
E_NOINTERFACE
;
}
}
static
ULONG
WINAPI
TestFilter_Pin_AddRef
(
IPin
*
iface
)
ULONG
WINAPI
testpin_AddRef
(
IPin
*
iface
)
{
{
ITestPinImpl
*
This
=
impl_from_IPin
(
iface
);
struct
testpin
*
pin
=
impl_from_IPin
(
iface
);
ULONG
refCount
=
InterlockedIncrement
(
&
This
->
refCount
);
return
InterlockedIncrement
(
&
pin
->
ref
);
return
refCount
;
}
}
static
ULONG
WINAPI
TestFilter_Pin_Release
(
IPin
*
iface
)
ULONG
WINAPI
testpin_Release
(
IPin
*
iface
)
{
{
ITestPinImpl
*
This
=
impl_from_IPin
(
iface
);
struct
testpin
*
pin
=
impl_from_IPin
(
iface
);
ULONG
refCount
=
InterlockedDecrement
(
&
This
->
refCount
);
return
InterlockedDecrement
(
&
pin
->
ref
);
if
(
!
refCount
)
{
FreeMediaType
(
&
This
->
mtCurrent
);
CoTaskMemFree
(
This
);
return
0
;
}
else
return
refCount
;
}
static
HRESULT
WINAPI
TestFilter_InputPin_Connect
(
IPin
*
iface
,
IPin
*
pConnector
,
const
AM_MEDIA_TYPE
*
pmt
)
{
return
E_UNEXPECTED
;
}
static
HRESULT
WINAPI
TestFilter_InputPin_ReceiveConnection
(
IPin
*
iface
,
IPin
*
pReceivePin
,
const
AM_MEDIA_TYPE
*
pmt
)
{
ITestPinImpl
*
This
=
impl_from_IPin
(
iface
);
PIN_DIRECTION
pindirReceive
;
HRESULT
hr
=
S_OK
;
EnterCriticalSection
(
This
->
pCritSec
);
{
if
(
!
(
IsEqualIID
(
&
pmt
->
majortype
,
&
This
->
mtCurrent
.
majortype
)
&&
(
IsEqualIID
(
&
pmt
->
subtype
,
&
This
->
mtCurrent
.
subtype
)
||
IsEqualIID
(
&
GUID_NULL
,
&
This
->
mtCurrent
.
subtype
))))
hr
=
VFW_E_TYPE_NOT_ACCEPTED
;
if
(
This
->
pConnectedTo
)
hr
=
VFW_E_ALREADY_CONNECTED
;
if
(
SUCCEEDED
(
hr
))
{
IPin_QueryDirection
(
pReceivePin
,
&
pindirReceive
);
if
(
pindirReceive
!=
PINDIR_OUTPUT
)
{
hr
=
VFW_E_INVALID_DIRECTION
;
}
}
if
(
SUCCEEDED
(
hr
))
{
CopyMediaType
(
&
This
->
mtCurrent
,
pmt
);
This
->
pConnectedTo
=
pReceivePin
;
IPin_AddRef
(
pReceivePin
);
}
}
LeaveCriticalSection
(
This
->
pCritSec
);
return
hr
;
}
}
static
HRESULT
WINAPI
TestFilter_Pin_Disconnect
(
IPin
*
iface
)
static
HRESULT
WINAPI
testpin_Disconnect
(
IPin
*
iface
)
{
{
HRESULT
hr
;
struct
testpin
*
pin
=
impl_from_IPin
(
iface
)
;
ITestPinImpl
*
This
=
impl_from_IPin
(
iface
);
if
(
winetest_debug
>
1
)
trace
(
"%p->Disconnect()
\n
"
,
pin
);
EnterCriticalSection
(
This
->
pCritSec
);
if
(
!
pin
->
peer
)
{
return
S_FALSE
;
if
(
This
->
pConnectedTo
)
{
IPin_Release
(
This
->
pConnectedTo
);
This
->
pConnectedTo
=
NULL
;
hr
=
S_OK
;
}
else
hr
=
S_FALSE
;
}
LeaveCriticalSection
(
This
->
pCritSec
);
return
hr
;
IPin_Release
(
pin
->
peer
);
pin
->
peer
=
NULL
;
return
S_OK
;
}
}
static
HRESULT
WINAPI
TestFilter_Pin_ConnectedTo
(
IPin
*
iface
,
IPin
**
ppPin
)
static
HRESULT
WINAPI
testpin_ConnectedTo
(
IPin
*
iface
,
IPin
**
peer
)
{
{
HRESULT
hr
;
struct
testpin
*
pin
=
impl_from_IPin
(
iface
)
;
ITestPinImpl
*
This
=
impl_from_IPin
(
iface
);
if
(
winetest_debug
>
1
)
trace
(
"%p->ConnectedTo()
\n
"
,
pin
);
EnterCriticalSection
(
This
->
pCritSec
);
*
peer
=
pin
->
peer
;
{
if
(
*
peer
)
if
(
This
->
pConnectedTo
)
{
{
*
ppPin
=
This
->
pConnectedTo
;
IPin_AddRef
(
*
peer
);
IPin_AddRef
(
*
ppPin
);
return
S_OK
;
hr
=
S_OK
;
}
else
{
hr
=
VFW_E_NOT_CONNECTED
;
*
ppPin
=
NULL
;
}
}
}
LeaveCriticalSection
(
This
->
pCritSec
);
return
VFW_E_NOT_CONNECTED
;
return
hr
;
}
}
static
HRESULT
WINAPI
TestFilter_Pin_ConnectionMediaType
(
IPin
*
iface
,
AM_MEDIA_TYPE
*
p
mt
)
static
HRESULT
WINAPI
testpin_ConnectionMediaType
(
IPin
*
iface
,
AM_MEDIA_TYPE
*
mt
)
{
{
HRESULT
hr
;
ok
(
0
,
"Unexpected call.
\n
"
);
ITestPinImpl
*
This
=
impl_from_IPin
(
iface
);
return
E_NOTIMPL
;
EnterCriticalSection
(
This
->
pCritSec
);
{
if
(
This
->
pConnectedTo
)
{
CopyMediaType
(
pmt
,
&
This
->
mtCurrent
);
hr
=
S_OK
;
}
else
{
ZeroMemory
(
pmt
,
sizeof
(
*
pmt
));
hr
=
VFW_E_NOT_CONNECTED
;
}
}
LeaveCriticalSection
(
This
->
pCritSec
);
return
hr
;
}
}
static
HRESULT
WINAPI
TestFilter_Pin_QueryPinInfo
(
IPin
*
iface
,
PIN_INFO
*
pI
nfo
)
static
HRESULT
WINAPI
testpin_QueryPinInfo
(
IPin
*
iface
,
PIN_INFO
*
i
nfo
)
{
{
ITestPinImpl
*
This
=
impl_from_IPin
(
iface
);
struct
testpin
*
pin
=
impl_from_IPin
(
iface
);
if
(
winetest_debug
>
1
)
trace
(
"%p->QueryPinInfo()
\n
"
,
pin
);
Copy_PinInfo
(
pInfo
,
&
This
->
pinInfo
);
IBaseFilter_AddRef
(
pInfo
->
pFilter
);
info
->
pFilter
=
pin
->
filter
;
IBaseFilter_AddRef
(
pin
->
filter
);
info
->
dir
=
pin
->
dir
;
info
->
achName
[
0
]
=
0
;
return
S_OK
;
return
S_OK
;
}
}
static
HRESULT
WINAPI
TestFilter_Pin_QueryDirection
(
IPin
*
iface
,
PIN_DIRECTION
*
pPinDir
)
{
ITestPinImpl
*
This
=
impl_from_IPin
(
iface
);
*
pPinDir
=
This
->
pinInfo
.
dir
;
static
HRESULT
WINAPI
testpin_QueryDirection
(
IPin
*
iface
,
PIN_DIRECTION
*
dir
)
{
struct
testpin
*
pin
=
impl_from_IPin
(
iface
);
if
(
winetest_debug
>
1
)
trace
(
"%p->QueryDirection()
\n
"
,
pin
);
*
dir
=
pin
->
dir
;
return
S_OK
;
return
S_OK
;
}
}
static
HRESULT
WINAPI
TestFilter_Pin_QueryId
(
IPin
*
iface
,
LPWSTR
*
I
d
)
static
HRESULT
WINAPI
testpin_QueryId
(
IPin
*
iface
,
WCHAR
**
i
d
)
{
{
if
(
winetest_debug
>
1
)
trace
(
"%p->QueryId()
\n
"
,
iface
);
return
E_NOTIMPL
;
return
E_NOTIMPL
;
}
}
static
HRESULT
WINAPI
TestFilter_Pin_QueryAccept
(
IPin
*
iface
,
const
AM_MEDIA_TYPE
*
p
mt
)
static
HRESULT
WINAPI
testpin_QueryAccept
(
IPin
*
iface
,
const
AM_MEDIA_TYPE
*
mt
)
{
{
ITestPinImpl
*
This
=
impl_from_IPin
(
iface
);
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
if
(
IsEqualIID
(
&
pmt
->
majortype
,
&
This
->
mtCurrent
.
majortype
)
&&
(
IsEqualIID
(
&
pmt
->
subtype
,
&
This
->
mtCurrent
.
subtype
)
||
IsEqualIID
(
&
GUID_NULL
,
&
This
->
mtCurrent
.
subtype
)))
return
S_OK
;
else
return
VFW_E_TYPE_NOT_ACCEPTED
;
}
}
static
HRESULT
WINAPI
TestFilter_Pin_EnumMediaTypes
(
IPin
*
iface
,
IEnumMediaTypes
**
ppEnum
)
static
HRESULT
WINAPI
testpin_EnumMediaTypes
(
IPin
*
iface
,
IEnumMediaTypes
**
out
)
{
{
ITestPinImpl
*
This
=
impl_from_IPin
(
iface
);
struct
testpin
*
pin
=
impl_from_IPin
(
iface
);
if
(
winetest_debug
>
1
)
trace
(
"%p->EnumMediaTypes()
\n
"
,
pin
);
return
IEnumMediaTypesImpl_Construct
(
&
This
->
mtCurrent
,
1
,
ppEnum
);
*
out
=
&
pin
->
IEnumMediaTypes_iface
;
IEnumMediaTypes_AddRef
(
*
out
);
pin
->
enum_idx
=
0
;
return
S_OK
;
}
}
static
HRESULT
WINAPI
TestFilter_Pin_QueryInternalConnections
(
IPin
*
iface
,
IPin
**
apPin
,
ULONG
*
cPin
)
static
HRESULT
WINAPI
testpin_QueryInternalConnections
(
IPin
*
iface
,
IPin
**
out
,
ULONG
*
count
)
{
{
if
(
winetest_debug
>
1
)
trace
(
"%p->QueryInternalConnections()
\n
"
,
iface
);
return
E_NOTIMPL
;
return
E_NOTIMPL
;
}
}
static
HRESULT
WINAPI
TestFilter_Pin_BeginFlush
(
IPin
*
iface
)
static
HRESULT
WINAPI
testpin_BeginFlush
(
IPin
*
iface
)
{
{
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
return
E_NOTIMPL
;
}
}
static
HRESULT
WINAPI
TestFilter_P
in_EndFlush
(
IPin
*
iface
)
static
HRESULT
WINAPI
testp
in_EndFlush
(
IPin
*
iface
)
{
{
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
return
E_NOTIMPL
;
}
}
static
HRESULT
WINAPI
TestFilter_Pin_NewSegment
(
IPin
*
iface
,
REFERENCE_TIME
tStart
,
REFERENCE_TIME
tStop
,
double
dR
ate
)
static
HRESULT
WINAPI
testpin_NewSegment
(
IPin
*
iface
,
REFERENCE_TIME
start
,
REFERENCE_TIME
stop
,
double
r
ate
)
{
{
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
return
E_NOTIMPL
;
}
}
static
HRESULT
WINAPI
TestFilter_Pin_EndOfStream
(
IPin
*
iface
)
static
HRESULT
WINAPI
testpin_EndOfStream
(
IPin
*
iface
)
{
{
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
return
E_NOTIMPL
;
}
}
static
const
IPinVtbl
TestFilter_InputPin_Vtbl
=
static
HRESULT
WINAPI
testsink_Connect
(
IPin
*
iface
,
IPin
*
peer
,
const
AM_MEDIA_TYPE
*
mt
)
{
TestFilter_Pin_QueryInterface
,
TestFilter_Pin_AddRef
,
TestFilter_Pin_Release
,
TestFilter_InputPin_Connect
,
TestFilter_InputPin_ReceiveConnection
,
TestFilter_Pin_Disconnect
,
TestFilter_Pin_ConnectedTo
,
TestFilter_Pin_ConnectionMediaType
,
TestFilter_Pin_QueryPinInfo
,
TestFilter_Pin_QueryDirection
,
TestFilter_Pin_QueryId
,
TestFilter_Pin_QueryAccept
,
TestFilter_Pin_EnumMediaTypes
,
TestFilter_Pin_QueryInternalConnections
,
TestFilter_Pin_EndOfStream
,
TestFilter_Pin_BeginFlush
,
TestFilter_Pin_EndFlush
,
TestFilter_Pin_NewSegment
};
static
HRESULT
WINAPI
TestFilter_OutputPin_ReceiveConnection
(
IPin
*
iface
,
IPin
*
pReceivePin
,
const
AM_MEDIA_TYPE
*
pmt
)
{
{
return
E_UNEXPECTED
;
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
}
}
/* Private helper function */
static
HRESULT
WINAPI
testsink_ReceiveConnection
(
IPin
*
iface
,
IPin
*
peer
,
const
AM_MEDIA_TYPE
*
mt
)
static
HRESULT
TestFilter_OutputPin_ConnectSpecific
(
ITestPinImpl
*
This
,
IPin
*
pReceivePin
,
const
AM_MEDIA_TYPE
*
pmt
)
{
{
HRESULT
hr
;
struct
testpin
*
pin
=
impl_from_IPin
(
iface
);
if
(
winetest_debug
>
1
)
trace
(
"%p->ReceiveConnection(%p)
\n
"
,
pin
,
peer
);
This
->
pConnectedTo
=
pReceivePin
;
IPin_AddRef
(
pReceivePin
);
hr
=
IPin_ReceiveConnection
(
pReceivePin
,
&
This
->
IPin_iface
,
pmt
);
if
(
FAILED
(
hr
))
{
IPin_Release
(
This
->
pConnectedTo
);
This
->
pConnectedTo
=
NULL
;
}
return
hr
;
pin
->
peer
=
peer
;
IPin_AddRef
(
peer
);
return
S_OK
;
}
}
static
HRESULT
WINAPI
TestFilter_OutputPin_Connect
(
IPin
*
iface
,
IPin
*
pReceivePin
,
const
AM_MEDIA_TYPE
*
pm
t
)
static
HRESULT
WINAPI
testsink_EnumMediaTypes
(
IPin
*
iface
,
IEnumMediaTypes
**
ou
t
)
{
{
ITestPinImpl
*
This
=
impl_from_IPin
(
iface
);
ok
(
0
,
"Unexpected call.
\n
"
);
HRESULT
hr
;
return
E_NOTIMPL
;
EnterCriticalSection
(
This
->
pCritSec
);
{
/* if we have been a specific type to connect with, then we can either connect
* with that or fail. We cannot choose different AM_MEDIA_TYPE */
if
(
pmt
&&
!
IsEqualGUID
(
&
pmt
->
majortype
,
&
GUID_NULL
)
&&
!
IsEqualGUID
(
&
pmt
->
subtype
,
&
GUID_NULL
))
hr
=
TestFilter_OutputPin_ConnectSpecific
(
This
,
pReceivePin
,
pmt
);
else
{
if
((
!
pmt
||
CompareMediaTypes
(
pmt
,
&
This
->
mtCurrent
,
TRUE
)
)
&&
(
TestFilter_OutputPin_ConnectSpecific
(
This
,
pReceivePin
,
&
This
->
mtCurrent
)
==
S_OK
))
hr
=
S_OK
;
else
hr
=
VFW_E_NO_ACCEPTABLE_TYPES
;
}
/* if negotiate media type */
}
/* if succeeded */
LeaveCriticalSection
(
This
->
pCritSec
);
return
hr
;
}
}
static
const
IPinVtbl
TestFilter_OutputPin_V
tbl
=
static
const
IPinVtbl
testsink_v
tbl
=
{
{
TestFilter_P
in_QueryInterface
,
testp
in_QueryInterface
,
TestFilter_P
in_AddRef
,
testp
in_AddRef
,
TestFilter_P
in_Release
,
testp
in_Release
,
TestFilter_OutputPin
_Connect
,
testsink
_Connect
,
TestFilter_OutputPin
_ReceiveConnection
,
testsink
_ReceiveConnection
,
TestFilter_P
in_Disconnect
,
testp
in_Disconnect
,
TestFilter_P
in_ConnectedTo
,
testp
in_ConnectedTo
,
TestFilter_P
in_ConnectionMediaType
,
testp
in_ConnectionMediaType
,
TestFilter_P
in_QueryPinInfo
,
testp
in_QueryPinInfo
,
TestFilter_P
in_QueryDirection
,
testp
in_QueryDirection
,
TestFilter_P
in_QueryId
,
testp
in_QueryId
,
TestFilter_P
in_QueryAccept
,
testp
in_QueryAccept
,
TestFilter_Pin
_EnumMediaTypes
,
testsink
_EnumMediaTypes
,
TestFilter_P
in_QueryInternalConnections
,
testp
in_QueryInternalConnections
,
TestFilter_P
in_EndOfStream
,
testp
in_EndOfStream
,
TestFilter_P
in_BeginFlush
,
testp
in_BeginFlush
,
TestFilter_P
in_EndFlush
,
testp
in_EndFlush
,
TestFilter_P
in_NewSegment
testp
in_NewSegment
};
};
static
HRESULT
TestFilter_Pin_Construct
(
const
IPinVtbl
*
Pin_Vtbl
,
const
PIN_INFO
*
pPinInfo
,
AM_MEDIA_TYPE
*
pinmt
,
static
void
testsink_init
(
struct
testpin
*
pin
)
LPCRITICAL_SECTION
pCritSec
,
IPin
**
ppPin
)
{
{
ITestPinImpl
*
pPinImpl
;
memset
(
pin
,
0
,
sizeof
(
*
pin
));
pin
->
IPin_iface
.
lpVtbl
=
&
testsink_vtbl
;
*
ppPin
=
NULL
;
pin
->
ref
=
1
;
pin
->
dir
=
PINDIR_INPUT
;
pPinImpl
=
CoTaskMemAlloc
(
sizeof
(
ITestPinImpl
));
pin
->
IEnumMediaTypes_iface
.
lpVtbl
=
&
testenummt_vtbl
;
if
(
!
pPinImpl
)
return
E_OUTOFMEMORY
;
pPinImpl
->
refCount
=
1
;
pPinImpl
->
pConnectedTo
=
NULL
;
pPinImpl
->
pCritSec
=
pCritSec
;
Copy_PinInfo
(
&
pPinImpl
->
pinInfo
,
pPinInfo
);
pPinImpl
->
mtCurrent
=
*
pinmt
;
pPinImpl
->
IPin_iface
.
lpVtbl
=
Pin_Vtbl
;
*
ppPin
=
&
pPinImpl
->
IPin_iface
;
return
S_OK
;
}
}
/* IEnumPins implementation */
static
HRESULT
WINAPI
testsource_Connect
(
IPin
*
iface
,
IPin
*
peer
,
const
AM_MEDIA_TYPE
*
mt
)
typedef
HRESULT
(
*
FNOBTAINPIN
)(
TestFilterImpl
*
tf
,
ULONG
pos
,
IPin
**
pin
,
DWORD
*
lastsynctick
);
typedef
struct
IEnumPinsImpl
{
{
IEnumPins
IEnumPins_iface
;
struct
testpin
*
pin
=
impl_from_IPin
(
iface
);
LONG
refCount
;
if
(
winetest_debug
>
1
)
trace
(
"%p->Connect(%p)
\n
"
,
pin
,
peer
);
ULONG
uIndex
;
TestFilterImpl
*
base
;
FNOBTAINPIN
receive_pin
;
DWORD
synctime
;
}
IEnumPinsImpl
;
static
const
struct
IEnumPinsVtbl
IEnumPinsImpl_Vtbl
;
ok
(
!
mt
,
"Got media type %p.
\n
"
,
mt
)
;
static
inline
IEnumPinsImpl
*
impl_from_IEnumPins
(
IEnumPins
*
iface
)
pin
->
peer
=
peer
;
{
IPin_AddRef
(
peer
);
return
CONTAINING_RECORD
(
iface
,
IEnumPinsImpl
,
IEnumPins_iface
);
return
IPin_ReceiveConnection
(
peer
,
&
pin
->
IPin_iface
,
mt
);
}
}
static
HRESULT
createenumpins
(
IEnumPins
**
ppEnum
,
FNOBTAINPIN
receive_pin
,
TestFilterImpl
*
base
)
static
HRESULT
WINAPI
testsource_ReceiveConnection
(
IPin
*
iface
,
IPin
*
peer
,
const
AM_MEDIA_TYPE
*
mt
)
{
{
IEnumPinsImpl
*
pEnumPins
;
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
if
(
!
ppEnum
)
}
return
E_POINTER
;
pEnumPins
=
CoTaskMemAlloc
(
sizeof
(
IEnumPinsImpl
));
static
const
IPinVtbl
testsource_vtbl
=
if
(
!
pEnumPins
)
{
{
testpin_QueryInterface
,
*
ppEnum
=
NULL
;
testpin_AddRef
,
return
E_OUTOFMEMORY
;
testpin_Release
,
}
testsource_Connect
,
pEnumPins
->
IEnumPins_iface
.
lpVtbl
=
&
IEnumPinsImpl_Vtbl
;
testsource_ReceiveConnection
,
pEnumPins
->
refCount
=
1
;
testpin_Disconnect
,
pEnumPins
->
uIndex
=
0
;
testpin_ConnectedTo
,
pEnumPins
->
receive_pin
=
receive_pin
;
testpin_ConnectionMediaType
,
pEnumPins
->
base
=
base
;
testpin_QueryPinInfo
,
IBaseFilter_AddRef
(
&
base
->
IBaseFilter_iface
);
testpin_QueryDirection
,
*
ppEnum
=
&
pEnumPins
->
IEnumPins_iface
;
testpin_QueryId
,
testpin_QueryAccept
,
testpin_EnumMediaTypes
,
testpin_QueryInternalConnections
,
testpin_EndOfStream
,
testpin_BeginFlush
,
testpin_EndFlush
,
testpin_NewSegment
};
receive_pin
(
base
,
~
0
,
NULL
,
&
pEnumPins
->
synctime
);
static
void
testsource_init
(
struct
testpin
*
pin
,
const
AM_MEDIA_TYPE
*
types
,
int
type_count
)
{
memset
(
pin
,
0
,
sizeof
(
*
pin
));
pin
->
IPin_iface
.
lpVtbl
=
&
testsource_vtbl
;
pin
->
ref
=
1
;
pin
->
dir
=
PINDIR_OUTPUT
;
return
S_OK
;
pin
->
IEnumMediaTypes_iface
.
lpVtbl
=
&
testenummt_vtbl
;
pin
->
types
=
types
;
pin
->
type_count
=
type_count
;
}
}
st
atic
HRESULT
WINAPI
IEnumPinsImpl_QueryInterface
(
IEnumPins
*
iface
,
REFIID
riid
,
LPVOID
*
ppv
)
st
ruct
testfilter
{
{
*
ppv
=
NULL
;
IBaseFilter
IBaseFilter_iface
;
LONG
ref
;
IFilterGraph
*
graph
;
WCHAR
*
name
;
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
))
IEnumPins
IEnumPins_iface
;
*
ppv
=
iface
;
struct
testpin
*
pins
;
else
if
(
IsEqualIID
(
riid
,
&
IID_IEnumPins
))
unsigned
int
pin_count
,
enum_idx
;
*
ppv
=
iface
;
}
;
if
(
*
ppv
)
static
inline
struct
testfilter
*
impl_from_IEnumPins
(
IEnumPins
*
iface
)
{
{
IUnknown_AddRef
((
IUnknown
*
)(
*
ppv
));
return
CONTAINING_RECORD
(
iface
,
struct
testfilter
,
IEnumPins_iface
);
return
S_OK
;
}
}
static
HRESULT
WINAPI
testenumpins_QueryInterface
(
IEnumPins
*
iface
,
REFIID
iid
,
void
**
out
)
{
ok
(
0
,
"Unexpected iid %s.
\n
"
,
wine_dbgstr_guid
(
iid
));
return
E_NOINTERFACE
;
return
E_NOINTERFACE
;
}
}
static
ULONG
WINAPI
IEnumPinsImpl
_AddRef
(
IEnumPins
*
iface
)
static
ULONG
WINAPI
testenumpins
_AddRef
(
IEnumPins
*
iface
)
{
{
IEnumPinsImpl
*
This
=
impl_from_IEnumPins
(
iface
);
struct
testfilter
*
filter
=
impl_from_IEnumPins
(
iface
);
ULONG
refCount
=
InterlockedIncrement
(
&
This
->
refCount
);
return
InterlockedIncrement
(
&
filter
->
ref
);
return
refCount
;
}
}
static
ULONG
WINAPI
IEnumPinsImpl
_Release
(
IEnumPins
*
iface
)
static
ULONG
WINAPI
testenumpins
_Release
(
IEnumPins
*
iface
)
{
{
IEnumPinsImpl
*
This
=
impl_from_IEnumPins
(
iface
);
struct
testfilter
*
filter
=
impl_from_IEnumPins
(
iface
);
ULONG
refCount
=
InterlockedDecrement
(
&
This
->
refCount
);
return
InterlockedDecrement
(
&
filter
->
ref
);
if
(
!
refCount
)
{
IBaseFilter_Release
(
&
This
->
base
->
IBaseFilter_iface
);
CoTaskMemFree
(
This
);
return
0
;
}
else
return
refCount
;
}
}
static
HRESULT
WINAPI
IEnumPinsImpl_Next
(
IEnumPins
*
iface
,
ULONG
cPins
,
IPin
**
ppPins
,
ULONG
*
pcF
etched
)
static
HRESULT
WINAPI
testenumpins_Next
(
IEnumPins
*
iface
,
ULONG
count
,
IPin
**
out
,
ULONG
*
f
etched
)
{
{
IEnumPinsImpl
*
This
=
impl_from_IEnumPins
(
iface
);
struct
testfilter
*
filter
=
impl_from_IEnumPins
(
iface
);
DWORD
synctime
=
This
->
synctime
;
unsigned
int
i
;
HRESULT
hr
=
S_OK
;
ULONG
i
=
0
;
if
(
!
ppPins
)
return
E_POINTER
;
if
(
cPins
>
1
&&
!
pcFetched
)
return
E_INVALIDARG
;
if
(
pcFetched
)
for
(
i
=
0
;
i
<
count
;
++
i
)
*
pcFetched
=
0
;
while
(
i
<
cPins
&&
hr
==
S_OK
)
{
{
hr
=
This
->
receive_pin
(
This
->
base
,
This
->
uIndex
+
i
,
&
ppPins
[
i
],
&
synctime
);
if
(
filter
->
enum_idx
+
i
>=
filter
->
pin_count
)
if
(
hr
==
S_OK
)
++
i
;
if
(
synctime
!=
This
->
synctime
)
break
;
break
;
}
if
(
!
i
&&
synctime
!=
This
->
synctime
)
out
[
i
]
=
&
filter
->
pins
[
filter
->
enum_idx
+
i
].
IPin_iface
;
return
VFW_E_ENUM_OUT_OF_SYNC
;
IPin_AddRef
(
out
[
i
]);
}
if
(
pcF
etched
)
if
(
f
etched
)
*
pcF
etched
=
i
;
*
f
etched
=
i
;
This
->
uInde
x
+=
i
;
filter
->
enum_id
x
+=
i
;
if
(
i
<
cPins
)
return
(
i
==
count
)
?
S_OK
:
S_FALSE
;
return
S_FALSE
;
return
S_OK
;
}
}
static
HRESULT
WINAPI
IEnumPinsImpl_Skip
(
IEnumPins
*
iface
,
ULONG
cPins
)
static
HRESULT
WINAPI
testenumpins_Skip
(
IEnumPins
*
iface
,
ULONG
count
)
{
{
IEnumPinsImpl
*
This
=
impl_from_IEnumPins
(
iface
);
ok
(
0
,
"Unexpected call.
\n
"
);
DWORD
synctime
=
This
->
synctime
;
return
E_NOTIMPL
;
HRESULT
hr
;
IPin
*
pin
=
NULL
;
hr
=
This
->
receive_pin
(
This
->
base
,
This
->
uIndex
+
cPins
,
&
pin
,
&
synctime
);
if
(
pin
)
IPin_Release
(
pin
);
if
(
synctime
!=
This
->
synctime
)
return
VFW_E_ENUM_OUT_OF_SYNC
;
if
(
hr
==
S_OK
)
This
->
uIndex
+=
cPins
;
return
hr
;
}
}
static
HRESULT
WINAPI
IEnumPinsImpl_Reset
(
IEnumPins
*
iface
)
static
HRESULT
WINAPI
testenumpins_Reset
(
IEnumPins
*
iface
)
{
{
IEnumPinsImpl
*
This
=
impl_from_IEnumPins
(
iface
);
struct
testfilter
*
filter
=
impl_from_IEnumPins
(
iface
);
filter
->
enum_idx
=
0
;
This
->
receive_pin
(
This
->
base
,
~
0
,
NULL
,
&
This
->
synctime
);
This
->
uIndex
=
0
;
return
S_OK
;
return
S_OK
;
}
}
static
HRESULT
WINAPI
IEnumPinsImpl_Clone
(
IEnumPins
*
iface
,
IEnumPins
**
ppEnum
)
static
HRESULT
WINAPI
testenumpins_Clone
(
IEnumPins
*
iface
,
IEnumPins
**
out
)
{
{
HRESULT
hr
;
ok
(
0
,
"Unexpected call.
\n
"
);
IEnumPinsImpl
*
This
=
impl_from_IEnumPins
(
iface
);
return
E_NOTIMPL
;
hr
=
createenumpins
(
ppEnum
,
This
->
receive_pin
,
This
->
base
);
if
(
FAILED
(
hr
))
return
hr
;
return
IEnumPins_Skip
(
*
ppEnum
,
This
->
uIndex
);
}
}
static
const
IEnumPinsVtbl
IEnumPinsImpl_V
tbl
=
static
const
IEnumPinsVtbl
testenumpins_v
tbl
=
{
{
IEnumPinsImpl
_QueryInterface
,
testenumpins
_QueryInterface
,
IEnumPinsImpl
_AddRef
,
testenumpins
_AddRef
,
IEnumPinsImpl
_Release
,
testenumpins
_Release
,
IEnumPinsImpl
_Next
,
testenumpins
_Next
,
IEnumPinsImpl
_Skip
,
testenumpins
_Skip
,
IEnumPinsImpl
_Reset
,
testenumpins
_Reset
,
IEnumPinsImpl_Clone
testenumpins_Clone
,
};
};
/* Test filter implementation - a filter that has few predefined pins with single media type
static
inline
struct
testfilter
*
impl_from_IBaseFilter
(
IBaseFilter
*
iface
)
* that accept only this single media type. Enough for Render(). */
typedef
struct
TestFilterPinData
{
{
PIN_DIRECTION
pinDir
;
return
CONTAINING_RECORD
(
iface
,
struct
testfilter
,
IBaseFilter_iface
);
const
GUID
*
mediasubtype
;
}
TestFilterPinData
;
static
const
IBaseFilterVtbl
TestFilter_Vtbl
;
static
inline
TestFilterImpl
*
impl_from_IBaseFilter
(
IBaseFilter
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
TestFilterImpl
,
IBaseFilter_iface
);
}
static
HRESULT
createtestfilter
(
const
CLSID
*
pClsid
,
const
TestFilterPinData
*
pinData
,
TestFilterImpl
**
tf
)
{
static
const
WCHAR
wcsInputPinName
[]
=
{
'i'
,
'n'
,
'p'
,
'u'
,
't'
,
' '
,
'p'
,
'i'
,
'n'
,
0
};
static
const
WCHAR
wcsOutputPinName
[]
=
{
'o'
,
'u'
,
't'
,
'p'
,
'u'
,
't'
,
' '
,
'p'
,
'i'
,
'n'
,
0
};
HRESULT
hr
;
PIN_INFO
pinInfo
;
TestFilterImpl
*
pTestFilter
=
NULL
;
UINT
nPins
,
i
;
AM_MEDIA_TYPE
mt
;
pTestFilter
=
CoTaskMemAlloc
(
sizeof
(
TestFilterImpl
));
if
(
!
pTestFilter
)
return
E_OUTOFMEMORY
;
pTestFilter
->
clsid
=
*
pClsid
;
pTestFilter
->
IBaseFilter_iface
.
lpVtbl
=
&
TestFilter_Vtbl
;
pTestFilter
->
refCount
=
1
;
InitializeCriticalSection
(
&
pTestFilter
->
csFilter
);
pTestFilter
->
state
=
State_Stopped
;
ZeroMemory
(
&
pTestFilter
->
filterInfo
,
sizeof
(
FILTER_INFO
));
nPins
=
0
;
while
(
pinData
[
nPins
].
mediasubtype
)
++
nPins
;
pTestFilter
->
ppPins
=
CoTaskMemAlloc
(
nPins
*
sizeof
(
IPin
*
));
if
(
!
pTestFilter
->
ppPins
)
{
hr
=
E_OUTOFMEMORY
;
goto
error
;
}
ZeroMemory
(
pTestFilter
->
ppPins
,
nPins
*
sizeof
(
IPin
*
));
for
(
i
=
0
;
i
<
nPins
;
i
++
)
{
ZeroMemory
(
&
mt
,
sizeof
(
mt
));
mt
.
majortype
=
MEDIATYPE_Video
;
mt
.
formattype
=
FORMAT_None
;
mt
.
subtype
=
*
pinData
[
i
].
mediasubtype
;
pinInfo
.
dir
=
pinData
[
i
].
pinDir
;
pinInfo
.
pFilter
=
&
pTestFilter
->
IBaseFilter_iface
;
if
(
pinInfo
.
dir
==
PINDIR_INPUT
)
{
lstrcpynW
(
pinInfo
.
achName
,
wcsInputPinName
,
ARRAY_SIZE
(
pinInfo
.
achName
));
hr
=
TestFilter_Pin_Construct
(
&
TestFilter_InputPin_Vtbl
,
&
pinInfo
,
&
mt
,
&
pTestFilter
->
csFilter
,
&
pTestFilter
->
ppPins
[
i
]);
}
else
{
lstrcpynW
(
pinInfo
.
achName
,
wcsOutputPinName
,
ARRAY_SIZE
(
pinInfo
.
achName
));
hr
=
TestFilter_Pin_Construct
(
&
TestFilter_OutputPin_Vtbl
,
&
pinInfo
,
&
mt
,
&
pTestFilter
->
csFilter
,
&
pTestFilter
->
ppPins
[
i
]);
}
if
(
FAILED
(
hr
)
||
!
pTestFilter
->
ppPins
[
i
])
goto
error
;
}
pTestFilter
->
nPins
=
nPins
;
*
tf
=
pTestFilter
;
return
S_OK
;
error:
if
(
pTestFilter
->
ppPins
)
{
for
(
i
=
0
;
i
<
nPins
;
i
++
)
{
if
(
pTestFilter
->
ppPins
[
i
])
IPin_Release
(
pTestFilter
->
ppPins
[
i
]);
}
}
CoTaskMemFree
(
pTestFilter
->
ppPins
);
DeleteCriticalSection
(
&
pTestFilter
->
csFilter
);
CoTaskMemFree
(
pTestFilter
);
return
hr
;
}
}
static
HRESULT
WINAPI
TestFilter_QueryInterface
(
IBaseFilter
*
iface
,
REFIID
riid
,
LPVOID
*
ppv
)
static
HRESULT
WINAPI
testfilter_QueryInterface
(
IBaseFilter
*
iface
,
REFIID
iid
,
void
**
out
)
{
{
TestFilterImpl
*
This
=
impl_from_IBaseFilter
(
iface
);
struct
testfilter
*
filter
=
impl_from_IBaseFilter
(
iface
);
if
(
winetest_debug
>
1
)
trace
(
"%p->QueryInterface(%s)
\n
"
,
filter
,
wine_dbgstr_guid
(
iid
));
*
ppv
=
NULL
;
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
))
*
ppv
=
This
;
else
if
(
IsEqualIID
(
riid
,
&
IID_IPersist
))
*
ppv
=
This
;
else
if
(
IsEqualIID
(
riid
,
&
IID_IMediaFilter
))
*
ppv
=
This
;
else
if
(
IsEqualIID
(
riid
,
&
IID_IBaseFilter
))
*
ppv
=
This
;
if
(
*
ppv
)
if
(
IsEqualGUID
(
iid
,
&
IID_IUnknown
)
||
IsEqualGUID
(
iid
,
&
IID_IPersist
)
||
IsEqualGUID
(
iid
,
&
IID_IMediaFilter
)
||
IsEqualGUID
(
iid
,
&
IID_IBaseFilter
))
{
{
IUnknown_AddRef
((
IUnknown
*
)(
*
ppv
));
*
out
=
&
filter
->
IBaseFilter_iface
;
IBaseFilter_AddRef
(
*
out
);
return
S_OK
;
return
S_OK
;
}
}
*
out
=
NULL
;
return
E_NOINTERFACE
;
return
E_NOINTERFACE
;
}
}
static
ULONG
WINAPI
TestFilter_AddRef
(
IBaseFilter
*
iface
)
static
ULONG
WINAPI
testfilter_AddRef
(
IBaseFilter
*
iface
)
{
{
TestFilterImpl
*
This
=
impl_from_IBaseFilter
(
iface
);
struct
testfilter
*
filter
=
impl_from_IBaseFilter
(
iface
);
ULONG
refCount
=
InterlockedIncrement
(
&
This
->
refCount
);
return
InterlockedIncrement
(
&
filter
->
ref
);
return
refCount
;
}
}
static
ULONG
WINAPI
TestFilter_Release
(
IBaseFilter
*
iface
)
static
ULONG
WINAPI
testfilter_Release
(
IBaseFilter
*
iface
)
{
{
TestFilterImpl
*
This
=
impl_from_IBaseFilter
(
iface
);
struct
testfilter
*
filter
=
impl_from_IBaseFilter
(
iface
);
ULONG
refCount
=
InterlockedDecrement
(
&
This
->
refCount
);
return
InterlockedDecrement
(
&
filter
->
ref
);
if
(
!
refCount
)
{
ULONG
i
;
for
(
i
=
0
;
i
<
This
->
nPins
;
i
++
)
{
IPin
*
pConnectedTo
;
if
(
SUCCEEDED
(
IPin_ConnectedTo
(
This
->
ppPins
[
i
],
&
pConnectedTo
)))
{
IPin_Disconnect
(
pConnectedTo
);
IPin_Release
(
pConnectedTo
);
}
IPin_Disconnect
(
This
->
ppPins
[
i
]);
IPin_Release
(
This
->
ppPins
[
i
]);
}
CoTaskMemFree
(
This
->
ppPins
);
DeleteCriticalSection
(
&
This
->
csFilter
);
CoTaskMemFree
(
This
);
return
0
;
}
else
return
refCount
;
}
}
/** IPersist methods **/
static
HRESULT
WINAPI
TestFilter_GetClassID
(
IBaseFilter
*
iface
,
CLSID
*
pC
lsid
)
static
HRESULT
WINAPI
testfilter_GetClassID
(
IBaseFilter
*
iface
,
CLSID
*
c
lsid
)
{
{
TestFilterImpl
*
This
=
impl_from_IBaseFilter
(
iface
);
if
(
winetest_debug
>
1
)
trace
(
"%p->GetClassID()
\n
"
,
iface
);
return
E_NOTIMPL
;
*
pClsid
=
This
->
clsid
;
return
S_OK
;
}
}
/** IMediaFilter methods **/
static
HRESULT
WINAPI
testfilter_Stop
(
IBaseFilter
*
iface
)
static
HRESULT
WINAPI
TestFilter_Stop
(
IBaseFilter
*
iface
)
{
{
if
(
winetest_debug
>
1
)
trace
(
"%p->Stop()
\n
"
,
iface
);
return
E_NOTIMPL
;
return
E_NOTIMPL
;
}
}
static
HRESULT
WINAPI
TestFilter_Pause
(
IBaseFilter
*
iface
)
static
HRESULT
WINAPI
testfilter_Pause
(
IBaseFilter
*
iface
)
{
{
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
return
E_NOTIMPL
;
}
}
static
HRESULT
WINAPI
TestFilter_Run
(
IBaseFilter
*
iface
,
REFERENCE_TIME
tS
tart
)
static
HRESULT
WINAPI
testfilter_Run
(
IBaseFilter
*
iface
,
REFERENCE_TIME
s
tart
)
{
{
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
return
E_NOTIMPL
;
}
}
static
HRESULT
WINAPI
TestFilter_GetState
(
IBaseFilter
*
iface
,
DWORD
dwMilliSecsTimeout
,
FILTER_STATE
*
pS
tate
)
static
HRESULT
WINAPI
testfilter_GetState
(
IBaseFilter
*
iface
,
DWORD
timeout
,
FILTER_STATE
*
s
tate
)
{
{
TestFilterImpl
*
This
=
impl_from_IBaseFilter
(
iface
);
if
(
winetest_debug
>
1
)
trace
(
"%p->GetState()
\n
"
,
iface
);
return
E_NOTIMPL
;
EnterCriticalSection
(
&
This
->
csFilter
);
{
*
pState
=
This
->
state
;
}
LeaveCriticalSection
(
&
This
->
csFilter
);
return
S_OK
;
}
}
static
HRESULT
WINAPI
TestFilter_SetSyncSource
(
IBaseFilter
*
iface
,
IReferenceClock
*
pC
lock
)
static
HRESULT
WINAPI
testfilter_SetSyncSource
(
IBaseFilter
*
iface
,
IReferenceClock
*
c
lock
)
{
{
if
(
winetest_debug
>
1
)
trace
(
"%p->SetSyncSource(%p)
\n
"
,
iface
,
clock
);
return
E_NOTIMPL
;
return
E_NOTIMPL
;
}
}
static
HRESULT
WINAPI
TestFilter_GetSyncSource
(
IBaseFilter
*
iface
,
IReferenceClock
**
ppC
lock
)
static
HRESULT
WINAPI
testfilter_GetSyncSource
(
IBaseFilter
*
iface
,
IReferenceClock
**
c
lock
)
{
{
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
return
E_NOTIMPL
;
}
}
/** IBaseFilter implementation **/
static
HRESULT
WINAPI
testfilter_EnumPins
(
IBaseFilter
*
iface
,
IEnumPins
**
out
)
static
HRESULT
getpin_callback
(
TestFilterImpl
*
tf
,
ULONG
pos
,
IPin
**
pin
,
DWORD
*
lastsynctick
)
{
{
/* Our pins are static, not changing so setting static tick count is ok */
struct
testfilter
*
filter
=
impl_from_IBaseFilter
(
iface
);
*
lastsynctick
=
0
;
if
(
winetest_debug
>
1
)
trace
(
"%p->EnumPins()
\n
"
,
filter
)
;
if
(
pos
>=
tf
->
nPins
)
*
out
=
&
filter
->
IEnumPins_iface
;
return
S_FALSE
;
IEnumPins_AddRef
(
*
out
);
filter
->
enum_idx
=
0
;
*
pin
=
tf
->
ppPins
[
pos
];
IPin_AddRef
(
*
pin
);
return
S_OK
;
return
S_OK
;
}
}
static
HRESULT
WINAPI
TestFilter_EnumPins
(
IBaseFilter
*
iface
,
IEnumPins
**
ppEnum
)
static
HRESULT
WINAPI
testfilter_FindPin
(
IBaseFilter
*
iface
,
const
WCHAR
*
id
,
IPin
**
pin
)
{
TestFilterImpl
*
This
=
impl_from_IBaseFilter
(
iface
);
return
createenumpins
(
ppEnum
,
getpin_callback
,
This
);
}
static
HRESULT
WINAPI
TestFilter_FindPin
(
IBaseFilter
*
iface
,
LPCWSTR
Id
,
IPin
**
ppPin
)
{
{
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
return
E_NOTIMPL
;
}
}
static
HRESULT
WINAPI
TestFilter_QueryFilterInfo
(
IBaseFilter
*
iface
,
FILTER_INFO
*
pI
nfo
)
static
HRESULT
WINAPI
testfilter_QueryFilterInfo
(
IBaseFilter
*
iface
,
FILTER_INFO
*
i
nfo
)
{
{
TestFilterImpl
*
This
=
impl_from_IBaseFilter
(
iface
);
struct
testfilter
*
filter
=
impl_from_IBaseFilter
(
iface
);
if
(
winetest_debug
>
1
)
trace
(
"%p->QueryFilterInfo()
\n
"
,
filter
);
lstrcpyW
(
pInfo
->
achName
,
This
->
filterInfo
.
achName
);
pInfo
->
pGraph
=
This
->
filterInfo
.
pGraph
;
if
(
pInfo
->
pGraph
)
IFilterGraph_AddRef
(
pInfo
->
pGraph
);
info
->
pGraph
=
filter
->
graph
;
if
(
filter
->
graph
)
IFilterGraph_AddRef
(
filter
->
graph
);
if
(
filter
->
name
)
lstrcpyW
(
info
->
achName
,
filter
->
name
);
else
info
->
achName
[
0
]
=
0
;
return
S_OK
;
return
S_OK
;
}
}
static
HRESULT
WINAPI
TestFilter_JoinFilterGraph
(
IBaseFilter
*
iface
,
IFilterGraph
*
pGraph
,
LPCWSTR
pN
ame
)
static
HRESULT
WINAPI
testfilter_JoinFilterGraph
(
IBaseFilter
*
iface
,
IFilterGraph
*
graph
,
const
WCHAR
*
n
ame
)
{
{
HRESULT
hr
=
S_OK
;
struct
testfilter
*
filter
=
impl_from_IBaseFilter
(
iface
)
;
TestFilterImpl
*
This
=
impl_from_IBaseFilter
(
iface
);
if
(
winetest_debug
>
1
)
trace
(
"%p->JoinFilterGraph(%p, %s)
\n
"
,
filter
,
graph
,
wine_dbgstr_w
(
name
)
);
EnterCriticalSection
(
&
This
->
csFilter
);
filter
->
graph
=
graph
;
heap_free
(
filter
->
name
);
if
(
name
)
{
{
if
(
pName
)
filter
->
name
=
heap_alloc
((
lstrlenW
(
name
)
+
1
)
*
sizeof
(
WCHAR
));
lstrcpyW
(
This
->
filterInfo
.
achName
,
pName
);
lstrcpyW
(
filter
->
name
,
name
);
else
*
This
->
filterInfo
.
achName
=
'\0'
;
This
->
filterInfo
.
pGraph
=
pGraph
;
/* NOTE: do NOT increase ref. count */
}
}
LeaveCriticalSection
(
&
This
->
csFilter
);
else
filter
->
name
=
NULL
;
return
hr
;
return
S_OK
;
}
}
static
HRESULT
WINAPI
TestFilter_QueryVendorInfo
(
IBaseFilter
*
iface
,
LPWSTR
*
pVendorI
nfo
)
static
HRESULT
WINAPI
testfilter_QueryVendorInfo
(
IBaseFilter
*
iface
,
WCHAR
**
i
nfo
)
{
{
return
E_NOTIMPL
;
return
E_NOTIMPL
;
}
}
static
const
IBaseFilterVtbl
TestFilter_V
tbl
=
static
const
IBaseFilterVtbl
testfilter_v
tbl
=
{
{
TestF
ilter_QueryInterface
,
testf
ilter_QueryInterface
,
TestF
ilter_AddRef
,
testf
ilter_AddRef
,
TestF
ilter_Release
,
testf
ilter_Release
,
TestF
ilter_GetClassID
,
testf
ilter_GetClassID
,
TestF
ilter_Stop
,
testf
ilter_Stop
,
TestF
ilter_Pause
,
testf
ilter_Pause
,
TestF
ilter_Run
,
testf
ilter_Run
,
TestF
ilter_GetState
,
testf
ilter_GetState
,
TestF
ilter_SetSyncSource
,
testf
ilter_SetSyncSource
,
TestF
ilter_GetSyncSource
,
testf
ilter_GetSyncSource
,
TestF
ilter_EnumPins
,
testf
ilter_EnumPins
,
TestF
ilter_FindPin
,
testf
ilter_FindPin
,
TestF
ilter_QueryFilterInfo
,
testf
ilter_QueryFilterInfo
,
TestF
ilter_JoinFilterGraph
,
testf
ilter_JoinFilterGraph
,
TestF
ilter_QueryVendorInfo
testf
ilter_QueryVendorInfo
};
};
/* IClassFactory implementation */
struct
testfilter_cf
typedef
struct
TestClassFactoryImpl
{
{
IClassFactory
IClassFactory_iface
;
IClassFactory
IClassFactory_iface
;
const
TestFilterPinData
*
filterPinData
;
struct
testfilter
*
filter
;
const
CLSID
*
clsid
;
};
}
TestClassFactoryImpl
;
static
inline
TestClassFactoryImpl
*
impl_from_IClassFactory
(
IClassFactory
*
iface
)
static
void
testfilter_init
(
struct
testfilter
*
filter
,
struct
testpin
*
pins
,
int
pin_count
)
{
{
return
CONTAINING_RECORD
(
iface
,
TestClassFactoryImpl
,
IClassFactory_iface
);
unsigned
int
i
;
memset
(
filter
,
0
,
sizeof
(
*
filter
));
filter
->
IBaseFilter_iface
.
lpVtbl
=
&
testfilter_vtbl
;
filter
->
IEnumPins_iface
.
lpVtbl
=
&
testenumpins_vtbl
;
filter
->
ref
=
1
;
filter
->
pins
=
pins
;
filter
->
pin_count
=
pin_count
;
for
(
i
=
0
;
i
<
pin_count
;
i
++
)
pins
[
i
].
filter
=
&
filter
->
IBaseFilter_iface
;
}
}
static
HRESULT
WINAPI
Test_IClassFactory_QueryInterface
(
static
HRESULT
WINAPI
testfilter_cf_QueryInterface
(
IClassFactory
*
iface
,
REFIID
iid
,
void
**
out
)
LPCLASSFACTORY
iface
,
REFIID
riid
,
LPVOID
*
ppvObj
)
{
{
if
(
ppvObj
==
NULL
)
return
E_POINTER
;
if
(
IsEqualGUID
(
iid
,
&
IID_IUnknown
)
||
IsEqualGUID
(
iid
,
&
IID_IClassFactory
))
if
(
IsEqualGUID
(
riid
,
&
IID_IUnknown
)
||
IsEqualGUID
(
riid
,
&
IID_IClassFactory
))
{
{
*
ppvObj
=
iface
;
*
out
=
iface
;
IClassFactory_AddRef
(
iface
);
return
S_OK
;
return
S_OK
;
}
}
*
ppvObj
=
NULL
;
*
out
=
NULL
;
return
E_NOINTERFACE
;
return
E_NOINTERFACE
;
}
}
static
ULONG
WINAPI
Test_IClassFactory_AddRef
(
LPCLASSFACTORY
iface
)
static
ULONG
WINAPI
testfilter_cf_AddRef
(
IClassFactory
*
iface
)
{
{
return
2
;
/* non-heap-based object */
return
2
;
}
}
static
ULONG
WINAPI
Test_IClassFactory_Release
(
LPCLASSFACTORY
iface
)
static
ULONG
WINAPI
testfilter_cf_Release
(
IClassFactory
*
iface
)
{
{
return
1
;
/* non-heap-based object */
return
1
;
}
}
static
HRESULT
WINAPI
Test_IClassFactory_CreateInstance
(
static
HRESULT
WINAPI
testfilter_cf_CreateInstance
(
IClassFactory
*
iface
,
IUnknown
*
outer
,
REFIID
iid
,
void
**
out
)
LPCLASSFACTORY
iface
,
LPUNKNOWN
pUnkOuter
,
REFIID
riid
,
LPVOID
*
ppvObj
)
{
{
TestClassFactoryImpl
*
This
=
impl_from_IClassFactory
(
iface
);
struct
testfilter_cf
*
factory
=
CONTAINING_RECORD
(
iface
,
struct
testfilter_cf
,
IClassFactory_iface
);
HRESULT
hr
;
TestFilterImpl
*
testfilter
;
*
ppvObj
=
NULL
;
return
IBaseFilter_QueryInterface
(
&
factory
->
filter
->
IBaseFilter_iface
,
iid
,
out
);
if
(
pUnkOuter
)
return
CLASS_E_NOAGGREGATION
;
hr
=
createtestfilter
(
This
->
clsid
,
This
->
filterPinData
,
&
testfilter
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
IBaseFilter_QueryInterface
(
&
testfilter
->
IBaseFilter_iface
,
riid
,
ppvObj
);
IBaseFilter_Release
(
&
testfilter
->
IBaseFilter_iface
);
}
return
hr
;
}
}
static
HRESULT
WINAPI
Test_IClassFactory_LockServer
(
static
HRESULT
WINAPI
testfilter_cf_LockServer
(
IClassFactory
*
iface
,
BOOL
lock
)
LPCLASSFACTORY
iface
,
BOOL
fLock
)
{
{
return
S_OK
;
return
E_NOTIMPL
;
}
}
static
IClassFactoryVtbl
TestClassFactory_V
tbl
=
static
IClassFactoryVtbl
testfilter_cf_v
tbl
=
{
{
Test_IClassFactory
_QueryInterface
,
testfilter_cf
_QueryInterface
,
Test_IClassFactory
_AddRef
,
testfilter_cf
_AddRef
,
Test_IClassFactory
_Release
,
testfilter_cf
_Release
,
Test_IClassFactory
_CreateInstance
,
testfilter_cf
_CreateInstance
,
Test_IClassFactory_LockServer
testfilter_cf_LockServer
,
};
};
static
HRESULT
get_connected_filter_name
(
TestFilterImpl
*
pFilter
,
char
*
FilterName
)
static
void
test_graph_builder_render
(
void
)
{
{
IPin
*
pin
=
NULL
;
static
const
WCHAR
testW
[]
=
{
't'
,
'e'
,
's'
,
't'
,
0
};
PIN_INFO
pinInfo
;
static
const
GUID
sink1_clsid
=
{
0x12345678
};
FILTER_INFO
filterInfo
;
static
const
GUID
sink2_clsid
=
{
0x87654321
};
HRESULT
hr
;
AM_MEDIA_TYPE
source_type
=
{{
0
}};
struct
testpin
source_pin
,
sink1_pin
,
sink2_pin
,
parser_pins
[
2
];
FilterName
[
0
]
=
0
;
struct
testfilter
source
,
sink1
,
sink2
,
parser
;
struct
testfilter_cf
sink1_cf
=
{
{
&
testfilter_cf_vtbl
},
&
sink1
};
hr
=
IPin_ConnectedTo
(
pFilter
->
ppPins
[
0
],
&
pin
);
struct
testfilter_cf
sink2_cf
=
{
{
&
testfilter_cf_vtbl
},
&
sink2
};
ok
(
hr
==
S_OK
,
"IPin_ConnectedTo failed with %x
\n
"
,
hr
);
hr
=
IPin_QueryPinInfo
(
pin
,
&
pinInfo
);
ok
(
hr
==
S_OK
,
"IPin_QueryPinInfo failed with %x
\n
"
,
hr
);
IPin_Release
(
pin
);
SetLastError
(
0xdeadbeef
);
hr
=
IBaseFilter_QueryFilterInfo
(
pinInfo
.
pFilter
,
&
filterInfo
);
if
(
hr
==
S_OK
&&
GetLastError
()
==
ERROR_CALL_NOT_IMPLEMENTED
)
{
IBaseFilter_Release
(
pinInfo
.
pFilter
);
return
E_NOTIMPL
;
}
ok
(
hr
==
S_OK
,
"IBaseFilter_QueryFilterInfo failed with %x
\n
"
,
hr
);
IBaseFilter_Release
(
pinInfo
.
pFilter
);
IFilterGraph_Release
(
filterInfo
.
pGraph
);
WideCharToMultiByte
(
CP_ACP
,
0
,
filterInfo
.
achName
,
-
1
,
FilterName
,
MAX_FILTER_NAME
,
NULL
,
NULL
);
return
S_OK
;
}
static
void
test_render_filter_priority
(
void
)
IFilterGraph2
*
graph
=
create_graph
();
{
REGFILTERPINS2
regpins
=
{
0
};
/* Tests filter choice priorities in Render(). */
REGPINTYPES
regtypes
=
{
0
};
DWORD
cookie1
=
0
,
cookie2
=
0
,
cookie3
=
0
;
REGFILTER2
regfilter
=
{
0
};
IFilterMapper2
*
mapper
;
DWORD
cookie1
,
cookie2
;
HRESULT
hr
;
HRESULT
hr
;
IFilterGraph2
*
pgraph2
=
NULL
;
ULONG
ref
;
IFilterMapper2
*
pMapper2
=
NULL
;
TestFilterImpl
*
ptestfilter
=
NULL
;
memset
(
&
source_type
.
majortype
,
0xcc
,
sizeof
(
GUID
));
TestFilterImpl
*
ptestfilter2
=
NULL
;
testsource_init
(
&
source_pin
,
&
source_type
,
1
);
static
const
CLSID
CLSID_TestFilter2
=
{
testfilter_init
(
&
source
,
&
source_pin
,
1
);
0x37a4edb0
,
testsink_init
(
&
sink1_pin
);
0x4d13
,
testfilter_init
(
&
sink1
,
&
sink1_pin
,
1
);
0x11dd
,
testsink_init
(
&
sink2_pin
);
{
0xe8
,
0x9b
,
0x00
,
0x19
,
0x66
,
0x2f
,
0xf0
,
0xce
}
testfilter_init
(
&
sink2
,
&
sink2_pin
,
1
);
};
testsink_init
(
&
parser_pins
[
0
]);
static
const
CLSID
CLSID_TestFilter3
=
{
testsource_init
(
&
parser_pins
[
1
],
&
source_type
,
1
);
0x37a4f2d8
,
testfilter_init
(
&
parser
,
parser_pins
,
2
);
0x4d13
,
0x11dd
,
IFilterGraph2_AddFilter
(
graph
,
&
source
.
IBaseFilter_iface
,
NULL
);
{
0xe8
,
0x9b
,
0x00
,
0x19
,
0x66
,
0x2f
,
0xf0
,
0xce
}
IFilterGraph2_AddFilter
(
graph
,
&
sink1
.
IBaseFilter_iface
,
NULL
);
};
IFilterGraph2_AddFilter
(
graph
,
&
sink2
.
IBaseFilter_iface
,
NULL
);
static
const
CLSID
CLSID_TestFilter4
=
{
0x37a4f3b4
,
hr
=
IFilterGraph2_Render
(
graph
,
&
source_pin
.
IPin_iface
);
0x4d13
,
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
0x11dd
,
ok
(
source_pin
.
peer
==
&
sink2_pin
.
IPin_iface
,
"Got peer %p.
\n
"
,
source_pin
.
peer
);
{
0xe8
,
0x9b
,
0x00
,
0x19
,
0x66
,
0x2f
,
0xf0
,
0xce
}
IFilterGraph2_Disconnect
(
graph
,
source_pin
.
peer
);
};
IFilterGraph2_Disconnect
(
graph
,
&
source_pin
.
IPin_iface
);
static
const
GUID
mediasubtype1
=
{
0x37a4f51c
,
0x4d13
,
0x11dd
,
{
0xe8
,
0x9b
,
0x00
,
0x19
,
0x66
,
0x2f
,
0xf0
,
0xce
}
};
static
const
GUID
mediasubtype2
=
{
0x37a4f5c6
,
0x4d13
,
0x11dd
,
{
0xe8
,
0x9b
,
0x00
,
0x19
,
0x66
,
0x2f
,
0xf0
,
0xce
}
};
static
const
TestFilterPinData
PinData1
[]
=
{
{
PINDIR_OUTPUT
,
&
mediasubtype1
},
{
0
,
0
}
};
static
const
TestFilterPinData
PinData2
[]
=
{
{
PINDIR_INPUT
,
&
mediasubtype1
},
{
0
,
0
}
};
static
const
TestFilterPinData
PinData3
[]
=
{
{
PINDIR_INPUT
,
&
GUID_NULL
},
{
0
,
0
}
};
static
const
TestFilterPinData
PinData4
[]
=
{
{
PINDIR_INPUT
,
&
mediasubtype1
},
{
PINDIR_OUTPUT
,
&
mediasubtype2
},
{
0
,
0
}
};
static
const
TestFilterPinData
PinData5
[]
=
{
{
PINDIR_INPUT
,
&
mediasubtype2
},
{
0
,
0
}
};
TestClassFactoryImpl
Filter1ClassFactory
=
{
{
&
TestClassFactory_Vtbl
},
PinData2
,
&
CLSID_TestFilter2
};
TestClassFactoryImpl
Filter2ClassFactory
=
{
{
&
TestClassFactory_Vtbl
},
PinData4
,
&
CLSID_TestFilter3
};
TestClassFactoryImpl
Filter3ClassFactory
=
{
{
&
TestClassFactory_Vtbl
},
PinData5
,
&
CLSID_TestFilter4
};
char
ConnectedFilterName1
[
MAX_FILTER_NAME
];
char
ConnectedFilterName2
[
MAX_FILTER_NAME
];
REGFILTER2
rgf2
;
REGFILTERPINS2
rgPins2
[
2
];
REGPINTYPES
rgPinType
[
2
];
static
const
WCHAR
wszFilterInstanceName1
[]
=
{
'T'
,
'e'
,
's'
,
't'
,
'f'
,
'i'
,
'l'
,
't'
,
'e'
,
'r'
,
'I'
,
'n'
,
's'
,
't'
,
'a'
,
'n'
,
'c'
,
'e'
,
'1'
,
0
};
static
const
WCHAR
wszFilterInstanceName2
[]
=
{
'T'
,
'e'
,
's'
,
't'
,
'f'
,
'i'
,
'l'
,
't'
,
'e'
,
'r'
,
'I'
,
'n'
,
's'
,
't'
,
'a'
,
'n'
,
'c'
,
'e'
,
'2'
,
0
};
static
const
WCHAR
wszFilterInstanceName3
[]
=
{
'T'
,
'e'
,
's'
,
't'
,
'f'
,
'i'
,
'l'
,
't'
,
'e'
,
'r'
,
'I'
,
'n'
,
's'
,
't'
,
'a'
,
'n'
,
'c'
,
'e'
,
'3'
,
0
};
static
const
WCHAR
wszFilterInstanceName4
[]
=
{
'T'
,
'e'
,
's'
,
't'
,
'f'
,
'i'
,
'l'
,
't'
,
'e'
,
'r'
,
'I'
,
'n'
,
's'
,
't'
,
'a'
,
'n'
,
'c'
,
'e'
,
'4'
,
0
};
/* Test which renderer of two already added to the graph will be chosen
* (one is "exact" match, other is "wildcard" match. Seems to depend
* on the order in which filters are added to the graph, thus indicating
* no preference given to exact match. */
pgraph2
=
create_graph
();
hr
=
createtestfilter
(
&
GUID_NULL
,
PinData1
,
&
ptestfilter
);
ok
(
hr
==
S_OK
,
"createtestfilter failed with %08x
\n
"
,
hr
);
hr
=
IFilterGraph2_AddFilter
(
pgraph2
,
&
ptestfilter
->
IBaseFilter_iface
,
wszFilterInstanceName1
);
ok
(
hr
==
S_OK
,
"IFilterGraph2_AddFilter failed with %08x
\n
"
,
hr
);
hr
=
createtestfilter
(
&
GUID_NULL
,
PinData2
,
&
ptestfilter2
);
ok
(
hr
==
S_OK
,
"createtestfilter failed with %08x
\n
"
,
hr
);
hr
=
IFilterGraph2_AddFilter
(
pgraph2
,
&
ptestfilter2
->
IBaseFilter_iface
,
wszFilterInstanceName2
);
ok
(
hr
==
S_OK
,
"IFilterGraph2_AddFilter failed with %08x
\n
"
,
hr
);
IBaseFilter_Release
(
&
ptestfilter2
->
IBaseFilter_iface
);
hr
=
createtestfilter
(
&
GUID_NULL
,
PinData3
,
&
ptestfilter2
);
ok
(
hr
==
S_OK
,
"createtestfilter failed with %08x
\n
"
,
hr
);
hr
=
IFilterGraph2_AddFilter
(
pgraph2
,
&
ptestfilter2
->
IBaseFilter_iface
,
wszFilterInstanceName3
);
ok
(
hr
==
S_OK
,
"IFilterGraph2_AddFilter failed with %08x
\n
"
,
hr
);
hr
=
IFilterGraph2_Render
(
pgraph2
,
ptestfilter
->
ppPins
[
0
]);
ok
(
hr
==
S_OK
,
"IFilterGraph2_Render failed with %08x
\n
"
,
hr
);
hr
=
get_connected_filter_name
(
ptestfilter
,
ConnectedFilterName1
);
IFilterGraph2_Release
(
pgraph2
);
IBaseFilter_Release
(
&
ptestfilter
->
IBaseFilter_iface
);
IBaseFilter_Release
(
&
ptestfilter2
->
IBaseFilter_iface
);
pgraph2
=
create_graph
();
hr
=
createtestfilter
(
&
GUID_NULL
,
PinData1
,
&
ptestfilter
);
ok
(
hr
==
S_OK
,
"createtestfilter failed with %08x
\n
"
,
hr
);
hr
=
IFilterGraph2_AddFilter
(
pgraph2
,
&
ptestfilter
->
IBaseFilter_iface
,
wszFilterInstanceName1
);
ok
(
hr
==
S_OK
,
"IFilterGraph2_AddFilter failed with %08x
\n
"
,
hr
);
hr
=
createtestfilter
(
&
GUID_NULL
,
PinData3
,
&
ptestfilter2
);
ok
(
hr
==
S_OK
,
"createtestfilter failed with %08x
\n
"
,
hr
);
hr
=
IFilterGraph2_AddFilter
(
pgraph2
,
&
ptestfilter2
->
IBaseFilter_iface
,
wszFilterInstanceName3
);
ok
(
hr
==
S_OK
,
"IFilterGraph2_AddFilter failed with %08x
\n
"
,
hr
);
IBaseFilter_Release
(
&
ptestfilter2
->
IBaseFilter_iface
);
hr
=
createtestfilter
(
&
GUID_NULL
,
PinData2
,
&
ptestfilter2
);
ok
(
hr
==
S_OK
,
"createtestfilter failed with %08x
\n
"
,
hr
);
hr
=
IFilterGraph2_AddFilter
(
pgraph2
,
&
ptestfilter2
->
IBaseFilter_iface
,
wszFilterInstanceName2
);
ok
(
hr
==
S_OK
,
"IFilterGraph2_AddFilter failed with %08x
\n
"
,
hr
);
hr
=
IFilterGraph2_Render
(
pgraph2
,
ptestfilter
->
ppPins
[
0
]);
ok
(
hr
==
S_OK
,
"IFilterGraph2_Render failed with %08x
\n
"
,
hr
);
hr
=
IFilterGraph2_Disconnect
(
pgraph2
,
NULL
);
ok
(
hr
==
E_POINTER
,
"IFilterGraph2_Disconnect failed. Expected E_POINTER, received %08x
\n
"
,
hr
);
get_connected_filter_name
(
ptestfilter
,
ConnectedFilterName2
);
ok
(
strcmp
(
ConnectedFilterName1
,
ConnectedFilterName2
),
"expected connected filters to be different but got %s both times
\n
"
,
ConnectedFilterName1
);
IFilterGraph2_Release
(
pgraph2
);
IBaseFilter_Release
(
&
ptestfilter
->
IBaseFilter_iface
);
IBaseFilter_Release
(
&
ptestfilter2
->
IBaseFilter_iface
);
/* Test if any preference is given to existing renderer which renders the pin directly vs
an existing renderer which renders the pin indirectly, through an additional middle filter,
again trying different orders of creation. Native appears not to give a preference. */
pgraph2
=
create_graph
();
hr
=
createtestfilter
(
&
GUID_NULL
,
PinData1
,
&
ptestfilter
);
IFilterGraph2_RemoveFilter
(
graph
,
&
sink1
.
IBaseFilter_iface
);
ok
(
hr
==
S_OK
,
"createtestfilter failed with %08x
\n
"
,
hr
);
IFilterGraph2_AddFilter
(
graph
,
&
sink1
.
IBaseFilter_iface
,
NULL
);
hr
=
IFilterGraph2_AddFilter
(
pgraph2
,
&
ptestfilter
->
IBaseFilter_iface
,
wszFilterInstanceName1
);
hr
=
IFilterGraph2_Render
(
graph
,
&
source_pin
.
IPin_iface
);
ok
(
hr
==
S_OK
,
"IFilterGraph2_AddFilter failed with %08x
\n
"
,
hr
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
source_pin
.
peer
==
&
sink1_pin
.
IPin_iface
,
"Got peer %p.
\n
"
,
source_pin
.
peer
);
hr
=
createtestfilter
(
&
GUID_NULL
,
PinData2
,
&
ptestfilter2
);
IFilterGraph2_Disconnect
(
graph
,
&
source_pin
.
IPin_iface
);
ok
(
hr
==
S_OK
,
"createtestfilter failed with %08x
\n
"
,
hr
);
IFilterGraph2_Disconnect
(
graph
,
&
sink1_pin
.
IPin_iface
);
hr
=
IFilterGraph2_AddFilter
(
pgraph2
,
&
ptestfilter2
->
IBaseFilter_iface
,
wszFilterInstanceName2
);
/* No preference is given to smaller chains. */
ok
(
hr
==
S_OK
,
"IFilterGraph2_AddFilter failed with %08x
\n
"
,
hr
);
I
BaseFilter_Release
(
&
ptestfilter2
->
IBaseFilter_iface
);
I
FilterGraph2_AddFilter
(
graph
,
&
parser
.
IBaseFilter_iface
,
NULL
);
hr
=
createtestfilter
(
&
GUID_NULL
,
PinData4
,
&
ptestfilter2
);
hr
=
IFilterGraph2_Render
(
graph
,
&
source_pin
.
IPin_iface
);
ok
(
hr
==
S_OK
,
"createtestfilter failed with %08x
\n
"
,
hr
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
source_pin
.
peer
==
&
parser_pins
[
0
].
IPin_iface
,
"Got peer %p.
\n
"
,
source_pin
.
peer
);
ok
(
parser_pins
[
1
].
peer
==
&
sink1_pin
.
IPin_iface
,
"Got peer %p.
\n
"
,
parser_pins
[
1
].
peer
);
IFilterGraph2_Disconnect
(
graph
,
source_pin
.
peer
);
IFilterGraph2_Disconnect
(
graph
,
&
source_pin
.
IPin_iface
);
hr
=
IFilterGraph2_AddFilter
(
pgraph2
,
&
ptestfilter2
->
IBaseFilter_iface
,
wszFilterInstanceName3
);
IFilterGraph2_RemoveFilter
(
graph
,
&
sink1
.
IBaseFilter_iface
);
ok
(
hr
==
S_OK
,
"IFilterGraph2_AddFilter failed with %08x
\n
"
,
hr
);
IFilterGraph2_AddFilter
(
graph
,
&
sink1
.
IBaseFilter_iface
,
NULL
);
IBaseFilter_Release
(
&
ptestfilter2
->
IBaseFilter_iface
);
hr
=
IFilterGraph2_Render
(
graph
,
&
source_pin
.
IPin_iface
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
source_pin
.
peer
==
&
sink1_pin
.
IPin_iface
,
"Got peer %p.
\n
"
,
source_pin
.
peer
);
hr
=
createtestfilter
(
&
GUID_NULL
,
PinData5
,
&
ptestfilter2
);
ref
=
IFilterGraph2_Release
(
graph
);
ok
(
hr
==
S_OK
,
"createtestfilter failed with %08x
\n
"
,
hr
);
ok
(
!
ref
,
"Got outstanding refcount %d.
\n
"
,
ref
);
hr
=
IFilterGraph2_AddFilter
(
pgraph2
,
&
ptestfilter2
->
IBaseFilter_iface
,
wszFilterInstanceName4
);
/* Test enumeration of filters from the registry. */
ok
(
hr
==
S_OK
,
"IFilterGraph2_AddFilter failed with %08x
\n
"
,
hr
);
hr
=
IFilterGraph2_Render
(
pgraph2
,
ptestfilter
->
ppPins
[
0
]);
graph
=
create_graph
();
ok
(
hr
==
S_OK
,
"IFilterGraph2_Render failed with %08x
\n
"
,
hr
);
IFilterGraph2_AddFilter
(
graph
,
&
source
.
IBaseFilter_iface
,
NULL
);
CoRegisterClassObject
(
&
sink1_clsid
,
(
IUnknown
*
)
&
sink1_cf
.
IClassFactory_iface
,
CLSCTX_INPROC_SERVER
,
REGCLS_MULTIPLEUSE
,
&
cookie1
);
CoRegisterClassObject
(
&
sink2_clsid
,
(
IUnknown
*
)
&
sink2_cf
.
IClassFactory_iface
,
CLSCTX_INPROC_SERVER
,
REGCLS_MULTIPLEUSE
,
&
cookie2
);
CoCreateInstance
(
&
CLSID_FilterMapper2
,
NULL
,
CLSCTX_INPROC_SERVER
,
&
IID_IFilterMapper2
,
(
void
**
)
&
mapper
);
regfilter
.
dwVersion
=
2
;
regfilter
.
dwMerit
=
MERIT_UNLIKELY
;
regfilter
.
cPins2
=
1
;
regfilter
.
rgPins2
=
&
regpins
;
regpins
.
dwFlags
=
0
;
regpins
.
cInstances
=
1
;
regpins
.
nMediaTypes
=
1
;
regpins
.
lpMediaType
=
&
regtypes
;
regtypes
.
clsMajorType
=
&
source_type
.
majortype
;
regtypes
.
clsMinorType
=
&
MEDIASUBTYPE_NULL
;
hr
=
IFilterMapper2_RegisterFilter
(
mapper
,
&
sink1_clsid
,
testW
,
NULL
,
NULL
,
NULL
,
&
regfilter
);
if
(
hr
==
E_ACCESSDENIED
)
{
skip
(
"Not enough permission to register filters.
\n
"
);
goto
out
;
}
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
get_connected_filter_name
(
ptestfilter
,
ConnectedFilterName1
);
regpins
.
dwFlags
=
REG_PINFLAG_B_RENDERER
;
ok
(
!
strcmp
(
ConnectedFilterName1
,
"TestfilterInstance3"
)
||
!
strcmp
(
ConnectedFilterName1
,
"TestfilterInstance2"
),
IFilterMapper2_RegisterFilter
(
mapper
,
&
sink2_clsid
,
testW
,
NULL
,
NULL
,
NULL
,
&
regfilter
);
"unexpected connected filter: %s
\n
"
,
ConnectedFilterName1
);
IFilterGraph2_Release
(
pgraph2
);
hr
=
IFilterGraph2_Render
(
graph
,
&
source_pin
.
IPin_iface
);
IBaseFilter_Release
(
&
ptestfilter
->
IBaseFilter_iface
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
IBaseFilter_Release
(
&
ptestfilter2
->
IBaseFilter_iface
);
ok
(
source_pin
.
peer
==
&
sink2_pin
.
IPin_iface
||
source_pin
.
peer
==
&
sink1_pin
.
IPin_iface
,
"Got peer %p.
\n
"
,
source_pin
.
peer
);
pgraph2
=
create_graph
();
ref
=
IFilterGraph2_Release
(
graph
);
ok
(
!
ref
,
"Got outstanding refcount %d.
\n
"
,
ref
);
hr
=
createtestfilter
(
&
GUID_NULL
,
PinData1
,
&
ptestfilter
);
/* Preference is given to filters already in the graph. */
ok
(
hr
==
S_OK
,
"createtestfilter failed with %08x
\n
"
,
hr
);
hr
=
IFilterGraph2_AddFilter
(
pgraph2
,
&
ptestfilter
->
IBaseFilter_iface
,
wszFilterInstanceName1
);
graph
=
create_graph
();
ok
(
hr
==
S_OK
,
"IFilterGraph2_AddFilter failed with %08x
\n
"
,
hr
);
IFilterGraph2_AddFilter
(
graph
,
&
source
.
IBaseFilter_iface
,
NULL
);
IFilterGraph2_AddFilter
(
graph
,
&
sink2
.
IBaseFilter_iface
,
NULL
);
hr
=
createtestfilter
(
&
GUID_NULL
,
PinData4
,
&
ptestfilter2
);
hr
=
IFilterGraph2_Render
(
graph
,
&
source_pin
.
IPin_iface
);
ok
(
hr
==
S_OK
,
"createtestfilter failed with %08x
\n
"
,
hr
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
source_pin
.
peer
==
&
sink2_pin
.
IPin_iface
,
"Got peer %p.
\n
"
,
source_pin
.
peer
);
hr
=
IFilterGraph2_AddFilter
(
pgraph2
,
&
ptestfilter2
->
IBaseFilter_iface
,
wszFilterInstanceName3
);
ref
=
IFilterGraph2_Release
(
graph
);
ok
(
hr
==
S_OK
,
"IFilterGraph2_AddFilter failed with %08x
\n
"
,
hr
);
ok
(
!
ref
,
"Got outstanding refcount %d.
\n
"
,
ref
);
IBaseFilter_Release
(
&
ptestfilter2
->
IBaseFilter_iface
);
/* No preference is given to renderer filters. */
hr
=
createtestfilter
(
&
GUID_NULL
,
PinData5
,
&
ptestfilter2
);
graph
=
create_graph
(
);
ok
(
hr
==
S_OK
,
"createtestfilter failed with %08x
\n
"
,
hr
);
IFilterGraph2_AddFilter
(
graph
,
&
source
.
IBaseFilter_iface
,
NULL
);
hr
=
IFilterGraph2_AddFilter
(
pgraph2
,
&
ptestfilter2
->
IBaseFilter_iface
,
wszFilterInstanceName4
);
IFilterMapper2_UnregisterFilter
(
mapper
,
NULL
,
NULL
,
&
sink1_clsid
);
ok
(
hr
==
S_OK
,
"IFilterGraph2_AddFilter failed with %08x
\n
"
,
hr
);
IFilterMapper2_UnregisterFilter
(
mapper
,
NULL
,
NULL
,
&
sink2_clsid
);
IBaseFilter_Release
(
&
ptestfilter2
->
IBaseFilter_iface
);
IFilterMapper2_RegisterFilter
(
mapper
,
&
sink1_clsid
,
testW
,
NULL
,
NULL
,
NULL
,
&
regfilter
);
regpins
.
dwFlags
=
0
;
IFilterMapper2_RegisterFilter
(
mapper
,
&
sink2_clsid
,
testW
,
NULL
,
NULL
,
NULL
,
&
regfilter
);
hr
=
createtestfilter
(
&
GUID_NULL
,
PinData2
,
&
ptestfilter2
);
hr
=
IFilterGraph2_Render
(
graph
,
&
source_pin
.
IPin_iface
);
ok
(
hr
==
S_OK
,
"createtestfilter failed with %08x
\n
"
,
hr
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
source_pin
.
peer
==
&
sink2_pin
.
IPin_iface
||
source_pin
.
peer
==
&
sink1_pin
.
IPin_iface
,
"Got peer %p.
\n
"
,
source_pin
.
peer
);
hr
=
IFilterGraph2_AddFilter
(
pgraph2
,
&
ptestfilter2
->
IBaseFilter_iface
,
wszFilterInstanceName2
);
ref
=
IFilterGraph2_Release
(
graph
);
ok
(
hr
==
S_OK
,
"IFilterGraph2_AddFilter failed with %08x
\n
"
,
hr
);
ok
(
!
ref
,
"Got outstanding refcount %d.
\n
"
,
ref
);
hr
=
IFilterGraph2_Render
(
pgraph2
,
ptestfilter
->
ppPins
[
0
]);
/* Preference is given to filters with higher merit. */
ok
(
hr
==
S_OK
,
"IFilterGraph2_Render failed with %08x
\n
"
,
hr
);
get_connected_filter_name
(
ptestfilter
,
ConnectedFilterName2
);
graph
=
create_graph
();
ok
(
!
strcmp
(
ConnectedFilterName2
,
"TestfilterInstance3"
)
||
!
strcmp
(
ConnectedFilterName2
,
"TestfilterInstance2"
),
IFilterGraph2_AddFilter
(
graph
,
&
source
.
IBaseFilter_iface
,
NULL
);
"unexpected connected filter: %s
\n
"
,
ConnectedFilterName2
);
ok
(
strcmp
(
ConnectedFilterName1
,
ConnectedFilterName2
),
"expected connected filters to be different but got %s both times
\n
"
,
ConnectedFilterName1
);
IFilterGraph2_Release
(
pgraph2
);
IFilterMapper2_UnregisterFilter
(
mapper
,
NULL
,
NULL
,
&
sink1_clsid
);
IBaseFilter_Release
(
&
ptestfilter
->
IBaseFilter_iface
);
IFilterMapper2_UnregisterFilter
(
mapper
,
NULL
,
NULL
,
&
sink2_clsid
);
IBaseFilter_Release
(
&
ptestfilter2
->
IBaseFilter_iface
);
/* Test if renderers are tried before non-renderers (intermediary filters). */
regfilter
.
dwMerit
=
MERIT_UNLIKELY
;
pgraph2
=
create_graph
();
IFilterMapper2_RegisterFilter
(
mapper
,
&
sink1_clsid
,
testW
,
NULL
,
NULL
,
NULL
,
&
regfilter
);
regfilter
.
dwMerit
=
MERIT_PREFERRED
;
IFilterMapper2_RegisterFilter
(
mapper
,
&
sink2_clsid
,
testW
,
NULL
,
NULL
,
NULL
,
&
regfilter
);
hr
=
CoCreateInstance
(
&
CLSID_FilterMapper2
,
NULL
,
CLSCTX_INPROC_SERVER
,
&
IID_IFilterMapper2
,
(
LPVOID
*
)
&
pMapper2
);
hr
=
IFilterGraph2_Render
(
graph
,
&
source_pin
.
IPin_iface
);
ok
(
hr
==
S_OK
,
"CoCreateInstance failed with %08x
\n
"
,
hr
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
source_pin
.
peer
==
&
sink2_pin
.
IPin_iface
,
"Got peer %p.
\n
"
,
source_pin
.
peer
);
hr
=
createtestfilter
(
&
GUID_NULL
,
PinData1
,
&
ptestfilter
);
ref
=
IFilterGraph2_Release
(
graph
);
ok
(
hr
==
S_OK
,
"createtestfilter failed with %08x
\n
"
,
hr
);
ok
(
!
ref
,
"Got outstanding refcount %d.
\n
"
,
ref
);
hr
=
IFilterGraph2_AddFilter
(
pgraph2
,
&
ptestfilter
->
IBaseFilter_iface
,
wszFilterInstanceName1
);
graph
=
create_graph
(
);
ok
(
hr
==
S_OK
,
"IFilterGraph2_AddFilter failed with %08x
\n
"
,
hr
);
IFilterGraph2_AddFilter
(
graph
,
&
source
.
IBaseFilter_iface
,
NULL
);
/* Register our filters with COM and with Filtermapper. */
IFilterMapper2_UnregisterFilter
(
mapper
,
NULL
,
NULL
,
&
sink1_clsid
);
hr
=
CoRegisterClassObject
(
Filter1ClassFactory
.
clsid
,
IFilterMapper2_UnregisterFilter
(
mapper
,
NULL
,
NULL
,
&
sink2_clsid
);
(
IUnknown
*
)
&
Filter1ClassFactory
.
IClassFactory_iface
,
CLSCTX_INPROC_SERVER
,
REGCLS_MULTIPLEUSE
,
&
cookie1
);
ok
(
hr
==
S_OK
,
"CoRegisterClassObject failed with %08x
\n
"
,
hr
);
hr
=
CoRegisterClassObject
(
Filter2ClassFactory
.
clsid
,
(
IUnknown
*
)
&
Filter2ClassFactory
.
IClassFactory_iface
,
CLSCTX_INPROC_SERVER
,
REGCLS_MULTIPLEUSE
,
&
cookie2
);
ok
(
hr
==
S_OK
,
"CoRegisterClassObject failed with %08x
\n
"
,
hr
);
hr
=
CoRegisterClassObject
(
Filter3ClassFactory
.
clsid
,
(
IUnknown
*
)
&
Filter3ClassFactory
.
IClassFactory_iface
,
CLSCTX_INPROC_SERVER
,
REGCLS_MULTIPLEUSE
,
&
cookie3
);
ok
(
hr
==
S_OK
,
"CoRegisterClassObject failed with %08x
\n
"
,
hr
);
rgf2
.
dwVersion
=
2
;
regfilter
.
dwMerit
=
MERIT_PREFERRED
;
rgf2
.
dwMerit
=
MERIT_UNLIKELY
;
IFilterMapper2_RegisterFilter
(
mapper
,
&
sink1_clsid
,
testW
,
NULL
,
NULL
,
NULL
,
&
regfilter
);
S2
(
U
(
rgf2
)).
cPins2
=
1
;
regfilter
.
dwMerit
=
MERIT_UNLIKELY
;
S2
(
U
(
rgf2
)).
rgPins2
=
rgPins2
;
IFilterMapper2_RegisterFilter
(
mapper
,
&
sink2_clsid
,
testW
,
NULL
,
NULL
,
NULL
,
&
regfilter
);
rgPins2
[
0
].
dwFlags
=
REG_PINFLAG_B_RENDERER
;
rgPins2
[
0
].
cInstances
=
1
;
rgPins2
[
0
].
nMediaTypes
=
1
;
rgPins2
[
0
].
lpMediaType
=
&
rgPinType
[
0
];
rgPins2
[
0
].
nMediums
=
0
;
rgPins2
[
0
].
lpMedium
=
NULL
;
rgPins2
[
0
].
clsPinCategory
=
NULL
;
rgPinType
[
0
].
clsMajorType
=
&
MEDIATYPE_Video
;
rgPinType
[
0
].
clsMinorType
=
&
mediasubtype1
;
hr
=
IFilterMapper2_RegisterFilter
(
pMapper2
,
&
CLSID_TestFilter2
,
wszFilterInstanceName2
,
NULL
,
hr
=
IFilterGraph2_Render
(
graph
,
&
source_pin
.
IPin_iface
);
&
CLSID_LegacyAmFilterCategory
,
NULL
,
&
rgf2
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
if
(
hr
==
E_ACCESSDENIED
)
ok
(
source_pin
.
peer
==
&
sink1_pin
.
IPin_iface
,
"Got peer %p.
\n
"
,
source_pin
.
peer
);
skip
(
"Not authorized to register filters
\n
"
);
else
{
ok
(
hr
==
S_OK
,
"IFilterMapper2_RegisterFilter failed with %x
\n
"
,
hr
);
rgf2
.
dwMerit
=
MERIT_PREFERRED
;
rgPinType
[
0
].
clsMinorType
=
&
mediasubtype2
;
hr
=
IFilterMapper2_RegisterFilter
(
pMapper2
,
&
CLSID_TestFilter4
,
wszFilterInstanceName4
,
NULL
,
&
CLSID_LegacyAmFilterCategory
,
NULL
,
&
rgf2
);
ok
(
hr
==
S_OK
,
"IFilterMapper2_RegisterFilter failed with %x
\n
"
,
hr
);
S2
(
U
(
rgf2
)).
cPins2
=
2
;
rgPins2
[
0
].
dwFlags
=
0
;
rgPinType
[
0
].
clsMinorType
=
&
mediasubtype1
;
rgPins2
[
1
].
dwFlags
=
REG_PINFLAG_B_OUTPUT
;
rgPins2
[
1
].
cInstances
=
1
;
rgPins2
[
1
].
nMediaTypes
=
1
;
rgPins2
[
1
].
lpMediaType
=
&
rgPinType
[
1
];
rgPins2
[
1
].
nMediums
=
0
;
rgPins2
[
1
].
lpMedium
=
NULL
;
rgPins2
[
1
].
clsPinCategory
=
NULL
;
rgPinType
[
1
].
clsMajorType
=
&
MEDIATYPE_Video
;
rgPinType
[
1
].
clsMinorType
=
&
mediasubtype2
;
hr
=
IFilterMapper2_RegisterFilter
(
pMapper2
,
&
CLSID_TestFilter3
,
wszFilterInstanceName3
,
NULL
,
&
CLSID_LegacyAmFilterCategory
,
NULL
,
&
rgf2
);
ok
(
hr
==
S_OK
,
"IFilterMapper2_RegisterFilter failed with %x
\n
"
,
hr
);
hr
=
IFilterGraph2_Render
(
pgraph2
,
ptestfilter
->
ppPins
[
0
]);
ok
(
hr
==
S_OK
,
"IFilterGraph2_Render failed with %08x
\n
"
,
hr
);
get_connected_filter_name
(
ptestfilter
,
ConnectedFilterName1
);
ok
(
!
strcmp
(
ConnectedFilterName1
,
"TestfilterInstance3"
),
"unexpected connected filter: %s
\n
"
,
ConnectedFilterName1
);
hr
=
IFilterMapper2_UnregisterFilter
(
pMapper2
,
&
CLSID_LegacyAmFilterCategory
,
NULL
,
&
CLSID_TestFilter2
);
ok
(
hr
==
S_OK
,
"IFilterMapper2_UnregisterFilter failed with %x
\n
"
,
hr
);
hr
=
IFilterMapper2_UnregisterFilter
(
pMapper2
,
&
CLSID_LegacyAmFilterCategory
,
NULL
,
&
CLSID_TestFilter3
);
ok
(
hr
==
S_OK
,
"IFilterMapper2_UnregisterFilter failed with %x
\n
"
,
hr
);
hr
=
IFilterMapper2_UnregisterFilter
(
pMapper2
,
&
CLSID_LegacyAmFilterCategory
,
NULL
,
&
CLSID_TestFilter4
);
ok
(
hr
==
S_OK
,
"IFilterMapper2_UnregisterFilter failed with %x
\n
"
,
hr
);
}
IBaseFilter_Release
(
&
ptestfilter
->
IBaseFilter_iface
);
IFilterMapper2_UnregisterFilter
(
mapper
,
NULL
,
NULL
,
&
sink1_clsid
);
IFilterGraph2_Release
(
pgraph2
);
IFilterMapper2_UnregisterFilter
(
mapper
,
NULL
,
NULL
,
&
sink2_clsid
);
IFilterMapper2_Release
(
pMapper2
);
hr
=
CoRevokeClassObject
(
cookie1
);
out:
ok
(
hr
==
S_OK
,
"CoRevokeClassObject failed with %08x
\n
"
,
hr
);
CoRevokeClassObject
(
cookie1
);
hr
=
CoRevokeClassObject
(
cookie2
);
CoRevokeClassObject
(
cookie2
);
ok
(
hr
==
S_OK
,
"CoRevokeClassObject failed with %08x
\n
"
,
hr
);
IFilterMapper2_Release
(
mapper
);
hr
=
CoRevokeClassObject
(
cookie3
);
ref
=
IFilterGraph2_Release
(
graph
);
ok
(
hr
==
S_OK
,
"CoRevokeClassObject failed with %08x
\n
"
,
hr
);
ok
(
!
ref
,
"Got outstanding refcount %d.
\n
"
,
ref
);
ok
(
source
.
ref
==
1
,
"Got outstanding refcount %d.
\n
"
,
source
.
ref
);
ok
(
source_pin
.
ref
==
1
,
"Got outstanding refcount %d.
\n
"
,
source_pin
.
ref
);
ok
(
sink1
.
ref
==
1
,
"Got outstanding refcount %d.
\n
"
,
sink1
.
ref
);
ok
(
sink1_pin
.
ref
==
1
,
"Got outstanding refcount %d.
\n
"
,
sink1_pin
.
ref
);
ok
(
sink2
.
ref
==
1
,
"Got outstanding refcount %d.
\n
"
,
sink2
.
ref
);
ok
(
sink2_pin
.
ref
==
1
,
"Got outstanding refcount %d.
\n
"
,
sink2_pin
.
ref
);
ok
(
parser
.
ref
==
1
,
"Got outstanding refcount %d.
\n
"
,
parser
.
ref
);
ok
(
parser_pins
[
0
].
ref
==
1
,
"Got outstanding refcount %d.
\n
"
,
parser_pins
[
0
].
ref
);
ok
(
parser_pins
[
1
].
ref
==
1
,
"Got outstanding refcount %d.
\n
"
,
parser_pins
[
1
].
ref
);
}
}
typedef
struct
IUnknownImpl
typedef
struct
IUnknownImpl
...
@@ -2499,7 +1831,7 @@ START_TEST(filtergraph)
...
@@ -2499,7 +1831,7 @@ START_TEST(filtergraph)
test_render_run
(
mpegfile
);
test_render_run
(
mpegfile
);
test_enum_filters
();
test_enum_filters
();
test_graph_builder
();
test_graph_builder
();
test_
render_filter_priority
();
test_
graph_builder_render
();
test_aggregate_filter_graph
();
test_aggregate_filter_graph
();
test_control_delegation
();
test_control_delegation
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment