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
98a0c1da
Commit
98a0c1da
authored
Feb 19, 2020
by
Zebediah Figura
Committed by
Alexandre Julliard
Feb 20, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
quartz/filtergraph: Maintain a topologically sorted list of filters.
Signed-off-by:
Zebediah Figura
<
z.figura12@gmail.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
7a392c55
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
85 additions
and
2 deletions
+85
-2
filtergraph.c
dlls/quartz/filtergraph.c
+85
-2
No files found.
dlls/quartz/filtergraph.c
View file @
98a0c1da
...
...
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include <stdarg.h>
#define COBJMACROS
...
...
@@ -150,9 +151,10 @@ typedef struct _ITF_CACHE_ENTRY {
struct
filter
{
struct
list
entry
;
struct
list
entry
,
sorted_entry
;
IBaseFilter
*
filter
;
WCHAR
*
name
;
BOOL
sorting
;
};
typedef
struct
_IFilterGraphImpl
{
...
...
@@ -183,8 +185,18 @@ typedef struct _IFilterGraphImpl {
IUnknown
*
outer_unk
;
LONG
ref
;
IUnknown
*
punkFilterMapper2
;
struct
list
filters
;
/* We keep two lists of filters, one unsorted and one topologically sorted.
* The former is necessary for functions like IGraphBuilder::Connect() and
* IGraphBuilder::Render() that iterate through the filter list but may
* add to it while doing so; the latter is for functions like
* IMediaControl::Run() that should propagate messages to all filters
* (including unconnected ones) but must do so in topological order from
* sinks to sources. We can easily guarantee that the loop in Connect() will
* touch each filter exactly once so long as we aren't reordering it, but
* using the sorted filters list there would be hard. This seems to be the
* easiest and clearest solution. */
struct
list
filters
,
sorted_filters
;
unsigned
int
name_index
;
IReferenceClock
*
refClock
;
...
...
@@ -617,6 +629,8 @@ static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface,
IBaseFilter_AddRef
(
entry
->
filter
=
filter
);
list_add_head
(
&
graph
->
filters
,
&
entry
->
entry
);
list_add_head
(
&
graph
->
sorted_filters
,
&
entry
->
sorted_entry
);
entry
->
sorting
=
FALSE
;
++
graph
->
version
;
return
duplicate_name
?
VFW_S_DUPLICATE_NAME
:
hr
;
...
...
@@ -694,6 +708,7 @@ static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilte
IBaseFilter_SetSyncSource
(
pFilter
,
NULL
);
IBaseFilter_Release
(
pFilter
);
list_remove
(
&
entry
->
entry
);
list_remove
(
&
entry
->
sorted_entry
);
CoTaskMemFree
(
entry
->
name
);
heap_free
(
entry
);
This
->
version
++
;
...
...
@@ -818,6 +833,70 @@ out:
#endif
}
static
struct
filter
*
find_sorted_filter
(
IFilterGraphImpl
*
graph
,
IBaseFilter
*
iface
)
{
struct
filter
*
filter
;
LIST_FOR_EACH_ENTRY
(
filter
,
&
graph
->
sorted_filters
,
struct
filter
,
sorted_entry
)
{
if
(
filter
->
filter
==
iface
)
return
filter
;
}
return
NULL
;
}
static
void
sort_filter_recurse
(
IFilterGraphImpl
*
graph
,
struct
filter
*
filter
,
struct
list
*
sorted
)
{
struct
filter
*
peer_filter
;
IEnumPins
*
enumpins
;
PIN_DIRECTION
dir
;
IPin
*
pin
,
*
peer
;
PIN_INFO
info
;
TRACE
(
"Sorting filter %p.
\n
"
,
filter
->
filter
);
/* Cyclic connections should be caught by CheckCircularConnection(). */
assert
(
!
filter
->
sorting
);
filter
->
sorting
=
TRUE
;
IBaseFilter_EnumPins
(
filter
->
filter
,
&
enumpins
);
while
(
IEnumPins_Next
(
enumpins
,
1
,
&
pin
,
NULL
)
==
S_OK
)
{
IPin_QueryDirection
(
pin
,
&
dir
);
if
(
dir
==
PINDIR_INPUT
&&
IPin_ConnectedTo
(
pin
,
&
peer
)
==
S_OK
)
{
IPin_QueryPinInfo
(
peer
,
&
info
);
/* Note that the filter may have already been sorted. */
if
((
peer_filter
=
find_sorted_filter
(
graph
,
info
.
pFilter
)))
sort_filter_recurse
(
graph
,
peer_filter
,
sorted
);
IBaseFilter_Release
(
info
.
pFilter
);
IPin_Release
(
peer
);
}
IPin_Release
(
pin
);
}
IEnumPins_Release
(
enumpins
);
filter
->
sorting
=
FALSE
;
list_remove
(
&
filter
->
sorted_entry
);
list_add_head
(
sorted
,
&
filter
->
sorted_entry
);
}
static
void
sort_filters
(
IFilterGraphImpl
*
graph
)
{
struct
list
sorted
=
LIST_INIT
(
sorted
),
*
cursor
;
while
((
cursor
=
list_head
(
&
graph
->
sorted_filters
)))
{
struct
filter
*
filter
=
LIST_ENTRY
(
cursor
,
struct
filter
,
sorted_entry
);
sort_filter_recurse
(
graph
,
filter
,
&
sorted
);
}
list_move_tail
(
&
graph
->
sorted_filters
,
&
sorted
);
}
/* NOTE: despite the implication, it doesn't matter which
* way round you put in the input and output pins */
...
...
@@ -869,6 +948,9 @@ static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface, IPin *ppi
}
}
if
(
SUCCEEDED
(
hr
))
sort_filters
(
This
);
return
hr
;
}
...
...
@@ -5702,6 +5784,7 @@ static HRESULT filter_graph_common_create(IUnknown *outer, void **out, BOOL thre
fimpl
->
IGraphVersion_iface
.
lpVtbl
=
&
IGraphVersion_VTable
;
fimpl
->
ref
=
1
;
list_init
(
&
fimpl
->
filters
);
list_init
(
&
fimpl
->
sorted_filters
);
fimpl
->
name_index
=
1
;
fimpl
->
refClock
=
NULL
;
fimpl
->
hEventCompletion
=
CreateEventW
(
0
,
TRUE
,
FALSE
,
0
);
...
...
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