Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-2-2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-2-2
Commits
7d1bb639
Commit
7d1bb639
authored
Sep 26, 2009
by
Rémi Denis-Courmont
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use doubly linked list for filter chaining
parent
c568ac6e
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
117 additions
and
105 deletions
+117
-105
src/misc/filter_chain.c
src/misc/filter_chain.c
+117
-105
No files found.
src/misc/filter_chain.c
View file @
7d1bb639
...
...
@@ -26,9 +26,9 @@
#endif
#include <vlc_filter.h>
#include <vlc_arrays.h>
#include <vlc_osd.h>
#include <libvlc.h>
#include <assert.h>
typedef
struct
{
...
...
@@ -38,10 +38,27 @@ typedef struct
}
filter_chain_allocator_t
;
static
int
AllocatorInit
(
const
filter_chain_allocator_t
*
,
filter_t
*
);
static
void
AllocatorClean
(
const
filter_chain_allocator_t
*
,
filter_t
*
);
typedef
struct
chained_filter_t
{
/* Public part of the filter structure */
filter_t
filter
;
/* Private filter chain data (shhhh!) */
struct
chained_filter_t
*
prev
,
*
next
;
vlc_mouse_t
*
mouse
;
}
chained_filter_t
;
/* Only use this with filter objects from _this_ C module */
static
inline
chained_filter_t
*
chained
(
filter_t
*
filter
)
{
return
(
chained_filter_t
*
)
filter
;
}
static
bool
IsInternalVideoAllocator
(
filter_t
*
);
static
int
AllocatorInit
(
const
filter_chain_allocator_t
*
,
chained_filter_t
*
);
static
void
AllocatorClean
(
const
filter_chain_allocator_t
*
,
chained_filter_t
*
);
static
bool
IsInternalVideoAllocator
(
chained_filter_t
*
);
static
int
InternalVideoInit
(
filter_t
*
,
void
*
);
static
void
InternalVideoClean
(
filter_t
*
);
...
...
@@ -55,27 +72,16 @@ static const filter_chain_allocator_t internal_video_allocator = {
/* */
struct
filter_chain_t
{
/* Parent object */
vlc_object_t
*
p_this
;
/* List of filters */
vlc_array_t
filters
;
vlc_array_t
mouses
;
vlc_object_t
*
p_this
;
/**< Owner object */
filter_chain_allocator_t
allocator
;
/**< Owner allocation callbacks */
/* Capability of all the filters in the chain */
char
*
psz_capability
;
chained_filter_t
*
first
,
*
last
;
/**< List of filters */
/* Input format (read only) */
es_format_t
fmt_in
;
/* allow changing fmt_out if true */
bool
b_allow_fmt_out_change
;
/* Output format (writable depending on ... */
es_format_t
fmt_out
;
/* User provided allocator */
filter_chain_allocator_t
allocator
;
es_format_t
fmt_in
;
/**< Chain input format (constant) */
es_format_t
fmt_out
;
/**< Chain current output format */
unsigned
length
;
/**< Number of filters */
bool
b_allow_fmt_out_change
;
/**< Can the output format be changed? */
char
psz_capability
[
1
];
/**< Module capability for all chained filters */
};
/**
...
...
@@ -101,21 +107,19 @@ filter_chain_t *__filter_chain_New( vlc_object_t *p_this,
void
(
*
pf_buffer_allocation_clean
)(
filter_t
*
),
void
*
p_buffer_allocation_data
)
{
filter_chain_t
*
p_chain
=
malloc
(
sizeof
(
*
p_chain
)
);
assert
(
p_this
);
assert
(
psz_capability
);
size_t
size
=
sizeof
(
filter_chain_t
)
+
strlen
(
psz_capability
);
filter_chain_t
*
p_chain
=
malloc
(
size
);
if
(
!
p_chain
)
return
NULL
;
p_chain
->
p_this
=
p_this
;
vlc_array_init
(
&
p_chain
->
filters
);
vlc_array_init
(
&
p_chain
->
mouses
);
p_chain
->
psz_capability
=
strdup
(
psz_capability
);
if
(
!
p_chain
->
psz_capability
)
{
vlc_array_clear
(
&
p_chain
->
mouses
);
vlc_array_clear
(
&
p_chain
->
filters
);
free
(
p_chain
);
return
NULL
;
}
p_chain
->
last
=
p_chain
->
first
=
NULL
;
p_chain
->
length
=
0
;
strcpy
(
p_chain
->
psz_capability
,
psz_capability
);
es_format_Init
(
&
p_chain
->
fmt_in
,
UNKNOWN_ES
,
0
);
es_format_Init
(
&
p_chain
->
fmt_out
,
UNKNOWN_ES
,
0
);
p_chain
->
b_allow_fmt_out_change
=
b_allow_fmt_out_change
;
...
...
@@ -137,9 +141,6 @@ void filter_chain_Delete( filter_chain_t *p_chain )
es_format_Clean
(
&
p_chain
->
fmt_in
);
es_format_Clean
(
&
p_chain
->
fmt_out
);
free
(
p_chain
->
psz_capability
);
vlc_array_clear
(
&
p_chain
->
mouses
);
vlc_array_clear
(
&
p_chain
->
filters
);
free
(
p_chain
);
}
/**
...
...
@@ -148,12 +149,11 @@ void filter_chain_Delete( filter_chain_t *p_chain )
void
filter_chain_Reset
(
filter_chain_t
*
p_chain
,
const
es_format_t
*
p_fmt_in
,
const
es_format_t
*
p_fmt_out
)
{
while
(
vlc_array_count
(
&
p_chain
->
filters
)
>
0
)
{
filter_t
*
p_filter
=
vlc_array_item_at_index
(
&
p_chain
->
filters
,
0
);
filter_t
*
p_filter
;
while
(
(
p_filter
=
&
p_chain
->
first
->
filter
)
!=
NULL
)
filter_chain_DeleteFilterInternal
(
p_chain
,
p_filter
);
}
if
(
p_fmt_in
)
{
es_format_Clean
(
&
p_chain
->
fmt_in
);
...
...
@@ -203,7 +203,7 @@ int filter_chain_DeleteFilter( filter_chain_t *p_chain, filter_t *p_filter )
int
filter_chain_GetLength
(
filter_chain_t
*
p_chain
)
{
return
vlc_array_count
(
&
p_chain
->
filters
)
;
return
p_chain
->
length
;
}
const
es_format_t
*
filter_chain_GetFmtOut
(
filter_chain_t
*
p_chain
)
...
...
@@ -212,12 +212,8 @@ const es_format_t *filter_chain_GetFmtOut( filter_chain_t *p_chain )
if
(
p_chain
->
b_allow_fmt_out_change
)
return
&
p_chain
->
fmt_out
;
const
int
i_count
=
vlc_array_count
(
&
p_chain
->
filters
);
if
(
i_count
>
0
)
{
filter_t
*
p_last
=
vlc_array_item_at_index
(
&
p_chain
->
filters
,
i_count
-
1
);
return
&
p_last
->
fmt_out
;
}
if
(
p_chain
->
last
!=
NULL
)
return
&
p_chain
->
last
->
filter
.
fmt_out
;
/* Unless filter_chain_Reset has been called we are doomed */
return
&
p_chain
->
fmt_out
;
...
...
@@ -225,9 +221,9 @@ const es_format_t *filter_chain_GetFmtOut( filter_chain_t *p_chain )
picture_t
*
filter_chain_VideoFilter
(
filter_chain_t
*
p_chain
,
picture_t
*
p_pic
)
{
for
(
int
i
=
0
;
i
<
vlc_array_count
(
&
p_chain
->
filters
);
i
++
)
for
(
chained_filter_t
*
f
=
p_chain
->
first
;
f
!=
NULL
;
f
=
f
->
next
)
{
filter_t
*
p_filter
=
vlc_array_item_at_index
(
&
p_chain
->
filters
,
i
)
;
filter_t
*
p_filter
=
&
f
->
filter
;
p_pic
=
p_filter
->
pf_video_filter
(
p_filter
,
p_pic
);
if
(
!
p_pic
)
...
...
@@ -238,9 +234,9 @@ picture_t *filter_chain_VideoFilter( filter_chain_t *p_chain, picture_t *p_pic )
block_t
*
filter_chain_AudioFilter
(
filter_chain_t
*
p_chain
,
block_t
*
p_block
)
{
for
(
int
i
=
0
;
i
<
vlc_array_count
(
&
p_chain
->
filters
);
i
++
)
for
(
chained_filter_t
*
f
=
p_chain
->
first
;
f
!=
NULL
;
f
=
f
->
next
)
{
filter_t
*
p_filter
=
vlc_array_item_at_index
(
&
p_chain
->
filters
,
i
)
;
filter_t
*
p_filter
=
&
f
->
filter
;
p_block
=
p_filter
->
pf_audio_filter
(
p_filter
,
p_block
);
if
(
!
p_block
)
...
...
@@ -252,10 +248,9 @@ block_t *filter_chain_AudioFilter( filter_chain_t *p_chain, block_t *p_block )
void
filter_chain_SubFilter
(
filter_chain_t
*
p_chain
,
mtime_t
display_date
)
{
for
(
int
i
=
0
;
i
<
vlc_array_count
(
&
p_chain
->
filters
);
i
++
)
for
(
chained_filter_t
*
f
=
p_chain
->
first
;
f
!=
NULL
;
f
=
f
->
next
)
{
filter_t
*
p_filter
=
vlc_array_item_at_index
(
&
p_chain
->
filters
,
i
);
filter_t
*
p_filter
=
&
f
->
filter
;
subpicture_t
*
p_subpic
=
p_filter
->
pf_sub_filter
(
p_filter
,
display_date
);
/* XXX I find that spu_t cast ugly */
if
(
p_subpic
)
...
...
@@ -267,10 +262,10 @@ int filter_chain_MouseFilter( filter_chain_t *p_chain, vlc_mouse_t *p_dst, const
{
vlc_mouse_t
current
=
*
p_src
;
for
(
int
i
=
vlc_array_count
(
&
p_chain
->
filters
)
-
1
;
i
>=
0
;
i
--
)
for
(
chained_filter_t
*
f
=
p_chain
->
first
;
f
!=
NULL
;
f
=
f
->
next
)
{
filter_t
*
p_filter
=
vlc_array_item_at_index
(
&
p_chain
->
filters
,
i
)
;
vlc_mouse_t
*
p_mouse
=
vlc_array_item_at_index
(
&
p_chain
->
mouses
,
i
)
;
filter_t
*
p_filter
=
&
f
->
filter
;
vlc_mouse_t
*
p_mouse
=
f
->
mouse
;
if
(
p_filter
->
pf_mouse
&&
p_mouse
)
{
...
...
@@ -296,22 +291,20 @@ static filter_t *filter_chain_AppendFilterInternal( filter_chain_t *p_chain,
const
es_format_t
*
p_fmt_in
,
const
es_format_t
*
p_fmt_out
)
{
filter_t
*
p_filter
=
vlc_custom_create
(
p_chain
->
p_this
,
sizeof
(
*
p_filter
),
VLC_OBJECT_GENERIC
,
"filter"
);
chained_filter_t
*
p_chained
=
vlc_custom_create
(
p_chain
->
p_this
,
sizeof
(
*
p_chained
),
VLC_OBJECT_GENERIC
,
"filter"
);
filter_t
*
p_filter
=
&
p_chained
->
filter
;
if
(
!
p_filter
)
return
NULL
;
vlc_object_attach
(
p_filter
,
p_chain
->
p_this
);
if
(
!
p_fmt_in
)
{
p_fmt_in
=
&
p_chain
->
fmt_in
;
const
int
i_count
=
vlc_array_count
(
&
p_chain
->
filters
);
if
(
i_count
>
0
)
{
filter_t
*
p_last
=
vlc_array_item_at_index
(
&
p_chain
->
filters
,
i_count
-
1
);
p_fmt_in
=
&
p_last
->
fmt_out
;
}
if
(
p_chain
->
last
!=
NULL
)
p_fmt_in
=
&
p_chain
->
last
->
filter
.
fmt_out
;
else
p_fmt_in
=
&
p_chain
->
fmt_in
;
}
if
(
!
p_fmt_out
)
...
...
@@ -336,15 +329,25 @@ static filter_t *filter_chain_AppendFilterInternal( filter_chain_t *p_chain,
es_format_Copy
(
&
p_chain
->
fmt_out
,
&
p_filter
->
fmt_out
);
}
if
(
AllocatorInit
(
&
p_chain
->
allocator
,
p_
filter
)
)
if
(
AllocatorInit
(
&
p_chain
->
allocator
,
p_
chained
)
)
goto
error
;
vlc_array_append
(
&
p_chain
->
filters
,
p_filter
);
if
(
p_chain
->
last
==
NULL
)
{
assert
(
p_chain
->
first
==
NULL
);
p_chain
->
first
=
p_chained
;
}
else
p_chain
->
last
->
next
=
p_chained
;
p_chained
->
prev
=
p_chain
->
last
;
p_chain
->
last
=
p_chained
;
p_chained
->
next
=
NULL
;
p_chain
->
length
++
;
vlc_mouse_t
*
p_mouse
=
malloc
(
sizeof
(
*
p_mouse
)
);
if
(
p_mouse
)
vlc_mouse_Init
(
p_mouse
);
vlc_array_append
(
&
p_chain
->
mouses
,
p_mouse
)
;
p_chained
->
mouse
=
p_mouse
;
msg_Dbg
(
p_chain
->
p_this
,
"Filter '%s' (%p) appended to chain"
,
psz_name
?
psz_name
:
module_get_name
(
p_filter
->
p_module
,
false
),
...
...
@@ -407,36 +410,40 @@ static int filter_chain_AppendFromStringInternal( filter_chain_t *p_chain,
static
int
filter_chain_DeleteFilterInternal
(
filter_chain_t
*
p_chain
,
filter_t
*
p_filter
)
{
const
int
i_filter_idx
=
vlc_array_index_of_item
(
&
p_chain
->
filters
,
p_filter
);
if
(
i_filter_idx
<
0
)
chained_filter_t
*
p_chained
=
chained
(
p_filter
);
/* Remove it from the chain */
if
(
p_chained
->
prev
!=
NULL
)
p_chained
->
prev
->
next
=
p_chained
->
next
;
else
{
/* Oops, filter wasn't found
* FIXME shoulnd't it be an assert instead ? */
msg_Err
(
p_chain
->
p_this
,
"Couldn't find filter %p when trying to remove it from chain"
,
p_filter
);
return
VLC_EGENERIC
;
assert
(
p_chained
==
p_chain
->
first
);
p_chain
->
first
=
p_chained
->
next
;
}
/* Remove it from the chain */
vlc_array_remove
(
&
p_chain
->
filters
,
i_filter_idx
);
if
(
p_chained
->
next
!=
NULL
)
p_chained
->
next
->
prev
=
p_chained
->
prev
;
else
{
assert
(
p_chained
==
p_chain
->
last
);
p_chain
->
last
=
p_chained
->
prev
;
}
p_chain
->
length
--
;
msg_Dbg
(
p_chain
->
p_this
,
"Filter %p removed from chain"
,
p_filter
);
/* Destroy the filter object */
if
(
IsInternalVideoAllocator
(
p_
filter
)
)
AllocatorClean
(
&
internal_video_allocator
,
p_
filter
);
if
(
IsInternalVideoAllocator
(
p_
chained
)
)
AllocatorClean
(
&
internal_video_allocator
,
p_
chained
);
else
AllocatorClean
(
&
p_chain
->
allocator
,
p_
filter
);
AllocatorClean
(
&
p_chain
->
allocator
,
p_
chained
);
vlc_object_detach
(
p_filter
);
if
(
p_filter
->
p_module
)
module_unneed
(
p_filter
,
p_filter
->
p_module
);
free
(
p_chained
->
mouse
);
vlc_object_release
(
p_filter
);
vlc_mouse_t
*
p_mouse
=
vlc_array_item_at_index
(
&
p_chain
->
mouses
,
i_filter_idx
);
free
(
p_mouse
);
vlc_array_remove
(
&
p_chain
->
mouses
,
i_filter_idx
);
/* FIXME: check fmt_in/fmt_out consitency */
return
VLC_SUCCESS
;
...
...
@@ -455,31 +462,32 @@ static int UpdateVideoBufferFunctions( filter_chain_t *p_chain )
* filter without having to worry about the parent's picture
* heap format.
*/
const
int
i_count
=
vlc_array_count
(
&
p_chain
->
filters
);
for
(
int
i
=
0
;
i
<
i_count
-
1
;
i
++
)
{
filter_t
*
p_filter
=
vlc_array_item_at_index
(
&
p_chain
->
filters
,
i
);
/* FIXME: we should only update the last and penultimate filters */
chained_filter_t
*
f
;
if
(
!
IsInternalVideoAllocator
(
p_filter
)
)
for
(
f
=
p_chain
->
first
;
f
!=
p_chain
->
last
;
f
=
f
->
next
)
{
if
(
!
IsInternalVideoAllocator
(
f
)
)
{
AllocatorClean
(
&
p_chain
->
allocator
,
p_filter
);
AllocatorClean
(
&
p_chain
->
allocator
,
f
);
AllocatorInit
(
&
internal_video_allocator
,
p_filter
);
AllocatorInit
(
&
internal_video_allocator
,
f
);
}
}
if
(
i_count
>=
1
)
if
(
f
!=
NULL
)
{
filter_t
*
p_filter
=
vlc_array_item_at_index
(
&
p_chain
->
filters
,
i_count
-
1
);
if
(
IsInternalVideoAllocator
(
p_filter
)
)
if
(
IsInternalVideoAllocator
(
f
)
)
{
AllocatorClean
(
&
internal_video_allocator
,
p_filter
);
AllocatorClean
(
&
internal_video_allocator
,
f
);
if
(
AllocatorInit
(
&
p_chain
->
allocator
,
p_filter
)
)
if
(
AllocatorInit
(
&
p_chain
->
allocator
,
f
)
)
return
VLC_EGENERIC
;
}
}
return
VLC_SUCCESS
;
}
/**
* This function should be called after every filter chain change
*/
...
...
@@ -522,21 +530,25 @@ static void InternalVideoClean( filter_t *p_filter )
p_filter
->
pf_vout_buffer_new
=
NULL
;
p_filter
->
pf_vout_buffer_del
=
NULL
;
}
static
bool
IsInternalVideoAllocator
(
filter_t
*
p_filter
)
static
bool
IsInternalVideoAllocator
(
chained_filter_t
*
p_filter
)
{
return
p_filter
->
pf_vout_buffer_new
==
VideoBufferNew
;
return
p_filter
->
filter
.
pf_vout_buffer_new
==
VideoBufferNew
;
}
/* */
static
int
AllocatorInit
(
const
filter_chain_allocator_t
*
p_alloc
,
filter_t
*
p_filter
)
static
int
AllocatorInit
(
const
filter_chain_allocator_t
*
p_alloc
,
chained_filter_t
*
p_filter
)
{
if
(
p_alloc
->
pf_init
)
return
p_alloc
->
pf_init
(
p_
filter
,
p_alloc
->
p_data
);
return
p_alloc
->
pf_init
(
&
p_filter
->
filter
,
p_alloc
->
p_data
);
return
VLC_SUCCESS
;
}
static
void
AllocatorClean
(
const
filter_chain_allocator_t
*
p_alloc
,
filter_t
*
p_filter
)
static
void
AllocatorClean
(
const
filter_chain_allocator_t
*
p_alloc
,
chained_filter_t
*
p_filter
)
{
if
(
p_alloc
->
pf_clean
)
p_alloc
->
pf_clean
(
p_
filter
);
p_alloc
->
pf_clean
(
&
p_filter
->
filter
);
}
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