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
feeef2f8
Commit
feeef2f8
authored
Jan 12, 2020
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfilter/vf_normalize: add support for >8 depth
parent
ac511730
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
105 additions
and
16 deletions
+105
-16
vf_normalize.c
libavfilter/vf_normalize.c
+105
-16
No files found.
libavfilter/vf_normalize.c
View file @
feeef2f8
...
...
@@ -73,6 +73,7 @@
*/
#include "libavutil/imgutils.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "avfilter.h"
...
...
@@ -82,12 +83,12 @@
#include "video.h"
typedef
struct
NormalizeHistory
{
uint
8_t
*
history
;
// History entries.
uint
32
_t
history_sum
;
// Sum of history entries.
uint
16_t
*
history
;
// History entries.
uint
64
_t
history_sum
;
// Sum of history entries.
}
NormalizeHistory
;
typedef
struct
NormalizeLocal
{
uint
8_t
in
;
// Original input byte value for this frame.
uint
16_t
in
;
// Original input byte value for this frame.
float
smoothed
;
// Smoothed input value [0,255].
float
out
;
// Output value [0,255]
}
NormalizeLocal
;
...
...
@@ -103,6 +104,9 @@ typedef struct NormalizeContext {
float
strength
;
uint8_t
co
[
4
];
// Offsets to R,G,B,A bytes respectively in each pixel
int
depth
;
int
sblackpt
[
4
];
int
swhitept
[
4
];
int
num_components
;
// Number of components in the pixel format
int
step
;
int
history_len
;
// Number of frames to average; based on smoothing factor
...
...
@@ -110,9 +114,9 @@ typedef struct NormalizeContext {
// Per-extremum, per-channel history, for temporal smoothing.
NormalizeHistory
min
[
3
],
max
[
3
];
// Min and max for each channel in {R,G,B}.
uint
8
_t
*
history_mem
;
// Single allocation for above history entries
uint
16
_t
*
history_mem
;
// Single allocation for above history entries
uint
8_t
lut
[
3
][
25
6
];
// Lookup table
uint
16_t
lut
[
3
][
6553
6
];
// Lookup table
void
(
*
find_min_max
)(
struct
NormalizeContext
*
s
,
AVFrame
*
in
,
NormalizeLocal
min
[
3
],
NormalizeLocal
max
[
3
]);
void
(
*
process
)(
struct
NormalizeContext
*
s
,
AVFrame
*
in
,
AVFrame
*
out
);
...
...
@@ -207,6 +211,80 @@ static void process_planar(NormalizeContext *s, AVFrame *in, AVFrame *out)
}
}
static
void
find_min_max_16
(
NormalizeContext
*
s
,
AVFrame
*
in
,
NormalizeLocal
min
[
3
],
NormalizeLocal
max
[
3
])
{
for
(
int
c
=
0
;
c
<
3
;
c
++
)
min
[
c
].
in
=
max
[
c
].
in
=
AV_RN16
(
in
->
data
[
0
]
+
2
*
s
->
co
[
c
]);
for
(
int
y
=
0
;
y
<
in
->
height
;
y
++
)
{
uint16_t
*
inp
=
(
uint16_t
*
)(
in
->
data
[
0
]
+
y
*
in
->
linesize
[
0
]);
for
(
int
x
=
0
;
x
<
in
->
width
;
x
++
)
{
for
(
int
c
=
0
;
c
<
3
;
c
++
)
{
min
[
c
].
in
=
FFMIN
(
min
[
c
].
in
,
inp
[
s
->
co
[
c
]]);
max
[
c
].
in
=
FFMAX
(
max
[
c
].
in
,
inp
[
s
->
co
[
c
]]);
}
inp
+=
s
->
step
;
}
}
}
static
void
process_16
(
NormalizeContext
*
s
,
AVFrame
*
in
,
AVFrame
*
out
)
{
for
(
int
y
=
0
;
y
<
in
->
height
;
y
++
)
{
uint16_t
*
inp
=
(
uint16_t
*
)(
in
->
data
[
0
]
+
y
*
in
->
linesize
[
0
]);
uint16_t
*
outp
=
(
uint16_t
*
)(
out
->
data
[
0
]
+
y
*
out
->
linesize
[
0
]);
for
(
int
x
=
0
;
x
<
in
->
width
;
x
++
)
{
for
(
int
c
=
0
;
c
<
3
;
c
++
)
outp
[
s
->
co
[
c
]]
=
s
->
lut
[
c
][
inp
[
s
->
co
[
c
]]];
if
(
s
->
num_components
==
4
)
// Copy alpha as-is.
outp
[
s
->
co
[
3
]]
=
inp
[
s
->
co
[
3
]];
inp
+=
s
->
step
;
outp
+=
s
->
step
;
}
}
}
static
void
find_min_max_planar_16
(
NormalizeContext
*
s
,
AVFrame
*
in
,
NormalizeLocal
min
[
3
],
NormalizeLocal
max
[
3
])
{
min
[
0
].
in
=
max
[
0
].
in
=
AV_RN16
(
in
->
data
[
2
]);
min
[
1
].
in
=
max
[
1
].
in
=
AV_RN16
(
in
->
data
[
0
]);
min
[
2
].
in
=
max
[
2
].
in
=
AV_RN16
(
in
->
data
[
1
]);
for
(
int
y
=
0
;
y
<
in
->
height
;
y
++
)
{
uint16_t
*
inrp
=
(
uint16_t
*
)(
in
->
data
[
2
]
+
y
*
in
->
linesize
[
2
]);
uint16_t
*
ingp
=
(
uint16_t
*
)(
in
->
data
[
0
]
+
y
*
in
->
linesize
[
0
]);
uint16_t
*
inbp
=
(
uint16_t
*
)(
in
->
data
[
1
]
+
y
*
in
->
linesize
[
1
]);
for
(
int
x
=
0
;
x
<
in
->
width
;
x
++
)
{
min
[
0
].
in
=
FFMIN
(
min
[
0
].
in
,
inrp
[
x
]);
max
[
0
].
in
=
FFMAX
(
max
[
0
].
in
,
inrp
[
x
]);
min
[
1
].
in
=
FFMIN
(
min
[
1
].
in
,
ingp
[
x
]);
max
[
1
].
in
=
FFMAX
(
max
[
1
].
in
,
ingp
[
x
]);
min
[
2
].
in
=
FFMIN
(
min
[
2
].
in
,
inbp
[
x
]);
max
[
2
].
in
=
FFMAX
(
max
[
2
].
in
,
inbp
[
x
]);
}
}
}
static
void
process_planar_16
(
NormalizeContext
*
s
,
AVFrame
*
in
,
AVFrame
*
out
)
{
for
(
int
y
=
0
;
y
<
in
->
height
;
y
++
)
{
uint16_t
*
inrp
=
(
uint16_t
*
)(
in
->
data
[
2
]
+
y
*
in
->
linesize
[
2
]);
uint16_t
*
ingp
=
(
uint16_t
*
)(
in
->
data
[
0
]
+
y
*
in
->
linesize
[
0
]);
uint16_t
*
inbp
=
(
uint16_t
*
)(
in
->
data
[
1
]
+
y
*
in
->
linesize
[
1
]);
uint16_t
*
inap
=
(
uint16_t
*
)(
in
->
data
[
3
]
+
y
*
in
->
linesize
[
3
]);
uint16_t
*
outrp
=
(
uint16_t
*
)(
out
->
data
[
2
]
+
y
*
out
->
linesize
[
2
]);
uint16_t
*
outgp
=
(
uint16_t
*
)(
out
->
data
[
0
]
+
y
*
out
->
linesize
[
0
]);
uint16_t
*
outbp
=
(
uint16_t
*
)(
out
->
data
[
1
]
+
y
*
out
->
linesize
[
1
]);
uint16_t
*
outap
=
(
uint16_t
*
)(
out
->
data
[
3
]
+
y
*
out
->
linesize
[
3
]);
for
(
int
x
=
0
;
x
<
in
->
width
;
x
++
)
{
outrp
[
x
]
=
s
->
lut
[
0
][
inrp
[
x
]];
outgp
[
x
]
=
s
->
lut
[
1
][
ingp
[
x
]];
outbp
[
x
]
=
s
->
lut
[
2
][
inbp
[
x
]];
if
(
s
->
num_components
==
4
)
outap
[
x
]
=
inap
[
x
];
}
}
}
// This function is the main guts of the filter. Normalizes the input frame
// into the output frame. The frames are known to have the same dimensions
// and pixel format.
...
...
@@ -269,9 +347,9 @@ static void normalize(NormalizeContext *s, AVFrame *in, AVFrame *out)
// Calculate the output range [min.out,max.out] as a ratio of the full-
// strength output range [blackpt,whitept] and the original input range
// [min.in,max.in], based on the user-specified filter strength.
min
[
c
].
out
=
(
s
->
blackpt
[
c
]
*
s
->
strength
)
min
[
c
].
out
=
(
s
->
sblackpt
[
c
]
*
s
->
strength
)
+
(
min
[
c
].
in
*
(
1
.
0
f
-
s
->
strength
));
max
[
c
].
out
=
(
s
->
whitept
[
c
]
*
s
->
strength
)
max
[
c
].
out
=
(
s
->
swhitept
[
c
]
*
s
->
strength
)
+
(
max
[
c
].
in
*
(
1
.
0
f
-
s
->
strength
));
// Now, build a lookup table which linearly maps the adjusted input range
...
...
@@ -291,8 +369,7 @@ static void normalize(NormalizeContext *s, AVFrame *in, AVFrame *out)
float
scale
=
(
max
[
c
].
out
-
min
[
c
].
out
)
/
(
max
[
c
].
smoothed
-
min
[
c
].
smoothed
);
for
(
in_val
=
min
[
c
].
in
;
in_val
<=
max
[
c
].
in
;
in_val
++
)
{
int
out_val
=
(
in_val
-
min
[
c
].
smoothed
)
*
scale
+
min
[
c
].
out
+
0
.
5
f
;
out_val
=
FFMAX
(
out_val
,
0
);
out_val
=
FFMIN
(
out_val
,
255
);
out_val
=
av_clip_uintp2_c
(
out_val
,
s
->
depth
);
s
->
lut
[
c
][
in_val
]
=
out_val
;
}
}
...
...
@@ -324,8 +401,11 @@ static int query_formats(AVFilterContext *ctx)
AV_PIX_FMT_RGB0
,
AV_PIX_FMT_0BGR
,
AV_PIX_FMT_BGR0
,
AV_PIX_FMT_GBRAP
,
AV_PIX_FMT_GBRP
,
AV_PIX_FMT_RGB48
,
AV_PIX_FMT_BGR48
,
AV_PIX_FMT_RGBA64
,
AV_PIX_FMT_BGRA64
,
AV_PIX_FMT_GBRP
,
AV_PIX_FMT_GBRP9
,
AV_PIX_FMT_GBRP10
,
AV_PIX_FMT_GBRP12
,
AV_PIX_FMT_GBRP14
,
AV_PIX_FMT_GBRP16
,
AV_PIX_FMT_GBRAP
,
AV_PIX_FMT_GBRAP10
,
AV_PIX_FMT_GBRAP12
,
AV_PIX_FMT_GBRAP16
,
AV_PIX_FMT_NONE
};
// According to filter_design.txt, using ff_set_common_formats() this way
...
...
@@ -345,11 +425,13 @@ static int config_input(AVFilterLink *inlink)
NormalizeContext
*
s
=
inlink
->
dst
->
priv
;
// Store offsets to R,G,B,A bytes respectively in each pixel
const
AVPixFmtDescriptor
*
desc
=
av_pix_fmt_desc_get
(
inlink
->
format
);
int
c
,
planar
;
int
c
,
planar
,
scale
;
ff_fill_rgba_map
(
s
->
co
,
inlink
->
format
);
s
->
depth
=
desc
->
comp
[
0
].
depth
;
scale
=
1
<<
(
s
->
depth
-
8
);
s
->
num_components
=
desc
->
nb_components
;
s
->
step
=
av_get_padded_bits_per_pixel
(
desc
)
>>
3
;
s
->
step
=
av_get_padded_bits_per_pixel
(
desc
)
>>
(
3
+
(
s
->
depth
>
8
))
;
// Convert smoothing value to history_len (a count of frames to average,
// must be at least 1). Currently this is a direct assignment, but the
// smoothing value was originally envisaged as a number of seconds. In
...
...
@@ -359,19 +441,26 @@ static int config_input(AVFilterLink *inlink)
// Allocate the history buffers -- there are 6 -- one for each extrema.
// s->smoothing is limited to INT_MAX/8, so that (s->history_len * 6)
// can't overflow on 32bit causing a too-small allocation.
s
->
history_mem
=
av_malloc
(
s
->
history_len
*
6
);
s
->
history_mem
=
av_malloc
(
s
->
history_len
*
6
*
sizeof
(
*
s
->
history_mem
)
);
if
(
s
->
history_mem
==
NULL
)
return
AVERROR
(
ENOMEM
);
for
(
c
=
0
;
c
<
3
;
c
++
)
{
s
->
min
[
c
].
history
=
s
->
history_mem
+
(
c
*
2
)
*
s
->
history_len
;
s
->
max
[
c
].
history
=
s
->
history_mem
+
(
c
*
2
+
1
)
*
s
->
history_len
;
s
->
sblackpt
[
c
]
=
scale
*
s
->
blackpt
[
c
]
+
(
s
->
blackpt
[
c
]
>>
(
s
->
depth
-
8
));
s
->
swhitept
[
c
]
=
scale
*
s
->
whitept
[
c
]
+
(
s
->
whitept
[
c
]
>>
(
s
->
depth
-
8
));
}
planar
=
desc
->
flags
&
AV_PIX_FMT_FLAG_PLANAR
;
s
->
find_min_max
=
planar
?
find_min_max_planar
:
find_min_max
;
s
->
process
=
planar
?
process_planar
:
process
;
if
(
s
->
depth
<=
8
)
{
s
->
find_min_max
=
planar
?
find_min_max_planar
:
find_min_max
;
s
->
process
=
planar
?
process_planar
:
process
;
}
else
{
s
->
find_min_max
=
planar
?
find_min_max_planar_16
:
find_min_max_16
;
s
->
process
=
planar
?
process_planar_16
:
process_16
;
}
return
0
;
}
...
...
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