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
314a783b
Commit
314a783b
authored
Feb 15, 2020
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfilter/vf_phase: add >8 bit support
parent
732d77dc
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
246 additions
and
148 deletions
+246
-148
phase_template.c
libavfilter/phase_template.c
+183
-0
vf_phase.c
libavfilter/vf_phase.c
+63
-148
No files found.
libavfilter/phase_template.c
0 → 100644
View file @
314a783b
/*
* Copyright (c) 2004 Ville Saari
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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/avassert.h"
#include "avfilter.h"
#include "formats.h"
#include "internal.h"
#include "video.h"
#undef pixel
#undef accumulator
#if DEPTH == 8
#define pixel uint8_t
#define accumulator int
#else
#define pixel uint16_t
#define accumulator int64_t
#endif
#define fn3(a,b) a##_##b
#define fn2(a,b) fn3(a,b)
#define fn(a) fn2(a, DEPTH)
/*
* This macro interpolates the value of both fields at a point halfway
* between lines and takes the squared difference. In field resolution
* the point is a quarter pixel below a line in one field and a quarter
* pixel above a line in other.
*
* (The result is actually multiplied by 25)
*/
#define DIFF(a, as, b, bs) ((t) = ((*(a) - (b)[bs]) << 2) + (a)[(as) << 1] - (b)[-(bs)], (t) * (t))
/*
* Find which field combination has the smallest average squared difference
* between the fields.
*/
static
enum
PhaseMode
fn
(
analyze_plane
)(
void
*
ctx
,
enum
PhaseMode
mode
,
AVFrame
*
old
,
AVFrame
*
new
)
{
double
bdiff
,
tdiff
,
pdiff
;
if
(
mode
==
AUTO
)
{
mode
=
new
->
interlaced_frame
?
new
->
top_field_first
?
TOP_FIRST
:
BOTTOM_FIRST
:
PROGRESSIVE
;
}
else
if
(
mode
==
AUTO_ANALYZE
)
{
mode
=
new
->
interlaced_frame
?
new
->
top_field_first
?
TOP_FIRST_ANALYZE
:
BOTTOM_FIRST_ANALYZE
:
FULL_ANALYZE
;
}
if
(
mode
<=
BOTTOM_FIRST
)
{
bdiff
=
pdiff
=
tdiff
=
65536
.
0
;
}
else
{
const
double
factor
=
1
.
/
(
25
.
*
(
1
<<
(
DEPTH
-
8
))
*
(
1
<<
(
DEPTH
-
8
)));
const
int
ns
=
new
->
linesize
[
0
]
/
sizeof
(
pixel
);
const
int
os
=
old
->
linesize
[
0
]
/
sizeof
(
pixel
);
const
pixel
*
nptr
=
(
pixel
*
)
new
->
data
[
0
];
const
pixel
*
optr
=
(
pixel
*
)
old
->
data
[
0
];
const
int
h
=
new
->
height
;
const
int
w
=
new
->
width
;
accumulator
bdif
,
tdif
,
pdif
;
double
scale
;
int
top
=
0
,
t
;
const
pixel
*
rend
,
*
end
=
nptr
+
(
h
-
2
)
*
ns
;
bdiff
=
pdiff
=
tdiff
=
0
.
0
;
nptr
+=
ns
;
optr
+=
os
;
while
(
nptr
<
end
)
{
pdif
=
tdif
=
bdif
=
0
;
switch
(
mode
)
{
case
TOP_FIRST_ANALYZE
:
if
(
top
)
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
pdif
+=
DIFF
(
nptr
,
ns
,
nptr
,
ns
);
tdif
+=
DIFF
(
nptr
,
ns
,
optr
,
os
);
}
}
else
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
pdif
+=
DIFF
(
nptr
,
ns
,
nptr
,
ns
);
tdif
+=
DIFF
(
optr
,
os
,
nptr
,
ns
);
}
}
break
;
case
BOTTOM_FIRST_ANALYZE
:
if
(
top
)
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
pdif
+=
DIFF
(
nptr
,
ns
,
nptr
,
ns
);
bdif
+=
DIFF
(
optr
,
os
,
nptr
,
ns
);
}
}
else
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
pdif
+=
DIFF
(
nptr
,
ns
,
nptr
,
ns
);
bdif
+=
DIFF
(
nptr
,
ns
,
optr
,
os
);
}
}
break
;
case
ANALYZE
:
if
(
top
)
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
tdif
+=
DIFF
(
nptr
,
ns
,
optr
,
os
);
bdif
+=
DIFF
(
optr
,
os
,
nptr
,
ns
);
}
}
else
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
bdif
+=
DIFF
(
nptr
,
ns
,
optr
,
os
);
tdif
+=
DIFF
(
optr
,
os
,
nptr
,
ns
);
}
}
break
;
case
FULL_ANALYZE
:
if
(
top
)
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
pdif
+=
DIFF
(
nptr
,
ns
,
nptr
,
ns
);
tdif
+=
DIFF
(
nptr
,
ns
,
optr
,
os
);
bdif
+=
DIFF
(
optr
,
os
,
nptr
,
ns
);
}
}
else
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
pdif
+=
DIFF
(
nptr
,
ns
,
nptr
,
ns
);
bdif
+=
DIFF
(
nptr
,
ns
,
optr
,
os
);
tdif
+=
DIFF
(
optr
,
os
,
nptr
,
ns
);
}
}
break
;
default:
av_assert0
(
0
);
}
pdiff
+=
(
double
)
pdif
;
tdiff
+=
(
double
)
tdif
;
bdiff
+=
(
double
)
bdif
;
nptr
+=
ns
-
w
;
optr
+=
os
-
w
;
top
^=
1
;
}
scale
=
1
.
0
/
(
w
*
(
h
-
3
))
*
factor
;
pdiff
*=
scale
;
tdiff
*=
scale
;
bdiff
*=
scale
;
if
(
mode
==
TOP_FIRST_ANALYZE
)
{
bdiff
=
65536
.
0
;
}
else
if
(
mode
==
BOTTOM_FIRST_ANALYZE
)
{
tdiff
=
65536
.
0
;
}
else
if
(
mode
==
ANALYZE
)
{
pdiff
=
65536
.
0
;
}
if
(
bdiff
<
pdiff
&&
bdiff
<
tdiff
)
{
mode
=
BOTTOM_FIRST
;
}
else
if
(
tdiff
<
pdiff
&&
tdiff
<
bdiff
)
{
mode
=
TOP_FIRST
;
}
else
{
mode
=
PROGRESSIVE
;
}
}
av_log
(
ctx
,
AV_LOG_DEBUG
,
"mode=%c tdiff=%f bdiff=%f pdiff=%f
\n
"
,
mode
==
BOTTOM_FIRST
?
'b'
:
mode
==
TOP_FIRST
?
't'
:
'p'
,
tdiff
,
bdiff
,
pdiff
);
return
mode
;
}
libavfilter/vf_phase.c
View file @
314a783b
...
@@ -39,6 +39,29 @@ enum PhaseMode {
...
@@ -39,6 +39,29 @@ enum PhaseMode {
AUTO_ANALYZE
AUTO_ANALYZE
};
};
#define DEPTH 8
#include "phase_template.c"
#undef DEPTH
#define DEPTH 9
#include "phase_template.c"
#undef DEPTH
#define DEPTH 10
#include "phase_template.c"
#undef DEPTH
#define DEPTH 12
#include "phase_template.c"
#undef DEPTH
#define DEPTH 14
#include "phase_template.c"
#undef DEPTH
#define DEPTH 16
#include "phase_template.c"
typedef
struct
PhaseContext
{
typedef
struct
PhaseContext
{
const
AVClass
*
class
;
const
AVClass
*
class
;
int
mode
;
///<PhaseMode
int
mode
;
///<PhaseMode
...
@@ -46,6 +69,8 @@ typedef struct PhaseContext {
...
@@ -46,6 +69,8 @@ typedef struct PhaseContext {
int
nb_planes
;
int
nb_planes
;
int
planeheight
[
4
];
int
planeheight
[
4
];
int
linesize
[
4
];
int
linesize
[
4
];
enum
PhaseMode
(
*
analyze_plane
)(
void
*
ctx
,
enum
PhaseMode
mode
,
AVFrame
*
old
,
AVFrame
*
new
);
}
PhaseContext
;
}
PhaseContext
;
#define OFFSET(x) offsetof(PhaseContext, x)
#define OFFSET(x) offsetof(PhaseContext, x)
...
@@ -71,10 +96,33 @@ AVFILTER_DEFINE_CLASS(phase);
...
@@ -71,10 +96,33 @@ AVFILTER_DEFINE_CLASS(phase);
static
int
query_formats
(
AVFilterContext
*
ctx
)
static
int
query_formats
(
AVFilterContext
*
ctx
)
{
{
static
const
enum
AVPixelFormat
pix_fmts
[]
=
{
static
const
enum
AVPixelFormat
pix_fmts
[]
=
{
AV_PIX_FMT_YUVA444P
,
AV_PIX_FMT_YUVA422P
,
AV_PIX_FMT_YUVA420P
,
AV_PIX_FMT_GRAY8
,
AV_PIX_FMT_YUVJ444P
,
AV_PIX_FMT_YUVJ440P
,
AV_PIX_FMT_YUVJ422P
,
AV_PIX_FMT_YUVJ420P
,
AV_PIX_FMT_YUVJ411P
,
AV_PIX_FMT_GRAY9
,
AV_PIX_FMT_YUV444P
,
AV_PIX_FMT_YUV440P
,
AV_PIX_FMT_YUV422P
,
AV_PIX_FMT_YUV420P
,
AV_PIX_FMT_YUV411P
,
AV_PIX_FMT_YUV410P
,
AV_PIX_FMT_GRAY10
,
AV_PIX_FMT_GBRP
,
AV_PIX_FMT_GBRAP
,
AV_PIX_FMT_GRAY8
,
AV_PIX_FMT_NONE
AV_PIX_FMT_GRAY12
,
AV_PIX_FMT_GRAY14
,
AV_PIX_FMT_GRAY16
,
AV_PIX_FMT_YUV410P
,
AV_PIX_FMT_YUV411P
,
AV_PIX_FMT_YUV420P
,
AV_PIX_FMT_YUV422P
,
AV_PIX_FMT_YUV440P
,
AV_PIX_FMT_YUV444P
,
AV_PIX_FMT_YUVJ420P
,
AV_PIX_FMT_YUVJ422P
,
AV_PIX_FMT_YUVJ440P
,
AV_PIX_FMT_YUVJ444P
,
AV_PIX_FMT_YUVJ411P
,
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_YUV440P10
,
AV_PIX_FMT_YUV444P12
,
AV_PIX_FMT_YUV422P12
,
AV_PIX_FMT_YUV420P12
,
AV_PIX_FMT_YUV440P12
,
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_GBRP
,
AV_PIX_FMT_GBRP9
,
AV_PIX_FMT_GBRP10
,
AV_PIX_FMT_GBRP12
,
AV_PIX_FMT_GBRP14
,
AV_PIX_FMT_GBRP16
,
AV_PIX_FMT_YUVA420P
,
AV_PIX_FMT_YUVA422P
,
AV_PIX_FMT_YUVA444P
,
AV_PIX_FMT_YUVA444P9
,
AV_PIX_FMT_YUVA444P10
,
AV_PIX_FMT_YUVA444P12
,
AV_PIX_FMT_YUVA444P16
,
AV_PIX_FMT_YUVA422P9
,
AV_PIX_FMT_YUVA422P10
,
AV_PIX_FMT_YUVA422P12
,
AV_PIX_FMT_YUVA422P16
,
AV_PIX_FMT_YUVA420P9
,
AV_PIX_FMT_YUVA420P10
,
AV_PIX_FMT_YUVA420P16
,
AV_PIX_FMT_GBRAP
,
AV_PIX_FMT_GBRAP10
,
AV_PIX_FMT_GBRAP12
,
AV_PIX_FMT_GBRAP16
,
AV_PIX_FMT_NONE
};
};
AVFilterFormats
*
fmts_list
=
ff_make_format_list
(
pix_fmts
);
AVFilterFormats
*
fmts_list
=
ff_make_format_list
(
pix_fmts
);
...
@@ -89,6 +137,16 @@ static int config_input(AVFilterLink *inlink)
...
@@ -89,6 +137,16 @@ static int config_input(AVFilterLink *inlink)
const
AVPixFmtDescriptor
*
desc
=
av_pix_fmt_desc_get
(
inlink
->
format
);
const
AVPixFmtDescriptor
*
desc
=
av_pix_fmt_desc_get
(
inlink
->
format
);
int
ret
;
int
ret
;
switch
(
desc
->
comp
[
0
].
depth
)
{
case
8
:
s
->
analyze_plane
=
analyze_plane_8
;
break
;
case
9
:
s
->
analyze_plane
=
analyze_plane_9
;
break
;
case
10
:
s
->
analyze_plane
=
analyze_plane_10
;
break
;
case
12
:
s
->
analyze_plane
=
analyze_plane_12
;
break
;
case
14
:
s
->
analyze_plane
=
analyze_plane_14
;
break
;
case
16
:
s
->
analyze_plane
=
analyze_plane_16
;
break
;
default:
av_assert0
(
0
);
};
if
((
ret
=
av_image_fill_linesizes
(
s
->
linesize
,
inlink
->
format
,
inlink
->
w
))
<
0
)
if
((
ret
=
av_image_fill_linesizes
(
s
->
linesize
,
inlink
->
format
,
inlink
->
w
))
<
0
)
return
ret
;
return
ret
;
...
@@ -100,149 +158,6 @@ static int config_input(AVFilterLink *inlink)
...
@@ -100,149 +158,6 @@ static int config_input(AVFilterLink *inlink)
return
0
;
return
0
;
}
}
/*
* This macro interpolates the value of both fields at a point halfway
* between lines and takes the squared difference. In field resolution
* the point is a quarter pixel below a line in one field and a quarter
* pixel above a line in other.
*
* (The result is actually multiplied by 25)
*/
#define DIFF(a, as, b, bs) ((t) = ((*(a) - (b)[bs]) << 2) + (a)[(as) << 1] - (b)[-(bs)], (t) * (t))
/*
* Find which field combination has the smallest average squared difference
* between the fields.
*/
static
enum
PhaseMode
analyze_plane
(
void
*
ctx
,
enum
PhaseMode
mode
,
AVFrame
*
old
,
AVFrame
*
new
)
{
double
bdiff
,
tdiff
,
pdiff
;
if
(
mode
==
AUTO
)
{
mode
=
new
->
interlaced_frame
?
new
->
top_field_first
?
TOP_FIRST
:
BOTTOM_FIRST
:
PROGRESSIVE
;
}
else
if
(
mode
==
AUTO_ANALYZE
)
{
mode
=
new
->
interlaced_frame
?
new
->
top_field_first
?
TOP_FIRST_ANALYZE
:
BOTTOM_FIRST_ANALYZE
:
FULL_ANALYZE
;
}
if
(
mode
<=
BOTTOM_FIRST
)
{
bdiff
=
pdiff
=
tdiff
=
65536
.
0
;
}
else
{
const
int
ns
=
new
->
linesize
[
0
];
const
int
os
=
old
->
linesize
[
0
];
const
uint8_t
*
nptr
=
new
->
data
[
0
];
const
uint8_t
*
optr
=
old
->
data
[
0
];
const
int
h
=
new
->
height
;
const
int
w
=
new
->
width
;
int
bdif
,
tdif
,
pdif
;
double
scale
;
int
top
=
0
,
t
;
const
uint8_t
*
rend
,
*
end
=
nptr
+
(
h
-
2
)
*
ns
;
bdiff
=
pdiff
=
tdiff
=
0
.
0
;
nptr
+=
ns
;
optr
+=
os
;
while
(
nptr
<
end
)
{
pdif
=
tdif
=
bdif
=
0
;
switch
(
mode
)
{
case
TOP_FIRST_ANALYZE
:
if
(
top
)
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
pdif
+=
DIFF
(
nptr
,
ns
,
nptr
,
ns
);
tdif
+=
DIFF
(
nptr
,
ns
,
optr
,
os
);
}
}
else
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
pdif
+=
DIFF
(
nptr
,
ns
,
nptr
,
ns
);
tdif
+=
DIFF
(
optr
,
os
,
nptr
,
ns
);
}
}
break
;
case
BOTTOM_FIRST_ANALYZE
:
if
(
top
)
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
pdif
+=
DIFF
(
nptr
,
ns
,
nptr
,
ns
);
bdif
+=
DIFF
(
optr
,
os
,
nptr
,
ns
);
}
}
else
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
pdif
+=
DIFF
(
nptr
,
ns
,
nptr
,
ns
);
bdif
+=
DIFF
(
nptr
,
ns
,
optr
,
os
);
}
}
break
;
case
ANALYZE
:
if
(
top
)
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
tdif
+=
DIFF
(
nptr
,
ns
,
optr
,
os
);
bdif
+=
DIFF
(
optr
,
os
,
nptr
,
ns
);
}
}
else
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
bdif
+=
DIFF
(
nptr
,
ns
,
optr
,
os
);
tdif
+=
DIFF
(
optr
,
os
,
nptr
,
ns
);
}
}
break
;
case
FULL_ANALYZE
:
if
(
top
)
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
pdif
+=
DIFF
(
nptr
,
ns
,
nptr
,
ns
);
tdif
+=
DIFF
(
nptr
,
ns
,
optr
,
os
);
bdif
+=
DIFF
(
optr
,
os
,
nptr
,
ns
);
}
}
else
{
for
(
rend
=
nptr
+
w
;
nptr
<
rend
;
nptr
++
,
optr
++
)
{
pdif
+=
DIFF
(
nptr
,
ns
,
nptr
,
ns
);
bdif
+=
DIFF
(
nptr
,
ns
,
optr
,
os
);
tdif
+=
DIFF
(
optr
,
os
,
nptr
,
ns
);
}
}
break
;
default:
av_assert0
(
0
);
}
pdiff
+=
(
double
)
pdif
;
tdiff
+=
(
double
)
tdif
;
bdiff
+=
(
double
)
bdif
;
nptr
+=
ns
-
w
;
optr
+=
os
-
w
;
top
^=
1
;
}
scale
=
1
.
0
/
(
w
*
(
h
-
3
))
/
25
.
0
;
pdiff
*=
scale
;
tdiff
*=
scale
;
bdiff
*=
scale
;
if
(
mode
==
TOP_FIRST_ANALYZE
)
{
bdiff
=
65536
.
0
;
}
else
if
(
mode
==
BOTTOM_FIRST_ANALYZE
)
{
tdiff
=
65536
.
0
;
}
else
if
(
mode
==
ANALYZE
)
{
pdiff
=
65536
.
0
;
}
if
(
bdiff
<
pdiff
&&
bdiff
<
tdiff
)
{
mode
=
BOTTOM_FIRST
;
}
else
if
(
tdiff
<
pdiff
&&
tdiff
<
bdiff
)
{
mode
=
TOP_FIRST
;
}
else
{
mode
=
PROGRESSIVE
;
}
}
av_log
(
ctx
,
AV_LOG_DEBUG
,
"mode=%c tdiff=%f bdiff=%f pdiff=%f
\n
"
,
mode
==
BOTTOM_FIRST
?
'b'
:
mode
==
TOP_FIRST
?
't'
:
'p'
,
tdiff
,
bdiff
,
pdiff
);
return
mode
;
}
static
int
filter_frame
(
AVFilterLink
*
inlink
,
AVFrame
*
in
)
static
int
filter_frame
(
AVFilterLink
*
inlink
,
AVFrame
*
in
)
{
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
AVFilterContext
*
ctx
=
inlink
->
dst
;
...
@@ -272,7 +187,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
...
@@ -272,7 +187,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
s
->
frame
=
in
;
s
->
frame
=
in
;
mode
=
PROGRESSIVE
;
mode
=
PROGRESSIVE
;
}
else
{
}
else
{
mode
=
analyze_plane
(
ctx
,
s
->
mode
,
s
->
frame
,
in
);
mode
=
s
->
analyze_plane
(
ctx
,
s
->
mode
,
s
->
frame
,
in
);
}
}
for
(
plane
=
0
;
plane
<
s
->
nb_planes
;
plane
++
)
{
for
(
plane
=
0
;
plane
<
s
->
nb_planes
;
plane
++
)
{
...
...
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