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
409a3bda
Commit
409a3bda
authored
Mar 02, 2012
by
Stefano Sabatini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavfi: add blackdetect filter
Address trac ticket #901.
parent
37fca5da
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
268 additions
and
2 deletions
+268
-2
Changelog
Changelog
+1
-0
filters.texi
doc/filters.texi
+54
-0
Makefile
libavfilter/Makefile
+1
-0
allfilters.c
libavfilter/allfilters.c
+1
-0
version.h
libavfilter/version.h
+2
-2
vf_blackdetect.c
libavfilter/vf_blackdetect.c
+209
-0
No files found.
Changelog
View file @
409a3bda
...
@@ -11,6 +11,7 @@ version next:
...
@@ -11,6 +11,7 @@ version next:
- ID3v2 attached pictures reading and writing
- ID3v2 attached pictures reading and writing
- WMA Lossless decoder
- WMA Lossless decoder
- bluray protocol
- bluray protocol
- blackdetect filter
version 0.10:
version 0.10:
...
...
doc/filters.texi
View file @
409a3bda
...
@@ -761,6 +761,60 @@ video, use the command:
...
@@ -761,6 +761,60 @@ video, use the command:
ass=sub.ass
ass=sub.ass
@end example
@end example
@section blackdetect
Detect video intervals that are (almost) completely black. Can be
useful to detect chapter transitions, commercials, or invalid
recordings. Output lines contains the time for the start, end and
duration of the detected black interval expressed in seconds.
In order to display the output lines, you need to set the loglevel at
least to the AV_LOG_INFO value.
This filter accepts a list of options in the form of
@var{key}=@var{value} pairs separated by ":". A description of the
accepted options follows.
@table @option
@item black_min_duration, d
Set the minimum detected black duration expressed in seconds. It must
be a non-negative floating point number.
Default value is 2.0.
@item picture_black_ratio_th, pic_th
Set the threshold for considering a picture "black".
Express the minimum value for the ratio:
@example
@var{nb_black_pixels} / @var{nb_pixels}
@end example
for which a picture is considered black.
Default value is 0.98.
@item pixel_black_th, pix_th
Set the threshold for considering a pixel "black".
The threshold expresses the maximum pixel luminance value for which a
pixel is considered "black". The provided value is scaled according to
the following equation:
@example
@var{absolute_threshold} = @var{luminance_minimum_value} + @var{pixel_black_th} * @var{luminance_range_size}
@end example
@var{luminance_range_size} and @var{luminance_minimum_value} depend on
the input video format, the range is [0-255] for YUV full-range
formats and [16-235] for YUV non full-range formats.
Default value is 0.10.
@end table
The following example sets the maximum pixel threshold to the minimum
value, and detects only black intervals of 2 or more seconds:
@example
blackdetect=d=2:pix_th=0.00
@end example
@section blackframe
@section blackframe
Detect frames that are (almost) completely black. Can be useful to
Detect frames that are (almost) completely black. Can be useful to
...
...
libavfilter/Makefile
View file @
409a3bda
...
@@ -48,6 +48,7 @@ OBJS-$(CONFIG_ABUFFERSINK_FILTER) += sink_buffer.o
...
@@ -48,6 +48,7 @@ OBJS-$(CONFIG_ABUFFERSINK_FILTER) += sink_buffer.o
OBJS-$(CONFIG_ANULLSINK_FILTER)
+=
asink_anullsink.o
OBJS-$(CONFIG_ANULLSINK_FILTER)
+=
asink_anullsink.o
OBJS-$(CONFIG_ASS_FILTER)
+=
vf_ass.o
OBJS-$(CONFIG_ASS_FILTER)
+=
vf_ass.o
OBJS-$(CONFIG_BLACKDETECT_FILTER)
+=
vf_blackdetect.o
OBJS-$(CONFIG_BLACKFRAME_FILTER)
+=
vf_blackframe.o
OBJS-$(CONFIG_BLACKFRAME_FILTER)
+=
vf_blackframe.o
OBJS-$(CONFIG_BOXBLUR_FILTER)
+=
vf_boxblur.o
OBJS-$(CONFIG_BOXBLUR_FILTER)
+=
vf_boxblur.o
OBJS-$(CONFIG_COPY_FILTER)
+=
vf_copy.o
OBJS-$(CONFIG_COPY_FILTER)
+=
vf_copy.o
...
...
libavfilter/allfilters.c
View file @
409a3bda
...
@@ -56,6 +56,7 @@ void avfilter_register_all(void)
...
@@ -56,6 +56,7 @@ void avfilter_register_all(void)
REGISTER_FILTER
(
ANULLSINK
,
anullsink
,
asink
);
REGISTER_FILTER
(
ANULLSINK
,
anullsink
,
asink
);
REGISTER_FILTER
(
ASS
,
ass
,
vf
);
REGISTER_FILTER
(
ASS
,
ass
,
vf
);
REGISTER_FILTER
(
BLACKDETECT
,
blackdetect
,
vf
);
REGISTER_FILTER
(
BLACKFRAME
,
blackframe
,
vf
);
REGISTER_FILTER
(
BLACKFRAME
,
blackframe
,
vf
);
REGISTER_FILTER
(
BOXBLUR
,
boxblur
,
vf
);
REGISTER_FILTER
(
BOXBLUR
,
boxblur
,
vf
);
REGISTER_FILTER
(
COPY
,
copy
,
vf
);
REGISTER_FILTER
(
COPY
,
copy
,
vf
);
...
...
libavfilter/version.h
View file @
409a3bda
...
@@ -29,8 +29,8 @@
...
@@ -29,8 +29,8 @@
#include "libavutil/avutil.h"
#include "libavutil/avutil.h"
#define LIBAVFILTER_VERSION_MAJOR 2
#define LIBAVFILTER_VERSION_MAJOR 2
#define LIBAVFILTER_VERSION_MINOR 6
2
#define LIBAVFILTER_VERSION_MINOR 6
3
#define LIBAVFILTER_VERSION_MICRO 10
1
#define LIBAVFILTER_VERSION_MICRO 10
0
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
LIBAVFILTER_VERSION_MINOR, \
LIBAVFILTER_VERSION_MINOR, \
...
...
libavfilter/vf_blackdetect.c
0 → 100644
View file @
409a3bda
/*
* Copyright (c) 2012 Stefano Sabatini
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Video black detector, loosely based on blackframe with extended
* syntax and features
*/
#include <float.h>
#include "libavutil/opt.h"
#include "libavutil/timestamp.h"
#include "avfilter.h"
#include "internal.h"
typedef
struct
{
const
AVClass
*
class
;
double
black_min_duration_time
;
///< minimum duration of detected black, in seconds
int64_t
black_min_duration
;
///< minimum duration of detected black, expressed in timebase units
int64_t
black_start
;
///< pts start time of the first black picture
int64_t
black_end
;
///< pts end time of the last black picture
int
black_started
;
double
picture_black_ratio_th
;
double
pixel_black_th
;
unsigned
int
pixel_black_th_i
;
unsigned
int
frame_count
;
///< frame number
unsigned
int
nb_black_pixels
;
///< number of black pixels counted so far
}
BlackDetectContext
;
#define OFFSET(x) offsetof(BlackDetectContext, x)
static
const
AVOption
blackdetect_options
[]
=
{
{
"d"
,
"set minimum detected black duration in seconds"
,
OFFSET
(
black_min_duration_time
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
2
},
0
,
DBL_MAX
},
{
"black_min_duration"
,
"set minimum detected black duration in seconds"
,
OFFSET
(
black_min_duration_time
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
2
},
0
,
DBL_MAX
},
{
"picture_black_ratio_th"
,
"set the picture black ratio threshold"
,
OFFSET
(
picture_black_ratio_th
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
.
98
},
0
,
1
},
{
"pic_th"
,
"set the picture black ratio threshold"
,
OFFSET
(
picture_black_ratio_th
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
.
98
},
0
,
1
},
{
"pixel_black_th"
,
"set the pixel black threshold"
,
OFFSET
(
pixel_black_th
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
.
10
},
0
,
1
},
{
"pix_th"
,
"set the pixel black threshold"
,
OFFSET
(
pixel_black_th
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
.
10
},
0
,
1
},
{
NULL
},
};
static
const
char
*
blackdetect_get_name
(
void
*
ctx
)
{
return
"blackdetect"
;
}
static
const
AVClass
blackdetect_class
=
{
.
class_name
=
"BlackDetectContext"
,
.
item_name
=
blackdetect_get_name
,
.
option
=
blackdetect_options
,
};
#define YUVJ_FORMATS \
PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ444P, PIX_FMT_YUVJ440P
static
enum
PixelFormat
yuvj_formats
[]
=
{
YUVJ_FORMATS
,
PIX_FMT_NONE
};
static
int
query_formats
(
AVFilterContext
*
ctx
)
{
static
const
enum
PixelFormat
pix_fmts
[]
=
{
PIX_FMT_YUV410P
,
PIX_FMT_YUV420P
,
PIX_FMT_GRAY8
,
PIX_FMT_NV12
,
PIX_FMT_NV21
,
PIX_FMT_YUV444P
,
PIX_FMT_YUV422P
,
PIX_FMT_YUV411P
,
YUVJ_FORMATS
,
PIX_FMT_NONE
};
avfilter_set_common_pixel_formats
(
ctx
,
avfilter_make_format_list
(
pix_fmts
));
return
0
;
}
static
av_cold
int
init
(
AVFilterContext
*
ctx
,
const
char
*
args
,
void
*
opaque
)
{
int
ret
;
BlackDetectContext
*
blackdetect
=
ctx
->
priv
;
blackdetect
->
class
=
&
blackdetect_class
;
av_opt_set_defaults
(
blackdetect
);
if
((
ret
=
av_set_options_string
(
blackdetect
,
args
,
"="
,
":"
))
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error parsing options string: '%s'
\n
"
,
args
);
return
ret
;
}
return
0
;
}
static
int
config_input
(
AVFilterLink
*
inlink
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
BlackDetectContext
*
blackdetect
=
ctx
->
priv
;
blackdetect
->
black_min_duration
=
blackdetect
->
black_min_duration_time
/
av_q2d
(
inlink
->
time_base
);
blackdetect
->
pixel_black_th_i
=
ff_fmt_is_in
(
inlink
->
format
,
yuvj_formats
)
?
// luminance_minimum_value + pixel_black_th * luminance_range_size
blackdetect
->
pixel_black_th
*
255
:
16
+
blackdetect
->
pixel_black_th
*
(
235
-
16
);
av_log
(
blackdetect
,
AV_LOG_INFO
,
"black_min_duration:%s pixel_black_th:%f pixel_black_th_i:%d picture_black_ratio_th:%f
\n
"
,
av_ts2timestr
(
blackdetect
->
black_min_duration
,
&
inlink
->
time_base
),
blackdetect
->
pixel_black_th
,
blackdetect
->
pixel_black_th_i
,
blackdetect
->
picture_black_ratio_th
);
return
0
;
}
static
void
draw_slice
(
AVFilterLink
*
inlink
,
int
y
,
int
h
,
int
slice_dir
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
BlackDetectContext
*
blackdetect
=
ctx
->
priv
;
AVFilterBufferRef
*
picref
=
inlink
->
cur_buf
;
int
x
,
i
;
const
uint8_t
*
p
=
picref
->
data
[
0
]
+
y
*
picref
->
linesize
[
0
];
for
(
i
=
0
;
i
<
h
;
i
++
)
{
for
(
x
=
0
;
x
<
inlink
->
w
;
x
++
)
blackdetect
->
nb_black_pixels
+=
p
[
x
]
<=
blackdetect
->
pixel_black_th_i
;
p
+=
picref
->
linesize
[
0
];
}
avfilter_draw_slice
(
ctx
->
outputs
[
0
],
y
,
h
,
slice_dir
);
}
static
void
end_frame
(
AVFilterLink
*
inlink
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
BlackDetectContext
*
blackdetect
=
ctx
->
priv
;
AVFilterBufferRef
*
picref
=
inlink
->
cur_buf
;
double
picture_black_ratio
=
0
;
picture_black_ratio
=
(
double
)
blackdetect
->
nb_black_pixels
/
(
inlink
->
w
*
inlink
->
h
);
av_log
(
ctx
,
AV_LOG_DEBUG
,
"frame:%u picture_black_ratio:%f pos:%"
PRId64
" pts:%s t:%s type:%c
\n
"
,
blackdetect
->
frame_count
,
picture_black_ratio
,
picref
->
pos
,
av_ts2str
(
picref
->
pts
),
av_ts2timestr
(
blackdetect
->
black_start
,
&
inlink
->
time_base
),
av_get_picture_type_char
(
picref
->
video
->
pict_type
));
if
(
picture_black_ratio
>=
blackdetect
->
picture_black_ratio_th
)
{
if
(
!
blackdetect
->
black_started
)
{
/* black starts here */
blackdetect
->
black_started
=
1
;
blackdetect
->
black_start
=
picref
->
pts
;
}
}
else
if
(
blackdetect
->
black_started
)
{
/* black ends here */
blackdetect
->
black_started
=
0
;
blackdetect
->
black_end
=
picref
->
pts
;
if
((
blackdetect
->
black_end
-
blackdetect
->
black_start
)
>=
blackdetect
->
black_min_duration
)
{
av_log
(
blackdetect
,
AV_LOG_INFO
,
"black_start:%s black_end:%s black_duration:%s
\n
"
,
av_ts2timestr
(
blackdetect
->
black_start
,
&
inlink
->
time_base
),
av_ts2timestr
(
blackdetect
->
black_end
,
&
inlink
->
time_base
),
av_ts2timestr
(
blackdetect
->
black_end
-
blackdetect
->
black_start
,
&
inlink
->
time_base
));
}
}
blackdetect
->
frame_count
++
;
blackdetect
->
nb_black_pixels
=
0
;
avfilter_end_frame
(
inlink
->
dst
->
outputs
[
0
]);
}
AVFilter
avfilter_vf_blackdetect
=
{
.
name
=
"blackdetect"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Detect video intervals that are (almost) black."
),
.
priv_size
=
sizeof
(
BlackDetectContext
),
.
init
=
init
,
.
query_formats
=
query_formats
,
.
inputs
=
(
const
AVFilterPad
[])
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
config_props
=
config_input
,
.
draw_slice
=
draw_slice
,
.
get_video_buffer
=
avfilter_null_get_video_buffer
,
.
start_frame
=
avfilter_null_start_frame
,
.
end_frame
=
end_frame
,
},
{
.
name
=
NULL
}
},
.
outputs
=
(
const
AVFilterPad
[])
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
},
{
.
name
=
NULL
}
},
};
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