Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
ffmpeg
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
ffmpeg
Commits
2ce79727
Commit
2ce79727
authored
Apr 18, 2012
by
Nicolas George
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfiltergraph: add avfilter_graph_request_oldest().
Keep a heap of all sink links ordered by timestamps.
parent
e0761fee
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
158 additions
and
8 deletions
+158
-8
avfilter.c
libavfilter/avfilter.c
+13
-0
avfilter.h
libavfilter/avfilter.h
+17
-0
avfiltergraph.c
libavfilter/avfiltergraph.c
+99
-8
avfiltergraph.h
libavfilter/avfiltergraph.h
+24
-0
internal.h
libavfilter/internal.h
+5
-0
No files found.
libavfilter/avfilter.c
View file @
2ce79727
...
...
@@ -278,6 +278,8 @@ int avfilter_config_links(AVFilterContext *filter)
if
(
!
link
)
continue
;
link
->
current_pts
=
AV_NOPTS_VALUE
;
switch
(
link
->
init_state
)
{
case
AVLINK_INIT
:
continue
;
...
...
@@ -568,6 +570,15 @@ int avfilter_poll_frame(AVFilterLink *link)
return
min
;
}
static
void
update_link_current_pts
(
AVFilterLink
*
link
)
{
if
(
link
->
cur_buf
->
pts
==
AV_NOPTS_VALUE
)
return
;
link
->
current_pts
=
link
->
cur_buf
->
pts
;
/* TODO use duration */
if
(
link
->
graph
&&
link
->
age_index
>=
0
)
ff_avfilter_graph_update_heap
(
link
->
graph
,
link
);
}
/* XXX: should we do the duplicating of the picture ref here, instead of
* forcing the source filter to do it? */
void
avfilter_start_frame
(
AVFilterLink
*
link
,
AVFilterBufferRef
*
picref
)
...
...
@@ -608,6 +619,7 @@ void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
}
start_frame
(
link
,
link
->
cur_buf
);
update_link_current_pts
(
link
);
}
void
avfilter_end_frame
(
AVFilterLink
*
link
)
...
...
@@ -712,6 +724,7 @@ void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
link
->
cur_buf
=
samplesref
;
filter_samples
(
link
,
link
->
cur_buf
);
update_link_current_pts
(
link
);
}
#define MAX_REGISTERED_AVFILTERS_NB 128
...
...
libavfilter/avfilter.h
View file @
2ce79727
...
...
@@ -696,6 +696,23 @@ struct AVFilterLink {
*/
struct
AVFilterGraph
*
graph
;
/**
* Current timestamp of the link, as defined by the most recent
* frame(s), in AV_TIME_BASE units.
*/
int64_t
current_pts
;
/**
* Private fields
*
* The following fields are for internal use only.
* Their type, offset, number and semantic can change without notice.
*/
/**
* Index in the age array.
*/
int
age_index
;
};
/**
...
...
libavfilter/avfiltergraph.c
View file @
2ce79727
...
...
@@ -24,6 +24,7 @@
#include <string.h>
#include "libavutil/audioconvert.h"
#include "libavutil/avassert.h"
#include "libavutil/pixdesc.h"
#include "avfilter.h"
#include "avfiltergraph.h"
...
...
@@ -374,19 +375,46 @@ int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx)
return
0
;
}
static
void
ff_avfilter_graph_config_pointers
(
AVFilterGraph
*
graph
,
AVClass
*
log_ctx
)
static
int
ff_avfilter_graph_config_pointers
(
AVFilterGraph
*
graph
,
AVClass
*
log_ctx
)
{
unsigned
i
,
j
;;
unsigned
i
,
j
;
int
sink_links_count
=
0
,
n
=
0
;
AVFilterContext
*
f
;
AVFilterLink
**
sinks
;
for
(
i
=
0
;
i
<
graph
->
filter_count
;
i
++
)
{
f
=
graph
->
filters
[
i
];
for
(
j
=
0
;
j
<
f
->
input_count
;
j
++
)
f
->
inputs
[
j
]
->
graph
=
graph
;
for
(
j
=
0
;
j
<
f
->
output_count
;
j
++
)
f
->
outputs
[
j
]
->
graph
=
graph
;
for
(
j
=
0
;
j
<
f
->
input_count
;
j
++
)
{
f
->
inputs
[
j
]
->
graph
=
graph
;
f
->
inputs
[
j
]
->
age_index
=
-
1
;
}
for
(
j
=
0
;
j
<
f
->
output_count
;
j
++
)
{
f
->
outputs
[
j
]
->
graph
=
graph
;
f
->
outputs
[
j
]
->
age_index
=
-
1
;
}
if
(
!
f
->
output_count
)
{
if
(
f
->
input_count
>
INT_MAX
-
sink_links_count
)
return
AVERROR
(
EINVAL
);
sink_links_count
+=
f
->
input_count
;
}
}
sinks
=
av_calloc
(
sink_links_count
,
sizeof
(
*
sinks
));
if
(
!
sinks
)
return
AVERROR
(
ENOMEM
);
for
(
i
=
0
;
i
<
graph
->
filter_count
;
i
++
)
{
f
=
graph
->
filters
[
i
];
if
(
!
f
->
output_count
)
{
for
(
j
=
0
;
j
<
f
->
input_count
;
j
++
)
{
sinks
[
n
]
=
f
->
inputs
[
j
];
f
->
inputs
[
j
]
->
age_index
=
n
++
;
}
}
}
av_assert0
(
n
==
sink_links_count
);
graph
->
sink_links
=
sinks
;
graph
->
sink_links_count
=
sink_links_count
;
return
0
;
}
int
avfilter_graph_config
(
AVFilterGraph
*
graphctx
,
void
*
log_ctx
)
...
...
@@ -399,7 +427,8 @@ int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
return
ret
;
if
((
ret
=
ff_avfilter_graph_config_links
(
graphctx
,
log_ctx
)))
return
ret
;
ff_avfilter_graph_config_pointers
(
graphctx
,
log_ctx
);
if
((
ret
=
ff_avfilter_graph_config_pointers
(
graphctx
,
log_ctx
)))
return
ret
;
return
0
;
}
...
...
@@ -461,3 +490,65 @@ int avfilter_graph_queue_command(AVFilterGraph *graph, const char *target, const
return
0
;
}
static
void
heap_bubble_up
(
AVFilterGraph
*
graph
,
AVFilterLink
*
link
,
int
index
)
{
AVFilterLink
**
links
=
graph
->
sink_links
;
while
(
index
)
{
int
parent
=
(
index
-
1
)
>>
1
;
if
(
links
[
parent
]
->
current_pts
>=
link
->
current_pts
)
break
;
links
[
index
]
=
links
[
parent
];
links
[
index
]
->
age_index
=
index
;
index
=
parent
;
}
links
[
index
]
=
link
;
link
->
age_index
=
index
;
}
static
void
heap_bubble_down
(
AVFilterGraph
*
graph
,
AVFilterLink
*
link
,
int
index
)
{
AVFilterLink
**
links
=
graph
->
sink_links
;
while
(
1
)
{
int
child
=
2
*
index
+
1
;
if
(
child
>=
graph
->
sink_links_count
)
break
;
if
(
child
+
1
<
graph
->
sink_links_count
&&
links
[
child
+
1
]
->
current_pts
<
links
[
child
]
->
current_pts
)
child
++
;
if
(
link
->
current_pts
<
links
[
child
]
->
current_pts
)
break
;
links
[
index
]
=
links
[
child
];
links
[
index
]
->
age_index
=
index
;
index
=
child
;
}
links
[
index
]
=
link
;
link
->
age_index
=
index
;
}
void
ff_avfilter_graph_update_heap
(
AVFilterGraph
*
graph
,
AVFilterLink
*
link
)
{
heap_bubble_up
(
graph
,
link
,
link
->
age_index
);
heap_bubble_down
(
graph
,
link
,
link
->
age_index
);
}
int
avfilter_graph_request_oldest
(
AVFilterGraph
*
graph
)
{
while
(
graph
->
sink_links_count
)
{
AVFilterLink
*
oldest
=
graph
->
sink_links
[
0
];
int
r
=
avfilter_request_frame
(
oldest
);
if
(
r
!=
AVERROR_EOF
)
return
r
;
/* EOF: remove the link from the heap */
if
(
oldest
->
age_index
<
--
graph
->
sink_links_count
)
heap_bubble_down
(
graph
,
graph
->
sink_links
[
graph
->
sink_links_count
],
oldest
->
age_index
);
oldest
->
age_index
=
-
1
;
}
return
AVERROR_EOF
;
}
libavfilter/avfiltergraph.h
View file @
2ce79727
...
...
@@ -33,6 +33,16 @@ typedef struct AVFilterGraph {
AVFilterContext
**
filters
;
char
*
scale_sws_opts
;
///< sws options to use for the auto-inserted scale filters
/**
* Private fields
*
* The following fields are for internal use only.
* Their type, offset, number and semantic can change without notice.
*/
AVFilterLink
**
sink_links
;
int
sink_links_count
;
}
AVFilterGraph
;
/**
...
...
@@ -221,4 +231,18 @@ int avfilter_graph_queue_command(AVFilterGraph *graph, const char *target, const
*/
char
*
avfilter_graph_dump
(
AVFilterGraph
*
graph
,
const
char
*
options
);
/**
* Request a frame on the oldest sink link.
*
* If the request returns AVERROR_EOF, try the next.
*
* Note that this function is not meant to be the sole scheduling mechanism
* of a filtergraph, only a convenience function to help drain a filtergraph
* in a balanced way under normal circumstances.
*
* @return the return value of avfilter_request_frame,
* or AVERROR_EOF of all links returned AVERROR_EOF.
*/
int
avfilter_graph_request_oldest
(
AVFilterGraph
*
graph
);
#endif
/* AVFILTER_AVFILTERGRAPH_H */
libavfilter/internal.h
View file @
2ce79727
...
...
@@ -65,6 +65,11 @@ int ff_avfilter_graph_config_links(AVFilterGraph *graphctx, AVClass *log_ctx);
*/
int
ff_avfilter_graph_config_formats
(
AVFilterGraph
*
graphctx
,
AVClass
*
log_ctx
);
/**
* Update the position of a link in the age heap.
*/
void
ff_avfilter_graph_update_heap
(
AVFilterGraph
*
graph
,
AVFilterLink
*
link
);
/** default handler for freeing audio/video buffer when there are no references left */
void
ff_avfilter_default_free_buffer
(
AVFilterBuffer
*
buf
);
...
...
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