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
dfdc1461
Commit
dfdc1461
authored
Jan 02, 2018
by
Mark Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavfi: Add filters to run arbitrary OpenCL programs
parent
202b59cd
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
447 additions
and
0 deletions
+447
-0
configure
configure
+2
-0
Makefile
libavfilter/Makefile
+2
-0
allfilters.c
libavfilter/allfilters.c
+2
-0
vf_program_opencl.c
libavfilter/vf_program_opencl.c
+441
-0
No files found.
configure
View file @
dfdc1461
...
...
@@ -3235,6 +3235,7 @@ negate_filter_deps="lut_filter"
nnedi_filter_deps
=
"gpl"
ocr_filter_deps
=
"libtesseract"
ocv_filter_deps
=
"libopencv"
openclsrc_filter_deps
=
"opencl"
overlay_opencl_filter_deps
=
"opencl"
overlay_qsv_filter_deps
=
"libmfx"
overlay_qsv_filter_select
=
"qsvvpp"
...
...
@@ -3244,6 +3245,7 @@ perspective_filter_deps="gpl"
phase_filter_deps
=
"gpl"
pp7_filter_deps
=
"gpl"
pp_filter_deps
=
"gpl postproc"
program_opencl_filter_deps
=
"opencl"
pullup_filter_deps
=
"gpl"
removelogo_filter_deps
=
"avcodec avformat swscale"
repeatfields_filter_deps
=
"gpl"
...
...
libavfilter/Makefile
View file @
dfdc1461
...
...
@@ -275,6 +275,7 @@ OBJS-$(CONFIG_PP_FILTER) += vf_pp.o
OBJS-$(CONFIG_PP7_FILTER)
+=
vf_pp7.o
OBJS-$(CONFIG_PREMULTIPLY_FILTER)
+=
vf_premultiply.o
framesync.o
OBJS-$(CONFIG_PREWITT_FILTER)
+=
vf_convolution.o
OBJS-$(CONFIG_PROGRAM_OPENCL_FILTER)
+=
vf_program_opencl.o
opencl.o
framesync.o
OBJS-$(CONFIG_PSEUDOCOLOR_FILTER)
+=
vf_pseudocolor.o
OBJS-$(CONFIG_PSNR_FILTER)
+=
vf_psnr.o
framesync.o
OBJS-$(CONFIG_PULLUP_FILTER)
+=
vf_pullup.o
...
...
@@ -370,6 +371,7 @@ OBJS-$(CONFIG_LIFE_FILTER) += vsrc_life.o
OBJS-$(CONFIG_MANDELBROT_FILTER)
+=
vsrc_mandelbrot.o
OBJS-$(CONFIG_MPTESTSRC_FILTER)
+=
vsrc_mptestsrc.o
OBJS-$(CONFIG_NULLSRC_FILTER)
+=
vsrc_testsrc.o
OBJS-$(CONFIG_OPENCLSRC_FILTER)
+=
vf_program_opencl.o
opencl.o
OBJS-$(CONFIG_RGBTESTSRC_FILTER)
+=
vsrc_testsrc.o
OBJS-$(CONFIG_SMPTEBARS_FILTER)
+=
vsrc_testsrc.o
OBJS-$(CONFIG_SMPTEHDBARS_FILTER)
+=
vsrc_testsrc.o
...
...
libavfilter/allfilters.c
View file @
dfdc1461
...
...
@@ -284,6 +284,7 @@ static void register_all(void)
REGISTER_FILTER
(
PP7
,
pp7
,
vf
);
REGISTER_FILTER
(
PREMULTIPLY
,
premultiply
,
vf
);
REGISTER_FILTER
(
PREWITT
,
prewitt
,
vf
);
REGISTER_FILTER
(
PROGRAM_OPENCL
,
program_opencl
,
vf
);
REGISTER_FILTER
(
PSEUDOCOLOR
,
pseudocolor
,
vf
);
REGISTER_FILTER
(
PSNR
,
psnr
,
vf
);
REGISTER_FILTER
(
PULLUP
,
pullup
,
vf
);
...
...
@@ -378,6 +379,7 @@ static void register_all(void)
REGISTER_FILTER
(
MANDELBROT
,
mandelbrot
,
vsrc
);
REGISTER_FILTER
(
MPTESTSRC
,
mptestsrc
,
vsrc
);
REGISTER_FILTER
(
NULLSRC
,
nullsrc
,
vsrc
);
REGISTER_FILTER
(
OPENCLSRC
,
openclsrc
,
vsrc
);
REGISTER_FILTER
(
RGBTESTSRC
,
rgbtestsrc
,
vsrc
);
REGISTER_FILTER
(
SMPTEBARS
,
smptebars
,
vsrc
);
REGISTER_FILTER
(
SMPTEHDBARS
,
smptehdbars
,
vsrc
);
...
...
libavfilter/vf_program_opencl.c
0 → 100644
View file @
dfdc1461
/*
* 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
*/
#include "libavutil/avstring.h"
#include "libavutil/buffer.h"
#include "libavutil/common.h"
#include "libavutil/hwcontext.h"
#include "libavutil/hwcontext_opencl.h"
#include "libavutil/log.h"
#include "libavutil/mem.h"
#include "libavutil/pixdesc.h"
#include "libavutil/opt.h"
#include "avfilter.h"
#include "framesync.h"
#include "internal.h"
#include "opencl.h"
#include "video.h"
typedef
struct
ProgramOpenCLContext
{
OpenCLFilterContext
ocf
;
int
loaded
;
cl_uint
index
;
cl_kernel
kernel
;
cl_command_queue
command_queue
;
FFFrameSync
fs
;
AVFrame
**
frames
;
const
char
*
source_file
;
const
char
*
kernel_name
;
int
nb_inputs
;
int
width
,
height
;
enum
AVPixelFormat
source_format
;
AVRational
source_rate
;
}
ProgramOpenCLContext
;
static
int
program_opencl_load
(
AVFilterContext
*
avctx
)
{
ProgramOpenCLContext
*
ctx
=
avctx
->
priv
;
cl_int
cle
;
int
err
;
err
=
ff_opencl_filter_load_program_from_file
(
avctx
,
ctx
->
source_file
);
if
(
err
<
0
)
return
err
;
ctx
->
command_queue
=
clCreateCommandQueue
(
ctx
->
ocf
.
hwctx
->
context
,
ctx
->
ocf
.
hwctx
->
device_id
,
0
,
&
cle
);
if
(
!
ctx
->
command_queue
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Failed to create OpenCL "
"command queue: %d.
\n
"
,
cle
);
return
AVERROR
(
EIO
);
}
ctx
->
kernel
=
clCreateKernel
(
ctx
->
ocf
.
program
,
ctx
->
kernel_name
,
&
cle
);
if
(
!
ctx
->
kernel
)
{
if
(
cle
==
CL_INVALID_KERNEL_NAME
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Kernel function '%s' not found in "
"program.
\n
"
,
ctx
->
kernel_name
);
}
else
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Failed to create kernel: %d.
\n
"
,
cle
);
}
return
AVERROR
(
EIO
);
}
ctx
->
loaded
=
1
;
return
0
;
}
static
int
program_opencl_run
(
AVFilterContext
*
avctx
)
{
AVFilterLink
*
outlink
=
avctx
->
outputs
[
0
];
ProgramOpenCLContext
*
ctx
=
avctx
->
priv
;
AVFrame
*
output
=
NULL
;
cl_int
cle
;
size_t
global_work
[
2
];
cl_mem
src
,
dst
;
int
err
,
input
,
plane
;
if
(
!
ctx
->
loaded
)
{
err
=
program_opencl_load
(
avctx
);
if
(
err
<
0
)
return
err
;
}
output
=
ff_get_video_buffer
(
outlink
,
outlink
->
w
,
outlink
->
h
);
if
(
!
output
)
{
err
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
for
(
plane
=
0
;
plane
<
FF_ARRAY_ELEMS
(
output
->
data
);
plane
++
)
{
dst
=
(
cl_mem
)
output
->
data
[
plane
];
if
(
!
dst
)
break
;
cle
=
clSetKernelArg
(
ctx
->
kernel
,
0
,
sizeof
(
cl_mem
),
&
dst
);
if
(
cle
!=
CL_SUCCESS
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Failed to set kernel "
"destination image argument: %d.
\n
"
,
cle
);
goto
fail
;
}
cle
=
clSetKernelArg
(
ctx
->
kernel
,
1
,
sizeof
(
cl_uint
),
&
ctx
->
index
);
if
(
cle
!=
CL_SUCCESS
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Failed to set kernel "
"index argument: %d.
\n
"
,
cle
);
goto
fail
;
}
for
(
input
=
0
;
input
<
ctx
->
nb_inputs
;
input
++
)
{
av_assert0
(
ctx
->
frames
[
input
]);
src
=
(
cl_mem
)
ctx
->
frames
[
input
]
->
data
[
plane
];
av_assert0
(
src
);
cle
=
clSetKernelArg
(
ctx
->
kernel
,
2
+
input
,
sizeof
(
cl_mem
),
&
src
);
if
(
cle
!=
CL_SUCCESS
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Failed to set kernel "
"source image argument %d: %d.
\n
"
,
input
,
cle
);
goto
fail
;
}
}
cle
=
clGetImageInfo
(
dst
,
CL_IMAGE_WIDTH
,
sizeof
(
size_t
),
&
global_work
[
0
],
NULL
);
cle
=
clGetImageInfo
(
dst
,
CL_IMAGE_HEIGHT
,
sizeof
(
size_t
),
&
global_work
[
1
],
NULL
);
av_log
(
avctx
,
AV_LOG_DEBUG
,
"Run kernel on plane %d "
"(%zux%zu).
\n
"
,
plane
,
global_work
[
0
],
global_work
[
1
]);
cle
=
clEnqueueNDRangeKernel
(
ctx
->
command_queue
,
ctx
->
kernel
,
2
,
NULL
,
global_work
,
NULL
,
0
,
NULL
,
NULL
);
if
(
cle
!=
CL_SUCCESS
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Failed to enqueue kernel: %d.
\n
"
,
cle
);
err
=
AVERROR
(
EIO
);
goto
fail
;
}
}
cle
=
clFinish
(
ctx
->
command_queue
);
if
(
cle
!=
CL_SUCCESS
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Failed to finish command queue: %d.
\n
"
,
cle
);
err
=
AVERROR
(
EIO
);
goto
fail
;
}
if
(
ctx
->
nb_inputs
>
0
)
{
err
=
av_frame_copy_props
(
output
,
ctx
->
frames
[
0
]);
if
(
err
<
0
)
goto
fail
;
}
else
{
output
->
pts
=
ctx
->
index
;
}
++
ctx
->
index
;
av_log
(
ctx
,
AV_LOG_DEBUG
,
"Filter output: %s, %ux%u (%"
PRId64
").
\n
"
,
av_get_pix_fmt_name
(
output
->
format
),
output
->
width
,
output
->
height
,
output
->
pts
);
return
ff_filter_frame
(
outlink
,
output
);
fail:
clFinish
(
ctx
->
command_queue
);
av_frame_free
(
&
output
);
return
err
;
}
static
int
program_opencl_request_frame
(
AVFilterLink
*
outlink
)
{
AVFilterContext
*
avctx
=
outlink
->
src
;
return
program_opencl_run
(
avctx
);
}
static
int
program_opencl_filter
(
FFFrameSync
*
fs
)
{
AVFilterContext
*
avctx
=
fs
->
parent
;
ProgramOpenCLContext
*
ctx
=
avctx
->
priv
;
int
err
,
i
;
for
(
i
=
0
;
i
<
ctx
->
nb_inputs
;
i
++
)
{
err
=
ff_framesync_get_frame
(
&
ctx
->
fs
,
i
,
&
ctx
->
frames
[
i
],
0
);
if
(
err
<
0
)
return
err
;
}
return
program_opencl_run
(
avctx
);
}
static
int
program_opencl_activate
(
AVFilterContext
*
avctx
)
{
ProgramOpenCLContext
*
ctx
=
avctx
->
priv
;
av_assert0
(
ctx
->
nb_inputs
>
0
);
return
ff_framesync_activate
(
&
ctx
->
fs
);
}
static
int
program_opencl_config_output
(
AVFilterLink
*
outlink
)
{
AVFilterContext
*
avctx
=
outlink
->
src
;
ProgramOpenCLContext
*
ctx
=
avctx
->
priv
;
int
err
;
err
=
ff_opencl_filter_config_output
(
outlink
);
if
(
err
<
0
)
return
err
;
if
(
ctx
->
nb_inputs
>
0
)
{
FFFrameSyncIn
*
in
;
int
i
;
err
=
ff_framesync_init
(
&
ctx
->
fs
,
avctx
,
ctx
->
nb_inputs
);
if
(
err
<
0
)
return
err
;
ctx
->
fs
.
opaque
=
ctx
;
ctx
->
fs
.
on_event
=
&
program_opencl_filter
;
in
=
ctx
->
fs
.
in
;
for
(
i
=
0
;
i
<
ctx
->
nb_inputs
;
i
++
)
{
const
AVFilterLink
*
inlink
=
avctx
->
inputs
[
i
];
in
[
i
].
time_base
=
inlink
->
time_base
;
in
[
i
].
sync
=
1
;
in
[
i
].
before
=
EXT_STOP
;
in
[
i
].
after
=
EXT_INFINITY
;
}
err
=
ff_framesync_configure
(
&
ctx
->
fs
);
if
(
err
<
0
)
return
err
;
}
else
{
outlink
->
time_base
=
av_inv_q
(
ctx
->
source_rate
);
}
return
0
;
}
static
av_cold
int
program_opencl_init
(
AVFilterContext
*
avctx
)
{
ProgramOpenCLContext
*
ctx
=
avctx
->
priv
;
int
err
;
ff_opencl_filter_init
(
avctx
);
ctx
->
ocf
.
output_width
=
ctx
->
width
;
ctx
->
ocf
.
output_height
=
ctx
->
height
;
if
(
!
strcmp
(
avctx
->
filter
->
name
,
"openclsrc"
))
{
if
(
!
ctx
->
ocf
.
output_width
||
!
ctx
->
ocf
.
output_height
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"OpenCL source requires output "
"dimensions to be specified.
\n
"
);
return
AVERROR
(
EINVAL
);
}
ctx
->
nb_inputs
=
0
;
ctx
->
ocf
.
output_format
=
ctx
->
source_format
;
}
else
{
int
i
;
ctx
->
frames
=
av_mallocz_array
(
ctx
->
nb_inputs
,
sizeof
(
*
ctx
->
frames
));
if
(
!
ctx
->
frames
)
return
AVERROR
(
ENOMEM
);
for
(
i
=
0
;
i
<
ctx
->
nb_inputs
;
i
++
)
{
AVFilterPad
input
;
memset
(
&
input
,
0
,
sizeof
(
input
));
input
.
type
=
AVMEDIA_TYPE_VIDEO
;
input
.
name
=
av_asprintf
(
"input%d"
,
i
);
if
(
!
input
.
name
)
return
AVERROR
(
ENOMEM
);
input
.
config_props
=
&
ff_opencl_filter_config_input
;
err
=
ff_insert_inpad
(
avctx
,
i
,
&
input
);
if
(
err
<
0
)
{
av_freep
(
&
input
.
name
);
return
err
;
}
}
}
return
0
;
}
static
av_cold
void
program_opencl_uninit
(
AVFilterContext
*
avctx
)
{
ProgramOpenCLContext
*
ctx
=
avctx
->
priv
;
cl_int
cle
;
int
i
;
if
(
ctx
->
nb_inputs
>
0
)
{
ff_framesync_uninit
(
&
ctx
->
fs
);
av_freep
(
&
ctx
->
frames
);
for
(
i
=
0
;
i
<
avctx
->
nb_inputs
;
i
++
)
av_freep
(
&
avctx
->
input_pads
[
i
].
name
);
}
if
(
ctx
->
kernel
)
{
cle
=
clReleaseKernel
(
ctx
->
kernel
);
if
(
cle
!=
CL_SUCCESS
)
av_log
(
avctx
,
AV_LOG_ERROR
,
"Failed to release "
"kernel: %d.
\n
"
,
cle
);
}
if
(
ctx
->
command_queue
)
{
cle
=
clReleaseCommandQueue
(
ctx
->
command_queue
);
if
(
cle
!=
CL_SUCCESS
)
av_log
(
avctx
,
AV_LOG_ERROR
,
"Failed to release "
"command queue: %d.
\n
"
,
cle
);
}
ff_opencl_filter_uninit
(
avctx
);
}
#define OFFSET(x) offsetof(ProgramOpenCLContext, x)
#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM)
#if CONFIG_PROGRAM_OPENCL_FILTER
static
const
AVOption
program_opencl_options
[]
=
{
{
"source"
,
"OpenCL program source file"
,
OFFSET
(
source_file
),
AV_OPT_TYPE_STRING
,
{
.
str
=
NULL
},
.
flags
=
FLAGS
},
{
"kernel"
,
"Kernel name in program"
,
OFFSET
(
kernel_name
),
AV_OPT_TYPE_STRING
,
{
.
str
=
NULL
},
.
flags
=
FLAGS
},
{
"inputs"
,
"Number of inputs"
,
OFFSET
(
nb_inputs
),
AV_OPT_TYPE_INT
,
{
.
i64
=
1
},
1
,
INT_MAX
,
FLAGS
},
{
"size"
,
"Video size"
,
OFFSET
(
width
),
AV_OPT_TYPE_IMAGE_SIZE
,
{
.
str
=
NULL
},
0
,
0
,
FLAGS
},
{
"s"
,
"Video size"
,
OFFSET
(
width
),
AV_OPT_TYPE_IMAGE_SIZE
,
{
.
str
=
NULL
},
0
,
0
,
FLAGS
},
{
NULL
},
};
FRAMESYNC_DEFINE_CLASS
(
program_opencl
,
ProgramOpenCLContext
,
fs
);
static
const
AVFilterPad
program_opencl_outputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
config_props
=
&
program_opencl_config_output
,
},
{
NULL
}
};
AVFilter
ff_vf_program_opencl
=
{
.
name
=
"program_opencl"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Filter video using an OpenCL program"
),
.
priv_size
=
sizeof
(
ProgramOpenCLContext
),
.
priv_class
=
&
program_opencl_class
,
.
preinit
=
&
program_opencl_framesync_preinit
,
.
init
=
&
program_opencl_init
,
.
uninit
=
&
program_opencl_uninit
,
.
query_formats
=
&
ff_opencl_filter_query_formats
,
.
activate
=
&
program_opencl_activate
,
.
inputs
=
NULL
,
.
outputs
=
program_opencl_outputs
,
.
flags_internal
=
FF_FILTER_FLAG_HWFRAME_AWARE
,
};
#endif
#if CONFIG_OPENCLSRC_FILTER
static
const
AVOption
openclsrc_options
[]
=
{
{
"source"
,
"OpenCL program source file"
,
OFFSET
(
source_file
),
AV_OPT_TYPE_STRING
,
{
.
str
=
NULL
},
.
flags
=
FLAGS
},
{
"kernel"
,
"Kernel name in program"
,
OFFSET
(
kernel_name
),
AV_OPT_TYPE_STRING
,
{
.
str
=
NULL
},
.
flags
=
FLAGS
},
{
"size"
,
"Video size"
,
OFFSET
(
width
),
AV_OPT_TYPE_IMAGE_SIZE
,
{
.
str
=
NULL
},
0
,
0
,
FLAGS
},
{
"s"
,
"Video size"
,
OFFSET
(
width
),
AV_OPT_TYPE_IMAGE_SIZE
,
{
.
str
=
NULL
},
0
,
0
,
FLAGS
},
{
"format"
,
"Video format"
,
OFFSET
(
source_format
),
AV_OPT_TYPE_PIXEL_FMT
,
{
.
i64
=
AV_PIX_FMT_NONE
},
-
1
,
INT_MAX
,
FLAGS
},
{
"rate"
,
"Video frame rate"
,
OFFSET
(
source_rate
),
AV_OPT_TYPE_VIDEO_RATE
,
{
.
str
=
"25"
},
0
,
INT_MAX
,
FLAGS
},
{
"r"
,
"Video frame rate"
,
OFFSET
(
source_rate
),
AV_OPT_TYPE_VIDEO_RATE
,
{
.
str
=
"25"
},
0
,
INT_MAX
,
FLAGS
},
{
NULL
},
};
AVFILTER_DEFINE_CLASS
(
openclsrc
);
static
const
AVFilterPad
openclsrc_outputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
config_props
=
&
program_opencl_config_output
,
.
request_frame
=
&
program_opencl_request_frame
,
},
{
NULL
}
};
AVFilter
ff_vsrc_openclsrc
=
{
.
name
=
"openclsrc"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Generate video using an OpenCL program"
),
.
priv_size
=
sizeof
(
ProgramOpenCLContext
),
.
priv_class
=
&
openclsrc_class
,
.
init
=
&
program_opencl_init
,
.
uninit
=
&
program_opencl_uninit
,
.
query_formats
=
&
ff_opencl_filter_query_formats
,
.
inputs
=
NULL
,
.
outputs
=
openclsrc_outputs
,
.
flags_internal
=
FF_FILTER_FLAG_HWFRAME_AWARE
,
};
#endif
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