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
7ddb0ef9
Commit
7ddb0ef9
authored
Apr 21, 2013
by
Stefano Sabatini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavfi: add zmq filters
parent
dc765627
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
329 additions
and
1 deletion
+329
-1
Changelog
Changelog
+1
-0
configure
configure
+5
-0
filters.texi
doc/filters.texi
+42
-0
Makefile
libavfilter/Makefile
+2
-0
allfilters.c
libavfilter/allfilters.c
+2
-0
f_zmq.c
libavfilter/f_zmq.c
+276
-0
version.h
libavfilter/version.h
+1
-1
No files found.
Changelog
View file @
7ddb0ef9
...
...
@@ -45,6 +45,7 @@ version <next>:
- RSD demuxer
- RedSpark demuxer
- ADPCM IMA Radical decoder
- zmq filters
version 1.2:
...
...
configure
View file @
7ddb0ef9
...
...
@@ -236,6 +236,7 @@ External library support:
--enable-libxavs enable AVS encoding via xavs [no]
--enable-libxvid enable Xvid encoding via xvidcore,
native MPEG-4/Xvid encoder exists [no]
--enable-libzmq enable message passing via libzmq [no]
--enable-openal enable OpenAL 1.1 capture support [no]
--enable-opencl enable OpenCL code
--enable-openssl enable openssl [no]
...
...
@@ -1195,6 +1196,7 @@ EXTERNAL_LIBRARY_LIST="
libx264
libxavs
libxvid
libzmq
openal
opencl
openssl
...
...
@@ -2122,6 +2124,7 @@ aresample_filter_deps="swresample"
ass_filter_deps
=
"libass"
asyncts_filter_deps
=
"avresample"
atempo_filter_deps
=
"avcodec rdft"
azmq_filter_deps
=
"libzmq"
blackframe_filter_deps
=
"gpl"
boxblur_filter_deps
=
"gpl"
colormatrix_filter_deps
=
"gpl"
...
...
@@ -2166,6 +2169,7 @@ yadif_filter_deps="gpl"
pixfmts_super2xsai_test_deps
=
"super2xsai_filter"
tinterlace_merge_test_deps
=
"tinterlace_filter"
tinterlace_pad_test_deps
=
"tinterlace_filter"
zmq_filter_deps
=
"libzmq"
# libraries
avcodec_deps
=
"avutil"
...
...
@@ -4055,6 +4059,7 @@ enabled libx264 && require libx264 x264.h x264_encoder_encode -lx264 &&
die
"ERROR: libx264 must be installed and version must be >= 0.118."
;
}
enabled libxavs
&&
require libxavs xavs.h xavs_encoder_encode
-lxavs
enabled libxvid
&&
require libxvid xvid.h xvid_global
-lxvidcore
enabled libzmq
&&
require_pkg_config libzmq zmq.h zmq_ctx_new
enabled openal
&&
{
{
for
al_libs
in
"
${
OPENAL_LIBS
}
"
"-lopenal"
"-lOpenAL32"
;
do
check_lib
'AL/al.h'
alGetError
"
${
al_libs
}
"
&&
break
;
done
}
||
die
"ERROR: openal not found"
;
}
&&
...
...
doc/filters.texi
View file @
7ddb0ef9
...
...
@@ -8371,6 +8371,48 @@ ffmpeg -i INPUT -filter_complex asplit=5 OUTPUT
@end example
@end itemize
@section zmq, azmq
Receive commands sent through a libzmq client, and forward them to
filters in the filtergraph.
@code{zmq} and @code{azmq} work as a pass-through filters. @code{zmq}
must be inserted between two video filters, @code{azmq} between two
audio filters.
To enable these filters you need to install the libzmq library and
headers and configure FFmpeg with @code{--enable-libzmq}.
For more information about libzmq see:
@url{http://www.zeromq.org/}
The @code{zmq} and @code{azmq} filters work as a libzmq server, which
receives messages sent through a network interface defined by the
@option{bind_address} option.
The received message must be in the form:
@example
@var{TARGET} @var{COMMAND} [@var{ARG}]
@end example
@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 argument list for the
given @var{COMMAND}.
Upon reception, the message is processed and the corresponding command
is injected into the filtergraph. Depending on the result, the filter
will send a reply to the client, adopting the format:
@example
@var{ERROR_CODE} @var{ERROR_REASON}
@var{MESSAGE}
@end example
@var{MESSAGE} is optional.
@c man end MULTIMEDIA FILTERS
@chapter Multimedia Sources
...
...
libavfilter/Makefile
View file @
7ddb0ef9
...
...
@@ -74,6 +74,7 @@ OBJS-$(CONFIG_ASTREAMSYNC_FILTER) += af_astreamsync.o
OBJS-$(CONFIG_ASYNCTS_FILTER)
+=
af_asyncts.o
OBJS-$(CONFIG_ATEMPO_FILTER)
+=
af_atempo.o
OBJS-$(CONFIG_ATRIM_FILTER)
+=
trim.o
OBJS-$(CONFIG_AZMQ_FILTER)
+=
f_zmq.o
OBJS-$(CONFIG_BANDPASS_FILTER)
+=
af_biquads.o
OBJS-$(CONFIG_BANDREJECT_FILTER)
+=
af_biquads.o
OBJS-$(CONFIG_BASS_FILTER)
+=
af_biquads.o
...
...
@@ -187,6 +188,7 @@ OBJS-$(CONFIG_VFLIP_FILTER) += vf_vflip.o
OBJS-$(CONFIG_VIDSTABDETECT_FILTER)
+=
vidstabutils.o
vf_vidstabdetect.o
OBJS-$(CONFIG_VIDSTABTRANSFORM_FILTER)
+=
vidstabutils.o
vf_vidstabtransform.o
OBJS-$(CONFIG_YADIF_FILTER)
+=
vf_yadif.o
OBJS-$(CONFIG_ZMQ_FILTER)
+=
f_zmq.o
OBJS-$(CONFIG_CELLAUTO_FILTER)
+=
vsrc_cellauto.o
OBJS-$(CONFIG_COLOR_FILTER)
+=
vsrc_testsrc.o
...
...
libavfilter/allfilters.c
View file @
7ddb0ef9
...
...
@@ -72,6 +72,7 @@ void avfilter_register_all(void)
REGISTER_FILTER
(
ASYNCTS
,
asyncts
,
af
);
REGISTER_FILTER
(
ATEMPO
,
atempo
,
af
);
REGISTER_FILTER
(
ATRIM
,
atrim
,
af
);
REGISTER_FILTER
(
AZMQ
,
azmq
,
af
);
REGISTER_FILTER
(
BANDPASS
,
bandpass
,
af
);
REGISTER_FILTER
(
BANDREJECT
,
bandreject
,
af
);
REGISTER_FILTER
(
BASS
,
bass
,
af
);
...
...
@@ -184,6 +185,7 @@ void avfilter_register_all(void)
REGISTER_FILTER
(
VIDSTABDETECT
,
vidstabdetect
,
vf
);
REGISTER_FILTER
(
VIDSTABTRANSFORM
,
vidstabtransform
,
vf
);
REGISTER_FILTER
(
YADIF
,
yadif
,
vf
);
REGISTER_FILTER
(
ZMQ
,
zmq
,
vf
);
REGISTER_FILTER
(
CELLAUTO
,
cellauto
,
vsrc
);
REGISTER_FILTER
(
COLOR
,
color
,
vsrc
);
...
...
libavfilter/f_zmq.c
0 → 100644
View file @
7ddb0ef9
/*
* Copyright (c) 2013 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
* receive commands through libzeromq and broker them to filters
*/
#include <zmq.h>
#include "libavutil/avstring.h"
#include "libavutil/bprint.h"
#include "libavutil/opt.h"
#include "avfilter.h"
#include "internal.h"
#include "avfiltergraph.h"
#include "audio.h"
#include "video.h"
typedef
struct
{
const
AVClass
*
class
;
void
*
zmq
;
void
*
responder
;
char
*
bind_address
;
int
command_count
;
}
ZMQContext
;
#define OFFSET(x) offsetof(ZMQContext, x)
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_VIDEO_PARAM
static
const
AVOption
options
[]
=
{
{
"bind_address"
,
"set bind address"
,
OFFSET
(
bind_address
),
AV_OPT_TYPE_STRING
,
{.
str
=
"tcp://*:5555"
},
0
,
0
,
FLAGS
},
{
"b"
,
"set bind address"
,
OFFSET
(
bind_address
),
AV_OPT_TYPE_STRING
,
{.
str
=
"tcp://*:5555"
},
0
,
0
,
FLAGS
},
{
NULL
}
};
static
av_cold
int
init
(
AVFilterContext
*
ctx
)
{
ZMQContext
*
zmq
=
ctx
->
priv
;
zmq
->
zmq
=
zmq_ctx_new
();
if
(
!
zmq
->
zmq
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Could not create ZMQ context: %s
\n
"
,
zmq_strerror
(
errno
));
return
AVERROR_EXTERNAL
;
}
zmq
->
responder
=
zmq_socket
(
zmq
->
zmq
,
ZMQ_REP
);
if
(
!
zmq
->
responder
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Could not create ZMQ socket: %s
\n
"
,
zmq_strerror
(
errno
));
return
AVERROR_EXTERNAL
;
}
if
(
zmq_bind
(
zmq
->
responder
,
zmq
->
bind_address
)
==
-
1
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Could not bind ZMQ socket to address '%s': %s
\n
"
,
zmq
->
bind_address
,
zmq_strerror
(
errno
));
return
AVERROR_EXTERNAL
;
}
zmq
->
command_count
=
-
1
;
return
0
;
}
static
void
av_cold
uninit
(
AVFilterContext
*
ctx
)
{
ZMQContext
*
zmq
=
ctx
->
priv
;
zmq_close
(
zmq
->
responder
);
zmq_ctx_destroy
(
zmq
->
zmq
);
}
typedef
struct
{
char
*
target
,
*
command
,
*
arg
;
}
Command
;
#define SPACES " \f\t\n\r"
static
int
parse_command
(
Command
*
cmd
,
const
char
*
command_str
,
void
*
log_ctx
)
{
const
char
**
buf
=
&
command_str
;
cmd
->
target
=
av_get_token
(
buf
,
SPACES
);
if
(
!
cmd
->
target
||
!
cmd
->
target
[
0
])
{
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"No target specified in command '%s'
\n
"
,
command_str
);
return
AVERROR
(
EINVAL
);
}
cmd
->
command
=
av_get_token
(
buf
,
SPACES
);
if
(
!
cmd
->
command
||
!
cmd
->
command
[
0
])
{
av_log
(
log_ctx
,
AV_LOG_ERROR
,
"No command specified in command '%s'
\n
"
,
command_str
);
return
AVERROR
(
EINVAL
);
}
cmd
->
arg
=
av_get_token
(
buf
,
SPACES
);
return
0
;
}
static
int
recv_msg
(
AVFilterContext
*
ctx
,
char
**
buf
,
int
*
buf_size
)
{
ZMQContext
*
zmq
=
ctx
->
priv
;
zmq_msg_t
msg
;
int
ret
=
0
;
if
(
zmq_msg_init
(
&
msg
)
==
-
1
)
{
av_log
(
ctx
,
AV_LOG_WARNING
,
"Could not initialize receive message: %s
\n
"
,
zmq_strerror
(
errno
));
return
AVERROR_EXTERNAL
;
}
if
(
zmq_msg_recv
(
&
msg
,
zmq
->
responder
,
ZMQ_DONTWAIT
)
==
-
1
)
{
if
(
errno
!=
EAGAIN
)
av_log
(
ctx
,
AV_LOG_WARNING
,
"Could not receive message: %s
\n
"
,
zmq_strerror
(
errno
));
ret
=
AVERROR_EXTERNAL
;
goto
end
;
}
*
buf_size
=
zmq_msg_size
(
&
msg
)
+
1
;
*
buf
=
av_malloc
(
*
buf_size
);
if
(
!*
buf
)
{
ret
=
AVERROR
(
ENOMEM
);
goto
end
;
}
memcpy
(
*
buf
,
zmq_msg_data
(
&
msg
),
*
buf_size
);
(
*
buf
)[
*
buf_size
-
1
]
=
0
;
end:
zmq_msg_close
(
&
msg
);
return
ret
;
}
static
int
filter_frame
(
AVFilterLink
*
inlink
,
AVFrame
*
ref
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
ZMQContext
*
zmq
=
ctx
->
priv
;
while
(
1
)
{
char
cmd_buf
[
1024
];
char
*
recv_buf
,
*
send_buf
;
int
recv_buf_size
;
Command
cmd
=
{
0
};
int
ret
;
/* receive command */
if
(
recv_msg
(
ctx
,
&
recv_buf
,
&
recv_buf_size
)
<
0
)
break
;
zmq
->
command_count
++
;
/* parse command */
if
(
parse_command
(
&
cmd
,
recv_buf
,
ctx
)
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Could not parse command #%d
\n
"
,
zmq
->
command_count
);
goto
end
;
}
/* process command */
av_log
(
ctx
,
AV_LOG_VERBOSE
,
"Processing command #%d target:%s command:%s arg:%s
\n
"
,
zmq
->
command_count
,
cmd
.
target
,
cmd
.
command
,
cmd
.
arg
);
ret
=
avfilter_graph_send_command
(
inlink
->
graph
,
cmd
.
target
,
cmd
.
command
,
cmd
.
arg
,
cmd_buf
,
sizeof
(
cmd_buf
),
AVFILTER_CMD_FLAG_ONE
);
send_buf
=
av_asprintf
(
"%d %s%s%s"
,
-
ret
,
av_err2str
(
ret
),
cmd_buf
[
0
]
?
"
\n
"
:
""
,
cmd_buf
);
if
(
!
send_buf
)
{
ret
=
AVERROR
(
ENOMEM
);
goto
end
;
}
av_log
(
ctx
,
AV_LOG_VERBOSE
,
"Sending command reply for command #%d:
\n
%s
\n
"
,
zmq
->
command_count
,
send_buf
);
if
(
zmq_send
(
zmq
->
responder
,
send_buf
,
strlen
(
send_buf
),
0
)
==
-
1
)
av_log
(
ctx
,
AV_LOG_ERROR
,
"Failed to send reply for command #%d: %s
\n
"
,
zmq
->
command_count
,
zmq_strerror
(
ret
));
end:
av_freep
(
&
send_buf
);
av_freep
(
&
recv_buf
);
recv_buf_size
=
0
;
av_freep
(
&
cmd
.
target
);
av_freep
(
&
cmd
.
command
);
av_freep
(
&
cmd
.
arg
);
}
return
ff_filter_frame
(
ctx
->
outputs
[
0
],
ref
);
}
#if CONFIG_ZMQ_FILTER
#define zmq_options options
AVFILTER_DEFINE_CLASS
(
zmq
);
static
const
AVFilterPad
zmq_inputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
filter_frame
=
filter_frame
,
},
{
NULL
}
};
static
const
AVFilterPad
zmq_outputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
},
{
NULL
}
};
AVFilter
avfilter_vf_zmq
=
{
.
name
=
"zmq"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Receive commands through ZMQ and broker them to filters."
),
.
init
=
init
,
.
uninit
=
uninit
,
.
priv_size
=
sizeof
(
ZMQContext
),
.
inputs
=
zmq_inputs
,
.
outputs
=
zmq_outputs
,
.
priv_class
=
&
zmq_class
,
};
#endif
#if CONFIG_AZMQ_FILTER
#define azmq_options options
AVFILTER_DEFINE_CLASS
(
azmq
);
static
const
AVFilterPad
azmq_inputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
get_audio_buffer
=
ff_null_get_audio_buffer
,
.
filter_frame
=
filter_frame
,
},
{
NULL
}
};
static
const
AVFilterPad
azmq_outputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
},
{
NULL
}
};
AVFilter
avfilter_af_azmq
=
{
.
name
=
"azmq"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Receive commands through ZMQ and broker them to filters."
),
.
init
=
init
,
.
uninit
=
uninit
,
.
priv_size
=
sizeof
(
ZMQContext
),
.
inputs
=
azmq_inputs
,
.
outputs
=
azmq_outputs
,
.
priv_class
=
&
azmq_class
,
};
#endif
libavfilter/version.h
View file @
7ddb0ef9
...
...
@@ -29,7 +29,7 @@
#include "libavutil/avutil.h"
#define LIBAVFILTER_VERSION_MAJOR 3
#define LIBAVFILTER_VERSION_MINOR 6
5
#define LIBAVFILTER_VERSION_MINOR 6
6
#define LIBAVFILTER_VERSION_MICRO 100
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
...
...
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