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
140a0485
Commit
140a0485
authored
Sep 10, 2016
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfilter/vf_overlay: split blend_image into functions for each overlay format
Signed-off-by:
Paul B Mahol
<
onemda@gmail.com
>
parent
054f912c
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
186 additions
and
166 deletions
+186
-166
vf_overlay.c
libavfilter/vf_overlay.c
+186
-166
No files found.
libavfilter/vf_overlay.c
View file @
140a0485
...
@@ -132,6 +132,8 @@ typedef struct OverlayContext {
...
@@ -132,6 +132,8 @@ typedef struct OverlayContext {
int
eof_action
;
///< action to take on EOF from source
int
eof_action
;
///< action to take on EOF from source
AVExpr
*
x_pexpr
,
*
y_pexpr
;
AVExpr
*
x_pexpr
,
*
y_pexpr
;
void
(
*
blend_image
)(
AVFilterContext
*
ctx
,
AVFrame
*
dst
,
const
AVFrame
*
src
,
int
x
,
int
y
);
}
OverlayContext
;
}
OverlayContext
;
static
av_cold
void
uninit
(
AVFilterContext
*
ctx
)
static
av_cold
void
uninit
(
AVFilterContext
*
ctx
)
...
@@ -304,22 +306,6 @@ static const enum AVPixelFormat alpha_pix_fmts[] = {
...
@@ -304,22 +306,6 @@ static const enum AVPixelFormat alpha_pix_fmts[] = {
AV_PIX_FMT_BGRA
,
AV_PIX_FMT_NONE
AV_PIX_FMT_BGRA
,
AV_PIX_FMT_NONE
};
};
static
int
config_input_main
(
AVFilterLink
*
inlink
)
{
OverlayContext
*
s
=
inlink
->
dst
->
priv
;
const
AVPixFmtDescriptor
*
pix_desc
=
av_pix_fmt_desc_get
(
inlink
->
format
);
av_image_fill_max_pixsteps
(
s
->
main_pix_step
,
NULL
,
pix_desc
);
s
->
hsub
=
pix_desc
->
log2_chroma_w
;
s
->
vsub
=
pix_desc
->
log2_chroma_h
;
s
->
main_is_packed_rgb
=
ff_fill_rgba_map
(
s
->
main_rgba_map
,
inlink
->
format
)
>=
0
;
s
->
main_has_alpha
=
ff_fmt_is_in
(
inlink
->
format
,
alpha_pix_fmts
);
return
0
;
}
static
int
config_input_overlay
(
AVFilterLink
*
inlink
)
static
int
config_input_overlay
(
AVFilterLink
*
inlink
)
{
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
AVFilterContext
*
ctx
=
inlink
->
dst
;
...
@@ -397,22 +383,17 @@ static int config_output(AVFilterLink *outlink)
...
@@ -397,22 +383,17 @@ static int config_output(AVFilterLink *outlink)
/**
/**
* Blend image in src to destination buffer dst at position (x, y).
* Blend image in src to destination buffer dst at position (x, y).
*/
*/
static
void
blend_image
(
AVFilterContext
*
ctx
,
static
void
blend_image_packed_rgb
(
AVFilterContext
*
ctx
,
AVFrame
*
dst
,
const
AVFrame
*
src
,
AVFrame
*
dst
,
const
AVFrame
*
src
,
int
x
,
int
y
)
int
x
,
int
y
)
{
{
OverlayContext
*
s
=
ctx
->
priv
;
OverlayContext
*
s
=
ctx
->
priv
;
int
i
,
imax
,
j
,
jmax
,
k
,
kmax
;
int
i
,
imax
,
j
,
jmax
;
const
int
src_w
=
src
->
width
;
const
int
src_w
=
src
->
width
;
const
int
src_h
=
src
->
height
;
const
int
src_h
=
src
->
height
;
const
int
dst_w
=
dst
->
width
;
const
int
dst_w
=
dst
->
width
;
const
int
dst_h
=
dst
->
height
;
const
int
dst_h
=
dst
->
height
;
if
(
x
>=
dst_w
||
x
+
src_w
<
0
||
y
>=
dst_h
||
y
+
src_h
<
0
)
return
;
/* no intersection */
if
(
s
->
main_is_packed_rgb
)
{
uint8_t
alpha
;
///< the amount of overlay to blend on to main
uint8_t
alpha
;
///< the amount of overlay to blend on to main
const
int
dr
=
s
->
main_rgba_map
[
R
];
const
int
dr
=
s
->
main_rgba_map
[
R
];
const
int
dg
=
s
->
main_rgba_map
[
G
];
const
int
dg
=
s
->
main_rgba_map
[
G
];
...
@@ -425,7 +406,7 @@ static void blend_image(AVFilterContext *ctx,
...
@@ -425,7 +406,7 @@ static void blend_image(AVFilterContext *ctx,
const
int
sa
=
s
->
overlay_rgba_map
[
A
];
const
int
sa
=
s
->
overlay_rgba_map
[
A
];
const
int
sstep
=
s
->
overlay_pix_step
[
0
];
const
int
sstep
=
s
->
overlay_pix_step
[
0
];
const
int
main_has_alpha
=
s
->
main_has_alpha
;
const
int
main_has_alpha
=
s
->
main_has_alpha
;
uint8_t
*
s
,
*
sp
,
*
d
,
*
dp
;
uint8_t
*
S
,
*
sp
,
*
d
,
*
dp
;
i
=
FFMAX
(
-
y
,
0
);
i
=
FFMAX
(
-
y
,
0
);
sp
=
src
->
data
[
0
]
+
i
*
src
->
linesize
[
0
];
sp
=
src
->
data
[
0
]
+
i
*
src
->
linesize
[
0
];
...
@@ -433,11 +414,11 @@ static void blend_image(AVFilterContext *ctx,
...
@@ -433,11 +414,11 @@ static void blend_image(AVFilterContext *ctx,
for
(
imax
=
FFMIN
(
-
y
+
dst_h
,
src_h
);
i
<
imax
;
i
++
)
{
for
(
imax
=
FFMIN
(
-
y
+
dst_h
,
src_h
);
i
<
imax
;
i
++
)
{
j
=
FFMAX
(
-
x
,
0
);
j
=
FFMAX
(
-
x
,
0
);
s
=
sp
+
j
*
sstep
;
S
=
sp
+
j
*
sstep
;
d
=
dp
+
(
x
+
j
)
*
dstep
;
d
=
dp
+
(
x
+
j
)
*
dstep
;
for
(
jmax
=
FFMIN
(
-
x
+
dst_w
,
src_w
);
j
<
jmax
;
j
++
)
{
for
(
jmax
=
FFMIN
(
-
x
+
dst_w
,
src_w
);
j
<
jmax
;
j
++
)
{
alpha
=
s
[
sa
];
alpha
=
S
[
sa
];
// if the main channel has an alpha channel, alpha has to be calculated
// if the main channel has an alpha channel, alpha has to be calculated
// to create an un-premultiplied (straight) alpha value
// to create an un-premultiplied (straight) alpha value
...
@@ -450,37 +431,49 @@ static void blend_image(AVFilterContext *ctx,
...
@@ -450,37 +431,49 @@ static void blend_image(AVFilterContext *ctx,
case
0
:
case
0
:
break
;
break
;
case
255
:
case
255
:
d
[
dr
]
=
s
[
sr
];
d
[
dr
]
=
S
[
sr
];
d
[
dg
]
=
s
[
sg
];
d
[
dg
]
=
S
[
sg
];
d
[
db
]
=
s
[
sb
];
d
[
db
]
=
S
[
sb
];
break
;
break
;
default:
default:
// main_value = main_value * (1 - alpha) + overlay_value * alpha
// main_value = main_value * (1 - alpha) + overlay_value * alpha
// since alpha is in the range 0-255, the result must divided by 255
// since alpha is in the range 0-255, the result must divided by 255
d
[
dr
]
=
FAST_DIV255
(
d
[
dr
]
*
(
255
-
alpha
)
+
s
[
sr
]
*
alpha
);
d
[
dr
]
=
FAST_DIV255
(
d
[
dr
]
*
(
255
-
alpha
)
+
S
[
sr
]
*
alpha
);
d
[
dg
]
=
FAST_DIV255
(
d
[
dg
]
*
(
255
-
alpha
)
+
s
[
sg
]
*
alpha
);
d
[
dg
]
=
FAST_DIV255
(
d
[
dg
]
*
(
255
-
alpha
)
+
S
[
sg
]
*
alpha
);
d
[
db
]
=
FAST_DIV255
(
d
[
db
]
*
(
255
-
alpha
)
+
s
[
sb
]
*
alpha
);
d
[
db
]
=
FAST_DIV255
(
d
[
db
]
*
(
255
-
alpha
)
+
S
[
sb
]
*
alpha
);
}
}
if
(
main_has_alpha
)
{
if
(
main_has_alpha
)
{
switch
(
alpha
)
{
switch
(
alpha
)
{
case
0
:
case
0
:
break
;
break
;
case
255
:
case
255
:
d
[
da
]
=
s
[
sa
];
d
[
da
]
=
S
[
sa
];
break
;
break
;
default:
default:
// apply alpha compositing: main_alpha += (1-main_alpha) * overlay_alpha
// apply alpha compositing: main_alpha += (1-main_alpha) * overlay_alpha
d
[
da
]
+=
FAST_DIV255
((
255
-
d
[
da
])
*
s
[
sa
]);
d
[
da
]
+=
FAST_DIV255
((
255
-
d
[
da
])
*
S
[
sa
]);
}
}
}
}
d
+=
dstep
;
d
+=
dstep
;
s
+=
sstep
;
S
+=
sstep
;
}
}
dp
+=
dst
->
linesize
[
0
];
dp
+=
dst
->
linesize
[
0
];
sp
+=
src
->
linesize
[
0
];
sp
+=
src
->
linesize
[
0
];
}
}
}
else
{
}
static
void
blend_image_yuv
(
AVFilterContext
*
ctx
,
AVFrame
*
dst
,
const
AVFrame
*
src
,
int
x
,
int
y
)
{
OverlayContext
*
s
=
ctx
->
priv
;
int
i
,
imax
,
j
,
jmax
,
k
,
kmax
;
const
int
src_w
=
src
->
width
;
const
int
src_h
=
src
->
height
;
const
int
dst_w
=
dst
->
width
;
const
int
dst_h
=
dst
->
height
;
const
int
main_has_alpha
=
s
->
main_has_alpha
;
const
int
main_has_alpha
=
s
->
main_has_alpha
;
if
(
main_has_alpha
)
{
if
(
main_has_alpha
)
{
uint8_t
alpha
;
///< the amount of overlay to blend on to main
uint8_t
alpha
;
///< the amount of overlay to blend on to main
uint8_t
*
s
,
*
sa
,
*
d
,
*
da
;
uint8_t
*
s
,
*
sa
,
*
d
,
*
da
;
...
@@ -582,7 +575,32 @@ static void blend_image(AVFilterContext *ctx,
...
@@ -582,7 +575,32 @@ static void blend_image(AVFilterContext *ctx,
ap
+=
(
1
<<
vsub
)
*
src
->
linesize
[
3
];
ap
+=
(
1
<<
vsub
)
*
src
->
linesize
[
3
];
}
}
}
}
}
static
int
config_input_main
(
AVFilterLink
*
inlink
)
{
OverlayContext
*
s
=
inlink
->
dst
->
priv
;
const
AVPixFmtDescriptor
*
pix_desc
=
av_pix_fmt_desc_get
(
inlink
->
format
);
av_image_fill_max_pixsteps
(
s
->
main_pix_step
,
NULL
,
pix_desc
);
s
->
hsub
=
pix_desc
->
log2_chroma_w
;
s
->
vsub
=
pix_desc
->
log2_chroma_h
;
s
->
main_is_packed_rgb
=
ff_fill_rgba_map
(
s
->
main_rgba_map
,
inlink
->
format
)
>=
0
;
s
->
main_has_alpha
=
ff_fmt_is_in
(
inlink
->
format
,
alpha_pix_fmts
);
switch
(
s
->
format
)
{
case
OVERLAY_FORMAT_YUV420
:
case
OVERLAY_FORMAT_YUV422
:
case
OVERLAY_FORMAT_YUV444
:
s
->
blend_image
=
blend_image_yuv
;
break
;
case
OVERLAY_FORMAT_RGB
:
s
->
blend_image
=
blend_image_packed_rgb
;
break
;
}
}
return
0
;
}
}
static
AVFrame
*
do_blend
(
AVFilterContext
*
ctx
,
AVFrame
*
mainpic
,
static
AVFrame
*
do_blend
(
AVFilterContext
*
ctx
,
AVFrame
*
mainpic
,
...
@@ -611,7 +629,9 @@ static AVFrame *do_blend(AVFilterContext *ctx, AVFrame *mainpic,
...
@@ -611,7 +629,9 @@ static AVFrame *do_blend(AVFilterContext *ctx, AVFrame *mainpic,
s
->
var_values
[
VAR_Y
],
s
->
y
);
s
->
var_values
[
VAR_Y
],
s
->
y
);
}
}
blend_image
(
ctx
,
mainpic
,
second
,
s
->
x
,
s
->
y
);
if
(
s
->
x
<
mainpic
->
width
&&
s
->
x
+
second
->
width
>=
0
||
s
->
y
<
mainpic
->
height
&&
s
->
y
+
second
->
height
>=
0
)
s
->
blend_image
(
ctx
,
mainpic
,
second
,
s
->
x
,
s
->
y
);
return
mainpic
;
return
mainpic
;
}
}
...
...
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