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
e21d4a7c
Commit
e21d4a7c
authored
Nov 18, 2019
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfilter/vf_chromakey: add >8 bit support
parent
d73f0627
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
143 additions
and
10 deletions
+143
-10
vf_chromakey.c
libavfilter/vf_chromakey.c
+143
-10
No files found.
libavfilter/vf_chromakey.c
View file @
e21d4a7c
...
...
@@ -20,6 +20,7 @@
#include "libavutil/opt.h"
#include "libavutil/imgutils.h"
#include "libavutil/intreadwrite.h"
#include "avfilter.h"
#include "formats.h"
#include "internal.h"
...
...
@@ -29,12 +30,15 @@ typedef struct ChromakeyContext {
const
AVClass
*
class
;
uint8_t
chromakey_rgba
[
4
];
uint
8
_t
chromakey_uv
[
2
];
uint
16
_t
chromakey_uv
[
2
];
float
similarity
;
float
blend
;
int
is_yuv
;
int
depth
;
int
mid
;
int
max
;
int
hsub_log2
;
int
vsub_log2
;
...
...
@@ -64,6 +68,28 @@ static uint8_t do_chromakey_pixel(ChromakeyContext *ctx, uint8_t u[9], uint8_t v
}
}
static
uint16_t
do_chromakey_pixel16
(
ChromakeyContext
*
ctx
,
uint16_t
u
[
9
],
uint16_t
v
[
9
])
{
double
max
=
ctx
->
max
;
double
diff
=
0
.
0
;
int
du
,
dv
,
i
;
for
(
i
=
0
;
i
<
9
;
++
i
)
{
du
=
(
int
)
u
[
i
]
-
ctx
->
chromakey_uv
[
0
];
dv
=
(
int
)
v
[
i
]
-
ctx
->
chromakey_uv
[
1
];
diff
+=
sqrt
((
du
*
du
+
dv
*
dv
)
/
(
max
*
max
));
}
diff
/=
9
.
0
;
if
(
ctx
->
blend
>
0
.
0001
)
{
return
av_clipd
((
diff
-
ctx
->
similarity
)
/
ctx
->
blend
,
0
.
0
,
1
.
0
)
*
max
;
}
else
{
return
(
diff
>
ctx
->
similarity
)
?
max
:
0
;
}
}
static
av_always_inline
void
get_pixel_uv
(
AVFrame
*
frame
,
int
hsub_log2
,
int
vsub_log2
,
int
x
,
int
y
,
uint8_t
*
u
,
uint8_t
*
v
)
{
if
(
x
<
0
||
x
>=
frame
->
width
||
y
<
0
||
y
>=
frame
->
height
)
...
...
@@ -76,6 +102,18 @@ static av_always_inline void get_pixel_uv(AVFrame *frame, int hsub_log2, int vsu
*
v
=
frame
->
data
[
2
][
frame
->
linesize
[
2
]
*
y
+
x
];
}
static
av_always_inline
void
get_pixel16_uv
(
AVFrame
*
frame
,
int
hsub_log2
,
int
vsub_log2
,
int
x
,
int
y
,
uint16_t
*
u
,
uint16_t
*
v
)
{
if
(
x
<
0
||
x
>=
frame
->
width
||
y
<
0
||
y
>=
frame
->
height
)
return
;
x
>>=
hsub_log2
;
y
>>=
vsub_log2
;
*
u
=
AV_RN16
(
&
frame
->
data
[
1
][
frame
->
linesize
[
1
]
*
y
+
2
*
x
]);
*
v
=
AV_RN16
(
&
frame
->
data
[
2
][
frame
->
linesize
[
2
]
*
y
+
2
*
x
]);
}
static
int
do_chromakey_slice
(
AVFilterContext
*
avctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
AVFrame
*
frame
=
arg
;
...
...
@@ -106,6 +144,40 @@ static int do_chromakey_slice(AVFilterContext *avctx, void *arg, int jobnr, int
return
0
;
}
static
int
do_chromakey16_slice
(
AVFilterContext
*
avctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
AVFrame
*
frame
=
arg
;
const
int
slice_start
=
(
frame
->
height
*
jobnr
)
/
nb_jobs
;
const
int
slice_end
=
(
frame
->
height
*
(
jobnr
+
1
))
/
nb_jobs
;
ChromakeyContext
*
ctx
=
avctx
->
priv
;
int
x
,
y
,
xo
,
yo
;
uint16_t
u
[
9
],
v
[
9
];
for
(
int
i
=
0
;
i
<
9
;
i
++
)
{
u
[
i
]
=
ctx
->
chromakey_uv
[
0
];
v
[
i
]
=
ctx
->
chromakey_uv
[
1
];
}
for
(
y
=
slice_start
;
y
<
slice_end
;
++
y
)
{
for
(
x
=
0
;
x
<
frame
->
width
;
++
x
)
{
uint16_t
*
dst
=
(
uint16_t
*
)(
frame
->
data
[
3
]
+
frame
->
linesize
[
3
]
*
y
);
for
(
yo
=
0
;
yo
<
3
;
++
yo
)
{
for
(
xo
=
0
;
xo
<
3
;
++
xo
)
{
get_pixel16_uv
(
frame
,
ctx
->
hsub_log2
,
ctx
->
vsub_log2
,
x
+
xo
-
1
,
y
+
yo
-
1
,
&
u
[
yo
*
3
+
xo
],
&
v
[
yo
*
3
+
xo
]);
}
}
dst
[
x
]
=
do_chromakey_pixel16
(
ctx
,
u
,
v
);
}
}
return
0
;
}
static
int
do_chromahold_slice
(
AVFilterContext
*
avctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
ChromakeyContext
*
ctx
=
avctx
->
priv
;
...
...
@@ -143,6 +215,45 @@ static int do_chromahold_slice(AVFilterContext *avctx, void *arg, int jobnr, int
return
0
;
}
static
int
do_chromahold16_slice
(
AVFilterContext
*
avctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
ChromakeyContext
*
ctx
=
avctx
->
priv
;
AVFrame
*
frame
=
arg
;
const
int
slice_start
=
((
frame
->
height
>>
ctx
->
vsub_log2
)
*
jobnr
)
/
nb_jobs
;
const
int
slice_end
=
((
frame
->
height
>>
ctx
->
vsub_log2
)
*
(
jobnr
+
1
))
/
nb_jobs
;
const
int
mid
=
ctx
->
mid
;
double
max
=
ctx
->
max
;
int
x
,
y
,
alpha
;
for
(
y
=
slice_start
;
y
<
slice_end
;
++
y
)
{
for
(
x
=
0
;
x
<
frame
->
width
>>
ctx
->
hsub_log2
;
++
x
)
{
int
u
=
AV_RN16
(
&
frame
->
data
[
1
][
frame
->
linesize
[
1
]
*
y
+
2
*
x
]);
int
v
=
AV_RN16
(
&
frame
->
data
[
2
][
frame
->
linesize
[
2
]
*
y
+
2
*
x
]);
double
diff
;
int
du
,
dv
;
du
=
u
-
ctx
->
chromakey_uv
[
0
];
dv
=
v
-
ctx
->
chromakey_uv
[
1
];
diff
=
sqrt
((
du
*
du
+
dv
*
dv
)
/
(
max
*
max
));
alpha
=
diff
>
ctx
->
similarity
;
if
(
ctx
->
blend
>
0
.
0001
)
{
double
f
=
1
.
-
av_clipd
((
diff
-
ctx
->
similarity
)
/
ctx
->
blend
,
0
.
0
,
1
.
0
);
AV_WN16
(
&
frame
->
data
[
1
][
frame
->
linesize
[
1
]
*
y
+
2
*
x
],
mid
+
(
u
-
mid
)
*
f
);
AV_WN16
(
&
frame
->
data
[
2
][
frame
->
linesize
[
2
]
*
y
+
2
*
x
],
mid
+
(
v
-
mid
)
*
f
);
}
else
if
(
alpha
)
{
AV_WN16
(
&
frame
->
data
[
1
][
frame
->
linesize
[
1
]
*
y
+
2
*
x
],
mid
);
AV_WN16
(
&
frame
->
data
[
2
][
frame
->
linesize
[
2
]
*
y
+
2
*
x
],
mid
);
}
}
}
return
0
;
}
static
int
filter_frame
(
AVFilterLink
*
link
,
AVFrame
*
frame
)
{
AVFilterContext
*
avctx
=
link
->
dst
;
...
...
@@ -159,22 +270,31 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame)
#define RGB_TO_U(rgb) (((- FIXNUM(0.16874) * rgb[0] - FIXNUM(0.33126) * rgb[1] + FIXNUM(0.50000) * rgb[2] + (1 << 9) - 1) >> 10) + 128)
#define RGB_TO_V(rgb) ((( FIXNUM(0.50000) * rgb[0] - FIXNUM(0.41869) * rgb[1] - FIXNUM(0.08131) * rgb[2] + (1 << 9) - 1) >> 10) + 128)
static
av_cold
int
initialize_chromakey
(
AVFilterContext
*
avctx
)
static
av_cold
int
config_output
(
AVFilterLink
*
outlink
)
{
const
AVPixFmtDescriptor
*
desc
=
av_pix_fmt_desc_get
(
outlink
->
format
);
AVFilterContext
*
avctx
=
outlink
->
src
;
ChromakeyContext
*
ctx
=
avctx
->
priv
;
int
factor
;
ctx
->
depth
=
desc
->
comp
[
0
].
depth
;
ctx
->
mid
=
1
<<
(
ctx
->
depth
-
1
);
ctx
->
max
=
(
1
<<
ctx
->
depth
)
-
1
;
factor
=
1
<<
(
ctx
->
depth
-
8
);
if
(
ctx
->
is_yuv
)
{
ctx
->
chromakey_uv
[
0
]
=
ctx
->
chromakey_rgba
[
1
];
ctx
->
chromakey_uv
[
1
]
=
ctx
->
chromakey_rgba
[
2
];
ctx
->
chromakey_uv
[
0
]
=
ctx
->
chromakey_rgba
[
1
]
*
factor
;
ctx
->
chromakey_uv
[
1
]
=
ctx
->
chromakey_rgba
[
2
]
*
factor
;
}
else
{
ctx
->
chromakey_uv
[
0
]
=
RGB_TO_U
(
ctx
->
chromakey_rgba
);
ctx
->
chromakey_uv
[
1
]
=
RGB_TO_V
(
ctx
->
chromakey_rgba
);
ctx
->
chromakey_uv
[
0
]
=
RGB_TO_U
(
ctx
->
chromakey_rgba
)
*
factor
;
ctx
->
chromakey_uv
[
1
]
=
RGB_TO_V
(
ctx
->
chromakey_rgba
)
*
factor
;
}
if
(
!
strcmp
(
avctx
->
filter
->
name
,
"chromakey"
))
{
ctx
->
do_slice
=
do_chromakey
_slice
;
ctx
->
do_slice
=
ctx
->
depth
<=
8
?
do_chromakey_slice
:
do_chromakey16
_slice
;
}
else
{
ctx
->
do_slice
=
do_chromahold
_slice
;
ctx
->
do_slice
=
ctx
->
depth
<=
8
?
do_chromahold_slice
:
do_chromahold16
_slice
;
}
return
0
;
...
...
@@ -186,6 +306,10 @@ static av_cold int query_formats(AVFilterContext *avctx)
AV_PIX_FMT_YUVA420P
,
AV_PIX_FMT_YUVA422P
,
AV_PIX_FMT_YUVA444P
,
AV_PIX_FMT_YUVA420P9
,
AV_PIX_FMT_YUVA422P9
,
AV_PIX_FMT_YUVA444P9
,
AV_PIX_FMT_YUVA420P10
,
AV_PIX_FMT_YUVA422P10
,
AV_PIX_FMT_YUVA444P10
,
AV_PIX_FMT_YUVA422P12
,
AV_PIX_FMT_YUVA444P12
,
AV_PIX_FMT_YUVA420P16
,
AV_PIX_FMT_YUVA422P16
,
AV_PIX_FMT_YUVA444P16
,
AV_PIX_FMT_NONE
};
...
...
@@ -196,6 +320,15 @@ static av_cold int query_formats(AVFilterContext *avctx)
AV_PIX_FMT_YUVA420P
,
AV_PIX_FMT_YUVA422P
,
AV_PIX_FMT_YUVA444P
,
AV_PIX_FMT_YUV420P9
,
AV_PIX_FMT_YUV422P9
,
AV_PIX_FMT_YUV444P9
,
AV_PIX_FMT_YUV420P10
,
AV_PIX_FMT_YUV422P10
,
AV_PIX_FMT_YUV444P10
,
AV_PIX_FMT_YUV444P12
,
AV_PIX_FMT_YUV422P12
,
AV_PIX_FMT_YUV420P12
,
AV_PIX_FMT_YUV444P14
,
AV_PIX_FMT_YUV422P14
,
AV_PIX_FMT_YUV420P14
,
AV_PIX_FMT_YUV420P16
,
AV_PIX_FMT_YUV422P16
,
AV_PIX_FMT_YUV444P16
,
AV_PIX_FMT_YUVA420P9
,
AV_PIX_FMT_YUVA422P9
,
AV_PIX_FMT_YUVA444P9
,
AV_PIX_FMT_YUVA420P10
,
AV_PIX_FMT_YUVA422P10
,
AV_PIX_FMT_YUVA444P10
,
AV_PIX_FMT_YUVA422P12
,
AV_PIX_FMT_YUVA444P12
,
AV_PIX_FMT_YUVA420P16
,
AV_PIX_FMT_YUVA422P16
,
AV_PIX_FMT_YUVA444P16
,
AV_PIX_FMT_NONE
};
...
...
@@ -235,6 +368,7 @@ static const AVFilterPad chromakey_outputs[] = {
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
config_props
=
config_output
,
},
{
NULL
}
};
...
...
@@ -257,7 +391,6 @@ AVFilter ff_vf_chromakey = {
.
description
=
NULL_IF_CONFIG_SMALL
(
"Turns a certain color into transparency. Operates on YUV colors."
),
.
priv_size
=
sizeof
(
ChromakeyContext
),
.
priv_class
=
&
chromakey_class
,
.
init
=
initialize_chromakey
,
.
query_formats
=
query_formats
,
.
inputs
=
chromakey_inputs
,
.
outputs
=
chromakey_outputs
,
...
...
@@ -287,6 +420,7 @@ static const AVFilterPad chromahold_outputs[] = {
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
config_props
=
config_output
,
},
{
NULL
}
};
...
...
@@ -298,7 +432,6 @@ AVFilter ff_vf_chromahold = {
.
description
=
NULL_IF_CONFIG_SMALL
(
"Turns a certain color range into gray."
),
.
priv_size
=
sizeof
(
ChromakeyContext
),
.
priv_class
=
&
chromahold_class
,
.
init
=
initialize_chromakey
,
.
query_formats
=
query_formats
,
.
inputs
=
chromahold_inputs
,
.
outputs
=
chromahold_outputs
,
...
...
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