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
f0a149e5
Commit
f0a149e5
authored
Apr 16, 2013
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavfi: remove bad inverse telecine filters
Signed-off-by:
Paul B Mahol
<
onemda@gmail.com
>
parent
a5ebd2d9
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1 addition
and
3202 deletions
+1
-3202
filters.texi
doc/filters.texi
+0
-3
Makefile
libavfilter/Makefile
+0
-4
vf_detc.c
libavfilter/libmpcodecs/vf_detc.c
+0
-453
vf_divtc.c
libavfilter/libmpcodecs/vf_divtc.c
+0
-722
vf_filmdint.c
libavfilter/libmpcodecs/vf_filmdint.c
+0
-1461
vf_ivtc.c
libavfilter/libmpcodecs/vf_ivtc.c
+0
-550
version.h
libavfilter/version.h
+1
-1
vf_mp.c
libavfilter/vf_mp.c
+0
-8
No files found.
doc/filters.texi
View file @
f0a149e5
...
...
@@ -4303,16 +4303,13 @@ the named filter.
The list of the currently supported filters follows:
@table @var
@item detc
@item dint
@item divtc
@item down3dright
@item eq2
@item eq
@item fil
@item fspp
@item ilpack
@item ivtc
@item mcdeint
@item ow
@item perspective
...
...
libavfilter/Makefile
View file @
f0a149e5
...
...
@@ -192,17 +192,13 @@ OBJS-$(CONFIG_NULLSINK_FILTER) += vsink_nullsink.o
OBJS-$(CONFIG_MP_FILTER)
+=
libmpcodecs/mp_image.o
OBJS-$(CONFIG_MP_FILTER)
+=
libmpcodecs/img_format.o
OBJS-$(CONFIG_MP_FILTER)
+=
libmpcodecs/vf_detc.o
OBJS-$(CONFIG_MP_FILTER)
+=
libmpcodecs/vf_dint.o
OBJS-$(CONFIG_MP_FILTER)
+=
libmpcodecs/vf_divtc.o
OBJS-$(CONFIG_MP_FILTER)
+=
libmpcodecs/vf_down3dright.o
OBJS-$(CONFIG_MP_FILTER)
+=
libmpcodecs/vf_eq2.o
OBJS-$(CONFIG_MP_FILTER)
+=
libmpcodecs/vf_eq.o
OBJS-$(CONFIG_MP_FILTER)
+=
libmpcodecs/vf_fil.o
#OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_filmdint.o
OBJS-$(CONFIG_MP_FILTER)
+=
libmpcodecs/vf_fspp.o
OBJS-$(CONFIG_MP_FILTER)
+=
libmpcodecs/vf_ilpack.o
OBJS-$(CONFIG_MP_FILTER)
+=
libmpcodecs/vf_ivtc.o
OBJS-$(CONFIG_MP_FILTER)
+=
libmpcodecs/vf_mcdeint.o
OBJS-$(CONFIG_MP_FILTER)
+=
libmpcodecs/vf_ow.o
OBJS-$(CONFIG_MP_FILTER)
+=
libmpcodecs/vf_perspective.o
...
...
libavfilter/libmpcodecs/vf_detc.c
deleted
100644 → 0
View file @
a5ebd2d9
/*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "mp_msg.h"
#include "img_format.h"
#include "mp_image.h"
#include "vf.h"
#include "libvo/fastmemcpy.h"
struct
metrics
{
int
even
;
int
odd
;
int
noise
;
int
temp
;
};
struct
vf_priv_s
{
int
frame
;
int
drop
,
lastdrop
;
struct
metrics
pm
;
int
thres
[
5
];
int
inframes
,
outframes
;
int
mode
;
int
(
*
analyze
)(
struct
vf_priv_s
*
,
mp_image_t
*
,
mp_image_t
*
);
int
needread
;
};
#define COMPE(a,b,e) (abs((a)-(b)) < (((a)+(b))>>(e)))
#define COMPARABLE(a,b) COMPE((a),(b),2)
#define VERYCLOSE(a,b) COMPE((a),(b),3)
#define OUTER_TC_NBHD(s) ( \
COMPARABLE((s)[-1].m.even,(s)[-1].m.odd) && \
COMPARABLE((s)[1].m.even,(s)[0].m.odd) && \
COMPARABLE((s)[2].m.even,(s)[1].m.odd) && \
COMPARABLE((s)[-1].m.noise,(s)[0].m.temp) && \
COMPARABLE((s)[2].m.noise,(s)[2].m.temp) )
#define INNER_TC_NBHD(s,l,h) ( \
COMPARABLE((s)[0].m.even,(l)) && \
COMPARABLE((s)[2].m.odd,(l)) && ( \
COMPARABLE((s)[0].m.noise,(h)) || \
COMPARABLE((s)[1].m.noise,(h)) ) )
enum
{
TC_DROP
,
TC_PROG
,
TC_IL1
,
TC_IL2
};
static
void
block_diffs
(
struct
metrics
*
m
,
unsigned
char
*
old
,
unsigned
char
*
new
,
int
os
,
int
ns
)
{
int
x
,
y
,
even
=
0
,
odd
=
0
,
noise
,
temp
;
unsigned
char
*
oldp
,
*
newp
;
m
->
noise
=
m
->
temp
=
0
;
for
(
x
=
8
;
x
;
x
--
)
{
oldp
=
old
++
;
newp
=
new
++
;
noise
=
temp
=
0
;
for
(
y
=
4
;
y
;
y
--
)
{
even
+=
abs
(
newp
[
0
]
-
oldp
[
0
]);
odd
+=
abs
(
newp
[
ns
]
-
oldp
[
os
]);
noise
+=
newp
[
ns
]
-
newp
[
0
];
temp
+=
oldp
[
os
]
-
newp
[
0
];
oldp
+=
os
<<
1
;
newp
+=
ns
<<
1
;
}
m
->
noise
+=
abs
(
noise
);
m
->
temp
+=
abs
(
temp
);
}
m
->
even
=
even
;
m
->
odd
=
odd
;
}
static
void
diff_planes
(
struct
metrics
*
m
,
unsigned
char
*
old
,
unsigned
char
*
new
,
int
w
,
int
h
,
int
os
,
int
ns
)
{
int
x
,
y
,
me
=
0
,
mo
=
0
,
mn
=
0
,
mt
=
0
;
struct
metrics
l
;
for
(
y
=
0
;
y
<
h
-
7
;
y
+=
8
)
{
for
(
x
=
0
;
x
<
w
-
7
;
x
+=
8
)
{
block_diffs
(
&
l
,
old
+
x
+
y
*
os
,
new
+
x
+
y
*
ns
,
os
,
ns
);
if
(
l
.
even
>
me
)
me
=
l
.
even
;
if
(
l
.
odd
>
mo
)
mo
=
l
.
odd
;
if
(
l
.
noise
>
mn
)
mn
=
l
.
noise
;
if
(
l
.
temp
>
mt
)
mt
=
l
.
temp
;
}
}
m
->
even
=
me
;
m
->
odd
=
mo
;
m
->
noise
=
mn
;
m
->
temp
=
mt
;
}
static
void
diff_fields
(
struct
metrics
*
metr
,
mp_image_t
*
old
,
mp_image_t
*
new
)
{
struct
metrics
m
,
mu
,
mv
;
diff_planes
(
&
m
,
old
->
planes
[
0
],
new
->
planes
[
0
],
new
->
w
,
new
->
h
,
old
->
stride
[
0
],
new
->
stride
[
0
]);
if
(
new
->
flags
&
MP_IMGFLAG_PLANAR
)
{
diff_planes
(
&
mu
,
old
->
planes
[
1
],
new
->
planes
[
1
],
new
->
chroma_width
,
new
->
chroma_height
,
old
->
stride
[
1
],
new
->
stride
[
1
]);
diff_planes
(
&
mv
,
old
->
planes
[
2
],
new
->
planes
[
2
],
new
->
chroma_width
,
new
->
chroma_height
,
old
->
stride
[
2
],
new
->
stride
[
2
]);
if
(
mu
.
even
>
m
.
even
)
m
.
even
=
mu
.
even
;
if
(
mu
.
odd
>
m
.
odd
)
m
.
odd
=
mu
.
odd
;
if
(
mu
.
noise
>
m
.
noise
)
m
.
noise
=
mu
.
noise
;
if
(
mu
.
temp
>
m
.
temp
)
m
.
temp
=
mu
.
temp
;
if
(
mv
.
even
>
m
.
even
)
m
.
even
=
mv
.
even
;
if
(
mv
.
odd
>
m
.
odd
)
m
.
odd
=
mv
.
odd
;
if
(
mv
.
noise
>
m
.
noise
)
m
.
noise
=
mv
.
noise
;
if
(
mv
.
temp
>
m
.
temp
)
m
.
temp
=
mv
.
temp
;
}
*
metr
=
m
;
}
static
void
status
(
int
f
,
struct
metrics
*
m
)
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"frame %d: e=%d o=%d n=%d t=%d
\n
"
,
f
,
m
->
even
,
m
->
odd
,
m
->
noise
,
m
->
temp
);
}
static
int
analyze_fixed_pattern
(
struct
vf_priv_s
*
p
,
mp_image_t
*
new
,
mp_image_t
*
old
)
{
if
(
p
->
frame
>=
0
)
p
->
frame
=
(
p
->
frame
+
1
)
%
5
;
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"frame %d
\n
"
,
p
->
frame
);
switch
(
p
->
frame
)
{
case
-
1
:
case
0
:
case
1
:
case
2
:
return
TC_PROG
;
case
3
:
return
TC_IL1
;
case
4
:
return
TC_IL2
;
}
return
0
;
}
static
int
analyze_aggressive
(
struct
vf_priv_s
*
p
,
mp_image_t
*
new
,
mp_image_t
*
old
)
{
struct
metrics
m
,
pm
;
if
(
p
->
frame
>=
0
)
p
->
frame
=
(
p
->
frame
+
1
)
%
5
;
diff_fields
(
&
m
,
old
,
new
);
status
(
p
->
frame
,
&
m
);
pm
=
p
->
pm
;
p
->
pm
=
m
;
if
(
p
->
frame
==
4
)
{
/* We need to break at scene changes, but is this a valid test? */
if
((
m
.
even
>
p
->
thres
[
2
])
&&
(
m
.
odd
>
p
->
thres
[
2
])
&&
(
m
.
temp
>
p
->
thres
[
3
])
&&
(
m
.
temp
>
5
*
pm
.
temp
)
&&
(
m
.
temp
*
2
>
m
.
noise
))
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"scene change breaking telecine!
\n
"
);
p
->
frame
=
-
1
;
return
TC_DROP
;
}
/* Thres. is to compensate for quantization errors when noise is low */
if
(
m
.
noise
-
m
.
temp
>
-
p
->
thres
[
4
])
{
if
(
COMPARABLE
(
m
.
even
,
pm
.
odd
))
{
//ff_mp_msg(MSGT_VFILTER, MSGL_V, "confirmed field match!\n");
return
TC_IL2
;
}
else
if
((
m
.
even
<
p
->
thres
[
0
])
&&
(
m
.
odd
<
p
->
thres
[
0
])
&&
VERYCLOSE
(
m
.
even
,
m
.
odd
)
&&
VERYCLOSE
(
m
.
noise
,
m
.
temp
)
&&
VERYCLOSE
(
m
.
noise
,
pm
.
noise
))
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"interlaced frame appears in duplicate!!!
\n
"
);
p
->
pm
=
pm
;
/* hack :) */
p
->
frame
=
3
;
return
TC_IL1
;
}
}
else
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"mismatched telecine fields!
\n
"
);
p
->
frame
=
-
1
;
}
}
if
(
2
*
m
.
even
*
m
.
temp
<
m
.
odd
*
m
.
noise
)
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"caught telecine sync!
\n
"
);
p
->
frame
=
3
;
return
TC_IL1
;
}
if
(
p
->
frame
<
3
)
{
if
(
m
.
noise
>
p
->
thres
[
3
])
{
if
(
m
.
noise
>
2
*
m
.
temp
)
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"merging fields out of sequence!
\n
"
);
return
TC_IL2
;
}
if
((
m
.
noise
>
2
*
pm
.
noise
)
&&
(
m
.
even
>
p
->
thres
[
2
])
&&
(
m
.
odd
>
p
->
thres
[
2
]))
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"dropping horrible interlaced frame!
\n
"
);
return
TC_DROP
;
}
}
}
switch
(
p
->
frame
)
{
case
-
1
:
if
(
4
*
m
.
noise
>
5
*
m
.
temp
)
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"merging fields out of sequence!
\n
"
);
return
TC_IL2
;
}
case
0
:
case
1
:
case
2
:
return
TC_PROG
;
case
3
:
if
((
m
.
even
>
p
->
thres
[
1
])
&&
(
m
.
even
>
m
.
odd
)
&&
(
m
.
temp
>
m
.
noise
))
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"lost telecine tracking!
\n
"
);
p
->
frame
=
-
1
;
return
TC_PROG
;
}
return
TC_IL1
;
case
4
:
return
TC_IL2
;
}
return
0
;
}
static
void
copy_image
(
mp_image_t
*
dmpi
,
mp_image_t
*
mpi
,
int
field
)
{
switch
(
field
)
{
case
0
:
my_memcpy_pic
(
dmpi
->
planes
[
0
],
mpi
->
planes
[
0
],
mpi
->
w
,
mpi
->
h
/
2
,
dmpi
->
stride
[
0
]
*
2
,
mpi
->
stride
[
0
]
*
2
);
if
(
mpi
->
flags
&
MP_IMGFLAG_PLANAR
)
{
my_memcpy_pic
(
dmpi
->
planes
[
1
],
mpi
->
planes
[
1
],
mpi
->
chroma_width
,
mpi
->
chroma_height
/
2
,
dmpi
->
stride
[
1
]
*
2
,
mpi
->
stride
[
1
]
*
2
);
my_memcpy_pic
(
dmpi
->
planes
[
2
],
mpi
->
planes
[
2
],
mpi
->
chroma_width
,
mpi
->
chroma_height
/
2
,
dmpi
->
stride
[
2
]
*
2
,
mpi
->
stride
[
2
]
*
2
);
}
break
;
case
1
:
my_memcpy_pic
(
dmpi
->
planes
[
0
]
+
dmpi
->
stride
[
0
],
mpi
->
planes
[
0
]
+
mpi
->
stride
[
0
],
mpi
->
w
,
mpi
->
h
/
2
,
dmpi
->
stride
[
0
]
*
2
,
mpi
->
stride
[
0
]
*
2
);
if
(
mpi
->
flags
&
MP_IMGFLAG_PLANAR
)
{
my_memcpy_pic
(
dmpi
->
planes
[
1
]
+
dmpi
->
stride
[
1
],
mpi
->
planes
[
1
]
+
mpi
->
stride
[
1
],
mpi
->
chroma_width
,
mpi
->
chroma_height
/
2
,
dmpi
->
stride
[
1
]
*
2
,
mpi
->
stride
[
1
]
*
2
);
my_memcpy_pic
(
dmpi
->
planes
[
2
]
+
dmpi
->
stride
[
2
],
mpi
->
planes
[
2
]
+
mpi
->
stride
[
2
],
mpi
->
chroma_width
,
mpi
->
chroma_height
/
2
,
dmpi
->
stride
[
2
]
*
2
,
mpi
->
stride
[
2
]
*
2
);
}
break
;
case
2
:
memcpy_pic
(
dmpi
->
planes
[
0
],
mpi
->
planes
[
0
],
mpi
->
w
,
mpi
->
h
,
dmpi
->
stride
[
0
],
mpi
->
stride
[
0
]);
if
(
mpi
->
flags
&
MP_IMGFLAG_PLANAR
)
{
memcpy_pic
(
dmpi
->
planes
[
1
],
mpi
->
planes
[
1
],
mpi
->
chroma_width
,
mpi
->
chroma_height
,
dmpi
->
stride
[
1
],
mpi
->
stride
[
1
]);
memcpy_pic
(
dmpi
->
planes
[
2
],
mpi
->
planes
[
2
],
mpi
->
chroma_width
,
mpi
->
chroma_height
,
dmpi
->
stride
[
2
],
mpi
->
stride
[
2
]);
}
break
;
}
}
static
int
do_put_image
(
struct
vf_instance
*
vf
,
mp_image_t
*
dmpi
)
{
struct
vf_priv_s
*
p
=
vf
->
priv
;
int
dropflag
;
switch
(
p
->
drop
)
{
default:
dropflag
=
0
;
break
;
case
1
:
dropflag
=
(
++
p
->
lastdrop
>=
5
);
break
;
case
2
:
dropflag
=
(
++
p
->
lastdrop
>=
5
)
&&
(
4
*
p
->
inframes
<=
5
*
p
->
outframes
);
break
;
}
if
(
dropflag
)
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"drop! [%d/%d=%g]
\n
"
,
p
->
outframes
,
p
->
inframes
,
(
float
)
p
->
outframes
/
p
->
inframes
);
p
->
lastdrop
=
0
;
return
0
;
}
p
->
outframes
++
;
return
ff_vf_next_put_image
(
vf
,
dmpi
,
MP_NOPTS_VALUE
);
}
static
int
put_image
(
struct
vf_instance
*
vf
,
mp_image_t
*
mpi
,
double
pts
)
{
int
ret
=
0
;
mp_image_t
*
dmpi
;
struct
vf_priv_s
*
p
=
vf
->
priv
;
p
->
inframes
++
;
if
(
p
->
needread
)
dmpi
=
ff_vf_get_image
(
vf
->
next
,
mpi
->
imgfmt
,
MP_IMGTYPE_STATIC
,
MP_IMGFLAG_ACCEPT_STRIDE
|
MP_IMGFLAG_PRESERVE
|
MP_IMGFLAG_READABLE
,
mpi
->
width
,
mpi
->
height
);
/* FIXME: is there a good way to get rid of static type? */
else
dmpi
=
ff_vf_get_image
(
vf
->
next
,
mpi
->
imgfmt
,
MP_IMGTYPE_STATIC
,
MP_IMGFLAG_ACCEPT_STRIDE
|
MP_IMGFLAG_PRESERVE
,
mpi
->
width
,
mpi
->
height
);
switch
(
p
->
analyze
(
p
,
mpi
,
dmpi
))
{
case
TC_DROP
:
/* Don't copy anything unless we'll need to read it. */
if
(
p
->
needread
)
copy_image
(
dmpi
,
mpi
,
2
);
p
->
lastdrop
=
0
;
break
;
case
TC_PROG
:
/* Copy and display the whole frame. */
copy_image
(
dmpi
,
mpi
,
2
);
ret
=
do_put_image
(
vf
,
dmpi
);
break
;
case
TC_IL1
:
/* Only copy bottom field unless we need to read. */
if
(
p
->
needread
)
copy_image
(
dmpi
,
mpi
,
2
);
else
copy_image
(
dmpi
,
mpi
,
1
);
p
->
lastdrop
=
0
;
break
;
case
TC_IL2
:
/* Copy top field and show frame, then copy bottom if needed. */
copy_image
(
dmpi
,
mpi
,
0
);
ret
=
do_put_image
(
vf
,
dmpi
);
if
(
p
->
needread
)
copy_image
(
dmpi
,
mpi
,
1
);
break
;
}
return
ret
;
}
static
int
query_format
(
struct
vf_instance
*
vf
,
unsigned
int
fmt
)
{
/* FIXME - figure out which other formats work */
switch
(
fmt
)
{
case
IMGFMT_YV12
:
case
IMGFMT_IYUV
:
case
IMGFMT_I420
:
return
ff_vf_next_query_format
(
vf
,
fmt
);
}
return
0
;
}
static
int
config
(
struct
vf_instance
*
vf
,
int
width
,
int
height
,
int
d_width
,
int
d_height
,
unsigned
int
flags
,
unsigned
int
outfmt
)
{
return
ff_vf_next_config
(
vf
,
width
,
height
,
d_width
,
d_height
,
flags
,
outfmt
);
}
static
void
uninit
(
struct
vf_instance
*
vf
)
{
free
(
vf
->
priv
);
}
static
struct
{
const
char
*
name
;
int
(
*
func
)(
struct
vf_priv_s
*
p
,
mp_image_t
*
new
,
mp_image_t
*
old
);
int
needread
;
}
anal_funcs
[]
=
{
{
"fixed"
,
analyze_fixed_pattern
,
0
},
{
"aggressive"
,
analyze_aggressive
,
1
},
{
NULL
,
NULL
,
0
}
};
#define STARTVARS if (0)
#define GETVAR(str, name, out, func) \
else if (!strncmp((str), name "=", sizeof(name))) \
(out) = (func)((str) + sizeof(name))
static
void
parse_var
(
struct
vf_priv_s
*
p
,
char
*
var
)
{
STARTVARS
;
GETVAR
(
var
,
"dr"
,
p
->
drop
,
atoi
);
GETVAR
(
var
,
"t0"
,
p
->
thres
[
0
],
atoi
);
GETVAR
(
var
,
"t1"
,
p
->
thres
[
1
],
atoi
);
GETVAR
(
var
,
"t2"
,
p
->
thres
[
2
],
atoi
);
GETVAR
(
var
,
"t3"
,
p
->
thres
[
3
],
atoi
);
GETVAR
(
var
,
"t4"
,
p
->
thres
[
4
],
atoi
);
GETVAR
(
var
,
"fr"
,
p
->
frame
,
atoi
);
GETVAR
(
var
,
"am"
,
p
->
mode
,
atoi
);
}
static
void
parse_args
(
struct
vf_priv_s
*
p
,
char
*
args
)
{
char
*
next
,
*
orig
;
for
(
args
=
orig
=
strdup
(
args
);
args
;
args
=
next
)
{
next
=
strchr
(
args
,
':'
);
if
(
next
)
*
next
++
=
0
;
parse_var
(
p
,
args
);
}
free
(
orig
);
}
static
int
vf_open
(
vf_instance_t
*
vf
,
char
*
args
)
{
struct
vf_priv_s
*
p
;
vf
->
config
=
config
;
vf
->
put_image
=
put_image
;
vf
->
query_format
=
query_format
;
vf
->
uninit
=
uninit
;
vf
->
default_reqs
=
VFCAP_ACCEPT_STRIDE
;
vf
->
priv
=
p
=
calloc
(
1
,
sizeof
(
struct
vf_priv_s
));
p
->
frame
=
-
1
;
p
->
thres
[
0
]
=
440
;
p
->
thres
[
1
]
=
720
;
p
->
thres
[
2
]
=
2500
;
p
->
thres
[
3
]
=
2500
;
p
->
thres
[
4
]
=
800
;
p
->
drop
=
0
;
p
->
mode
=
1
;
if
(
args
)
parse_args
(
p
,
args
);
p
->
analyze
=
anal_funcs
[
p
->
mode
].
func
;
p
->
needread
=
anal_funcs
[
p
->
mode
].
needread
;
return
1
;
}
const
vf_info_t
ff_vf_info_detc
=
{
"de-telecine filter"
,
"detc"
,
"Rich Felker"
,
""
,
vf_open
,
NULL
};
libavfilter/libmpcodecs/vf_divtc.c
deleted
100644 → 0
View file @
a5ebd2d9
/*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <math.h>
#include "config.h"
#include "mp_msg.h"
#include "cpudetect.h"
#include "libavutil/common.h"
#include "libavutil/x86/asm.h"
#include "mpbswap.h"
#include "img_format.h"
#include "mp_image.h"
#include "vf.h"
#include "libvo/fastmemcpy.h"
const
vf_info_t
ff_vf_info_divtc
;
struct
vf_priv_s
{
int
deghost
,
pass
,
phase
,
window
,
fcount
,
bcount
,
frameno
,
misscount
,
ocount
,
sum
[
5
];
double
threshold
;
FILE
*
file
;
int8_t
*
bdata
;
unsigned
int
*
csdata
;
int
*
history
;
};
/*
* diff_MMX and diff_C stolen from vf_decimate.c
*/
#if HAVE_MMX && HAVE_EBX_AVAILABLE
static
int
diff_MMX
(
unsigned
char
*
old
,
unsigned
char
*
new
,
int
os
,
int
ns
)
{
volatile
short
out
[
4
];
__asm__
(
"movl $8, %%ecx
\n\t
"
"pxor %%mm4, %%mm4
\n\t
"
"pxor %%mm7, %%mm7
\n\t
"
ASMALIGN
(
4
)
"1:
\n\t
"
"movq (%%"
REG_S
"), %%mm0
\n\t
"
"movq (%%"
REG_S
"), %%mm2
\n\t
"
"add %%"
REG_a
", %%"
REG_S
"
\n\t
"
"movq (%%"
REG_D
"), %%mm1
\n\t
"
"add %%"
REG_b
", %%"
REG_D
"
\n\t
"
"psubusb %%mm1, %%mm2
\n\t
"
"psubusb %%mm0, %%mm1
\n\t
"
"movq %%mm2, %%mm0
\n\t
"
"movq %%mm1, %%mm3
\n\t
"
"punpcklbw %%mm7, %%mm0
\n\t
"
"punpcklbw %%mm7, %%mm1
\n\t
"
"punpckhbw %%mm7, %%mm2
\n\t
"
"punpckhbw %%mm7, %%mm3
\n\t
"
"paddw %%mm0, %%mm4
\n\t
"
"paddw %%mm1, %%mm4
\n\t
"
"paddw %%mm2, %%mm4
\n\t
"
"paddw %%mm3, %%mm4
\n\t
"
"decl %%ecx
\n\t
"
"jnz 1b
\n\t
"
"movq %%mm4, (%%"
REG_d
")
\n\t
"
"emms
\n\t
"
:
:
"S"
(
old
),
"D"
(
new
),
"a"
((
long
)
os
),
"b"
((
long
)
ns
),
"d"
(
out
)
:
"%ecx"
,
"memory"
);
return
out
[
0
]
+
out
[
1
]
+
out
[
2
]
+
out
[
3
];
}
#endif
static
int
diff_C
(
unsigned
char
*
old
,
unsigned
char
*
new
,
int
os
,
int
ns
)
{
int
x
,
y
,
d
=
0
;
for
(
y
=
8
;
y
;
y
--
,
new
+=
ns
,
old
+=
os
)
for
(
x
=
8
;
x
;
x
--
)
d
+=
abs
(
new
[
x
]
-
old
[
x
]);
return
d
;
}
static
int
(
*
diff
)(
unsigned
char
*
,
unsigned
char
*
,
int
,
int
);
static
int
diff_plane
(
unsigned
char
*
old
,
unsigned
char
*
new
,
int
w
,
int
h
,
int
os
,
int
ns
,
int
arg
)
{
int
x
,
y
,
d
,
max
=
0
,
sum
=
0
,
n
=
0
;
for
(
y
=
0
;
y
<
h
-
7
;
y
+=
8
)
{
for
(
x
=
0
;
x
<
w
-
7
;
x
+=
8
)
{
d
=
diff
(
old
+
x
+
y
*
os
,
new
+
x
+
y
*
ns
,
os
,
ns
);
if
(
d
>
max
)
max
=
d
;
sum
+=
d
;
n
++
;
}
}
return
(
sum
+
n
*
max
)
/
2
;
}
/*
static unsigned int checksum_plane(unsigned char *p, unsigned char *z,
int w, int h, int s, int zs, int arg)
{
unsigned int shift, sum;
unsigned char *e;
for(sum=0; h; h--, p+=s-w)
for(e=p+w, shift=32; p<e;)
sum^=(*p++)<<(shift=(shift-8)&31);
return sum;
}
*/
static
unsigned
int
checksum_plane
(
unsigned
char
*
p
,
unsigned
char
*
z
,
int
w
,
int
h
,
int
s
,
int
zs
,
int
arg
)
{
unsigned
int
shift
;
uint32_t
sum
,
t
;
unsigned
char
*
e
,
*
e2
;
#if HAVE_FAST_64BIT
typedef
uint64_t
wsum_t
;
#else
typedef
uint32_t
wsum_t
;
#endif
wsum_t
wsum
;
for
(
sum
=
0
;
h
;
h
--
,
p
+=
s
-
w
)
{
for
(
shift
=
0
,
e
=
p
+
w
;
(
int
)
p
&
(
sizeof
(
wsum_t
)
-
1
)
&&
p
<
e
;)
sum
^=*
p
++<<
(
shift
=
(
shift
-
8
)
&
31
);
for
(
wsum
=
0
,
e2
=
e
-
sizeof
(
wsum_t
)
+
1
;
p
<
e2
;
p
+=
sizeof
(
wsum_t
))
wsum
^=*
(
wsum_t
*
)
p
;
#if HAVE_FAST_64BIT
t
=
be2me_32
((
uint32_t
)(
wsum
>>
32
^
wsum
));
#else
t
=
be2me_32
(
wsum
);
#endif
for
(
sum
^=
(
t
<<
shift
|
t
>>
(
32
-
shift
));
p
<
e
;)
sum
^=*
p
++<<
(
shift
=
(
shift
-
8
)
&
31
);
}
return
sum
;
}
static
int
deghost_plane
(
unsigned
char
*
d
,
unsigned
char
*
s
,
int
w
,
int
h
,
int
ds
,
int
ss
,
int
threshold
)
{
int
t
;
unsigned
char
*
e
;
for
(;
h
;
h
--
,
s
+=
ss
-
w
,
d
+=
ds
-
w
)
for
(
e
=
d
+
w
;
d
<
e
;
d
++
,
s
++
)
if
(
abs
(
*
d
-*
s
)
>=
threshold
)
*
d
=
(
t
=
(
*
d
<<
1
)
-*
s
)
<
0
?
0
:
t
>
255
?
255
:
t
;
return
0
;
}
static
int
copyop
(
unsigned
char
*
d
,
unsigned
char
*
s
,
int
bpl
,
int
h
,
int
dstride
,
int
sstride
,
int
dummy
)
{
memcpy_pic
(
d
,
s
,
bpl
,
h
,
dstride
,
sstride
);
return
0
;
}
static
int
imgop
(
int
(
*
planeop
)(
unsigned
char
*
,
unsigned
char
*
,
int
,
int
,
int
,
int
,
int
),
mp_image_t
*
dst
,
mp_image_t
*
src
,
int
arg
)
{
if
(
dst
->
flags
&
MP_IMGFLAG_PLANAR
)
return
planeop
(
dst
->
planes
[
0
],
src
?
src
->
planes
[
0
]
:
0
,
dst
->
w
,
dst
->
h
,
dst
->
stride
[
0
],
src
?
src
->
stride
[
0
]
:
0
,
arg
)
+
planeop
(
dst
->
planes
[
1
],
src
?
src
->
planes
[
1
]
:
0
,
dst
->
chroma_width
,
dst
->
chroma_height
,
dst
->
stride
[
1
],
src
?
src
->
stride
[
1
]
:
0
,
arg
)
+
planeop
(
dst
->
planes
[
2
],
src
?
src
->
planes
[
2
]
:
0
,
dst
->
chroma_width
,
dst
->
chroma_height
,
dst
->
stride
[
2
],
src
?
src
->
stride
[
2
]
:
0
,
arg
);
return
planeop
(
dst
->
planes
[
0
],
src
?
src
->
planes
[
0
]
:
0
,
dst
->
w
*
(
dst
->
bpp
/
8
),
dst
->
h
,
dst
->
stride
[
0
],
src
?
src
->
stride
[
0
]
:
0
,
arg
);
}
/*
* Find the phase in which the telecine pattern fits best to the
* given 5 frame slice of frame difference measurements.
*
* If phase1 and phase2 are not negative, only the two specified
* phases are tested.
*/
static
int
match
(
struct
vf_priv_s
*
p
,
int
*
diffs
,
int
phase1
,
int
phase2
,
double
*
strength
)
{
static
const
int
pattern1
[]
=
{
-
4
,
1
,
1
,
1
,
1
},
pattern2
[]
=
{
-
2
,
-
3
,
4
,
4
,
-
3
},
*
pattern
;
int
f
,
m
,
n
,
t
[
5
];
pattern
=
p
->
deghost
>
0
?
pattern2
:
pattern1
;
for
(
f
=
0
;
f
<
5
;
f
++
)
{
if
(
phase1
<
0
||
phase2
<
0
||
f
==
phase1
||
f
==
phase2
)
{
for
(
n
=
t
[
f
]
=
0
;
n
<
5
;
n
++
)
t
[
f
]
+=
diffs
[
n
]
*
pattern
[(
n
-
f
+
5
)
%
5
];
}
else
t
[
f
]
=
INT_MIN
;
}
/* find the best match */
for
(
m
=
0
,
n
=
1
;
n
<
5
;
n
++
)
if
(
t
[
n
]
>
t
[
m
])
m
=
n
;
if
(
strength
)
{
/* the second best match */
for
(
f
=
m
?
0
:
1
,
n
=
f
+
1
;
n
<
5
;
n
++
)
if
(
n
!=
m
&&
t
[
n
]
>
t
[
f
])
f
=
n
;
*
strength
=
(
t
[
m
]
>
0
?
(
double
)(
t
[
m
]
-
t
[
f
])
/
t
[
m
]
:
0
.
0
);
}
return
m
;
}
static
int
put_image
(
struct
vf_instance
*
vf
,
mp_image_t
*
mpi
,
double
pts
)
{
mp_image_t
*
dmpi
,
*
tmpi
=
0
;
int
n
,
m
,
f
,
newphase
;
struct
vf_priv_s
*
p
=
vf
->
priv
;
unsigned
int
checksum
;
double
d
;
dmpi
=
ff_vf_get_image
(
vf
->
next
,
mpi
->
imgfmt
,
MP_IMGTYPE_STATIC
,
MP_IMGFLAG_ACCEPT_STRIDE
|
MP_IMGFLAG_PRESERVE
|
MP_IMGFLAG_READABLE
,
mpi
->
width
,
mpi
->
height
);
ff_vf_clone_mpi_attributes
(
dmpi
,
mpi
);
newphase
=
p
->
phase
;
switch
(
p
->
pass
)
{
case
1
:
fprintf
(
p
->
file
,
"%08x %d
\n
"
,
(
unsigned
int
)
imgop
((
void
*
)
checksum_plane
,
mpi
,
0
,
0
),
p
->
frameno
?
imgop
(
diff_plane
,
dmpi
,
mpi
,
0
)
:
0
);
break
;
case
2
:
if
(
p
->
frameno
/
5
>
p
->
bcount
)
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_ERR
,
"
\n
%s: Log file ends prematurely! "
"Switching to one pass mode.
\n
"
,
vf
->
info
->
name
);
p
->
pass
=
0
;
break
;
}
checksum
=
(
unsigned
int
)
imgop
((
void
*
)
checksum_plane
,
mpi
,
0
,
0
);
if
(
checksum
!=
p
->
csdata
[
p
->
frameno
])
{
for
(
f
=
0
;
f
<
100
;
f
++
)
if
(
p
->
frameno
+
f
<
p
->
fcount
&&
p
->
csdata
[
p
->
frameno
+
f
]
==
checksum
)
break
;
else
if
(
p
->
frameno
-
f
>=
0
&&
p
->
csdata
[
p
->
frameno
-
f
]
==
checksum
)
{
f
=-
f
;
break
;
}
if
(
f
<
100
)
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_INFO
,
"
\n
%s: Mismatch with pass-1: %+d frame(s).
\n
"
,
vf
->
info
->
name
,
f
);
p
->
frameno
+=
f
;
p
->
misscount
=
0
;
}
else
if
(
p
->
misscount
++>=
30
)
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_ERR
,
"
\n
%s: Sync with pass-1 lost! "
"Switching to one pass mode.
\n
"
,
vf
->
info
->
name
);
p
->
pass
=
0
;
break
;
}
}
n
=
(
p
->
frameno
)
/
5
;
if
(
n
>=
p
->
bcount
)
n
=
p
->
bcount
-
1
;
newphase
=
p
->
bdata
[
n
];
break
;
default:
if
(
p
->
frameno
)
{
int
*
sump
=
p
->
sum
+
p
->
frameno
%
5
,
*
histp
=
p
->
history
+
p
->
frameno
%
p
->
window
;
*
sump
-=*
histp
;
*
sump
+=
(
*
histp
=
imgop
(
diff_plane
,
dmpi
,
mpi
,
0
));
}
m
=
match
(
p
,
p
->
sum
,
-
1
,
-
1
,
&
d
);
if
(
d
>=
p
->
threshold
)
newphase
=
m
;
}
n
=
p
->
ocount
++%
5
;
if
(
newphase
!=
p
->
phase
&&
((
p
->
phase
+
4
)
%
5
<
n
)
==
((
newphase
+
4
)
%
5
<
n
))
{
p
->
phase
=
newphase
;
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_STATUS
,
"
\n
%s: Telecine phase %d.
\n
"
,
vf
->
info
->
name
,
p
->
phase
);
}
switch
((
p
->
frameno
++-
p
->
phase
+
10
)
%
5
)
{
case
0
:
imgop
(
copyop
,
dmpi
,
mpi
,
0
);
return
0
;
case
4
:
if
(
p
->
deghost
>
0
)
{
tmpi
=
ff_vf_get_image
(
vf
->
next
,
mpi
->
imgfmt
,
MP_IMGTYPE_TEMP
,
MP_IMGFLAG_ACCEPT_STRIDE
|
MP_IMGFLAG_READABLE
,
mpi
->
width
,
mpi
->
height
);
ff_vf_clone_mpi_attributes
(
tmpi
,
mpi
);
imgop
(
copyop
,
tmpi
,
mpi
,
0
);
imgop
(
deghost_plane
,
tmpi
,
dmpi
,
p
->
deghost
);
imgop
(
copyop
,
dmpi
,
mpi
,
0
);
return
ff_vf_next_put_image
(
vf
,
tmpi
,
MP_NOPTS_VALUE
);
}
}
imgop
(
copyop
,
dmpi
,
mpi
,
0
);
return
ff_vf_next_put_image
(
vf
,
dmpi
,
MP_NOPTS_VALUE
);
}
static
int
analyze
(
struct
vf_priv_s
*
p
)
{
int
*
buf
=
0
,
*
bp
,
bufsize
=
0
,
n
,
b
,
f
,
i
,
j
,
m
,
s
;
unsigned
int
*
cbuf
=
0
,
*
cp
;
int8_t
*
pbuf
;
int8_t
lbuf
[
256
];
int
sum
[
5
];
double
d
;
/* read the file */
n
=
15
;
while
(
fgets
(
lbuf
,
256
,
p
->
file
))
{
if
(
n
>=
bufsize
-
19
)
{
bufsize
=
bufsize
?
bufsize
*
2
:
30000
;
if
((
bp
=
realloc
(
buf
,
bufsize
*
sizeof
*
buf
)))
buf
=
bp
;
if
((
cp
=
realloc
(
cbuf
,
bufsize
*
sizeof
*
cbuf
)))
cbuf
=
cp
;
if
(
!
bp
||
!
cp
)
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_FATAL
,
"%s: Not enough memory.
\n
"
,
ff_vf_info_divtc
.
name
);
free
(
buf
);
free
(
cbuf
);
return
0
;
}
}
sscanf
(
lbuf
,
"%x %d"
,
cbuf
+
n
,
buf
+
n
);
n
++
;
}
if
(
n
<=
15
)
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_FATAL
,
"%s: Empty 2-pass log file.
\n
"
,
ff_vf_info_divtc
.
name
);
free
(
buf
);
free
(
cbuf
);
return
0
;
}
/* generate some dummy data past the beginning and end of the array */
buf
+=
15
,
cbuf
+=
15
;
n
-=
15
;
memcpy
(
buf
-
15
,
buf
,
15
*
sizeof
*
buf
);
memset
(
cbuf
-
15
,
0
,
15
*
sizeof
*
cbuf
);
while
(
n
%
5
)
buf
[
n
]
=
buf
[
n
-
5
],
cbuf
[
n
]
=
0
,
n
++
;
memcpy
(
buf
+
n
,
buf
+
n
-
15
,
15
*
sizeof
*
buf
);
memset
(
cbuf
+
n
,
0
,
15
*
sizeof
*
cbuf
);
p
->
csdata
=
cbuf
;
p
->
fcount
=
n
;
/* array with one slot for each slice of 5 frames */
p
->
bdata
=
pbuf
=
malloc
(
p
->
bcount
=
b
=
(
n
/
5
));
memset
(
pbuf
,
255
,
b
);
/* resolve the automatic mode */
if
(
p
->
deghost
<
0
)
{
int
deghost
=-
p
->
deghost
;
double
s0
=
0
.
0
,
s1
=
0
.
0
;
for
(
f
=
0
;
f
<
n
;
f
+=
5
)
{
p
->
deghost
=
0
;
match
(
p
,
buf
+
f
,
-
1
,
-
1
,
&
d
);
s0
+=
d
;
p
->
deghost
=
1
;
match
(
p
,
buf
+
f
,
-
1
,
-
1
,
&
d
);
s1
+=
d
;
}
p
->
deghost
=
s1
>
s0
?
deghost
:
0
;
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_INFO
,
"%s: Deghosting %-3s (relative pattern strength %+.2fdB).
\n
"
,
ff_vf_info_divtc
.
name
,
p
->
deghost
?
"ON"
:
"OFF"
,
10
.
0
*
log10
(
s1
/
s0
));
}
/* analyze the data */
for
(
f
=
0
;
f
<
5
;
f
++
)
for
(
sum
[
f
]
=
0
,
n
=-
15
;
n
<
20
;
n
+=
5
)
sum
[
f
]
+=
buf
[
n
+
f
];
for
(
f
=
0
;
f
<
b
;
f
++
)
{
m
=
match
(
p
,
sum
,
-
1
,
-
1
,
&
d
);
if
(
d
>=
p
->
threshold
)
pbuf
[
f
]
=
m
;
if
(
f
<
b
-
1
)
for
(
n
=
0
;
n
<
5
;
n
++
)
sum
[
n
]
=
sum
[
n
]
-
buf
[
5
*
(
f
-
3
)
+
n
]
+
buf
[
5
*
(
f
+
4
)
+
n
];
}
/* fill in the gaps */
/* the beginning */
for
(
f
=
0
;
f
<
b
&&
pbuf
[
f
]
==-
1
;
f
++
);
if
(
f
==
b
)
{
free
(
buf
-
15
);
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_FATAL
,
"%s: No telecine pattern found!
\n
"
,
ff_vf_info_divtc
.
name
);
return
0
;
}
for
(
n
=
0
;
n
<
f
;
pbuf
[
n
++
]
=
pbuf
[
f
]);
/* the end */
for
(
f
=
b
-
1
;
pbuf
[
f
]
==-
1
;
f
--
);
for
(
n
=
f
+
1
;
n
<
b
;
pbuf
[
n
++
]
=
pbuf
[
f
]);
/* the rest */
for
(
f
=
0
;;)
{
while
(
f
<
b
&&
pbuf
[
f
]
!=-
1
)
f
++
;
if
(
f
==
b
)
break
;
for
(
n
=
f
;
pbuf
[
n
]
==-
1
;
n
++
);
if
(
pbuf
[
f
-
1
]
==
pbuf
[
n
])
{
/* just a gap */
while
(
f
<
n
)
pbuf
[
f
++
]
=
pbuf
[
n
];
}
else
{
/* phase change, reanalyze the original data in the gap with zero
threshold for only the two phases that appear at the ends */
for
(
i
=
0
;
i
<
5
;
i
++
)
for
(
sum
[
i
]
=
0
,
j
=
5
*
f
-
15
;
j
<
5
*
f
;
j
+=
5
)
sum
[
i
]
+=
buf
[
i
+
j
];
for
(
i
=
f
;
i
<
n
;
i
++
)
{
pbuf
[
i
]
=
match
(
p
,
sum
,
pbuf
[
f
-
1
],
pbuf
[
n
],
0
);
for
(
j
=
0
;
j
<
5
;
j
++
)
sum
[
j
]
=
sum
[
j
]
-
buf
[
5
*
(
i
-
3
)
+
j
]
+
buf
[
5
*
(
i
+
4
)
+
j
];
}
/* estimate the transition point by dividing the gap
in the same proportion as the number of matches of each kind */
for
(
i
=
f
,
m
=
f
;
i
<
n
;
i
++
)
if
(
pbuf
[
i
]
==
pbuf
[
f
-
1
])
m
++
;
/* find the transition of the right direction nearest to the
estimated point */
if
(
m
>
f
&&
m
<
n
)
{
for
(
j
=
m
;
j
>
f
;
j
--
)
if
(
pbuf
[
j
-
1
]
==
pbuf
[
f
-
1
]
&&
pbuf
[
j
]
==
pbuf
[
n
])
break
;
for
(
s
=
m
;
s
<
n
;
s
++
)
if
(
pbuf
[
s
-
1
]
==
pbuf
[
f
-
1
]
&&
pbuf
[
s
]
==
pbuf
[
n
])
break
;
m
=
(
s
-
m
<
m
-
j
)
?
s
:
j
;
}
/* and rewrite the data to allow only this one transition */
for
(
i
=
f
;
i
<
m
;
i
++
)
pbuf
[
i
]
=
pbuf
[
f
-
1
];
for
(;
i
<
n
;
i
++
)
pbuf
[
i
]
=
pbuf
[
n
];
f
=
n
;
}
}
free
(
buf
-
15
);
return
1
;
}
static
int
query_format
(
struct
vf_instance
*
vf
,
unsigned
int
fmt
)
{
switch
(
fmt
)
{
case
IMGFMT_444P
:
case
IMGFMT_IYUV
:
case
IMGFMT_RGB24
:
case
IMGFMT_422P
:
case
IMGFMT_UYVY
:
case
IMGFMT_BGR24
:
case
IMGFMT_411P
:
case
IMGFMT_YUY2
:
case
IMGFMT_IF09
:
case
IMGFMT_YV12
:
case
IMGFMT_I420
:
case
IMGFMT_YVU9
:
case
IMGFMT_IUYV
:
case
IMGFMT_Y800
:
case
IMGFMT_Y8
:
return
ff_vf_next_query_format
(
vf
,
fmt
);
}
return
0
;
}
static
void
uninit
(
struct
vf_instance
*
vf
)
{
if
(
vf
->
priv
)
{
if
(
vf
->
priv
->
file
)
fclose
(
vf
->
priv
->
file
);
if
(
vf
->
priv
->
csdata
)
free
(
vf
->
priv
->
csdata
-
15
);
free
(
vf
->
priv
->
bdata
);
free
(
vf
->
priv
->
history
);
free
(
vf
->
priv
);
}
}
static
int
vf_open
(
vf_instance_t
*
vf
,
char
*
args
)
{
struct
vf_priv_s
*
p
;
const
char
*
filename
=
"framediff.log"
;
char
*
ap
,
*
q
,
*
a
;
if
(
args
&&
!
(
args
=
strdup
(
args
)))
{
nomem:
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_FATAL
,
"%s: Not enough memory.
\n
"
,
vf
->
info
->
name
);
fail:
uninit
(
vf
);
free
(
args
);
return
0
;
}
vf
->
put_image
=
put_image
;
vf
->
uninit
=
uninit
;
vf
->
query_format
=
query_format
;
vf
->
default_reqs
=
VFCAP_ACCEPT_STRIDE
;
if
(
!
(
vf
->
priv
=
p
=
calloc
(
1
,
sizeof
(
struct
vf_priv_s
))))
goto
nomem
;
p
->
phase
=
5
;
p
->
threshold
=
0
.
5
;
p
->
window
=
30
;
if
((
ap
=
args
))
while
(
*
ap
)
{
q
=
ap
;
if
((
ap
=
strchr
(
q
,
':'
)))
*
ap
++=
0
;
else
ap
=
q
+
strlen
(
q
);
if
((
a
=
strchr
(
q
,
'='
)))
*
a
++=
0
;
else
a
=
q
+
strlen
(
q
);
switch
(
*
q
)
{
case
0
:
break
;
case
'f'
:
filename
=
a
;
break
;
case
't'
:
p
->
threshold
=
atof
(
a
);
break
;
case
'w'
:
p
->
window
=
5
*
(
atoi
(
a
)
+
4
)
/
5
;
break
;
case
'd'
:
p
->
deghost
=
atoi
(
a
);
break
;
case
'p'
:
if
(
q
[
1
]
==
'h'
)
p
->
phase
=
atoi
(
a
);
else
p
->
pass
=
atoi
(
a
);
break
;
case
'h'
:
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_INFO
,
"
\n
%s options:
\n\n
"
"pass=1|2 - Use 2-pass mode.
\n
"
"file=filename - Set the 2-pass log file name "
"(default %s).
\n
"
"threshold=value - Set the pattern recognition "
"sensitivity (default %g).
\n
"
"deghost=value - Select deghosting threshold "
"(default %d).
\n
"
"window=numframes - Set the statistics window "
"for 1-pass mode (default %d).
\n
"
"phase=0|1|2|3|4 - Set the initial phase "
"for 1-pass mode (default %d).
\n\n
"
"The option names can be abbreviated to the shortest "
"unique prefix.
\n\n
"
,
vf
->
info
->
name
,
filename
,
p
->
threshold
,
p
->
deghost
,
p
->
window
,
p
->
phase
%
5
);
break
;
default:
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_FATAL
,
"%s: Unknown argument %s.
\n
"
,
vf
->
info
->
name
,
q
);
goto
fail
;
}
}
switch
(
p
->
pass
)
{
case
1
:
if
(
!
(
p
->
file
=
fopen
(
filename
,
"w"
)))
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_FATAL
,
"%s: Can't create file %s.
\n
"
,
vf
->
info
->
name
,
filename
);
goto
fail
;
}
break
;
case
2
:
if
(
!
(
p
->
file
=
fopen
(
filename
,
"r"
)))
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_FATAL
,
"%s: Can't open file %s.
\n
"
,
vf
->
info
->
name
,
filename
);
goto
fail
;
}
if
(
!
analyze
(
p
))
goto
fail
;
fclose
(
p
->
file
);
p
->
file
=
0
;
break
;
}
if
(
p
->
window
<
5
)
p
->
window
=
5
;
if
(
!
(
p
->
history
=
calloc
(
sizeof
*
p
->
history
,
p
->
window
)))
goto
nomem
;
diff
=
diff_C
;
#if HAVE_MMX && HAVE_EBX_AVAILABLE
if
(
ff_gCpuCaps
.
hasMMX
)
diff
=
diff_MMX
;
#endif
free
(
args
);
return
1
;
}
const
vf_info_t
ff_vf_info_divtc
=
{
"inverse telecine for deinterlaced video"
,
"divtc"
,
"Ville Saari"
,
""
,
vf_open
,
NULL
};
libavfilter/libmpcodecs/vf_filmdint.c
deleted
100644 → 0
View file @
a5ebd2d9
/*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include "config.h"
#include "mp_msg.h"
#include "cpudetect.h"
#include "img_format.h"
#include "mp_image.h"
#include "vd.h"
#include "vf.h"
#include "cmmx.h"
#include "libavutil/x86/asm.h"
#include "libvo/fastmemcpy.h"
#define NUM_STORED 4
enum
pu_field_type_t
{
PU_1ST_OF_3
,
PU_2ND_OF_3
,
PU_3RD_OF_3
,
PU_1ST_OF_2
,
PU_2ND_OF_2
,
PU_INTERLACED
};
struct
metrics
{
/* This struct maps to a packed word 64-bit MMX register */
unsigned
short
int
even
;
unsigned
short
int
odd
;
unsigned
short
int
noise
;
unsigned
short
int
temp
;
}
__attribute__
((
aligned
(
8
)));
struct
frame_stats
{
struct
metrics
tiny
,
low
,
high
,
bigger
,
twox
,
max
;
struct
{
unsigned
int
even
,
odd
,
noise
,
temp
;
}
sad
;
unsigned
short
interlaced_high
;
unsigned
short
interlaced_low
;
unsigned
short
num_blocks
;
};
struct
vf_priv_s
{
unsigned
long
inframes
;
unsigned
long
outframes
;
enum
pu_field_type_t
prev_type
;
unsigned
swapped
,
chroma_swapped
;
unsigned
luma_only
;
unsigned
verbose
;
unsigned
fast
;
unsigned
long
w
,
h
,
cw
,
ch
,
stride
,
chroma_stride
,
nplanes
;
unsigned
long
sad_thres
;
unsigned
long
dint_thres
;
unsigned
char
*
memory_allocated
;
unsigned
char
*
planes
[
2
*
NUM_STORED
][
4
];
unsigned
char
**
old_planes
;
unsigned
long
static_idx
;
unsigned
long
temp_idx
;
unsigned
long
crop_x
,
crop_y
,
crop_cx
,
crop_cy
;
unsigned
long
export_count
,
merge_count
;
unsigned
long
num_breaks
;
unsigned
long
num_copies
;
long
in_inc
,
out_dec
,
iosync
;
long
num_fields
;
long
prev_fields
;
long
notout
;
long
mmx2
;
unsigned
small_bytes
[
2
];
unsigned
mmx_temp
[
2
];
struct
frame_stats
stats
[
2
];
struct
metrics
thres
;
char
chflag
;
double
diff_time
,
merge_time
,
decode_time
,
vo_time
,
filter_time
;
};
#define PPZ { 2000, 2000, 0, 2000 }
#define PPR { 2000, 2000, 0, 2000 }
static
const
struct
frame_stats
ppzs
=
{
PPZ
,
PPZ
,
PPZ
,
PPZ
,
PPZ
,
PPZ
,
PPZ
,
0
,
0
,
9999
};
static
const
struct
frame_stats
pprs
=
{
PPR
,
PPR
,
PPR
,
PPR
,
PPR
,
PPR
,
PPR
,
0
,
0
,
9999
};
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) (((a)>(b))?(a):(b))
#endif
#define PDIFFUB(X,Y,T) "movq " #X "," #T "\n\t" \
"psubusb " #Y "," #T "\n\t" \
"psubusb " #X "," #Y "\n\t" \
"paddusb " #Y "," #T "\n\t"
#define PDIFFUBT(X,Y,T) "movq " #X "," #T "\n\t" \
"psubusb " #Y "," #T "\n\t" \
"psubusb " #X "," #Y "\n\t" \
"paddusb " #T "," #Y "\n\t"
#define PSUMBW(X,T,Z) "movq " #X "," #T "\n\t" \
"punpcklbw " #Z "," #X "\n\t" \
"punpckhbw " #Z "," #T "\n\t" \
"paddw " #T "," #X "\n\t" \
"movq " #X "," #T "\n\t" \
"psllq $32, " #T "\n\t" \
"paddw " #T "," #X "\n\t" \
"movq " #X "," #T "\n\t" \
"psllq $16, " #T "\n\t" \
"paddw " #T "," #X "\n\t" \
"psrlq $48, " #X "\n\t"
#define PSADBW(X,Y,T,Z) PDIFFUBT(X,Y,T) PSUMBW(Y,T,Z)
#define PMAXUB(X,Y) "psubusb " #X "," #Y "\n\tpaddusb " #X "," #Y "\n\t"
#define PMAXUW(X,Y) "psubusw " #X "," #Y "\n\tpaddusw " #X "," #Y "\n\t"
#define PMINUBT(X,Y,T) "movq " #Y "," #T "\n\t" \
"psubusb " #X "," #T "\n\t" \
"psubusb " #T "," #Y "\n\t"
#define PAVGB(X,Y) "pavgusb " #X "," #Y "\n\t"
static
inline
void
get_metrics_c
(
unsigned
char
*
a
,
unsigned
char
*
b
,
int
as
,
int
bs
,
int
lines
,
struct
metrics
*
m
)
{
a
-=
as
;
b
-=
bs
;
do
{
cmmx_t
old_po
=
*
(
cmmx_t
*
)(
a
);
cmmx_t
po
=
*
(
cmmx_t
*
)(
b
);
cmmx_t
e
=
*
(
cmmx_t
*
)(
b
+
bs
);
cmmx_t
old_o
=
*
(
cmmx_t
*
)(
a
+
2
*
as
);
cmmx_t
o
=
*
(
cmmx_t
*
)(
b
+
2
*
bs
);
cmmx_t
ne
=
*
(
cmmx_t
*
)(
b
+
3
*
bs
);
cmmx_t
old_no
=
*
(
cmmx_t
*
)(
a
+
4
*
as
);
cmmx_t
no
=
*
(
cmmx_t
*
)(
b
+
4
*
bs
);
cmmx_t
qup_old_odd
=
p31avgb
(
old_o
,
old_po
);
cmmx_t
qup_odd
=
p31avgb
(
o
,
po
);
cmmx_t
qdown_old_odd
=
p31avgb
(
old_o
,
old_no
);
cmmx_t
qdown_odd
=
p31avgb
(
o
,
no
);
cmmx_t
qup_even
=
p31avgb
(
ne
,
e
);
cmmx_t
qdown_even
=
p31avgb
(
e
,
ne
);
cmmx_t
temp_up_diff
=
pdiffub
(
qdown_even
,
qup_old_odd
);
cmmx_t
noise_up_diff
=
pdiffub
(
qdown_even
,
qup_odd
);
cmmx_t
temp_down_diff
=
pdiffub
(
qup_even
,
qdown_old_odd
);
cmmx_t
noise_down_diff
=
pdiffub
(
qup_even
,
qdown_odd
);
cmmx_t
odd_diff
=
pdiffub
(
o
,
old_o
);
m
->
odd
+=
psumbw
(
odd_diff
);
m
->
even
+=
psadbw
(
e
,
*
(
cmmx_t
*
)(
a
+
as
));
temp_up_diff
=
pminub
(
temp_up_diff
,
temp_down_diff
);
temp_up_diff
=
pminub
(
temp_up_diff
,
odd_diff
);
m
->
temp
+=
psumbw
(
temp_up_diff
);
noise_up_diff
=
pminub
(
noise_up_diff
,
odd_diff
);
noise_up_diff
=
pminub
(
noise_up_diff
,
noise_down_diff
);
m
->
noise
+=
psumbw
(
noise_up_diff
);
a
+=
2
*
as
;
b
+=
2
*
bs
;
}
while
(
--
lines
);
}
static
inline
void
get_metrics_fast_c
(
unsigned
char
*
a
,
unsigned
char
*
b
,
int
as
,
int
bs
,
int
lines
,
struct
metrics
*
m
)
{
a
-=
as
;
b
-=
bs
;
do
{
cmmx_t
old_po
=
(
*
(
cmmx_t
*
)(
a
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
po
=
(
*
(
cmmx_t
*
)(
b
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
old_e
=
(
*
(
cmmx_t
*
)(
a
+
as
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
e
=
(
*
(
cmmx_t
*
)(
b
+
bs
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
old_o
=
(
*
(
cmmx_t
*
)(
a
+
2
*
as
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
o
=
(
*
(
cmmx_t
*
)(
b
+
2
*
bs
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
ne
=
(
*
(
cmmx_t
*
)(
b
+
3
*
bs
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
old_no
=
(
*
(
cmmx_t
*
)(
a
+
4
*
as
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
no
=
(
*
(
cmmx_t
*
)(
b
+
4
*
bs
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
qup_old_odd
=
p31avgb_s
(
old_o
,
old_po
);
cmmx_t
qup_odd
=
p31avgb_s
(
o
,
po
);
cmmx_t
qdown_old_odd
=
p31avgb_s
(
old_o
,
old_no
);
cmmx_t
qdown_odd
=
p31avgb_s
(
o
,
no
);
cmmx_t
qup_even
=
p31avgb_s
(
ne
,
e
);
cmmx_t
qdown_even
=
p31avgb_s
(
e
,
ne
);
cmmx_t
temp_up_diff
=
pdiffub_s
(
qdown_even
,
qup_old_odd
);
cmmx_t
noise_up_diff
=
pdiffub_s
(
qdown_even
,
qup_odd
);
cmmx_t
temp_down_diff
=
pdiffub_s
(
qup_even
,
qdown_old_odd
);
cmmx_t
noise_down_diff
=
pdiffub_s
(
qup_even
,
qdown_odd
);
cmmx_t
odd_diff
=
pdiffub_s
(
o
,
old_o
);
m
->
odd
+=
psumbw_s
(
odd_diff
)
<<
1
;
m
->
even
+=
psadbw_s
(
e
,
old_e
)
<<
1
;
temp_up_diff
=
pminub_s
(
temp_up_diff
,
temp_down_diff
);
temp_up_diff
=
pminub_s
(
temp_up_diff
,
odd_diff
);
m
->
temp
+=
psumbw_s
(
temp_up_diff
)
<<
1
;
noise_up_diff
=
pminub_s
(
noise_up_diff
,
odd_diff
);
noise_up_diff
=
pminub_s
(
noise_up_diff
,
noise_down_diff
);
m
->
noise
+=
psumbw_s
(
noise_up_diff
)
<<
1
;
a
+=
2
*
as
;
b
+=
2
*
bs
;
}
while
(
--
lines
);
}
static
inline
void
get_metrics_faster_c
(
unsigned
char
*
a
,
unsigned
char
*
b
,
int
as
,
int
bs
,
int
lines
,
struct
metrics
*
m
)
{
a
-=
as
;
b
-=
bs
;
do
{
cmmx_t
old_po
=
(
*
(
cmmx_t
*
)(
a
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
po
=
(
*
(
cmmx_t
*
)(
b
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
old_e
=
(
*
(
cmmx_t
*
)(
a
+
as
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
e
=
(
*
(
cmmx_t
*
)(
b
+
bs
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
old_o
=
(
*
(
cmmx_t
*
)(
a
+
2
*
as
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
o
=
(
*
(
cmmx_t
*
)(
b
+
2
*
bs
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
ne
=
(
*
(
cmmx_t
*
)(
b
+
3
*
bs
)
>>
1
)
&
~
SIGN_BITS
;
cmmx_t
down_even
=
p31avgb_s
(
e
,
ne
);
cmmx_t
up_odd
=
p31avgb_s
(
o
,
po
);
cmmx_t
up_old_odd
=
p31avgb_s
(
old_o
,
old_po
);
cmmx_t
odd_diff
=
pdiffub_s
(
o
,
old_o
);
cmmx_t
temp_diff
=
pdiffub_s
(
down_even
,
up_old_odd
);
cmmx_t
noise_diff
=
pdiffub_s
(
down_even
,
up_odd
);
m
->
even
+=
psadbw_s
(
e
,
old_e
)
<<
1
;
m
->
odd
+=
psumbw_s
(
odd_diff
)
<<
1
;
temp_diff
=
pminub_s
(
temp_diff
,
odd_diff
);
noise_diff
=
pminub_s
(
noise_diff
,
odd_diff
);
m
->
noise
+=
psumbw_s
(
noise_diff
)
<<
1
;
m
->
temp
+=
psumbw_s
(
temp_diff
)
<<
1
;
a
+=
2
*
as
;
b
+=
2
*
bs
;
}
while
(
--
lines
);
}
static
inline
void
get_block_stats
(
struct
metrics
*
m
,
struct
vf_priv_s
*
p
,
struct
frame_stats
*
s
)
{
unsigned
two_e
=
m
->
even
+
MAX
(
m
->
even
,
p
->
thres
.
even
);
unsigned
two_o
=
m
->
odd
+
MAX
(
m
->
odd
,
p
->
thres
.
odd
);
unsigned
two_n
=
m
->
noise
+
MAX
(
m
->
noise
,
p
->
thres
.
noise
);
unsigned
two_t
=
m
->
temp
+
MAX
(
m
->
temp
,
p
->
thres
.
temp
);
unsigned
e_big
=
m
->
even
>=
(
m
->
odd
+
two_o
+
1
)
/
2
;
unsigned
o_big
=
m
->
odd
>=
(
m
->
even
+
two_e
+
1
)
/
2
;
unsigned
n_big
=
m
->
noise
>=
(
m
->
temp
+
two_t
+
1
)
/
2
;
unsigned
t_big
=
m
->
temp
>=
(
m
->
noise
+
two_n
+
1
)
/
2
;
unsigned
e2x
=
m
->
even
>=
two_o
;
unsigned
o2x
=
m
->
odd
>=
two_e
;
unsigned
n2x
=
m
->
noise
>=
two_t
;
unsigned
t2x
=
m
->
temp
>=
two_n
;
unsigned
ntiny_e
=
m
->
even
>
p
->
thres
.
even
;
unsigned
ntiny_o
=
m
->
odd
>
p
->
thres
.
odd
;
unsigned
ntiny_n
=
m
->
noise
>
p
->
thres
.
noise
;
unsigned
ntiny_t
=
m
->
temp
>
p
->
thres
.
temp
;
unsigned
nlow_e
=
m
->
even
>
2
*
p
->
thres
.
even
;
unsigned
nlow_o
=
m
->
odd
>
2
*
p
->
thres
.
odd
;
unsigned
nlow_n
=
m
->
noise
>
2
*
p
->
thres
.
noise
;
unsigned
nlow_t
=
m
->
temp
>
2
*
p
->
thres
.
temp
;
unsigned
high_e
=
m
->
even
>
4
*
p
->
thres
.
even
;
unsigned
high_o
=
m
->
odd
>
4
*
p
->
thres
.
odd
;
unsigned
high_n
=
m
->
noise
>
4
*
p
->
thres
.
noise
;
unsigned
high_t
=
m
->
temp
>
4
*
p
->
thres
.
temp
;
unsigned
low_il
=
!
n_big
&&
!
t_big
&&
ntiny_n
&&
ntiny_t
;
unsigned
high_il
=
!
n_big
&&
!
t_big
&&
nlow_n
&&
nlow_t
;
if
(
low_il
|
high_il
)
{
s
->
interlaced_low
+=
low_il
;
s
->
interlaced_high
+=
high_il
;
}
else
{
s
->
tiny
.
even
+=
ntiny_e
;
s
->
tiny
.
odd
+=
ntiny_o
;
s
->
tiny
.
noise
+=
ntiny_n
;
s
->
tiny
.
temp
+=
ntiny_t
;
s
->
low
.
even
+=
nlow_e
;
s
->
low
.
odd
+=
nlow_o
;
s
->
low
.
noise
+=
nlow_n
;
s
->
low
.
temp
+=
nlow_t
;
s
->
high
.
even
+=
high_e
;
s
->
high
.
odd
+=
high_o
;
s
->
high
.
noise
+=
high_n
;
s
->
high
.
temp
+=
high_t
;
if
(
m
->
even
>=
p
->
sad_thres
)
s
->
sad
.
even
+=
m
->
even
;
if
(
m
->
odd
>=
p
->
sad_thres
)
s
->
sad
.
odd
+=
m
->
odd
;
if
(
m
->
noise
>=
p
->
sad_thres
)
s
->
sad
.
noise
+=
m
->
noise
;
if
(
m
->
temp
>=
p
->
sad_thres
)
s
->
sad
.
temp
+=
m
->
temp
;
}
s
->
num_blocks
++
;
s
->
max
.
even
=
MAX
(
s
->
max
.
even
,
m
->
even
);
s
->
max
.
odd
=
MAX
(
s
->
max
.
odd
,
m
->
odd
);
s
->
max
.
noise
=
MAX
(
s
->
max
.
noise
,
m
->
noise
);
s
->
max
.
temp
=
MAX
(
s
->
max
.
temp
,
m
->
temp
);
s
->
bigger
.
even
+=
e_big
;
s
->
bigger
.
odd
+=
o_big
;
s
->
bigger
.
noise
+=
n_big
;
s
->
bigger
.
temp
+=
t_big
;
s
->
twox
.
even
+=
e2x
;
s
->
twox
.
odd
+=
o2x
;
s
->
twox
.
noise
+=
n2x
;
s
->
twox
.
temp
+=
t2x
;
}
static
inline
struct
metrics
block_metrics_c
(
unsigned
char
*
a
,
unsigned
char
*
b
,
int
as
,
int
bs
,
int
lines
,
struct
vf_priv_s
*
p
,
struct
frame_stats
*
s
)
{
struct
metrics
tm
;
tm
.
even
=
tm
.
odd
=
tm
.
noise
=
tm
.
temp
=
0
;
get_metrics_c
(
a
,
b
,
as
,
bs
,
lines
,
&
tm
);
if
(
sizeof
(
cmmx_t
)
<
8
)
get_metrics_c
(
a
+
4
,
b
+
4
,
as
,
bs
,
lines
,
&
tm
);
get_block_stats
(
&
tm
,
p
,
s
);
return
tm
;
}
static
inline
struct
metrics
block_metrics_fast_c
(
unsigned
char
*
a
,
unsigned
char
*
b
,
int
as
,
int
bs
,
int
lines
,
struct
vf_priv_s
*
p
,
struct
frame_stats
*
s
)
{
struct
metrics
tm
;
tm
.
even
=
tm
.
odd
=
tm
.
noise
=
tm
.
temp
=
0
;
get_metrics_fast_c
(
a
,
b
,
as
,
bs
,
lines
,
&
tm
);
if
(
sizeof
(
cmmx_t
)
<
8
)
get_metrics_fast_c
(
a
+
4
,
b
+
4
,
as
,
bs
,
lines
,
&
tm
);
get_block_stats
(
&
tm
,
p
,
s
);
return
tm
;
}
static
inline
struct
metrics
block_metrics_faster_c
(
unsigned
char
*
a
,
unsigned
char
*
b
,
int
as
,
int
bs
,
int
lines
,
struct
vf_priv_s
*
p
,
struct
frame_stats
*
s
)
{
struct
metrics
tm
;
tm
.
even
=
tm
.
odd
=
tm
.
noise
=
tm
.
temp
=
0
;
get_metrics_faster_c
(
a
,
b
,
as
,
bs
,
lines
,
&
tm
);
if
(
sizeof
(
cmmx_t
)
<
8
)
get_metrics_faster_c
(
a
+
4
,
b
+
4
,
as
,
bs
,
lines
,
&
tm
);
get_block_stats
(
&
tm
,
p
,
s
);
return
tm
;
}
#define MEQ(X,Y) ((X).even == (Y).even && (X).odd == (Y).odd && (X).temp == (Y).temp && (X).noise == (Y).noise)
#define BLOCK_METRICS_TEMPLATE() \
__asm__ volatile("pxor %mm7, %mm7\n\t"
/* The result is colleted in mm7 */
\
"pxor %mm6, %mm6\n\t"
/* Temp to stay at 0 */
\
); \
a -= as; \
b -= bs; \
do { \
__asm__ volatile( \
"movq (%0,%2), %%mm0\n\t" \
"movq (%1,%3), %%mm1\n\t"
/* mm1 = even */
\
PSADBW(%%mm1, %%mm0, %%mm4, %%mm6) \
"paddusw %%mm0, %%mm7\n\t"
/* even diff */
\
"movq (%0,%2,2), %%mm0\n\t"
/* mm0 = old odd */
\
"movq (%1,%3,2), %%mm2\n\t"
/* mm2 = odd */
\
"movq (%0), %%mm3\n\t" \
"psubusb %4, %%mm3\n\t" \
PAVGB(%%mm0, %%mm3) \
PAVGB(%%mm0, %%mm3)
/* mm3 = qup old odd */
\
"movq %%mm0, %%mm5\n\t" \
PSADBW(%%mm2, %%mm0, %%mm4, %%mm6) \
"psllq $16, %%mm0\n\t" \
"paddusw %%mm0, %%mm7\n\t" \
"movq (%1), %%mm4\n\t" \
"lea (%0,%2,2), %0\n\t" \
"lea (%1,%3,2), %1\n\t" \
"psubusb %4, %%mm4\n\t" \
PAVGB(%%mm2, %%mm4) \
PAVGB(%%mm2, %%mm4)
/* mm4 = qup odd */
\
PDIFFUBT(%%mm5, %%mm2, %%mm0)
/* mm2 =abs(oldodd-odd) */
\
"movq (%1,%3), %%mm5\n\t" \
"psubusb %4, %%mm5\n\t" \
PAVGB(%%mm1, %%mm5) \
PAVGB(%%mm5, %%mm1)
/* mm1 = qdown even */
\
PAVGB((%1,%3), %%mm5)
/* mm5 = qup next even */
\
PDIFFUBT(%%mm1, %%mm3, %%mm0)
/* mm3 = abs(qupoldo-qde) */
\
PDIFFUBT(%%mm1, %%mm4, %%mm0)
/* mm4 = abs(qupodd-qde) */
\
PMINUBT(%%mm2, %%mm3, %%mm0)
/* limit temp to odd diff */
\
PMINUBT(%%mm2, %%mm4, %%mm0)
/* limit noise to odd diff */
\
"movq (%1,%3,2), %%mm2\n\t" \
"psubusb %4, %%mm2\n\t" \
PAVGB((%1), %%mm2) \
PAVGB((%1), %%mm2)
/* mm2 = qdown odd */
\
"movq (%0,%2,2), %%mm1\n\t" \
"psubusb %4, %%mm1\n\t" \
PAVGB((%0), %%mm1) \
PAVGB((%0), %%mm1)
/* mm1 = qdown old odd */
\
PDIFFUBT(%%mm5, %%mm2, %%mm0)
/* mm2 = abs(qdo-qune) */
\
PDIFFUBT(%%mm5, %%mm1, %%mm0)
/* mm1 = abs(qdoo-qune) */
\
PMINUBT(%%mm4, %%mm2, %%mm0)
/* current */
\
PMINUBT(%%mm3, %%mm1, %%mm0)
/* old */
\
PSUMBW(%%mm2, %%mm0, %%mm6) \
PSUMBW(%%mm1, %%mm0, %%mm6) \
"psllq $32, %%mm2\n\t" \
"psllq $48, %%mm1\n\t" \
"paddusw %%mm2, %%mm7\n\t" \
"paddusw %%mm1, %%mm7\n\t" \
: "=r" (a), "=r" (b) \
: "r"((x86_reg)as), "r"((x86_reg)bs), "m" (ones), "0"(a), "1"(b), "X"(*a), "X"(*b) \
); \
} while (--lines);
static
inline
struct
metrics
block_metrics_3dnow
(
unsigned
char
*
a
,
unsigned
char
*
b
,
int
as
,
int
bs
,
int
lines
,
struct
vf_priv_s
*
p
,
struct
frame_stats
*
s
)
{
struct
metrics
tm
;
#if !HAVE_AMD3DNOW
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_FATAL
,
"block_metrics_3dnow: internal error
\n
"
);
#else
static
const
unsigned
long
long
ones
=
0x0101010101010101ull
;
BLOCK_METRICS_TEMPLATE
();
__asm__
volatile
(
"movq %%mm7, %0
\n\t
emms"
:
"=m"
(
tm
));
get_block_stats
(
&
tm
,
p
,
s
);
#endif
return
tm
;
}
#undef PSUMBW
#undef PSADBW
#undef PMAXUB
#undef PMINUBT
#undef PAVGB
#define PSUMBW(X,T,Z) "psadbw " #Z "," #X "\n\t"
#define PSADBW(X,Y,T,Z) "psadbw " #X "," #Y "\n\t"
#define PMAXUB(X,Y) "pmaxub " #X "," #Y "\n\t"
#define PMINUBT(X,Y,T) "pminub " #X "," #Y "\n\t"
#define PAVGB(X,Y) "pavgb " #X "," #Y "\n\t"
static
inline
struct
metrics
block_metrics_mmx2
(
unsigned
char
*
a
,
unsigned
char
*
b
,
int
as
,
int
bs
,
int
lines
,
struct
vf_priv_s
*
p
,
struct
frame_stats
*
s
)
{
struct
metrics
tm
;
#if !HAVE_MMX
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_FATAL
,
"block_metrics_mmx2: internal error
\n
"
);
#else
static
const
unsigned
long
long
ones
=
0x0101010101010101ull
;
x86_reg
interlaced
;
x86_reg
prefetch_line
=
(((
long
)
a
>>
3
)
&
7
)
+
10
;
#ifdef DEBUG
struct
frame_stats
ts
=
*
s
;
#endif
__asm__
volatile
(
"prefetcht0 (%0,%2)
\n\t
"
"prefetcht0 (%1,%3)
\n\t
"
:
:
"r"
(
a
),
"r"
(
b
),
"r"
(
prefetch_line
*
as
),
"r"
(
prefetch_line
*
bs
));
BLOCK_METRICS_TEMPLATE
();
s
->
num_blocks
++
;
__asm__
volatile
(
"movq %3, %%mm0
\n\t
"
"movq %%mm7, %%mm1
\n\t
"
"psubusw %%mm0, %%mm1
\n\t
"
"movq %%mm1, %%mm2
\n\t
"
"paddusw %%mm0, %%mm2
\n\t
"
"paddusw %%mm7, %%mm2
\n\t
"
"pshufw $0xb1, %%mm2, %%mm3
\n\t
"
"pavgw %%mm7, %%mm2
\n\t
"
"pshufw $0xb1, %%mm2, %%mm2
\n\t
"
"psubusw %%mm7, %%mm2
\n\t
"
"pcmpeqw %%mm6, %%mm2
\n\t
"
/* 1 if >= 1.5x */
"psubusw %%mm7, %%mm3
\n\t
"
"pcmpeqw %%mm6, %%mm3
\n\t
"
/* 1 if >= 2x */
"movq %1, %%mm4
\n\t
"
"movq %2, %%mm5
\n\t
"
"psubw %%mm2, %%mm4
\n\t
"
"psubw %%mm3, %%mm5
\n\t
"
"movq %%mm4, %1
\n\t
"
"movq %%mm5, %2
\n\t
"
"pxor %%mm4, %%mm4
\n\t
"
"pcmpeqw %%mm1, %%mm4
\n\t
"
/* 1 if <= t */
"psubusw %%mm0, %%mm1
\n\t
"
"pxor %%mm5, %%mm5
\n\t
"
"pcmpeqw %%mm1, %%mm5
\n\t
"
/* 1 if <= 2t */
"psubusw %%mm0, %%mm1
\n\t
"
"psubusw %%mm0, %%mm1
\n\t
"
"pcmpeqw %%mm6, %%mm1
\n\t
"
/* 1 if <= 4t */
"pshufw $0xb1, %%mm2, %%mm0
\n\t
"
"por %%mm2, %%mm0
\n\t
"
/* 1 if not close */
"punpckhdq %%mm0, %%mm0
\n\t
"
"movq %%mm4, %%mm2
\n\t
"
/* tttt */
"punpckhdq %%mm5, %%mm2
\n\t
"
/* ttll */
"por %%mm2, %%mm0
\n\t
"
"pcmpeqd %%mm6, %%mm0
\n\t
"
/* close && big */
"psrlq $16, %%mm0
\n\t
"
"psrlw $15, %%mm0
\n\t
"
"movd %%mm0, %0
\n\t
"
:
"=r"
(
interlaced
),
"=m"
(
s
->
bigger
),
"=m"
(
s
->
twox
)
:
"m"
(
p
->
thres
)
);
if
(
interlaced
)
{
s
->
interlaced_high
+=
interlaced
>>
16
;
s
->
interlaced_low
+=
interlaced
;
}
else
{
__asm__
volatile
(
"pcmpeqw %%mm0, %%mm0
\n\t
"
/* -1 */
"psubw %%mm0, %%mm4
\n\t
"
"psubw %%mm0, %%mm5
\n\t
"
"psubw %%mm0, %%mm1
\n\t
"
"paddw %0, %%mm4
\n\t
"
"paddw %1, %%mm5
\n\t
"
"paddw %2, %%mm1
\n\t
"
"movq %%mm4, %0
\n\t
"
"movq %%mm5, %1
\n\t
"
"movq %%mm1, %2
\n\t
"
:
"=m"
(
s
->
tiny
),
"=m"
(
s
->
low
),
"=m"
(
s
->
high
)
);
__asm__
volatile
(
"pshufw $0, %2, %%mm0
\n\t
"
"psubusw %%mm7, %%mm0
\n\t
"
"pcmpeqw %%mm6, %%mm0
\n\t
"
/* 0 if below sad_thres */
"pand %%mm7, %%mm0
\n\t
"
"movq %%mm0, %%mm1
\n\t
"
"punpcklwd %%mm6, %%mm0
\n\t
"
/* sad even, odd */
"punpckhwd %%mm6, %%mm1
\n\t
"
/* sad noise, temp */
"paddd %0, %%mm0
\n\t
"
"paddd %1, %%mm1
\n\t
"
"movq %%mm0, %0
\n\t
"
"movq %%mm1, %1
\n\t
"
:
"=m"
(
s
->
sad
.
even
),
"=m"
(
s
->
sad
.
noise
)
:
"m"
(
p
->
sad_thres
)
);
}
__asm__
volatile
(
"movq %%mm7, (%1)
\n\t
"
PMAXUW
((
%
0
),
%%
mm7
)
"movq %%mm7, (%0)
\n\t
"
"emms"
:
:
"r"
(
&
s
->
max
),
"r"
(
&
tm
),
"X"
(
s
->
max
)
:
"memory"
);
#ifdef DEBUG
if
(
1
)
{
struct
metrics
cm
;
a
-=
7
*
as
;
b
-=
7
*
bs
;
cm
=
block_metrics_c
(
a
,
b
,
as
,
bs
,
4
,
p
,
&
ts
);
if
(
!
MEQ
(
tm
,
cm
))
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_WARN
,
"Bad metrics
\n
"
);
if
(
s
)
{
# define CHECK(X) if (!MEQ(s->X, ts.X)) \
ff_mp_msg(MSGT_VFILTER, MSGL_WARN, "Bad " #X "\n");
CHECK
(
tiny
);
CHECK
(
low
);
CHECK
(
high
);
CHECK
(
sad
);
CHECK
(
max
);
}
}
#endif
#endif
return
tm
;
}
static
inline
int
dint_copy_line_mmx2
(
unsigned
char
*
dst
,
unsigned
char
*
a
,
long
bos
,
long
cos
,
int
ds
,
int
ss
,
int
w
,
int
t
)
{
#if !HAVE_MMX
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_FATAL
,
"dint_copy_line_mmx2: internal error
\n
"
);
return
0
;
#else
unsigned
long
len
=
(
w
+
7
)
>>
3
;
int
ret
;
__asm__
volatile
(
"pxor %%mm6, %%mm6
\n\t
"
/* deinterlaced pixel counter */
"movd %0, %%mm7
\n\t
"
"punpcklbw %%mm7, %%mm7
\n\t
"
"punpcklwd %%mm7, %%mm7
\n\t
"
"punpckldq %%mm7, %%mm7
\n\t
"
/* mm7 = threshold */
:
/* no output */
:
"rm"
(
t
)
);
do
{
__asm__
volatile
(
"movq (%0), %%mm0
\n\t
"
"movq (%0,%3,2), %%mm1
\n\t
"
"movq %%mm0, (%2)
\n\t
"
"pmaxub %%mm1, %%mm0
\n\t
"
"pavgb (%0), %%mm1
\n\t
"
"psubusb %%mm1, %%mm0
\n\t
"
"paddusb %%mm7, %%mm0
\n\t
"
/* mm0 = max-avg+thr */
"movq (%0,%1), %%mm2
\n\t
"
"movq (%0,%5), %%mm3
\n\t
"
"movq %%mm2, %%mm4
\n\t
"
PDIFFUBT
(
%%
mm1
,
%%
mm2
,
%%
mm5
)
PDIFFUBT
(
%%
mm1
,
%%
mm3
,
%%
mm5
)
"pminub %%mm2, %%mm3
\n\t
"
"pcmpeqb %%mm3, %%mm2
\n\t
"
/* b = min */
"pand %%mm2, %%mm4
\n\t
"
"pandn (%0,%5), %%mm2
\n\t
"
"por %%mm4, %%mm2
\n\t
"
"pminub %%mm0, %%mm3
\n\t
"
"pcmpeqb %%mm0, %%mm3
\n\t
"
/* set to 1s if >= threshold */
"psubb %%mm3, %%mm6
\n\t
"
/* count pixels above thr. */
"pand %%mm3, %%mm1
\n\t
"
"pandn %%mm2, %%mm3
\n\t
"
"por %%mm3, %%mm1
\n\t
"
/* avg if >= threshold */
"movq %%mm1, (%2,%4)
\n\t
"
:
/* no output */
:
"r"
(
a
),
"r"
((
x86_reg
)
bos
),
"r"
((
x86_reg
)
dst
),
"r"
((
x86_reg
)
ss
),
"r"
((
x86_reg
)
ds
),
"r"
((
x86_reg
)
cos
)
);
a
+=
8
;
dst
+=
8
;
}
while
(
--
len
);
__asm__
volatile
(
"pxor %%mm7, %%mm7
\n\t
"
"psadbw %%mm6, %%mm7
\n\t
"
"movd %%mm7, %0
\n\t
"
"emms
\n\t
"
:
"=r"
(
ret
)
);
return
ret
;
#endif
}
static
inline
int
dint_copy_line
(
unsigned
char
*
dst
,
unsigned
char
*
a
,
long
bos
,
long
cos
,
int
ds
,
int
ss
,
int
w
,
int
t
)
{
unsigned
long
len
=
((
unsigned
long
)
w
+
sizeof
(
cmmx_t
)
-
1
)
/
sizeof
(
cmmx_t
);
cmmx_t
dint_count
=
0
;
cmmx_t
thr
;
t
|=
t
<<
8
;
thr
=
t
|
(
t
<<
16
);
if
(
sizeof
(
cmmx_t
)
>
4
)
thr
|=
thr
<<
(
sizeof
(
cmmx_t
)
*
4
);
do
{
cmmx_t
e
=
*
(
cmmx_t
*
)
a
;
cmmx_t
ne
=
*
(
cmmx_t
*
)(
a
+
2
*
ss
);
cmmx_t
o
=
*
(
cmmx_t
*
)(
a
+
bos
);
cmmx_t
oo
=
*
(
cmmx_t
*
)(
a
+
cos
);
cmmx_t
maxe
=
pmaxub
(
e
,
ne
);
cmmx_t
avge
=
pavgb
(
e
,
ne
);
cmmx_t
max_diff
=
maxe
-
avge
+
thr
;
/* 0<=max-avg<128, thr<128 */
cmmx_t
diffo
=
pdiffub
(
avge
,
o
);
cmmx_t
diffoo
=
pdiffub
(
avge
,
oo
);
cmmx_t
diffcmp
=
pcmpgtub
(
diffo
,
diffoo
);
cmmx_t
bo
=
((
oo
^
o
)
&
diffcmp
)
^
o
;
cmmx_t
diffbo
=
((
diffoo
^
diffo
)
&
diffcmp
)
^
diffo
;
cmmx_t
above_thr
=
~
pcmpgtub
(
max_diff
,
diffbo
);
cmmx_t
bo_or_avg
=
((
avge
^
bo
)
&
above_thr
)
^
bo
;
dint_count
+=
above_thr
&
ONE_BYTES
;
*
(
cmmx_t
*
)(
dst
)
=
e
;
*
(
cmmx_t
*
)(
dst
+
ds
)
=
bo_or_avg
;
a
+=
sizeof
(
cmmx_t
);
dst
+=
sizeof
(
cmmx_t
);
}
while
(
--
len
);
return
psumbw
(
dint_count
);
}
static
int
dint_copy_plane
(
unsigned
char
*
d
,
unsigned
char
*
a
,
unsigned
char
*
b
,
unsigned
char
*
c
,
unsigned
long
w
,
unsigned
long
h
,
unsigned
long
ds
,
unsigned
long
ss
,
unsigned
long
threshold
,
long
field
,
long
mmx2
)
{
unsigned
long
ret
=
0
;
long
bos
=
b
-
a
;
long
cos
=
c
-
a
;
if
(
field
)
{
fast_memcpy
(
d
,
b
,
w
);
h
--
;
d
+=
ds
;
a
+=
ss
;
}
bos
+=
ss
;
cos
+=
ss
;
while
(
h
>
2
)
{
if
(
threshold
>=
128
)
{
fast_memcpy
(
d
,
a
,
w
);
fast_memcpy
(
d
+
ds
,
a
+
bos
,
w
);
}
else
if
(
mmx2
==
1
)
{
ret
+=
dint_copy_line_mmx2
(
d
,
a
,
bos
,
cos
,
ds
,
ss
,
w
,
threshold
);
}
else
ret
+=
dint_copy_line
(
d
,
a
,
bos
,
cos
,
ds
,
ss
,
w
,
threshold
);
h
-=
2
;
d
+=
2
*
ds
;
a
+=
2
*
ss
;
}
fast_memcpy
(
d
,
a
,
w
);
if
(
h
==
2
)
fast_memcpy
(
d
+
ds
,
a
+
bos
,
w
);
return
ret
;
}
static
void
copy_merge_fields
(
struct
vf_priv_s
*
p
,
mp_image_t
*
dmpi
,
unsigned
char
**
old
,
unsigned
char
**
new
,
unsigned
long
show
)
{
unsigned
long
threshold
=
256
;
unsigned
long
field
=
p
->
swapped
;
unsigned
long
dint_pixels
=
0
;
unsigned
char
**
other
=
old
;
if
(
show
>=
12
||
!
(
show
&
3
))
show
>>=
2
,
other
=
new
,
new
=
old
;
if
(
show
<=
2
)
{
/* Single field: de-interlace */
threshold
=
p
->
dint_thres
;
field
^=
show
&
1
;
old
=
new
;
}
else
if
(
show
==
3
)
old
=
new
;
else
field
^=
1
;
dint_pixels
+=
dint_copy_plane
(
dmpi
->
planes
[
0
],
old
[
0
],
new
[
0
],
other
[
0
],
p
->
w
,
p
->
h
,
dmpi
->
stride
[
0
],
p
->
stride
,
threshold
,
field
,
p
->
mmx2
);
if
(
dmpi
->
flags
&
MP_IMGFLAG_PLANAR
)
{
if
(
p
->
luma_only
)
old
=
new
,
other
=
new
;
else
threshold
=
threshold
/
2
+
1
;
field
^=
p
->
chroma_swapped
;
dint_copy_plane
(
dmpi
->
planes
[
1
],
old
[
1
],
new
[
1
],
other
[
1
],
p
->
cw
,
p
->
ch
,
dmpi
->
stride
[
1
],
p
->
chroma_stride
,
threshold
,
field
,
p
->
mmx2
);
dint_copy_plane
(
dmpi
->
planes
[
2
],
old
[
2
],
new
[
2
],
other
[
2
],
p
->
cw
,
p
->
ch
,
dmpi
->
stride
[
2
],
p
->
chroma_stride
,
threshold
,
field
,
p
->
mmx2
);
}
if
(
dint_pixels
>
0
&&
p
->
verbose
)
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_INFO
,
"Deinterlaced %lu pixels
\n
"
,
dint_pixels
);
}
static
void
diff_planes
(
struct
vf_priv_s
*
p
,
struct
frame_stats
*
s
,
unsigned
char
*
of
,
unsigned
char
*
nf
,
int
w
,
int
h
,
int
os
,
int
ns
,
int
swapped
)
{
int
i
,
y
;
int
align
=
-
(
long
)
nf
&
7
;
of
+=
align
;
nf
+=
align
;
w
-=
align
;
if
(
swapped
)
of
-=
os
,
nf
-=
ns
;
i
=
(
h
*
3
>>
7
)
&
~
1
;
of
+=
i
*
os
+
8
;
nf
+=
i
*
ns
+
8
;
h
-=
i
;
w
-=
16
;
memset
(
s
,
0
,
sizeof
(
*
s
));
for
(
y
=
(
h
-
8
)
>>
3
;
y
;
y
--
)
{
if
(
p
->
mmx2
==
1
)
{
for
(
i
=
0
;
i
<
w
;
i
+=
8
)
block_metrics_mmx2
(
of
+
i
,
nf
+
i
,
os
,
ns
,
4
,
p
,
s
);
}
else
if
(
p
->
mmx2
==
2
)
{
for
(
i
=
0
;
i
<
w
;
i
+=
8
)
block_metrics_3dnow
(
of
+
i
,
nf
+
i
,
os
,
ns
,
4
,
p
,
s
);
}
else
if
(
p
->
fast
>
3
)
{
for
(
i
=
0
;
i
<
w
;
i
+=
8
)
block_metrics_faster_c
(
of
+
i
,
nf
+
i
,
os
,
ns
,
4
,
p
,
s
);
}
else
if
(
p
->
fast
>
1
)
{
for
(
i
=
0
;
i
<
w
;
i
+=
8
)
block_metrics_fast_c
(
of
+
i
,
nf
+
i
,
os
,
ns
,
4
,
p
,
s
);
}
else
{
for
(
i
=
0
;
i
<
w
;
i
+=
8
)
block_metrics_c
(
of
+
i
,
nf
+
i
,
os
,
ns
,
4
,
p
,
s
);
}
of
+=
8
*
os
;
nf
+=
8
*
ns
;
}
}
#define METRICS(X) (X).even, (X).odd, (X).noise, (X).temp
static
void
diff_fields
(
struct
vf_priv_s
*
p
,
struct
frame_stats
*
s
,
unsigned
char
**
old
,
unsigned
char
**
new
)
{
diff_planes
(
p
,
s
,
old
[
0
],
new
[
0
],
p
->
w
,
p
->
h
,
p
->
stride
,
p
->
stride
,
p
->
swapped
);
s
->
sad
.
even
=
(
s
->
sad
.
even
*
16ul
)
/
s
->
num_blocks
;
s
->
sad
.
odd
=
(
s
->
sad
.
odd
*
16ul
)
/
s
->
num_blocks
;
s
->
sad
.
noise
=
(
s
->
sad
.
noise
*
16ul
)
/
s
->
num_blocks
;
s
->
sad
.
temp
=
(
s
->
sad
.
temp
*
16ul
)
/
s
->
num_blocks
;
if
(
p
->
verbose
)
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_INFO
,
"%lu%c M:%d/%d/%d/%d - %d, "
"t:%d/%d/%d/%d, l:%d/%d/%d/%d, h:%d/%d/%d/%d, bg:%d/%d/%d/%d, "
"2x:%d/%d/%d/%d, sad:%d/%d/%d/%d, lil:%d, hil:%d, ios:%.1f
\n
"
,
p
->
inframes
,
p
->
chflag
,
METRICS
(
s
->
max
),
s
->
num_blocks
,
METRICS
(
s
->
tiny
),
METRICS
(
s
->
low
),
METRICS
(
s
->
high
),
METRICS
(
s
->
bigger
),
METRICS
(
s
->
twox
),
METRICS
(
s
->
sad
),
s
->
interlaced_low
,
s
->
interlaced_high
,
p
->
iosync
/
(
double
)
p
->
in_inc
);
}
static
const
char
*
parse_args
(
struct
vf_priv_s
*
p
,
const
char
*
args
)
{
args
--
;
while
(
args
&&
*++
args
&&
(
sscanf
(
args
,
"io=%lu:%lu"
,
&
p
->
out_dec
,
&
p
->
in_inc
)
==
2
||
sscanf
(
args
,
"diff_thres=%hu"
,
&
p
->
thres
.
even
)
==
1
||
sscanf
(
args
,
"comb_thres=%hu"
,
&
p
->
thres
.
noise
)
==
1
||
sscanf
(
args
,
"sad_thres=%lu"
,
&
p
->
sad_thres
)
==
1
||
sscanf
(
args
,
"dint_thres=%lu"
,
&
p
->
dint_thres
)
==
1
||
sscanf
(
args
,
"fast=%u"
,
&
p
->
fast
)
==
1
||
sscanf
(
args
,
"mmx2=%lu"
,
&
p
->
mmx2
)
==
1
||
sscanf
(
args
,
"luma_only=%u"
,
&
p
->
luma_only
)
==
1
||
sscanf
(
args
,
"verbose=%u"
,
&
p
->
verbose
)
==
1
||
sscanf
(
args
,
"crop=%lu:%lu:%lu:%lu"
,
&
p
->
w
,
&
p
->
h
,
&
p
->
crop_x
,
&
p
->
crop_y
)
==
4
))
args
=
strchr
(
args
,
'/'
);
return
args
;
}
static
unsigned
long
gcd
(
unsigned
long
x
,
unsigned
long
y
)
{
unsigned
long
t
;
if
(
x
>
y
)
t
=
x
,
x
=
y
,
y
=
t
;
while
(
x
)
{
t
=
y
%
x
;
y
=
x
;
x
=
t
;
}
return
y
;
}
static
void
init
(
struct
vf_priv_s
*
p
,
mp_image_t
*
mpi
)
{
unsigned
long
i
;
unsigned
long
plane_size
,
chroma_plane_size
;
unsigned
char
*
plane
;
unsigned
long
cos
,
los
;
p
->
crop_cx
=
p
->
crop_x
>>
mpi
->
chroma_x_shift
;
p
->
crop_cy
=
p
->
crop_y
>>
mpi
->
chroma_y_shift
;
if
(
mpi
->
flags
&
MP_IMGFLAG_ACCEPT_STRIDE
)
{
p
->
stride
=
(
mpi
->
w
+
15
)
&
~
15
;
p
->
chroma_stride
=
p
->
stride
>>
mpi
->
chroma_x_shift
;
}
else
{
p
->
stride
=
mpi
->
width
;
p
->
chroma_stride
=
mpi
->
chroma_width
;
}
p
->
cw
=
p
->
w
>>
mpi
->
chroma_x_shift
;
p
->
ch
=
p
->
h
>>
mpi
->
chroma_y_shift
;
p
->
nplanes
=
1
;
p
->
static_idx
=
0
;
p
->
temp_idx
=
0
;
p
->
old_planes
=
p
->
planes
[
0
];
plane_size
=
mpi
->
h
*
p
->
stride
;
chroma_plane_size
=
mpi
->
flags
&
MP_IMGFLAG_PLANAR
?
mpi
->
chroma_height
*
p
->
chroma_stride
:
0
;
p
->
memory_allocated
=
malloc
(
NUM_STORED
*
(
plane_size
+
2
*
chroma_plane_size
)
+
8
*
p
->
chroma_stride
+
4096
);
/* align to page boundary */
plane
=
p
->
memory_allocated
+
(
-
(
long
)
p
->
memory_allocated
&
4095
);
memset
(
plane
,
0
,
NUM_STORED
*
plane_size
);
los
=
p
->
crop_x
+
p
->
crop_y
*
p
->
stride
;
cos
=
p
->
crop_cx
+
p
->
crop_cy
*
p
->
chroma_stride
;
for
(
i
=
0
;
i
!=
NUM_STORED
;
i
++
,
plane
+=
plane_size
)
{
p
->
planes
[
i
][
0
]
=
plane
;
p
->
planes
[
NUM_STORED
+
i
][
0
]
=
plane
+
los
;
}
if
(
mpi
->
flags
&
MP_IMGFLAG_PLANAR
)
{
p
->
nplanes
=
3
;
memset
(
plane
,
0x80
,
NUM_STORED
*
2
*
chroma_plane_size
);
for
(
i
=
0
;
i
!=
NUM_STORED
;
i
++
)
{
p
->
planes
[
i
][
1
]
=
plane
;
p
->
planes
[
NUM_STORED
+
i
][
1
]
=
plane
+
cos
;
plane
+=
chroma_plane_size
;
p
->
planes
[
i
][
2
]
=
plane
;
p
->
planes
[
NUM_STORED
+
i
][
2
]
=
plane
+
cos
;
plane
+=
chroma_plane_size
;
}
}
p
->
out_dec
<<=
2
;
i
=
gcd
(
p
->
in_inc
,
p
->
out_dec
);
p
->
in_inc
/=
i
;
p
->
out_dec
/=
i
;
p
->
iosync
=
0
;
p
->
num_fields
=
3
;
}
static
inline
double
get_time
(
void
)
{
struct
timeval
tv
;
gettimeofday
(
&
tv
,
0
);
return
tv
.
tv_sec
+
tv
.
tv_usec
*
1e-6
;
}
static
void
get_image
(
struct
vf_instance
*
vf
,
mp_image_t
*
mpi
)
{
struct
vf_priv_s
*
p
=
vf
->
priv
;
static
unsigned
char
**
planes
,
planes_idx
;
if
(
mpi
->
type
==
MP_IMGTYPE_STATIC
)
return
;
if
(
!
p
->
planes
[
0
][
0
])
init
(
p
,
mpi
);
if
(
mpi
->
type
==
MP_IMGTYPE_TEMP
||
(
mpi
->
type
==
MP_IMGTYPE_IPB
&&
!
(
mpi
->
flags
&
MP_IMGFLAG_READABLE
)))
planes_idx
=
NUM_STORED
/
2
+
(
++
p
->
temp_idx
%
(
NUM_STORED
/
2
));
else
planes_idx
=
++
p
->
static_idx
%
(
NUM_STORED
/
2
);
planes
=
p
->
planes
[
planes_idx
];
mpi
->
priv
=
p
->
planes
[
NUM_STORED
+
planes_idx
];
if
(
mpi
->
priv
==
p
->
old_planes
)
{
unsigned
char
**
old_planes
=
p
->
planes
[
NUM_STORED
+
2
+
(
++
p
->
temp_idx
&
1
)];
my_memcpy_pic
(
old_planes
[
0
],
p
->
old_planes
[
0
],
p
->
w
,
p
->
h
,
p
->
stride
,
p
->
stride
);
if
(
mpi
->
flags
&
MP_IMGFLAG_PLANAR
)
{
my_memcpy_pic
(
old_planes
[
1
],
p
->
old_planes
[
1
],
p
->
cw
,
p
->
ch
,
p
->
chroma_stride
,
p
->
chroma_stride
);
my_memcpy_pic
(
old_planes
[
2
],
p
->
old_planes
[
2
],
p
->
cw
,
p
->
ch
,
p
->
chroma_stride
,
p
->
chroma_stride
);
}
p
->
old_planes
=
old_planes
;
p
->
num_copies
++
;
}
mpi
->
planes
[
0
]
=
planes
[
0
];
mpi
->
stride
[
0
]
=
p
->
stride
;
if
(
mpi
->
flags
&
MP_IMGFLAG_PLANAR
)
{
mpi
->
planes
[
1
]
=
planes
[
1
];
mpi
->
planes
[
2
]
=
planes
[
2
];
mpi
->
stride
[
1
]
=
mpi
->
stride
[
2
]
=
p
->
chroma_stride
;
}
mpi
->
width
=
p
->
stride
;
mpi
->
flags
|=
MP_IMGFLAG_DIRECT
;
mpi
->
flags
&=
~
MP_IMGFLAG_DRAW_CALLBACK
;
}
static
inline
long
cmpe
(
unsigned
long
x
,
unsigned
long
y
,
unsigned
long
err
,
unsigned
long
e
)
{
long
diff
=
x
-
y
;
long
unit
=
((
x
+
y
+
err
)
>>
e
);
long
ret
=
(
diff
>
unit
)
-
(
diff
<
-
unit
);
unit
>>=
1
;
return
ret
+
(
diff
>
unit
)
-
(
diff
<
-
unit
);
}
static
unsigned
long
find_breaks
(
struct
vf_priv_s
*
p
,
struct
frame_stats
*
s
)
{
struct
frame_stats
*
ps
=
&
p
->
stats
[(
p
->
inframes
-
1
)
&
1
];
long
notfilm
=
5
*
p
->
in_inc
-
p
->
out_dec
;
unsigned
long
n
=
s
->
num_blocks
>>
8
;
unsigned
long
sad_comb_cmp
=
cmpe
(
s
->
sad
.
temp
,
s
->
sad
.
noise
,
512
,
1
);
unsigned
long
ret
=
8
;
if
(
cmpe
(
s
->
sad
.
temp
,
s
->
sad
.
even
,
512
,
1
)
>
0
)
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_WARN
,
"@@@@@@@@ Bottom-first field??? @@@@@@@@
\n
"
);
if
(
s
->
sad
.
temp
>
1000
&&
s
->
sad
.
noise
>
1000
)
return
3
;
if
(
s
->
interlaced_high
>=
2
*
n
&&
s
->
sad
.
temp
>
256
&&
s
->
sad
.
noise
>
256
)
return
3
;
if
(
s
->
high
.
noise
>
s
->
num_blocks
/
4
&&
s
->
sad
.
noise
>
10000
&&
s
->
sad
.
noise
>
2
*
s
->
sad
.
even
&&
s
->
sad
.
noise
>
2
*
ps
->
sad
.
odd
)
{
// Mid-frame scene change
if
(
s
->
tiny
.
temp
+
s
->
interlaced_low
<
n
||
s
->
low
.
temp
+
s
->
interlaced_high
<
n
/
4
||
s
->
high
.
temp
+
s
->
interlaced_high
<
n
/
8
||
s
->
sad
.
temp
<
160
)
return
1
;
return
3
;
}
if
(
s
->
high
.
temp
>
s
->
num_blocks
/
4
&&
s
->
sad
.
temp
>
10000
&&
s
->
sad
.
temp
>
2
*
ps
->
sad
.
odd
&&
s
->
sad
.
temp
>
2
*
ps
->
sad
.
even
)
{
// Start frame scene change
if
(
s
->
tiny
.
noise
+
s
->
interlaced_low
<
n
||
s
->
low
.
noise
+
s
->
interlaced_high
<
n
/
4
||
s
->
high
.
noise
+
s
->
interlaced_high
<
n
/
8
||
s
->
sad
.
noise
<
160
)
return
2
;
return
3
;
}
if
(
sad_comb_cmp
==
2
)
return
2
;
if
(
sad_comb_cmp
==
-
2
)
return
1
;
if
(
s
->
tiny
.
odd
>
3
*
MAX
(
n
,
s
->
tiny
.
even
)
+
s
->
interlaced_low
)
return
1
;
if
(
s
->
tiny
.
even
>
3
*
MAX
(
n
,
s
->
tiny
.
odd
)
+
s
->
interlaced_low
&&
(
!
sad_comb_cmp
||
(
s
->
low
.
noise
<=
n
/
4
&&
s
->
low
.
temp
<=
n
/
4
)))
return
4
;
if
(
s
->
sad
.
noise
<
64
&&
s
->
sad
.
temp
<
64
&&
s
->
low
.
noise
<=
n
/
2
&&
s
->
high
.
noise
<=
n
/
4
&&
s
->
low
.
temp
<=
n
/
2
&&
s
->
high
.
temp
<=
n
/
4
)
goto
still
;
if
(
s
->
tiny
.
temp
>
3
*
MAX
(
n
,
s
->
tiny
.
noise
)
+
s
->
interlaced_low
)
return
2
;
if
(
s
->
tiny
.
noise
>
3
*
MAX
(
n
,
s
->
tiny
.
temp
)
+
s
->
interlaced_low
)
return
1
;
if
(
s
->
low
.
odd
>
3
*
MAX
(
n
/
4
,
s
->
low
.
even
)
+
s
->
interlaced_high
)
return
1
;
if
(
s
->
low
.
even
>
3
*
MAX
(
n
/
4
,
s
->
low
.
odd
)
+
s
->
interlaced_high
&&
s
->
sad
.
even
>
2
*
s
->
sad
.
odd
&&
(
!
sad_comb_cmp
||
(
s
->
low
.
noise
<=
n
/
4
&&
s
->
low
.
temp
<=
n
/
4
)))
return
4
;
if
(
s
->
low
.
temp
>
3
*
MAX
(
n
/
4
,
s
->
low
.
noise
)
+
s
->
interlaced_high
)
return
2
;
if
(
s
->
low
.
noise
>
3
*
MAX
(
n
/
4
,
s
->
low
.
temp
)
+
s
->
interlaced_high
)
return
1
;
if
(
sad_comb_cmp
==
1
&&
s
->
sad
.
noise
<
64
)
return
2
;
if
(
sad_comb_cmp
==
-
1
&&
s
->
sad
.
temp
<
64
)
return
1
;
if
(
s
->
tiny
.
odd
<=
n
||
(
s
->
tiny
.
noise
<=
n
/
2
&&
s
->
tiny
.
temp
<=
n
/
2
))
{
if
(
s
->
interlaced_low
<=
n
)
{
if
(
p
->
num_fields
==
1
)
goto
still
;
if
(
s
->
tiny
.
even
<=
n
||
ps
->
tiny
.
noise
<=
n
/
2
)
/* Still frame */
goto
still
;
if
(
s
->
bigger
.
even
>=
2
*
MAX
(
n
,
s
->
bigger
.
odd
)
+
s
->
interlaced_low
)
return
4
;
if
(
s
->
low
.
even
>=
2
*
n
+
s
->
interlaced_low
)
return
4
;
goto
still
;
}
}
if
(
s
->
low
.
odd
<=
n
/
4
)
{
if
(
s
->
interlaced_high
<=
n
/
4
)
{
if
(
p
->
num_fields
==
1
)
goto
still
;
if
(
s
->
low
.
even
<=
n
/
4
)
/* Still frame */
goto
still
;
if
(
s
->
bigger
.
even
>=
2
*
MAX
(
n
/
4
,
s
->
bigger
.
odd
)
+
s
->
interlaced_high
)
return
4
;
if
(
s
->
low
.
even
>=
n
/
2
+
s
->
interlaced_high
)
return
4
;
goto
still
;
}
}
if
(
s
->
bigger
.
temp
>
2
*
MAX
(
n
,
s
->
bigger
.
noise
)
+
s
->
interlaced_low
)
return
2
;
if
(
s
->
bigger
.
noise
>
2
*
MAX
(
n
,
s
->
bigger
.
temp
)
+
s
->
interlaced_low
)
return
1
;
if
(
s
->
bigger
.
temp
>
2
*
MAX
(
n
,
s
->
bigger
.
noise
)
+
s
->
interlaced_high
)
return
2
;
if
(
s
->
bigger
.
noise
>
2
*
MAX
(
n
,
s
->
bigger
.
temp
)
+
s
->
interlaced_high
)
return
1
;
if
(
s
->
twox
.
temp
>
2
*
MAX
(
n
,
s
->
twox
.
noise
)
+
s
->
interlaced_high
)
return
2
;
if
(
s
->
twox
.
noise
>
2
*
MAX
(
n
,
s
->
twox
.
temp
)
+
s
->
interlaced_high
)
return
1
;
if
(
s
->
bigger
.
even
>
2
*
MAX
(
n
,
s
->
bigger
.
odd
)
+
s
->
interlaced_low
&&
s
->
bigger
.
temp
<
n
&&
s
->
bigger
.
noise
<
n
)
return
4
;
if
(
s
->
interlaced_low
>
MIN
(
2
*
n
,
s
->
tiny
.
odd
))
return
3
;
ret
=
8
+
(
1
<<
(
s
->
sad
.
temp
>
s
->
sad
.
noise
));
still:
if
(
p
->
num_fields
==
1
&&
p
->
prev_fields
==
3
&&
notfilm
>=
0
&&
(
s
->
tiny
.
temp
<=
s
->
tiny
.
noise
||
s
->
sad
.
temp
<
s
->
sad
.
noise
+
16
))
return
1
;
if
(
p
->
notout
<
p
->
num_fields
&&
p
->
iosync
>
2
*
p
->
in_inc
&&
notfilm
<
0
)
notfilm
=
0
;
if
(
p
->
num_fields
<
2
||
(
p
->
num_fields
==
2
&&
p
->
prev_fields
==
2
&&
notfilm
<
0
))
return
ret
;
if
(
!
notfilm
&&
(
p
->
prev_fields
&~
1
)
==
2
)
{
if
(
p
->
prev_fields
+
p
->
num_fields
==
5
)
{
if
(
s
->
tiny
.
noise
<=
s
->
tiny
.
temp
||
s
->
low
.
noise
==
0
||
s
->
low
.
noise
<
s
->
low
.
temp
||
s
->
sad
.
noise
<
s
->
sad
.
temp
+
16
)
return
2
;
}
if
(
p
->
prev_fields
+
p
->
num_fields
==
4
)
{
if
(
s
->
tiny
.
temp
<=
s
->
tiny
.
noise
||
s
->
low
.
temp
==
0
||
s
->
low
.
temp
<
s
->
low
.
noise
||
s
->
sad
.
temp
<
s
->
sad
.
noise
+
16
)
return
1
;
}
}
if
(
p
->
num_fields
>
2
&&
ps
->
sad
.
noise
>
s
->
sad
.
noise
&&
ps
->
sad
.
noise
>
s
->
sad
.
temp
)
return
4
;
return
2
>>
(
s
->
sad
.
noise
>
s
->
sad
.
temp
);
}
#define ITOC(X) (!(X) ? ' ' : (X) + ((X)>9 ? 'a'-10 : '0'))
static
int
put_image
(
struct
vf_instance
*
vf
,
mp_image_t
*
mpi
,
double
pts
)
{
mp_image_t
*
dmpi
;
struct
vf_priv_s
*
p
=
vf
->
priv
;
unsigned
char
**
planes
,
**
old_planes
;
struct
frame_stats
*
s
=
&
p
->
stats
[
p
->
inframes
&
1
];
struct
frame_stats
*
ps
=
&
p
->
stats
[(
p
->
inframes
-
1
)
&
1
];
int
swapped
=
0
;
const
int
flags
=
mpi
->
fields
;
int
breaks
,
prev
;
int
show_fields
=
0
;
int
dropped_fields
=
0
;
double
start_time
,
diff_time
;
char
prev_chflag
=
p
->
chflag
;
int
keep_rate
;
if
(
!
p
->
planes
[
0
][
0
])
init
(
p
,
mpi
);
old_planes
=
p
->
old_planes
;
if
((
mpi
->
flags
&
MP_IMGFLAG_DIRECT
)
&&
mpi
->
priv
)
{
planes
=
mpi
->
priv
;
mpi
->
priv
=
0
;
}
else
{
planes
=
p
->
planes
[
2
+
(
++
p
->
temp_idx
&
1
)];
my_memcpy_pic
(
planes
[
0
],
mpi
->
planes
[
0
]
+
p
->
crop_x
+
p
->
crop_y
*
mpi
->
stride
[
0
],
p
->
w
,
p
->
h
,
p
->
stride
,
mpi
->
stride
[
0
]);
if
(
mpi
->
flags
&
MP_IMGFLAG_PLANAR
)
{
my_memcpy_pic
(
planes
[
1
],
mpi
->
planes
[
1
]
+
p
->
crop_cx
+
p
->
crop_cy
*
mpi
->
stride
[
1
],
p
->
cw
,
p
->
ch
,
p
->
chroma_stride
,
mpi
->
stride
[
1
]);
my_memcpy_pic
(
planes
[
2
],
mpi
->
planes
[
2
]
+
p
->
crop_cx
+
p
->
crop_cy
*
mpi
->
stride
[
2
],
p
->
cw
,
p
->
ch
,
p
->
chroma_stride
,
mpi
->
stride
[
2
]);
p
->
num_copies
++
;
}
}
p
->
old_planes
=
planes
;
p
->
chflag
=
';'
;
if
(
flags
&
MP_IMGFIELD_ORDERED
)
{
swapped
=
!
(
flags
&
MP_IMGFIELD_TOP_FIRST
);
p
->
chflag
=
(
flags
&
MP_IMGFIELD_REPEAT_FIRST
?
'|'
:
flags
&
MP_IMGFIELD_TOP_FIRST
?
':'
:
'.'
);
}
p
->
swapped
=
swapped
;
start_time
=
get_time
();
if
(
p
->
chflag
==
'|'
)
{
*
s
=
ppzs
;
p
->
iosync
+=
p
->
in_inc
;
}
else
if
((
p
->
fast
&
1
)
&&
prev_chflag
==
'|'
)
*
s
=
pprs
;
else
diff_fields
(
p
,
s
,
old_planes
,
planes
);
diff_time
=
get_time
();
p
->
diff_time
+=
diff_time
-
start_time
;
breaks
=
p
->
inframes
?
find_breaks
(
p
,
s
)
:
2
;
p
->
inframes
++
;
keep_rate
=
4
*
p
->
in_inc
==
p
->
out_dec
;
switch
(
breaks
)
{
case
0
:
case
8
:
case
9
:
case
10
:
if
(
!
keep_rate
&&
p
->
notout
<
p
->
num_fields
&&
p
->
iosync
<
2
*
p
->
in_inc
)
break
;
if
(
p
->
notout
<
p
->
num_fields
)
dropped_fields
=
-
2
;
case
4
:
if
(
keep_rate
||
p
->
iosync
>=
-
2
*
p
->
in_inc
)
show_fields
=
(
4
<<
p
->
num_fields
)
-
1
;
break
;
case
3
:
if
(
keep_rate
)
show_fields
=
2
;
else
if
(
p
->
iosync
>
0
)
{
if
(
p
->
notout
>=
p
->
num_fields
&&
p
->
iosync
>
2
*
p
->
in_inc
)
{
show_fields
=
4
;
/* prev odd only */
if
(
p
->
num_fields
>
1
)
show_fields
|=
8
;
/* + prev even */
}
else
{
show_fields
=
2
;
/* even only */
if
(
p
->
notout
>=
p
->
num_fields
)
dropped_fields
+=
p
->
num_fields
;
}
}
break
;
case
2
:
if
(
p
->
iosync
<=
-
3
*
p
->
in_inc
)
{
if
(
p
->
notout
>=
p
->
num_fields
)
dropped_fields
=
p
->
num_fields
;
break
;
}
if
(
p
->
num_fields
==
1
)
{
int
prevbreak
=
ps
->
sad
.
noise
>=
128
;
if
(
p
->
iosync
<
4
*
p
->
in_inc
)
{
show_fields
=
3
;
dropped_fields
=
prevbreak
;
}
else
{
show_fields
=
4
|
(
!
prevbreak
<<
3
);
if
(
p
->
notout
<
1
+
p
->
prev_fields
)
dropped_fields
=
-!
prevbreak
;
}
break
;
}
default:
if
(
keep_rate
)
show_fields
=
3
<<
(
breaks
&
1
);
else
if
(
p
->
notout
>=
p
->
num_fields
&&
p
->
iosync
>=
(
breaks
==
1
?
-
p
->
in_inc
:
p
->
in_inc
<<
(
p
->
num_fields
==
1
)))
{
show_fields
=
(
1
<<
(
2
+
p
->
num_fields
))
-
(
1
<<
breaks
);
}
else
{
if
(
p
->
notout
>=
p
->
num_fields
)
dropped_fields
+=
p
->
num_fields
+
2
-
breaks
;
if
(
breaks
==
1
)
{
if
(
p
->
iosync
>=
4
*
p
->
in_inc
)
show_fields
=
6
;
}
else
if
(
p
->
iosync
>
-
3
*
p
->
in_inc
)
show_fields
=
3
;
/* odd+even */
}
break
;
}
show_fields
&=
15
;
prev
=
p
->
prev_fields
;
if
(
breaks
<
8
)
{
if
(
p
->
num_fields
==
1
)
breaks
&=
~
4
;
if
(
breaks
)
p
->
num_breaks
++
;
if
(
breaks
==
3
)
p
->
prev_fields
=
p
->
num_fields
=
1
;
else
if
(
breaks
)
{
p
->
prev_fields
=
p
->
num_fields
+
(
breaks
==
1
)
-
(
breaks
==
4
);
p
->
num_fields
=
breaks
-
(
breaks
==
4
)
+
(
p
->
chflag
==
'|'
);
}
else
p
->
num_fields
+=
2
;
}
else
p
->
num_fields
+=
2
;
p
->
iosync
+=
4
*
p
->
in_inc
;
if
(
p
->
chflag
==
'|'
)
p
->
iosync
+=
p
->
in_inc
;
if
(
show_fields
)
{
p
->
iosync
-=
p
->
out_dec
;
p
->
notout
=
!
(
show_fields
&
1
)
+
!
(
show_fields
&
3
);
if
(((
show_fields
&
3
)
==
3
&&
(
s
->
low
.
noise
+
s
->
interlaced_low
<
(
s
->
num_blocks
>>
8
)
||
s
->
sad
.
noise
<
160
))
||
((
show_fields
&
12
)
==
12
&&
(
ps
->
low
.
noise
+
ps
->
interlaced_low
<
(
s
->
num_blocks
>>
8
)
||
ps
->
sad
.
noise
<
160
)))
{
p
->
export_count
++
;
dmpi
=
ff_vf_get_image
(
vf
->
next
,
mpi
->
imgfmt
,
MP_IMGTYPE_EXPORT
,
MP_IMGFLAG_PRESERVE
|
MP_IMGFLAG_READABLE
,
p
->
w
,
p
->
h
);
if
((
show_fields
&
3
)
!=
3
)
planes
=
old_planes
;
dmpi
->
planes
[
0
]
=
planes
[
0
];
dmpi
->
stride
[
0
]
=
p
->
stride
;
dmpi
->
width
=
mpi
->
width
;
if
(
mpi
->
flags
&
MP_IMGFLAG_PLANAR
)
{
dmpi
->
planes
[
1
]
=
planes
[
1
];
dmpi
->
planes
[
2
]
=
planes
[
2
];
dmpi
->
stride
[
1
]
=
p
->
chroma_stride
;
dmpi
->
stride
[
2
]
=
p
->
chroma_stride
;
}
}
else
{
p
->
merge_count
++
;
dmpi
=
ff_vf_get_image
(
vf
->
next
,
mpi
->
imgfmt
,
MP_IMGTYPE_TEMP
,
MP_IMGFLAG_ACCEPT_STRIDE
,
p
->
w
,
p
->
h
);
copy_merge_fields
(
p
,
dmpi
,
old_planes
,
planes
,
show_fields
);
}
p
->
outframes
++
;
}
else
p
->
notout
+=
2
;
if
(
p
->
verbose
)
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_INFO
,
"%lu %lu: %x %c %c %lu%s%s%c%s
\n
"
,
p
->
inframes
,
p
->
outframes
,
breaks
,
breaks
<
8
&&
breaks
>
0
?
(
int
)
p
->
prev_fields
+
'0'
:
' '
,
ITOC
(
show_fields
),
p
->
num_breaks
,
5
*
p
->
in_inc
==
p
->
out_dec
&&
breaks
<
8
&&
breaks
>
0
&&
((
prev
&~
1
)
!=
2
||
prev
+
p
->
prev_fields
!=
5
)
?
" ######## bad telecine ########"
:
""
,
dropped_fields
?
" ======== dropped "
:
""
,
ITOC
(
dropped_fields
),
!
show_fields
||
(
show_fields
&
(
show_fields
-
1
))
?
""
:
" @@@@@@@@@@@@@@@@@"
);
p
->
merge_time
+=
get_time
()
-
diff_time
;
return
show_fields
?
ff_vf_next_put_image
(
vf
,
dmpi
,
MP_NOPTS_VALUE
)
:
0
;
}
static
int
query_format
(
struct
vf_instance
*
vf
,
unsigned
int
fmt
)
{
/* FIXME - support more formats */
switch
(
fmt
)
{
case
IMGFMT_YV12
:
case
IMGFMT_IYUV
:
case
IMGFMT_I420
:
case
IMGFMT_411P
:
case
IMGFMT_422P
:
case
IMGFMT_444P
:
return
ff_vf_next_query_format
(
vf
,
fmt
);
}
return
0
;
}
static
int
config
(
struct
vf_instance
*
vf
,
int
width
,
int
height
,
int
d_width
,
int
d_height
,
unsigned
int
flags
,
unsigned
int
outfmt
)
{
unsigned
long
cxm
=
0
;
unsigned
long
cym
=
0
;
struct
vf_priv_s
*
p
=
vf
->
priv
;
// rounding:
if
(
!
IMGFMT_IS_RGB
(
outfmt
)
&&
!
IMGFMT_IS_BGR
(
outfmt
)){
switch
(
outfmt
){
case
IMGFMT_444P
:
case
IMGFMT_Y800
:
case
IMGFMT_Y8
:
break
;
case
IMGFMT_YVU9
:
case
IMGFMT_IF09
:
cym
=
3
;
case
IMGFMT_411P
:
cxm
=
3
;
break
;
case
IMGFMT_YV12
:
case
IMGFMT_I420
:
case
IMGFMT_IYUV
:
cym
=
1
;
default:
cxm
=
1
;
}
}
p
->
chroma_swapped
=
!!
(
p
->
crop_y
&
(
cym
+
1
));
if
(
p
->
w
)
p
->
w
+=
p
->
crop_x
&
cxm
;
if
(
p
->
h
)
p
->
h
+=
p
->
crop_y
&
cym
;
p
->
crop_x
&=
~
cxm
;
p
->
crop_y
&=
~
cym
;
if
(
!
p
->
w
||
p
->
w
>
width
)
p
->
w
=
width
;
if
(
!
p
->
h
||
p
->
h
>
height
)
p
->
h
=
height
;
if
(
p
->
crop_x
+
p
->
w
>
width
)
p
->
crop_x
=
0
;
if
(
p
->
crop_y
+
p
->
h
>
height
)
p
->
crop_y
=
0
;
if
(
!
opt_screen_size_x
&&
!
opt_screen_size_y
){
d_width
=
d_width
*
p
->
w
/
width
;
d_height
=
d_height
*
p
->
h
/
height
;
}
return
ff_vf_next_config
(
vf
,
p
->
w
,
p
->
h
,
d_width
,
d_height
,
flags
,
outfmt
);
}
static
void
uninit
(
struct
vf_instance
*
vf
)
{
struct
vf_priv_s
*
p
=
vf
->
priv
;
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_INFO
,
"diff_time: %.3f, merge_time: %.3f, "
"export: %lu, merge: %lu, copy: %lu
\n
"
,
p
->
diff_time
,
p
->
merge_time
,
p
->
export_count
,
p
->
merge_count
,
p
->
num_copies
);
free
(
p
->
memory_allocated
);
free
(
p
);
}
static
int
vf_open
(
vf_instance_t
*
vf
,
char
*
args
)
{
struct
vf_priv_s
*
p
;
vf
->
get_image
=
get_image
;
vf
->
put_image
=
put_image
;
vf
->
config
=
config
;
vf
->
query_format
=
query_format
;
vf
->
uninit
=
uninit
;
vf
->
default_reqs
=
VFCAP_ACCEPT_STRIDE
;
vf
->
priv
=
p
=
calloc
(
1
,
sizeof
(
struct
vf_priv_s
));
p
->
out_dec
=
5
;
p
->
in_inc
=
4
;
p
->
thres
.
noise
=
128
;
p
->
thres
.
even
=
128
;
p
->
sad_thres
=
64
;
p
->
dint_thres
=
4
;
p
->
luma_only
=
0
;
p
->
fast
=
3
;
p
->
mmx2
=
ff_gCpuCaps
.
hasMMX2
?
1
:
ff_gCpuCaps
.
has3DNow
?
2
:
0
;
if
(
args
)
{
const
char
*
args_remain
=
parse_args
(
p
,
args
);
if
(
args_remain
)
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_FATAL
,
"filmdint: unknown suboption: %s
\n
"
,
args_remain
);
return
0
;
}
if
(
p
->
out_dec
<
p
->
in_inc
)
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_FATAL
,
"filmdint: increasing the frame rate is not supported
\n
"
);
return
0
;
}
}
if
(
p
->
mmx2
>
2
)
p
->
mmx2
=
0
;
#if !HAVE_MMX
p
->
mmx2
=
0
;
#endif
#if !HAVE_AMD3DNOW
p
->
mmx2
&=
1
;
#endif
p
->
thres
.
odd
=
p
->
thres
.
even
;
p
->
thres
.
temp
=
p
->
thres
.
noise
;
p
->
diff_time
=
0
;
p
->
merge_time
=
0
;
return
1
;
}
const
vf_info_t
ff_vf_info_filmdint
=
{
"Advanced inverse telecine filer"
,
"filmdint"
,
"Zoltan Hidvegi"
,
""
,
vf_open
,
NULL
};
libavfilter/libmpcodecs/vf_ivtc.c
deleted
100644 → 0
View file @
a5ebd2d9
/*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "mp_msg.h"
#include "cpudetect.h"
#include "img_format.h"
#include "mp_image.h"
#include "vf.h"
#include "libavutil/x86/asm.h"
#include "libvo/fastmemcpy.h"
struct
metrics
{
/* difference: total, even lines, odd lines */
int
d
,
e
,
o
;
/* noise: temporal, spacial (current), spacial (past) */
int
t
,
s
,
p
;
};
struct
frameinfo
{
/* peak, relative, mean */
struct
metrics
p
,
r
,
m
;
};
struct
vf_priv_s
{
struct
frameinfo
fi
[
2
];
mp_image_t
*
dmpi
;
int
first
;
int
drop
,
lastdrop
,
dropnext
;
int
inframes
,
outframes
;
};
enum
{
F_DROP
,
F_MERGE
,
F_NEXT
,
F_SHOW
};
#if HAVE_MMX && HAVE_EBX_AVAILABLE
static
void
block_diffs_MMX
(
struct
metrics
*
m
,
unsigned
char
*
old
,
unsigned
char
*
new
,
int
os
,
int
ns
)
{
int
i
;
short
out
[
24
];
// output buffer for the partial metrics from the mmx code
__asm__
(
"movl $4, %%ecx
\n\t
"
"pxor %%mm4, %%mm4
\n\t
"
// 4 even difference sums
"pxor %%mm5, %%mm5
\n\t
"
// 4 odd difference sums
"pxor %%mm7, %%mm7
\n\t
"
// all zeros
ASMALIGN
(
4
)
"1:
\n\t
"
// Even difference
"movq (%%"
REG_S
"), %%mm0
\n\t
"
"movq (%%"
REG_S
"), %%mm2
\n\t
"
"add %%"
REG_a
", %%"
REG_S
"
\n\t
"
"movq (%%"
REG_D
"), %%mm1
\n\t
"
"add %%"
REG_b
", %%"
REG_D
"
\n\t
"
"psubusb %%mm1, %%mm2
\n\t
"
"psubusb %%mm0, %%mm1
\n\t
"
"movq %%mm2, %%mm0
\n\t
"
"movq %%mm1, %%mm3
\n\t
"
"punpcklbw %%mm7, %%mm0
\n\t
"
"punpcklbw %%mm7, %%mm1
\n\t
"
"punpckhbw %%mm7, %%mm2
\n\t
"
"punpckhbw %%mm7, %%mm3
\n\t
"
"paddw %%mm0, %%mm4
\n\t
"
"paddw %%mm1, %%mm4
\n\t
"
"paddw %%mm2, %%mm4
\n\t
"
"paddw %%mm3, %%mm4
\n\t
"
// Odd difference
"movq (%%"
REG_S
"), %%mm0
\n\t
"
"movq (%%"
REG_S
"), %%mm2
\n\t
"
"add %%"
REG_a
", %%"
REG_S
"
\n\t
"
"movq (%%"
REG_D
"), %%mm1
\n\t
"
"add %%"
REG_b
", %%"
REG_D
"
\n\t
"
"psubusb %%mm1, %%mm2
\n\t
"
"psubusb %%mm0, %%mm1
\n\t
"
"movq %%mm2, %%mm0
\n\t
"
"movq %%mm1, %%mm3
\n\t
"
"punpcklbw %%mm7, %%mm0
\n\t
"
"punpcklbw %%mm7, %%mm1
\n\t
"
"punpckhbw %%mm7, %%mm2
\n\t
"
"punpckhbw %%mm7, %%mm3
\n\t
"
"paddw %%mm0, %%mm5
\n\t
"
"paddw %%mm1, %%mm5
\n\t
"
"paddw %%mm2, %%mm5
\n\t
"
"paddw %%mm3, %%mm5
\n\t
"
"decl %%ecx
\n\t
"
"jnz 1b
\n\t
"
"movq %%mm4, (%%"
REG_d
")
\n\t
"
"movq %%mm5, 8(%%"
REG_d
")
\n\t
"
:
:
"S"
(
old
),
"D"
(
new
),
"a"
(
os
),
"b"
(
ns
),
"d"
(
out
)
:
"memory"
);
m
->
e
=
out
[
0
]
+
out
[
1
]
+
out
[
2
]
+
out
[
3
];
m
->
o
=
out
[
4
]
+
out
[
5
]
+
out
[
6
]
+
out
[
7
];
m
->
d
=
m
->
e
+
m
->
o
;
__asm__
(
// First loop to measure first four columns
"movl $4, %%ecx
\n\t
"
"pxor %%mm4, %%mm4
\n\t
"
// Past spacial noise
"pxor %%mm5, %%mm5
\n\t
"
// Temporal noise
"pxor %%mm6, %%mm6
\n\t
"
// Current spacial noise
ASMALIGN
(
4
)
"2:
\n\t
"
"movq (%%"
REG_S
"), %%mm0
\n\t
"
"movq (%%"
REG_S
",%%"
REG_a
"), %%mm1
\n\t
"
"add %%"
REG_a
", %%"
REG_S
"
\n\t
"
"add %%"
REG_a
", %%"
REG_S
"
\n\t
"
"movq (%%"
REG_D
"), %%mm2
\n\t
"
"movq (%%"
REG_D
",%%"
REG_b
"), %%mm3
\n\t
"
"add %%"
REG_b
", %%"
REG_D
"
\n\t
"
"add %%"
REG_b
", %%"
REG_D
"
\n\t
"
"punpcklbw %%mm7, %%mm0
\n\t
"
"punpcklbw %%mm7, %%mm1
\n\t
"
"punpcklbw %%mm7, %%mm2
\n\t
"
"punpcklbw %%mm7, %%mm3
\n\t
"
"paddw %%mm1, %%mm4
\n\t
"
"paddw %%mm1, %%mm5
\n\t
"
"paddw %%mm3, %%mm6
\n\t
"
"psubw %%mm0, %%mm4
\n\t
"
"psubw %%mm2, %%mm5
\n\t
"
"psubw %%mm2, %%mm6
\n\t
"
"decl %%ecx
\n\t
"
"jnz 2b
\n\t
"
"movq %%mm0, %%mm1
\n\t
"
"movq %%mm0, %%mm2
\n\t
"
"movq %%mm0, %%mm3
\n\t
"
"pcmpgtw %%mm4, %%mm1
\n\t
"
"pcmpgtw %%mm5, %%mm2
\n\t
"
"pcmpgtw %%mm6, %%mm3
\n\t
"
"pxor %%mm1, %%mm4
\n\t
"
"pxor %%mm2, %%mm5
\n\t
"
"pxor %%mm3, %%mm6
\n\t
"
"psubw %%mm1, %%mm4
\n\t
"
"psubw %%mm2, %%mm5
\n\t
"
"psubw %%mm3, %%mm6
\n\t
"
"movq %%mm4, (%%"
REG_d
")
\n\t
"
"movq %%mm5, 16(%%"
REG_d
")
\n\t
"
"movq %%mm6, 32(%%"
REG_d
")
\n\t
"
"mov %%"
REG_a
", %%"
REG_c
"
\n\t
"
"shl $3, %%"
REG_c
"
\n\t
"
"sub %%"
REG_c
", %%"
REG_S
"
\n\t
"
"mov %%"
REG_b
", %%"
REG_c
"
\n\t
"
"shl $3, %%"
REG_c
"
\n\t
"
"sub %%"
REG_c
", %%"
REG_D
"
\n\t
"
// Second loop for the last four columns
"movl $4, %%ecx
\n\t
"
"pxor %%mm4, %%mm4
\n\t
"
"pxor %%mm5, %%mm5
\n\t
"
"pxor %%mm6, %%mm6
\n\t
"
ASMALIGN
(
4
)
"3:
\n\t
"
"movq (%%"
REG_S
"), %%mm0
\n\t
"
"movq (%%"
REG_S
",%%"
REG_a
"), %%mm1
\n\t
"
"add %%"
REG_a
", %%"
REG_S
"
\n\t
"
"add %%"
REG_a
", %%"
REG_S
"
\n\t
"
"movq (%%"
REG_D
"), %%mm2
\n\t
"
"movq (%%"
REG_D
",%%"
REG_b
"), %%mm3
\n\t
"
"add %%"
REG_b
", %%"
REG_D
"
\n\t
"
"add %%"
REG_b
", %%"
REG_D
"
\n\t
"
"punpckhbw %%mm7, %%mm0
\n\t
"
"punpckhbw %%mm7, %%mm1
\n\t
"
"punpckhbw %%mm7, %%mm2
\n\t
"
"punpckhbw %%mm7, %%mm3
\n\t
"
"paddw %%mm1, %%mm4
\n\t
"
"paddw %%mm1, %%mm5
\n\t
"
"paddw %%mm3, %%mm6
\n\t
"
"psubw %%mm0, %%mm4
\n\t
"
"psubw %%mm2, %%mm5
\n\t
"
"psubw %%mm2, %%mm6
\n\t
"
"decl %%ecx
\n\t
"
"jnz 3b
\n\t
"
"movq %%mm0, %%mm1
\n\t
"
"movq %%mm0, %%mm2
\n\t
"
"movq %%mm0, %%mm3
\n\t
"
"pcmpgtw %%mm4, %%mm1
\n\t
"
"pcmpgtw %%mm5, %%mm2
\n\t
"
"pcmpgtw %%mm6, %%mm3
\n\t
"
"pxor %%mm1, %%mm4
\n\t
"
"pxor %%mm2, %%mm5
\n\t
"
"pxor %%mm3, %%mm6
\n\t
"
"psubw %%mm1, %%mm4
\n\t
"
"psubw %%mm2, %%mm5
\n\t
"
"psubw %%mm3, %%mm6
\n\t
"
"movq %%mm4, 8(%%"
REG_d
")
\n\t
"
"movq %%mm5, 24(%%"
REG_d
")
\n\t
"
"movq %%mm6, 40(%%"
REG_d
")
\n\t
"
"emms
\n\t
"
:
:
"S"
(
old
),
"D"
(
new
),
"a"
((
long
)
os
),
"b"
((
long
)
ns
),
"d"
(
out
)
:
"memory"
);
m
->
p
=
m
->
t
=
m
->
s
=
0
;
for
(
i
=
0
;
i
<
8
;
i
++
)
{
m
->
p
+=
out
[
i
];
m
->
t
+=
out
[
8
+
i
];
m
->
s
+=
out
[
16
+
i
];
}
//printf("e=%d o=%d d=%d p=%d t=%d s=%d\n", m->e, m->o, m->d, m->p, m->t, m->s);
}
#endif
//#define MAG(a) ((a)*(a))
//#define MAG(a) (abs(a))
#define MAG(a) (((a)^((a)>>31))-((a)>>31))
//#define LOWPASS(s) (((s)[-2] + 4*(s)[-1] + 6*(s)[0] + 4*(s)[1] + (s)[2])>>4)
//#define LOWPASS(s) (((s)[-1] + 2*(s)[0] + (s)[1])>>2)
#define LOWPASS(s) ((s)[0])
static
void
block_diffs_C
(
struct
metrics
*
m
,
unsigned
char
*
old
,
unsigned
char
*
new
,
int
os
,
int
ns
)
{
int
x
,
y
,
e
=
0
,
o
=
0
,
s
=
0
,
p
=
0
,
t
=
0
;
unsigned
char
*
oldp
,
*
newp
;
m
->
s
=
m
->
p
=
m
->
t
=
0
;
for
(
x
=
8
;
x
;
x
--
)
{
oldp
=
old
++
;
newp
=
new
++
;
s
=
p
=
t
=
0
;
for
(
y
=
4
;
y
;
y
--
)
{
e
+=
MAG
(
newp
[
0
]
-
oldp
[
0
]);
o
+=
MAG
(
newp
[
ns
]
-
oldp
[
os
]);
s
+=
newp
[
ns
]
-
newp
[
0
];
p
+=
oldp
[
os
]
-
oldp
[
0
];
t
+=
oldp
[
os
]
-
newp
[
0
];
oldp
+=
os
<<
1
;
newp
+=
ns
<<
1
;
}
m
->
s
+=
MAG
(
s
);
m
->
p
+=
MAG
(
p
);
m
->
t
+=
MAG
(
t
);
}
m
->
e
=
e
;
m
->
o
=
o
;
m
->
d
=
e
+
o
;
}
static
void
(
*
block_diffs
)(
struct
metrics
*
,
unsigned
char
*
,
unsigned
char
*
,
int
,
int
);
#define MAXUP(a,b) ((a) = ((a)>(b)) ? (a) : (b))
static
void
diff_planes
(
struct
frameinfo
*
fi
,
unsigned
char
*
old
,
unsigned
char
*
new
,
int
w
,
int
h
,
int
os
,
int
ns
)
{
int
x
,
y
;
struct
metrics
l
;
struct
metrics
*
peak
=&
fi
->
p
,
*
rel
=&
fi
->
r
,
*
mean
=&
fi
->
m
;
memset
(
peak
,
0
,
sizeof
(
struct
metrics
));
memset
(
rel
,
0
,
sizeof
(
struct
metrics
));
memset
(
mean
,
0
,
sizeof
(
struct
metrics
));
for
(
y
=
0
;
y
<
h
-
7
;
y
+=
8
)
{
for
(
x
=
8
;
x
<
w
-
8
-
7
;
x
+=
8
)
{
block_diffs
(
&
l
,
old
+
x
+
y
*
os
,
new
+
x
+
y
*
ns
,
os
,
ns
);
mean
->
d
+=
l
.
d
;
mean
->
e
+=
l
.
e
;
mean
->
o
+=
l
.
o
;
mean
->
s
+=
l
.
s
;
mean
->
p
+=
l
.
p
;
mean
->
t
+=
l
.
t
;
MAXUP
(
peak
->
d
,
l
.
d
);
MAXUP
(
peak
->
e
,
l
.
e
);
MAXUP
(
peak
->
o
,
l
.
o
);
MAXUP
(
peak
->
s
,
l
.
s
);
MAXUP
(
peak
->
p
,
l
.
p
);
MAXUP
(
peak
->
t
,
l
.
t
);
MAXUP
(
rel
->
e
,
l
.
e
-
l
.
o
);
MAXUP
(
rel
->
o
,
l
.
o
-
l
.
e
);
MAXUP
(
rel
->
s
,
l
.
s
-
l
.
t
);
MAXUP
(
rel
->
p
,
l
.
p
-
l
.
t
);
MAXUP
(
rel
->
t
,
l
.
t
-
l
.
p
);
MAXUP
(
rel
->
d
,
l
.
t
-
l
.
s
);
/* hack */
}
}
x
=
(
w
/
8
-
2
)
*
(
h
/
8
);
mean
->
d
/=
x
;
mean
->
e
/=
x
;
mean
->
o
/=
x
;
mean
->
s
/=
x
;
mean
->
p
/=
x
;
mean
->
t
/=
x
;
}
static
void
diff_fields
(
struct
frameinfo
*
fi
,
mp_image_t
*
old
,
mp_image_t
*
new
)
{
diff_planes
(
fi
,
old
->
planes
[
0
],
new
->
planes
[
0
],
new
->
w
,
new
->
h
,
old
->
stride
[
0
],
new
->
stride
[
0
]);
}
static
void
stats
(
struct
frameinfo
*
f
)
{
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
" pd=%d re=%d ro=%d rp=%d rt=%d rs=%d rd=%d pp=%d pt=%d ps=%d
\r
"
,
f
->
p
.
d
,
f
->
r
.
e
,
f
->
r
.
o
,
f
->
r
.
p
,
f
->
r
.
t
,
f
->
r
.
s
,
f
->
r
.
d
,
f
->
p
.
p
,
f
->
p
.
t
,
f
->
p
.
s
);
}
static
int
foo
(
struct
vf_priv_s
*
p
,
mp_image_t
*
new
,
mp_image_t
*
cur
)
{
struct
frameinfo
*
f
=
p
->
fi
;
f
[
0
]
=
f
[
1
];
diff_fields
(
&
f
[
1
],
cur
,
new
);
stats
(
&
f
[
1
]);
// Immediately drop this frame if it's already been used.
if
(
p
->
dropnext
)
{
p
->
dropnext
=
0
;
return
F_DROP
;
}
// Sometimes a pulldown frame comes all by itself, so both
// its top and bottom field are duplicates from the adjacent
// two frames. We can just drop such a frame, but we
// immediately show the next frame instead to keep the frame
// drops evenly spaced during normal 3:2 pulldown sequences.
if
((
3
*
f
[
1
].
r
.
o
<
f
[
1
].
r
.
e
)
&&
(
f
[
1
].
r
.
s
<
f
[
1
].
r
.
d
))
{
p
->
dropnext
=
1
;
return
F_NEXT
;
}
// If none of these conditions hold, we will consider the frame
// progressive and just show it as-is.
if
(
!
(
(
3
*
f
[
0
].
r
.
e
<
f
[
0
].
r
.
o
)
||
((
2
*
f
[
0
].
r
.
d
<
f
[
0
].
r
.
s
)
&&
(
f
[
0
].
r
.
s
>
1200
))
||
((
2
*
f
[
1
].
r
.
t
<
f
[
1
].
r
.
p
)
&&
(
f
[
1
].
r
.
p
>
1200
))
))
return
F_SHOW
;
// Otherwise, we have to decide whether to merge or drop.
// If the noise metric only increases minimally, we're off
// to a good start...
if
(((
2
*
f
[
1
].
r
.
t
<
3
*
f
[
1
].
r
.
p
)
&&
(
f
[
1
].
r
.
t
<
3600
))
||
(
f
[
1
].
r
.
t
<
900
)
||
(
f
[
1
].
r
.
d
<
900
))
{
// ...and if noise decreases or the duplicate even field
// is detected, we go ahead with the merge.
if
((
3
*
f
[
0
].
r
.
e
<
f
[
0
].
r
.
o
)
||
(
2
*
f
[
1
].
r
.
t
<
f
[
1
].
r
.
p
))
{
p
->
dropnext
=
1
;
return
F_MERGE
;
}
}
return
F_DROP
;
}
static
void
copy_image
(
mp_image_t
*
dmpi
,
mp_image_t
*
mpi
,
int
field
)
{
switch
(
field
)
{
case
0
:
my_memcpy_pic
(
dmpi
->
planes
[
0
],
mpi
->
planes
[
0
],
mpi
->
w
,
mpi
->
h
/
2
,
dmpi
->
stride
[
0
]
*
2
,
mpi
->
stride
[
0
]
*
2
);
if
(
mpi
->
flags
&
MP_IMGFLAG_PLANAR
)
{
my_memcpy_pic
(
dmpi
->
planes
[
1
],
mpi
->
planes
[
1
],
mpi
->
chroma_width
,
mpi
->
chroma_height
/
2
,
dmpi
->
stride
[
1
]
*
2
,
mpi
->
stride
[
1
]
*
2
);
my_memcpy_pic
(
dmpi
->
planes
[
2
],
mpi
->
planes
[
2
],
mpi
->
chroma_width
,
mpi
->
chroma_height
/
2
,
dmpi
->
stride
[
2
]
*
2
,
mpi
->
stride
[
2
]
*
2
);
}
break
;
case
1
:
my_memcpy_pic
(
dmpi
->
planes
[
0
]
+
dmpi
->
stride
[
0
],
mpi
->
planes
[
0
]
+
mpi
->
stride
[
0
],
mpi
->
w
,
mpi
->
h
/
2
,
dmpi
->
stride
[
0
]
*
2
,
mpi
->
stride
[
0
]
*
2
);
if
(
mpi
->
flags
&
MP_IMGFLAG_PLANAR
)
{
my_memcpy_pic
(
dmpi
->
planes
[
1
]
+
dmpi
->
stride
[
1
],
mpi
->
planes
[
1
]
+
mpi
->
stride
[
1
],
mpi
->
chroma_width
,
mpi
->
chroma_height
/
2
,
dmpi
->
stride
[
1
]
*
2
,
mpi
->
stride
[
1
]
*
2
);
my_memcpy_pic
(
dmpi
->
planes
[
2
]
+
dmpi
->
stride
[
2
],
mpi
->
planes
[
2
]
+
mpi
->
stride
[
2
],
mpi
->
chroma_width
,
mpi
->
chroma_height
/
2
,
dmpi
->
stride
[
2
]
*
2
,
mpi
->
stride
[
2
]
*
2
);
}
break
;
case
2
:
memcpy_pic
(
dmpi
->
planes
[
0
],
mpi
->
planes
[
0
],
mpi
->
w
,
mpi
->
h
,
dmpi
->
stride
[
0
],
mpi
->
stride
[
0
]);
if
(
mpi
->
flags
&
MP_IMGFLAG_PLANAR
)
{
memcpy_pic
(
dmpi
->
planes
[
1
],
mpi
->
planes
[
1
],
mpi
->
chroma_width
,
mpi
->
chroma_height
,
dmpi
->
stride
[
1
],
mpi
->
stride
[
1
]);
memcpy_pic
(
dmpi
->
planes
[
2
],
mpi
->
planes
[
2
],
mpi
->
chroma_width
,
mpi
->
chroma_height
,
dmpi
->
stride
[
2
],
mpi
->
stride
[
2
]);
}
break
;
}
}
static
int
do_put_image
(
struct
vf_instance
*
vf
,
mp_image_t
*
dmpi
)
{
struct
vf_priv_s
*
p
=
vf
->
priv
;
int
dropflag
=
0
;
if
(
!
p
->
dropnext
)
switch
(
p
->
drop
)
{
case
0
:
dropflag
=
0
;
break
;
case
1
:
dropflag
=
(
++
p
->
lastdrop
>=
5
);
break
;
case
2
:
dropflag
=
(
++
p
->
lastdrop
>=
5
)
&&
(
4
*
p
->
inframes
<=
5
*
p
->
outframes
);
break
;
}
if
(
dropflag
)
{
//ff_mp_msg(MSGT_VFILTER, MSGL_V, "drop! [%d/%d=%g]\n",
// p->outframes, p->inframes, (float)p->outframes/p->inframes);
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"!"
);
p
->
lastdrop
=
0
;
return
0
;
}
p
->
outframes
++
;
return
ff_vf_next_put_image
(
vf
,
dmpi
,
MP_NOPTS_VALUE
);
}
static
int
put_image
(
struct
vf_instance
*
vf
,
mp_image_t
*
mpi
,
double
pts
)
{
int
ret
=
0
;
struct
vf_priv_s
*
p
=
vf
->
priv
;
p
->
inframes
++
;
if
(
p
->
first
)
{
/* hack */
p
->
first
=
0
;
return
1
;
}
if
(
!
p
->
dmpi
)
p
->
dmpi
=
ff_vf_get_image
(
vf
->
next
,
mpi
->
imgfmt
,
MP_IMGTYPE_STATIC
,
MP_IMGFLAG_ACCEPT_STRIDE
|
MP_IMGFLAG_PRESERVE
|
MP_IMGFLAG_READABLE
,
mpi
->
width
,
mpi
->
height
);
/* FIXME -- not correct, off by one frame! */
p
->
dmpi
->
qscale
=
mpi
->
qscale
;
p
->
dmpi
->
qstride
=
mpi
->
qstride
;
p
->
dmpi
->
qscale_type
=
mpi
->
qscale_type
;
switch
(
foo
(
p
,
mpi
,
p
->
dmpi
))
{
case
F_DROP
:
copy_image
(
p
->
dmpi
,
mpi
,
2
);
ret
=
0
;
p
->
lastdrop
=
0
;
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"DROP
\n
"
);
break
;
case
F_MERGE
:
copy_image
(
p
->
dmpi
,
mpi
,
0
);
ret
=
do_put_image
(
vf
,
p
->
dmpi
);
copy_image
(
p
->
dmpi
,
mpi
,
1
);
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"MERGE
\n
"
);
p
->
dmpi
=
NULL
;
break
;
case
F_NEXT
:
copy_image
(
p
->
dmpi
,
mpi
,
2
);
ret
=
do_put_image
(
vf
,
p
->
dmpi
);
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"NEXT
\n
"
);
p
->
dmpi
=
NULL
;
break
;
case
F_SHOW
:
ret
=
do_put_image
(
vf
,
p
->
dmpi
);
copy_image
(
p
->
dmpi
,
mpi
,
2
);
ff_mp_msg
(
MSGT_VFILTER
,
MSGL_V
,
"OK
\n
"
);
p
->
dmpi
=
NULL
;
break
;
}
return
ret
;
}
static
int
query_format
(
struct
vf_instance
*
vf
,
unsigned
int
fmt
)
{
switch
(
fmt
)
{
case
IMGFMT_YV12
:
case
IMGFMT_IYUV
:
case
IMGFMT_I420
:
return
ff_vf_next_query_format
(
vf
,
fmt
);
}
return
0
;
}
static
void
uninit
(
struct
vf_instance
*
vf
)
{
free
(
vf
->
priv
);
}
static
int
vf_open
(
vf_instance_t
*
vf
,
char
*
args
)
{
struct
vf_priv_s
*
p
;
vf
->
put_image
=
put_image
;
vf
->
query_format
=
query_format
;
vf
->
uninit
=
uninit
;
vf
->
default_reqs
=
VFCAP_ACCEPT_STRIDE
;
vf
->
priv
=
p
=
calloc
(
1
,
sizeof
(
struct
vf_priv_s
));
p
->
drop
=
0
;
p
->
first
=
1
;
if
(
args
)
sscanf
(
args
,
"%d"
,
&
p
->
drop
);
block_diffs
=
block_diffs_C
;
#if HAVE_MMX && HAVE_EBX_AVAILABLE
if
(
ff_gCpuCaps
.
hasMMX
)
block_diffs
=
block_diffs_MMX
;
#endif
return
1
;
}
const
vf_info_t
ff_vf_info_ivtc
=
{
"inverse telecine, take 2"
,
"ivtc"
,
"Rich Felker"
,
""
,
vf_open
,
NULL
};
libavfilter/version.h
View file @
f0a149e5
...
...
@@ -30,7 +30,7 @@
#define LIBAVFILTER_VERSION_MAJOR 3
#define LIBAVFILTER_VERSION_MINOR 56
#define LIBAVFILTER_VERSION_MICRO 10
1
#define LIBAVFILTER_VERSION_MICRO 10
2
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
LIBAVFILTER_VERSION_MINOR, \
...
...
libavfilter/vf_mp.c
View file @
f0a149e5
...
...
@@ -123,17 +123,13 @@ static const struct {
{
0
,
AV_PIX_FMT_NONE
}
};
extern
const
vf_info_t
ff_vf_info_detc
;
extern
const
vf_info_t
ff_vf_info_dint
;
extern
const
vf_info_t
ff_vf_info_divtc
;
extern
const
vf_info_t
ff_vf_info_down3dright
;
extern
const
vf_info_t
ff_vf_info_eq2
;
extern
const
vf_info_t
ff_vf_info_eq
;
extern
const
vf_info_t
ff_vf_info_fil
;
//extern const vf_info_t ff_vf_info_filmdint;
extern
const
vf_info_t
ff_vf_info_fspp
;
extern
const
vf_info_t
ff_vf_info_ilpack
;
extern
const
vf_info_t
ff_vf_info_ivtc
;
extern
const
vf_info_t
ff_vf_info_mcdeint
;
extern
const
vf_info_t
ff_vf_info_ow
;
extern
const
vf_info_t
ff_vf_info_perspective
;
...
...
@@ -149,17 +145,13 @@ extern const vf_info_t ff_vf_info_uspp;
static
const
vf_info_t
*
const
filters
[]
=
{
&
ff_vf_info_detc
,
&
ff_vf_info_dint
,
&
ff_vf_info_divtc
,
&
ff_vf_info_down3dright
,
&
ff_vf_info_eq2
,
&
ff_vf_info_eq
,
&
ff_vf_info_fil
,
// &ff_vf_info_filmdint, cmmx.h vd.h ‘opt_screen_size_x’
&
ff_vf_info_fspp
,
&
ff_vf_info_ilpack
,
&
ff_vf_info_ivtc
,
&
ff_vf_info_mcdeint
,
&
ff_vf_info_ow
,
&
ff_vf_info_perspective
,
...
...
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