Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
ffmpeg
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
ffmpeg
Commits
0244879f
Commit
0244879f
authored
Jun 18, 2011
by
Stefano Sabatini
Committed by
Anton Khirnov
Oct 19, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavfi: add testsrc source
Signed-off-by:
Anton Khirnov
<
anton@khirnov.net
>
parent
4e64c4d5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
408 additions
and
1 deletion
+408
-1
filters.texi
doc/filters.texi
+46
-0
Makefile
libavfilter/Makefile
+1
-0
allfilters.c
libavfilter/allfilters.c
+1
-0
avfilter.h
libavfilter/avfilter.h
+1
-1
vsrc_testsrc.c
libavfilter/vsrc_testsrc.c
+359
-0
No files found.
doc/filters.texi
View file @
0244879f
...
...
@@ -1974,6 +1974,52 @@ Some examples follow:
frei0r_src=200x200:10:partik0l=1234 [overlay]; [in][overlay] overlay
@end example
@section testsrc
Generate a test video pattern, showing a color pattern, a scrolling
gradient and a timestamp. This is mainly intended for testing
purposes.
It accepts an optional sequence of @var{key}=@var{value} pairs,
separated by ":". The description of the accepted options follows.
@table @option
@item size, s
Specify the size of the sourced video, it may be a string of the form
@var{width}x@var{heigth}, or the name of a size abbreviation. The
default value is "320x240".
@item rate, r
Specify the frame rate of the sourced video, as the number of frames
generated per second. It has to be a string in the format
@var{frame_rate_num}/@var{frame_rate_den}, an integer number, a float
number or a valid video frame rate abbreviation. The default value is
"25".
@item sar
Set the sample aspect ratio of the sourced video.
@item duration
Set the video duration of the sourced video. The accepted syntax is:
@example
[-]HH[:MM[:SS[.m...]]]
[-]S+[.m...]
@end example
See also the function @code{av_parse_time()}.
If not specified, or the expressed duration is negative, the video is
supposed to be generated forever.
@end table
For example the following:
@example
testsrc=duration=5.3:size=qcif:rate=10
@end example
will generate a video with a duration of 5.3 seconds, with size
176x144 and a framerate of 10 frames per second.
@c man end VIDEO SOURCES
@chapter Video Sinks
...
...
libavfilter/Makefile
View file @
0244879f
...
...
@@ -64,6 +64,7 @@ OBJS-$(CONFIG_COLOR_FILTER) += vsrc_color.o
OBJS-$(CONFIG_FREI0R_SRC_FILTER)
+=
vf_frei0r.o
OBJS-$(CONFIG_MOVIE_FILTER)
+=
vsrc_movie.o
OBJS-$(CONFIG_NULLSRC_FILTER)
+=
vsrc_nullsrc.o
OBJS-$(CONFIG_TESTSRC_FILTER)
+=
vsrc_testsrc.o
OBJS-$(CONFIG_NULLSINK_FILTER)
+=
vsink_nullsink.o
...
...
libavfilter/allfilters.c
View file @
0244879f
...
...
@@ -85,6 +85,7 @@ void avfilter_register_all(void)
REGISTER_FILTER
(
FREI0R
,
frei0r_src
,
vsrc
);
REGISTER_FILTER
(
MOVIE
,
movie
,
vsrc
);
REGISTER_FILTER
(
NULLSRC
,
nullsrc
,
vsrc
);
REGISTER_FILTER
(
TESTSRC
,
testsrc
,
vsrc
);
REGISTER_FILTER
(
NULLSINK
,
nullsink
,
vsink
);
}
libavfilter/avfilter.h
View file @
0244879f
...
...
@@ -29,7 +29,7 @@
#include "libavutil/rational.h"
#define LIBAVFILTER_VERSION_MAJOR 2
#define LIBAVFILTER_VERSION_MINOR 1
1
#define LIBAVFILTER_VERSION_MINOR 1
2
#define LIBAVFILTER_VERSION_MICRO 0
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
...
...
libavfilter/vsrc_testsrc.c
0 → 100644
View file @
0244879f
/*
* Copyright (c) 2007 Nicolas George <nicolas.george@normalesup.org>
* Copyright (c) 2011 Stefano Sabatini
*
* This file is part of Libav.
*
* Libav 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.
*
* Libav 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 Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Based on the test pattern generator demuxer by Nicolas George:
* http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2007-October/037845.html
*/
#include <float.h>
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#include "libavutil/parseutils.h"
#include "avfilter.h"
typedef
struct
{
const
AVClass
*
class
;
int
h
,
w
;
unsigned
int
nb_frame
;
AVRational
time_base
;
int64_t
pts
,
max_pts
;
char
*
size
;
///< video frame size
char
*
rate
;
///< video frame rate
char
*
duration
;
///< total duration of the generated video
AVRational
sar
;
///< sample aspect ratio
void
(
*
fill_picture_fn
)(
AVFilterContext
*
ctx
,
AVFilterBufferRef
*
picref
);
}
TestSourceContext
;
#define OFFSET(x) offsetof(TestSourceContext, x)
static
const
AVOption
testsrc_options
[]
=
{
{
"size"
,
"set video size"
,
OFFSET
(
size
),
FF_OPT_TYPE_STRING
,
{.
str
=
"320x240"
}},
{
"s"
,
"set video size"
,
OFFSET
(
size
),
FF_OPT_TYPE_STRING
,
{.
str
=
"320x240"
}},
{
"rate"
,
"set video rate"
,
OFFSET
(
rate
),
FF_OPT_TYPE_STRING
,
{.
str
=
"25"
},
},
{
"r"
,
"set video rate"
,
OFFSET
(
rate
),
FF_OPT_TYPE_STRING
,
{.
str
=
"25"
},
},
{
"duration"
,
"set video duration"
,
OFFSET
(
duration
),
FF_OPT_TYPE_STRING
,
{.
str
=
NULL
},
},
{
"sar"
,
"set video sample aspect ratio"
,
OFFSET
(
sar
),
FF_OPT_TYPE_RATIONAL
,
{
1
},
0
,
INT_MAX
},
{
NULL
},
};
static
av_cold
int
init_common
(
AVFilterContext
*
ctx
,
const
char
*
args
,
void
*
opaque
)
{
TestSourceContext
*
test
=
ctx
->
priv
;
AVRational
frame_rate_q
;
int64_t
duration
=
-
1
;
int
ret
=
0
;
av_opt_set_defaults
(
test
);
if
((
ret
=
(
av_set_options_string
(
test
,
args
,
"="
,
":"
)))
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error parsing options string: '%s'
\n
"
,
args
);
return
ret
;
}
if
((
ret
=
av_parse_video_size
(
&
test
->
w
,
&
test
->
h
,
test
->
size
))
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Invalid frame size: '%s'
\n
"
,
test
->
size
);
return
ret
;
}
if
((
ret
=
av_parse_video_rate
(
&
frame_rate_q
,
test
->
rate
))
<
0
||
frame_rate_q
.
den
<=
0
||
frame_rate_q
.
num
<=
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Invalid frame rate: '%s'
\n
"
,
test
->
rate
);
return
ret
;
}
if
((
test
->
duration
)
&&
(
ret
=
av_parse_time
(
&
duration
,
test
->
duration
,
1
))
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Invalid duration: '%s'
\n
"
,
test
->
duration
);
return
ret
;
}
test
->
time_base
.
num
=
frame_rate_q
.
den
;
test
->
time_base
.
den
=
frame_rate_q
.
num
;
test
->
max_pts
=
duration
>=
0
?
av_rescale_q
(
duration
,
AV_TIME_BASE_Q
,
test
->
time_base
)
:
-
1
;
test
->
nb_frame
=
0
;
test
->
pts
=
0
;
av_log
(
ctx
,
AV_LOG_DEBUG
,
"size:%dx%d rate:%d/%d duration:%f sar:%d/%d
\n
"
,
test
->
w
,
test
->
h
,
frame_rate_q
.
num
,
frame_rate_q
.
den
,
duration
<
0
?
-
1
:
test
->
max_pts
*
av_q2d
(
test
->
time_base
),
test
->
sar
.
num
,
test
->
sar
.
den
);
return
0
;
}
static
int
config_props
(
AVFilterLink
*
outlink
)
{
TestSourceContext
*
test
=
outlink
->
src
->
priv
;
outlink
->
w
=
test
->
w
;
outlink
->
h
=
test
->
h
;
outlink
->
sample_aspect_ratio
=
test
->
sar
;
outlink
->
time_base
=
test
->
time_base
;
return
0
;
}
static
int
request_frame
(
AVFilterLink
*
outlink
)
{
TestSourceContext
*
test
=
outlink
->
src
->
priv
;
AVFilterBufferRef
*
picref
;
if
(
test
->
max_pts
>=
0
&&
test
->
pts
>
test
->
max_pts
)
return
AVERROR_EOF
;
picref
=
avfilter_get_video_buffer
(
outlink
,
AV_PERM_WRITE
,
test
->
w
,
test
->
h
);
picref
->
pts
=
test
->
pts
++
;
picref
->
pos
=
-
1
;
picref
->
video
->
key_frame
=
1
;
picref
->
video
->
interlaced
=
0
;
picref
->
video
->
pict_type
=
AV_PICTURE_TYPE_I
;
picref
->
video
->
pixel_aspect
=
test
->
sar
;
test
->
nb_frame
++
;
test
->
fill_picture_fn
(
outlink
->
src
,
picref
);
avfilter_start_frame
(
outlink
,
avfilter_ref_buffer
(
picref
,
~
0
));
avfilter_draw_slice
(
outlink
,
0
,
picref
->
video
->
h
,
1
);
avfilter_end_frame
(
outlink
);
avfilter_unref_buffer
(
picref
);
return
0
;
}
static
const
char
*
testsrc_get_name
(
void
*
ctx
)
{
return
"testsrc"
;
}
static
const
AVClass
testsrc_class
=
{
.
class_name
=
"TestSourceContext"
,
.
item_name
=
testsrc_get_name
,
.
option
=
testsrc_options
,
};
/**
* Fill a rectangle with value val.
*
* @param val the RGB value to set
* @param dst pointer to the destination buffer to fill
* @param dst_linesize linesize of destination
* @param segment_width width of the segment
* @param x horizontal coordinate where to draw the rectangle in the destination buffer
* @param y horizontal coordinate where to draw the rectangle in the destination buffer
* @param w width of the rectangle to draw, expressed as a number of segment_width units
* @param h height of the rectangle to draw, expressed as a number of segment_width units
*/
static
void
draw_rectangle
(
unsigned
val
,
uint8_t
*
dst
,
int
dst_linesize
,
unsigned
segment_width
,
unsigned
x
,
unsigned
y
,
unsigned
w
,
unsigned
h
)
{
int
i
;
int
step
=
3
;
dst
+=
segment_width
*
(
step
*
x
+
y
*
dst_linesize
);
w
*=
segment_width
*
step
;
h
*=
segment_width
;
for
(
i
=
0
;
i
<
h
;
i
++
)
{
memset
(
dst
,
val
,
w
);
dst
+=
dst_linesize
;
}
}
static
void
draw_digit
(
int
digit
,
uint8_t
*
dst
,
unsigned
dst_linesize
,
unsigned
segment_width
)
{
#define TOP_HBAR 1
#define MID_HBAR 2
#define BOT_HBAR 4
#define LEFT_TOP_VBAR 8
#define LEFT_BOT_VBAR 16
#define RIGHT_TOP_VBAR 32
#define RIGHT_BOT_VBAR 64
struct
{
int
x
,
y
,
w
,
h
;
}
segments
[]
=
{
{
1
,
0
,
5
,
1
},
/* TOP_HBAR */
{
1
,
6
,
5
,
1
},
/* MID_HBAR */
{
1
,
12
,
5
,
1
},
/* BOT_HBAR */
{
0
,
1
,
1
,
5
},
/* LEFT_TOP_VBAR */
{
0
,
7
,
1
,
5
},
/* LEFT_BOT_VBAR */
{
6
,
1
,
1
,
5
},
/* RIGHT_TOP_VBAR */
{
6
,
7
,
1
,
5
}
/* RIGHT_BOT_VBAR */
};
static
const
unsigned
char
masks
[
10
]
=
{
/* 0 */
TOP_HBAR
|
BOT_HBAR
|
LEFT_TOP_VBAR
|
LEFT_BOT_VBAR
|
RIGHT_TOP_VBAR
|
RIGHT_BOT_VBAR
,
/* 1 */
RIGHT_TOP_VBAR
|
RIGHT_BOT_VBAR
,
/* 2 */
TOP_HBAR
|
MID_HBAR
|
BOT_HBAR
|
LEFT_BOT_VBAR
|
RIGHT_TOP_VBAR
,
/* 3 */
TOP_HBAR
|
MID_HBAR
|
BOT_HBAR
|
RIGHT_TOP_VBAR
|
RIGHT_BOT_VBAR
,
/* 4 */
MID_HBAR
|
LEFT_TOP_VBAR
|
RIGHT_TOP_VBAR
|
RIGHT_BOT_VBAR
,
/* 5 */
TOP_HBAR
|
BOT_HBAR
|
MID_HBAR
|
LEFT_TOP_VBAR
|
RIGHT_BOT_VBAR
,
/* 6 */
TOP_HBAR
|
BOT_HBAR
|
MID_HBAR
|
LEFT_TOP_VBAR
|
LEFT_BOT_VBAR
|
RIGHT_BOT_VBAR
,
/* 7 */
TOP_HBAR
|
RIGHT_TOP_VBAR
|
RIGHT_BOT_VBAR
,
/* 8 */
TOP_HBAR
|
BOT_HBAR
|
MID_HBAR
|
LEFT_TOP_VBAR
|
LEFT_BOT_VBAR
|
RIGHT_TOP_VBAR
|
RIGHT_BOT_VBAR
,
/* 9 */
TOP_HBAR
|
BOT_HBAR
|
MID_HBAR
|
LEFT_TOP_VBAR
|
RIGHT_TOP_VBAR
|
RIGHT_BOT_VBAR
,
};
unsigned
mask
=
masks
[
digit
];
int
i
;
draw_rectangle
(
0
,
dst
,
dst_linesize
,
segment_width
,
0
,
0
,
8
,
13
);
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
segments
);
i
++
)
if
(
mask
&
(
1
<<
i
))
draw_rectangle
(
255
,
dst
,
dst_linesize
,
segment_width
,
segments
[
i
].
x
,
segments
[
i
].
y
,
segments
[
i
].
w
,
segments
[
i
].
h
);
}
#define GRADIENT_SIZE (6 * 256)
static
void
test_fill_picture
(
AVFilterContext
*
ctx
,
AVFilterBufferRef
*
picref
)
{
TestSourceContext
*
test
=
ctx
->
priv
;
uint8_t
*
p
,
*
p0
;
int
x
,
y
;
int
color
,
color_rest
;
int
icolor
;
int
radius
;
int
quad0
,
quad
;
int
dquad_x
,
dquad_y
;
int
grad
,
dgrad
,
rgrad
,
drgrad
;
int
seg_size
;
int
second
;
int
i
;
uint8_t
*
data
=
picref
->
data
[
0
];
int
width
=
picref
->
video
->
w
;
int
height
=
picref
->
video
->
h
;
/* draw colored bars and circle */
radius
=
(
width
+
height
)
/
4
;
quad0
=
width
*
width
/
4
+
height
*
height
/
4
-
radius
*
radius
;
dquad_y
=
1
-
height
;
p0
=
data
;
for
(
y
=
0
;
y
<
height
;
y
++
)
{
p
=
p0
;
color
=
0
;
color_rest
=
0
;
quad
=
quad0
;
dquad_x
=
1
-
width
;
for
(
x
=
0
;
x
<
width
;
x
++
)
{
icolor
=
color
;
if
(
quad
<
0
)
icolor
^=
7
;
quad
+=
dquad_x
;
dquad_x
+=
2
;
*
(
p
++
)
=
icolor
&
1
?
255
:
0
;
*
(
p
++
)
=
icolor
&
2
?
255
:
0
;
*
(
p
++
)
=
icolor
&
4
?
255
:
0
;
color_rest
+=
8
;
if
(
color_rest
>=
width
)
{
color_rest
-=
width
;
color
++
;
}
}
quad0
+=
dquad_y
;
dquad_y
+=
2
;
p0
+=
picref
->
linesize
[
0
];
}
/* draw sliding color line */
p
=
data
+
picref
->
linesize
[
0
]
*
height
*
3
/
4
;
grad
=
(
256
*
test
->
nb_frame
*
test
->
time_base
.
num
/
test
->
time_base
.
den
)
%
GRADIENT_SIZE
;
rgrad
=
0
;
dgrad
=
GRADIENT_SIZE
/
width
;
drgrad
=
GRADIENT_SIZE
%
width
;
for
(
x
=
0
;
x
<
width
;
x
++
)
{
*
(
p
++
)
=
grad
<
256
||
grad
>=
5
*
256
?
255
:
grad
>=
2
*
256
&&
grad
<
4
*
256
?
0
:
grad
<
2
*
256
?
2
*
256
-
1
-
grad
:
grad
-
4
*
256
;
*
(
p
++
)
=
grad
>=
4
*
256
?
0
:
grad
>=
1
*
256
&&
grad
<
3
*
256
?
255
:
grad
<
1
*
256
?
grad
:
4
*
256
-
1
-
grad
;
*
(
p
++
)
=
grad
<
2
*
256
?
0
:
grad
>=
3
*
256
&&
grad
<
5
*
256
?
255
:
grad
<
3
*
256
?
grad
-
2
*
256
:
6
*
256
-
1
-
grad
;
grad
+=
dgrad
;
rgrad
+=
drgrad
;
if
(
rgrad
>=
GRADIENT_SIZE
)
{
grad
++
;
rgrad
-=
GRADIENT_SIZE
;
}
if
(
grad
>=
GRADIENT_SIZE
)
grad
-=
GRADIENT_SIZE
;
}
for
(
y
=
height
/
8
;
y
>
0
;
y
--
)
{
memcpy
(
p
,
p
-
picref
->
linesize
[
0
],
3
*
width
);
p
+=
picref
->
linesize
[
0
];
}
/* draw digits */
seg_size
=
width
/
80
;
if
(
seg_size
>=
1
&&
height
>=
13
*
seg_size
)
{
second
=
test
->
nb_frame
*
test
->
time_base
.
num
/
test
->
time_base
.
den
;
x
=
width
-
(
width
-
seg_size
*
64
)
/
2
;
y
=
(
height
-
seg_size
*
13
)
/
2
;
p
=
data
+
(
x
*
3
+
y
*
picref
->
linesize
[
0
]);
for
(
i
=
0
;
i
<
8
;
i
++
)
{
p
-=
3
*
8
*
seg_size
;
draw_digit
(
second
%
10
,
p
,
picref
->
linesize
[
0
],
seg_size
);
second
/=
10
;
if
(
second
==
0
)
break
;
}
}
}
static
av_cold
int
test_init
(
AVFilterContext
*
ctx
,
const
char
*
args
,
void
*
opaque
)
{
TestSourceContext
*
test
=
ctx
->
priv
;
test
->
class
=
&
testsrc_class
;
test
->
fill_picture_fn
=
test_fill_picture
;
return
init_common
(
ctx
,
args
,
opaque
);
}
static
int
test_query_formats
(
AVFilterContext
*
ctx
)
{
static
const
enum
PixelFormat
pix_fmts
[]
=
{
PIX_FMT_RGB24
,
PIX_FMT_NONE
};
avfilter_set_common_formats
(
ctx
,
avfilter_make_format_list
(
pix_fmts
));
return
0
;
}
AVFilter
avfilter_vsrc_testsrc
=
{
.
name
=
"testsrc"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Generate test pattern."
),
.
priv_size
=
sizeof
(
TestSourceContext
),
.
init
=
test_init
,
.
query_formats
=
test_query_formats
,
.
inputs
=
(
AVFilterPad
[])
{{
.
name
=
NULL
}},
.
outputs
=
(
AVFilterPad
[])
{{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
request_frame
=
request_frame
,
.
config_props
=
config_props
,
},
{
.
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