Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
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
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
740c9952
Commit
740c9952
authored
Aug 13, 2012
by
Stefano Sabatini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavfi: add asendcmd and sendcmd filters
parent
7fe1ecef
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
715 additions
and
2 deletions
+715
-2
Changelog
Changelog
+1
-0
filters.texi
doc/filters.texi
+131
-0
Makefile
libavfilter/Makefile
+2
-0
allfilters.c
libavfilter/allfilters.c
+2
-0
f_sendcmd.c
libavfilter/f_sendcmd.c
+577
-0
version.h
libavfilter/version.h
+2
-2
No files found.
Changelog
View file @
740c9952
...
...
@@ -62,6 +62,7 @@ version next:
- RTP depacketization of JPEG
- Smooth Streaming live segmenter muxer
- F4V muxer
- sendcmd and asendcmd filters
version 0.11:
...
...
doc/filters.texi
View file @
740c9952
...
...
@@ -4248,6 +4248,137 @@ tools.
Below is a description of the currently available multimedia filters.
@section asendcmd, sendcmd
Send commands to filters in the filtergraph.
These filters read commands to be sent to other filters in the
filtergraph.
@code{asendcmd} must be inserted between two audio filters,
@code{sendcmd} must be inserted between two video filters, but apart
from that they act the same way.
The specification of commands can be provided in the filter arguments
with the @var{commands} option, or in a file specified by the
@var{filename} option.
These filters accept the following options:
@table @option
@item commands, c
Set the commands to be read and sent to the other filters.
@item filename, f
Set the filename of the commands to be read and sent to the other
filters.
@end table
@subsection Commands syntax
A commands description consists of a sequence of interval
specifications, comprising a list of commands to be executed when a
particular event related to that interval occurs. The occurring event
is typically the current frame time entering or leaving a given time
interval.
An interval is specified by the following syntax:
@example
@var{START}[-@var{END}] @var{COMMANDS};
@end example
The time interval is specified by the @var{START} and @var{END} times.
@var{END} is optional and defaults to the maximum time.
The current frame time is considered within the specified interval if
it is included in the interval [@var{START}, @var{END}), that is when
the time is greater or equal to @var{START} and is lesser than
@var{END}.
@var{COMMANDS} consists of a sequence of one or more command
specifications, separated by ",", relating to that interval. The
syntax of a command specification is given by:
@example
[@var{FLAGS}] @var{TARGET} @var{COMMAND} @var{ARG}
@end example
@var{FLAGS} is optional and specifies the type of events relating to
the time interval which enable sending the specified command, and must
be a non-null sequence of identifier flags separated by "+" or "|" and
enclosed between "[" and "]".
The following flags are recognized:
@table @option
@item enter
The command is sent when the current frame timestamp enters the
specified interval. In other words, the command is sent when the
previous frame timestamp was not in the given interval, and the
current is.
@item leave
The command is sent when the current frame timestamp leaves the
specified interval. In other words, the command is sent when the
previous frame timestamp was in the given interval, and the
current is not.
@end table
If @var{FLAGS} is not specified, a default value of @code{[enter]} is
assumed.
@var{TARGET} specifies the target of the command, usually the name of
the filter class or a specific filter instance name.
@var{COMMAND} specifies the name of the command for the target filter.
@var{ARG} is optional and specifies the optional list of argument for
the given @var{COMMAND}.
Between one interval specification and another, whitespaces, or
sequences of characters starting with @code{#} until the end of line,
are ignored and can be used to annotate comments.
A simplified BNF description of the commands specification syntax
follows:
@example
@var{COMMAND_FLAG} ::= "enter" | "leave"
@var{COMMAND_FLAGS} ::= @var{COMMAND_FLAG} [(+|"|")@var{COMMAND_FLAG}]
@var{COMMAND} ::= ["[" @var{COMMAND_FLAGS} "]"] @var{TARGET} @var{COMMAND} [@var{ARG}]
@var{COMMANDS} ::= @var{COMMAND} [,@var{COMMANDS}]
@var{INTERVAL} ::= @var{START}[-@var{END}] @var{COMMANDS}
@var{INTERVALS} ::= @var{INTERVAL}[;@var{INTERVALS}]
@end example
@subsection Examples
@itemize
@item
Specify audio tempo change at second 4:
@example
asendcmd=c='4.0 atempo tempo 1.5',atempo
@end example
@item
Specify a list of drawtext and hue commands in a file.
@example
# show text in the interval 5-10
5.0-10.0 [enter] drawtext reinit 'fontfile=FreeSerif.ttf:text=hello world',
[leave] drawtext reinit 'fontfile=FreeSerif.ttf:text=';
# desaturate the image in the interval 15-20
15.0-20.0 [enter] hue reinit s=0,
[enter] drawtext reinit 'fontfile=FreeSerif.ttf:text=nocolor',
[leave] hue reinit s=1,
[leave] drawtext reinit 'fontfile=FreeSerif.ttf:text=color';
# apply an exponential saturation fade-out effect, starting from time 25
25 [enter] hue s=exp(t-25)
@end example
A filtergraph allowing to read and process the above command list
stored in a file @file{test.cmd}, can be specified with:
@example
sendcmd=f=test.cmd,drawtext=fontfile=FreeSerif.ttf:text='',hue
@end example
@end itemize
@section asetpts, setpts
Change the PTS (presentation timestamp) of the input frames.
...
...
libavfilter/Makefile
View file @
740c9952
...
...
@@ -53,6 +53,7 @@ OBJS-$(CONFIG_AMERGE_FILTER) += af_amerge.o
OBJS-$(CONFIG_AMIX_FILTER)
+=
af_amix.o
OBJS-$(CONFIG_ANULL_FILTER)
+=
af_anull.o
OBJS-$(CONFIG_ARESAMPLE_FILTER)
+=
af_aresample.o
OBJS-$(CONFIG_ASENDCMD_FILTER)
+=
f_sendcmd.o
OBJS-$(CONFIG_ASETNSAMPLES_FILTER)
+=
af_asetnsamples.o
OBJS-$(CONFIG_ASETPTS_FILTER)
+=
f_setpts.o
OBJS-$(CONFIG_ASETTB_FILTER)
+=
f_settb.o
...
...
@@ -122,6 +123,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o
OBJS-$(CONFIG_REMOVELOGO_FILTER)
+=
bbox.o
lswsutils.o
lavfutils.o
vf_removelogo.o
OBJS-$(CONFIG_SCALE_FILTER)
+=
vf_scale.o
OBJS-$(CONFIG_SELECT_FILTER)
+=
vf_select.o
OBJS-$(CONFIG_SENDCMD_FILTER)
+=
f_sendcmd.o
OBJS-$(CONFIG_SETDAR_FILTER)
+=
vf_aspect.o
OBJS-$(CONFIG_SETFIELD_FILTER)
+=
vf_setfield.o
OBJS-$(CONFIG_SETPTS_FILTER)
+=
f_setpts.o
...
...
libavfilter/allfilters.c
View file @
740c9952
...
...
@@ -42,6 +42,7 @@ void avfilter_register_all(void)
REGISTER_FILTER
(
AMIX
,
amix
,
af
);
REGISTER_FILTER
(
ANULL
,
anull
,
af
);
REGISTER_FILTER
(
ARESAMPLE
,
aresample
,
af
);
REGISTER_FILTER
(
ASENDCMD
,
asendcmd
,
af
);
REGISTER_FILTER
(
ASETNSAMPLES
,
asetnsamples
,
af
);
REGISTER_FILTER
(
ASETPTS
,
asetpts
,
af
);
REGISTER_FILTER
(
ASETTB
,
asettb
,
af
);
...
...
@@ -113,6 +114,7 @@ void avfilter_register_all(void)
REGISTER_FILTER
(
REMOVELOGO
,
removelogo
,
vf
);
REGISTER_FILTER
(
SCALE
,
scale
,
vf
);
REGISTER_FILTER
(
SELECT
,
select
,
vf
);
REGISTER_FILTER
(
SENDCMD
,
sendcmd
,
vf
);
REGISTER_FILTER
(
SETDAR
,
setdar
,
vf
);
REGISTER_FILTER
(
SETFIELD
,
setfield
,
vf
);
REGISTER_FILTER
(
SETPTS
,
setpts
,
vf
);
...
...
libavfilter/f_sendcmd.c
0 → 100644
View file @
740c9952
/*
* Copyright (c) 2012 Stefano Sabatini
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* send commands filter
*/
#include "libavutil/avstring.h"
#include "libavutil/bprint.h"
#include "libavutil/file.h"
#include "libavutil/opt.h"
#include "libavutil/parseutils.h"
#include "avfilter.h"
#include "internal.h"
#include "avfiltergraph.h"
#include "audio.h"
#include "video.h"
#define COMMAND_FLAG_ENTER 1
#define COMMAND_FLAG_LEAVE 2
static
inline
char
*
make_command_flags_str
(
AVBPrint
*
pbuf
,
int
flags
)
{
const
char
*
flag_strings
[]
=
{
"enter"
,
"leave"
};
int
i
,
is_first
=
1
;
av_bprint_init
(
pbuf
,
0
,
AV_BPRINT_SIZE_AUTOMATIC
);
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
flag_strings
);
i
++
)
{
if
(
flags
&
1
<<
i
)
{
if
(
!
is_first
)
av_bprint_chars
(
pbuf
,
'+'
,
1
);
av_bprintf
(
pbuf
,
"%s"
,
flag_strings
[
i
]);
is_first
=
0
;
}
}
return
pbuf
->
str
;
}
typedef
struct
{
int
flags
;
char
*
target
,
*
command
,
*
arg
;
int
index
;
}
Command
;
typedef
struct
{
int64_t
start_ts
;
///< start timestamp expressed as microseconds units
int64_t
end_ts
;
///< end timestamp expressed as microseconds units
int
index
;
///< unique index for these interval commands
Command
*
commands
;
int
nb_commands
;
int
enabled
;
///< current time detected inside this interval
}
Interval
;
typedef
struct
{
const
AVClass
*
class
;
Interval
*
intervals
;
int
nb_intervals
;
char
*
commands_filename
;
char
*
commands_str
;
}
SendCmdContext
;
#define OFFSET(x) offsetof(SendCmdContext, x)
static
const
AVOption
sendcmd_options
[]
=
{
{
"commands"
,
"set commands"
,
OFFSET
(
commands_str
),
AV_OPT_TYPE_STRING
,
{.
str
=
NULL
},
0
,
0
},
{
"c"
,
"set commands"
,
OFFSET
(
commands_str
),
AV_OPT_TYPE_STRING
,
{.
str
=
NULL
},
0
,
0
},
{
"filename"
,
"set commands file"
,
OFFSET
(
commands_filename
),
AV_OPT_TYPE_STRING
,
{.
str
=
NULL
},
0
,
0
},
{
"f"
,
"set commands file"
,
OFFSET
(
commands_filename
),
AV_OPT_TYPE_STRING
,
{.
str
=
NULL
},
0
,
0
},
{
NULL
},
};
AVFILTER_DEFINE_CLASS
(
sendcmd
);
#define SPACES " \f\t\n\r"
static
void
skip_comments
(
const
char
**
buf
)
{
while
(
**
buf
)
{
/* skip leading spaces */
*
buf
+=
strspn
(
*
buf
,
SPACES
);
if
(
**
buf
!=
'#'
)
break
;
(
*
buf
)
++
;
/* skip comment until the end of line */
*
buf
+=
strcspn
(
*
buf
,
"
\n
"
);
if
(
**
buf
)
(
*
buf
)
++
;
}
}
#define COMMAND_DELIMS " \f\t\n\r,;"
static
int
parse_command
(
Command
*
cmd
,
int
cmd_count
,
int
interval_count
,
const
char
**
buf
,
void
*
log_ctx
)
{
int
ret
;
memset
(
cmd
,
0
,
sizeof
(
Command
));
cmd
->
index
=
cmd_count
;
/* format: [FLAGS] target command arg */
*
buf
+=
strspn
(
*
buf
,
SPACES
);
/* parse flags */
if
(
**
buf
==
'['
)
{
(
*
buf
)
++
;
/* skip "[" */
while
(
**
buf
)
{
int
len
=
strcspn
(
*
buf
,
"|+]"
);
if
(
!
strncmp
(
*
buf
,
"enter"
,
strlen
(
"enter"
)))
cmd
->
flags
|=
COMMAND_FLAG_ENTER
;
else
if
(
!
strncmp
(
*
buf
,
"leave"
,
strlen
(
"leave"
)))
cmd
->
flags
|=
COMMAND_FLAG_LEAVE
;
else
{
char
flag_buf
[
64
];
av_strlcpy
(
flag_buf
,
*
buf
,
sizeof
(
flag_buf
));
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"Unknown flag '%s' in in interval #%d, command #%d
\n
"
,
flag_buf
,
interval_count
,
cmd_count
);
return
AVERROR
(
EINVAL
);
}
*
buf
+=
len
;
if
(
**
buf
==
']'
)
break
;
if
(
!
strspn
(
*
buf
,
"+|"
))
{
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"Invalid flags char '%c' in interval #%d, command #%d
\n
"
,
**
buf
,
interval_count
,
cmd_count
);
return
AVERROR
(
EINVAL
);
}
if
(
**
buf
)
(
*
buf
)
++
;
}
if
(
**
buf
!=
']'
)
{
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"Missing flag terminator or extraneous data found at the end of flags "
"in interval #%d, command #%d
\n
"
,
interval_count
,
cmd_count
);
return
AVERROR
(
EINVAL
);
}
(
*
buf
)
++
;
/* skip "]" */
}
else
{
cmd
->
flags
=
COMMAND_FLAG_ENTER
;
}
*
buf
+=
strspn
(
*
buf
,
SPACES
);
cmd
->
target
=
av_get_token
(
buf
,
COMMAND_DELIMS
);
if
(
!
cmd
->
target
||
!
cmd
->
target
[
0
])
{
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"No target specified in in interval #%d, command #%d
\n
"
,
interval_count
,
cmd_count
);
ret
=
AVERROR
(
EINVAL
);
goto
fail
;
}
*
buf
+=
strspn
(
*
buf
,
SPACES
);
cmd
->
command
=
av_get_token
(
buf
,
COMMAND_DELIMS
);
if
(
!
cmd
->
command
||
!
cmd
->
command
[
0
])
{
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"No command specified in in interval #%d, command #%d
\n
"
,
interval_count
,
cmd_count
);
ret
=
AVERROR
(
EINVAL
);
goto
fail
;
}
*
buf
+=
strspn
(
*
buf
,
SPACES
);
cmd
->
arg
=
av_get_token
(
buf
,
COMMAND_DELIMS
);
return
1
;
fail:
av_freep
(
&
cmd
->
target
);
av_freep
(
&
cmd
->
command
);
av_freep
(
&
cmd
->
arg
);
return
ret
;
}
static
int
parse_commands
(
Command
**
cmds
,
int
*
nb_cmds
,
int
interval_count
,
const
char
**
buf
,
void
*
log_ctx
)
{
int
cmd_count
=
0
;
int
ret
,
n
=
0
;
AVBPrint
pbuf
;
*
cmds
=
NULL
;
*
nb_cmds
=
0
;
while
(
**
buf
)
{
Command
cmd
;
if
((
ret
=
parse_command
(
&
cmd
,
cmd_count
,
interval_count
,
buf
,
log_ctx
))
<
0
)
return
ret
;
cmd_count
++
;
/* (re)allocate commands array if required */
if
(
*
nb_cmds
==
n
)
{
n
=
FFMAX
(
16
,
2
*
n
);
/* first allocation = 16, or double the number */
*
cmds
=
av_realloc_f
(
*
cmds
,
n
,
2
*
sizeof
(
Command
));
if
(
!*
cmds
)
{
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"Could not (re)allocate command array
\n
"
);
return
AVERROR
(
ENOMEM
);
}
}
(
*
cmds
)[(
*
nb_cmds
)
++
]
=
cmd
;
*
buf
+=
strspn
(
*
buf
,
SPACES
);
if
(
**
buf
&&
**
buf
!=
';'
&&
**
buf
!=
','
)
{
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"Missing separator or extraneous data found at the end of "
"interval #%d, in command #%d
\n
"
,
interval_count
,
cmd_count
);
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"Command was parsed as: flags:[%s] target:%s command:%s arg:%s
\n
"
,
make_command_flags_str
(
&
pbuf
,
cmd
.
flags
),
cmd
.
target
,
cmd
.
command
,
cmd
.
arg
);
return
AVERROR
(
EINVAL
);
}
if
(
**
buf
==
';'
)
break
;
if
(
**
buf
==
','
)
(
*
buf
)
++
;
}
return
0
;
}
#define DELIMS " \f\t\n\r,;"
static
int
parse_interval
(
Interval
*
interval
,
int
interval_count
,
const
char
**
buf
,
void
*
log_ctx
)
{
char
*
intervalstr
;
int
ret
;
*
buf
+=
strspn
(
*
buf
,
SPACES
);
if
(
!**
buf
)
return
0
;
/* reset data */
memset
(
interval
,
0
,
sizeof
(
Interval
));
interval
->
index
=
interval_count
;
/* format: INTERVAL COMMANDS */
/* parse interval */
intervalstr
=
av_get_token
(
buf
,
DELIMS
);
if
(
intervalstr
&&
intervalstr
[
0
])
{
char
*
start
,
*
end
;
start
=
av_strtok
(
intervalstr
,
"-"
,
&
end
);
if
((
ret
=
av_parse_time
(
&
interval
->
start_ts
,
start
,
1
))
<
0
)
{
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"Invalid start time specification '%s' in interval #%d
\n
"
,
start
,
interval_count
);
goto
end
;
}
if
(
end
)
{
if
((
ret
=
av_parse_time
(
&
interval
->
end_ts
,
end
,
1
))
<
0
)
{
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"Invalid end time specification '%s' in interval #%d
\n
"
,
end
,
interval_count
);
goto
end
;
}
}
else
{
interval
->
end_ts
=
INT64_MAX
;
}
if
(
interval
->
end_ts
<
interval
->
start_ts
)
{
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"Invalid end time '%s' in interval #%d: "
"cannot be lesser than start time '%s'
\n
"
,
end
,
interval_count
,
start
);
ret
=
AVERROR
(
EINVAL
);
goto
end
;
}
}
else
{
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"No interval specified for interval #%d
\n
"
,
interval_count
);
ret
=
AVERROR
(
EINVAL
);
goto
end
;
}
/* parse commands */
ret
=
parse_commands
(
&
interval
->
commands
,
&
interval
->
nb_commands
,
interval_count
,
buf
,
log_ctx
);
end:
av_free
(
intervalstr
);
return
ret
;
}
static
int
parse_intervals
(
Interval
**
intervals
,
int
*
nb_intervals
,
const
char
*
buf
,
void
*
log_ctx
)
{
int
interval_count
=
0
;
int
ret
,
n
=
0
;
*
intervals
=
NULL
;
*
nb_intervals
=
0
;
while
(
1
)
{
Interval
interval
;
skip_comments
(
&
buf
);
if
(
!
(
*
buf
))
break
;
if
((
ret
=
parse_interval
(
&
interval
,
interval_count
,
&
buf
,
log_ctx
))
<
0
)
return
ret
;
buf
+=
strspn
(
buf
,
SPACES
);
if
(
*
buf
)
{
if
(
*
buf
!=
';'
)
{
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"Missing terminator or extraneous data found at the end of interval #%d
\n
"
,
interval_count
);
return
AVERROR
(
EINVAL
);
}
buf
++
;
/* skip ';' */
}
interval_count
++
;
/* (re)allocate commands array if required */
if
(
*
nb_intervals
==
n
)
{
n
=
FFMAX
(
16
,
2
*
n
);
/* first allocation = 16, or double the number */
*
intervals
=
av_realloc_f
(
*
intervals
,
n
,
2
*
sizeof
(
Interval
));
if
(
!*
intervals
)
{
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"Could not (re)allocate intervals array
\n
"
);
return
AVERROR
(
ENOMEM
);
}
}
(
*
intervals
)[(
*
nb_intervals
)
++
]
=
interval
;
}
return
0
;
}
static
int
cmp_intervals
(
const
void
*
a
,
const
void
*
b
)
{
const
Interval
*
i1
=
a
;
const
Interval
*
i2
=
b
;
int64_t
ts_diff
=
i1
->
start_ts
-
i2
->
start_ts
;
int
ret
;
ret
=
ts_diff
>
0
?
1
:
ts_diff
<
0
?
-
1
:
0
;
return
ret
==
0
?
i1
->
index
-
i2
->
index
:
ret
;
}
static
av_cold
int
init
(
AVFilterContext
*
ctx
,
const
char
*
args
)
{
SendCmdContext
*
sendcmd
=
ctx
->
priv
;
int
ret
,
i
,
j
;
char
*
buf
;
sendcmd
->
class
=
&
sendcmd_class
;
av_opt_set_defaults
(
sendcmd
);
if
((
ret
=
av_set_options_string
(
sendcmd
,
args
,
"="
,
":"
))
<
0
)
return
ret
;
if
(
sendcmd
->
commands_filename
&&
sendcmd
->
commands_str
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Only one of the filename or commands options must be specified
\n
"
);
return
AVERROR
(
EINVAL
);
}
if
(
sendcmd
->
commands_filename
)
{
uint8_t
*
file_buf
;
size_t
file_bufsize
;
ret
=
av_file_map
(
sendcmd
->
commands_filename
,
&
file_buf
,
&
file_bufsize
,
0
,
ctx
);
if
(
ret
<
0
)
return
ret
;
/* create a 0-terminated string based on the read file */
buf
=
av_malloc
(
file_bufsize
+
1
);
if
(
!
buf
)
return
AVERROR
(
ENOMEM
);
memcpy
(
buf
,
file_buf
,
file_bufsize
);
buf
[
file_bufsize
]
=
0
;
av_file_unmap
(
file_buf
,
file_bufsize
);
sendcmd
->
commands_str
=
buf
;
}
if
((
ret
=
parse_intervals
(
&
sendcmd
->
intervals
,
&
sendcmd
->
nb_intervals
,
sendcmd
->
commands_str
,
ctx
))
<
0
)
return
ret
;
qsort
(
sendcmd
->
intervals
,
sendcmd
->
nb_intervals
,
sizeof
(
Interval
),
cmp_intervals
);
av_log
(
ctx
,
AV_LOG_DEBUG
,
"Parsed commands:
\n
"
);
for
(
i
=
0
;
i
<
sendcmd
->
nb_intervals
;
i
++
)
{
AVBPrint
pbuf
;
Interval
*
interval
=
&
sendcmd
->
intervals
[
i
];
av_log
(
ctx
,
AV_LOG_VERBOSE
,
"start_time:%f end_time:%f index:%d
\n
"
,
(
double
)
interval
->
start_ts
/
1000000
,
(
double
)
interval
->
end_ts
/
1000000
,
interval
->
index
);
for
(
j
=
0
;
j
<
interval
->
nb_commands
;
j
++
)
{
Command
*
cmd
=
&
interval
->
commands
[
j
];
av_log
(
ctx
,
AV_LOG_VERBOSE
,
" [%s] target:%s command:%s arg:%s index:%d
\n
"
,
make_command_flags_str
(
&
pbuf
,
cmd
->
flags
),
cmd
->
target
,
cmd
->
command
,
cmd
->
arg
,
cmd
->
index
);
}
}
return
0
;
}
static
void
av_cold
uninit
(
AVFilterContext
*
ctx
)
{
SendCmdContext
*
sendcmd
=
ctx
->
priv
;
int
i
,
j
;
av_opt_free
(
sendcmd
);
for
(
i
=
0
;
i
<
sendcmd
->
nb_intervals
;
i
++
)
{
Interval
*
interval
=
&
sendcmd
->
intervals
[
i
];
for
(
j
=
0
;
j
<
interval
->
nb_commands
;
j
++
)
{
Command
*
cmd
=
&
interval
->
commands
[
j
];
av_free
(
cmd
->
target
);
av_free
(
cmd
->
command
);
av_free
(
cmd
->
arg
);
}
av_free
(
interval
->
commands
);
}
av_freep
(
&
sendcmd
->
intervals
);
}
static
int
process_frame
(
AVFilterLink
*
inlink
,
AVFilterBufferRef
*
ref
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
SendCmdContext
*
sendcmd
=
ctx
->
priv
;
int64_t
ts
;
int
i
,
j
,
ret
;
if
(
ref
->
pts
==
AV_NOPTS_VALUE
)
goto
end
;
ts
=
av_rescale_q
(
ref
->
pts
,
inlink
->
time_base
,
AV_TIME_BASE_Q
);
#define WITHIN_INTERVAL(ts, start_ts, end_ts) ((ts) >= (start_ts) && (ts) < (end_ts))
for
(
i
=
0
;
i
<
sendcmd
->
nb_intervals
;
i
++
)
{
Interval
*
interval
=
&
sendcmd
->
intervals
[
i
];
int
flags
=
0
;
if
(
!
interval
->
enabled
&&
WITHIN_INTERVAL
(
ts
,
interval
->
start_ts
,
interval
->
end_ts
))
{
flags
+=
COMMAND_FLAG_ENTER
;
interval
->
enabled
=
1
;
}
if
(
interval
->
enabled
&&
!
WITHIN_INTERVAL
(
ts
,
interval
->
start_ts
,
interval
->
end_ts
))
{
flags
+=
COMMAND_FLAG_LEAVE
;
interval
->
enabled
=
0
;
}
if
(
flags
)
{
AVBPrint
pbuf
;
av_log
(
ctx
,
AV_LOG_VERBOSE
,
"[%s] interval #%d start_ts:%f end_ts:%f ts:%f
\n
"
,
make_command_flags_str
(
&
pbuf
,
flags
),
interval
->
index
,
(
double
)
interval
->
start_ts
/
1000000
,
(
double
)
interval
->
end_ts
/
1000000
,
(
double
)
ts
/
1000000
);
for
(
j
=
0
;
flags
&&
j
<
interval
->
nb_commands
;
j
++
)
{
Command
*
cmd
=
&
interval
->
commands
[
j
];
char
buf
[
1024
];
if
(
cmd
->
flags
&
flags
)
{
av_log
(
ctx
,
AV_LOG_VERBOSE
,
"Processing command #%d target:%s command:%s arg:%s
\n
"
,
cmd
->
index
,
cmd
->
target
,
cmd
->
command
,
cmd
->
arg
);
ret
=
avfilter_graph_send_command
(
inlink
->
graph
,
cmd
->
target
,
cmd
->
command
,
cmd
->
arg
,
buf
,
sizeof
(
buf
),
AVFILTER_CMD_FLAG_ONE
);
av_log
(
ctx
,
AV_LOG_VERBOSE
,
"Command reply for command #%d: ret:%s res:%s
\n
"
,
cmd
->
index
,
av_err2str
(
ret
),
buf
);
}
}
}
}
end:
/* give the reference away, do not store in cur_buf */
inlink
->
cur_buf
=
NULL
;
switch
(
inlink
->
type
)
{
case
AVMEDIA_TYPE_VIDEO
:
return
ff_start_frame
(
inlink
->
dst
->
outputs
[
0
],
ref
);
case
AVMEDIA_TYPE_AUDIO
:
return
ff_filter_samples
(
inlink
->
dst
->
outputs
[
0
],
ref
);
}
return
AVERROR
(
ENOSYS
);
}
#if CONFIG_SENDCMD_FILTER
AVFilter
avfilter_vf_sendcmd
=
{
.
name
=
"sendcmd"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Send commands to filters."
),
.
init
=
init
,
.
uninit
=
uninit
,
.
priv_size
=
sizeof
(
SendCmdContext
),
.
inputs
=
(
const
AVFilterPad
[])
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
get_video_buffer
=
ff_null_get_video_buffer
,
.
start_frame
=
process_frame
,
.
end_frame
=
ff_null_end_frame
,
},
{
.
name
=
NULL
}
},
.
outputs
=
(
const
AVFilterPad
[])
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
},
{
.
name
=
NULL
}
},
};
#endif
#if CONFIG_ASENDCMD_FILTER
AVFilter
avfilter_af_asendcmd
=
{
.
name
=
"asendcmd"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Send commands to filters."
),
.
init
=
init
,
.
uninit
=
uninit
,
.
priv_size
=
sizeof
(
SendCmdContext
),
.
inputs
=
(
const
AVFilterPad
[])
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
get_audio_buffer
=
ff_null_get_audio_buffer
,
.
filter_samples
=
process_frame
,
},
{
.
name
=
NULL
}
},
.
outputs
=
(
const
AVFilterPad
[])
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
},
{
.
name
=
NULL
}
},
};
#endif
libavfilter/version.h
View file @
740c9952
...
...
@@ -29,8 +29,8 @@
#include "libavutil/avutil.h"
#define LIBAVFILTER_VERSION_MAJOR 3
#define LIBAVFILTER_VERSION_MINOR 1
6
#define LIBAVFILTER_VERSION_MICRO 10
6
#define LIBAVFILTER_VERSION_MINOR 1
7
#define LIBAVFILTER_VERSION_MICRO 10
0
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
LIBAVFILTER_VERSION_MINOR, \
...
...
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